Skip to content

Commit

Permalink
chore: update gift code
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Mar 9, 2024
1 parent 98690e0 commit 6136a10
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 19 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ _🚀 **Next Generation AI One-Stop Solution**_
1. **丰富且美观的仪表盘**, 包含本日和当月入账信息, 订阅人数, 模型使用统计折线图, 饼状图分析, 收入统计, 用户类型统计, 模型使用统计, 请求次数和模型错误数量统计图表等
![仪表盘](/screenshot/admin.png)
2. **支持用户管理**, *用户列表*, *用户详情*, *管理操作* (*修改密码*, *修改邮箱*, *封禁 / 解封用户*, *设为管理员*, *点数变更*, *点数设置*, *订阅管理*, *订阅等级设置*, *释放订阅用量* 等操作)
3. **支持邀请码和兑换码管理** 支持管理操作, 支持批量生成和保存为文件
3. **支持礼品码和兑换码管理** 支持管理操作, 支持批量生成和保存为文件
4. **价格设定**, 支持模型价格设定 (_**次数计费**_, **_Token 弹性计费_**, _**不计费**_ 等类型), 支持同步上游 Chat Nio 站点的价格设定 (可选是否覆盖本站已有模型价格规则), 未设定价格模型检测 (如果非管理员将自动检测并停止使用模型进而防止金额损失)
![购买点数](/screenshot/shop.png)
![价格设定](/screenshot/charge.png)
Expand Down Expand Up @@ -213,9 +213,11 @@ _🚀 **Next Generation AI One-Stop Solution**_
- 后端域名用于(且目前仅限于) Midjourney Proxy 服务的后端回调地址, 如无需使用 Midjourney Proxy 服务, 请忽略此设置。
7. **如何配置支付方式?**
- Chat Nio 开源版支持发卡模式, 设置系统设置中的购买链接为你的发卡地址即可。卡密可通过用户管理中兑换码管理中批量生成。
8. **邀请码和兑换码有什么区别**
- 邀请码一种类型只能一个用户只能绑定一次, 发福利等方式可使用邀请码, 可在头像下拉菜单中的邀请码中兑换
8. **礼品码和兑换码有什么区别**
- 礼品码一种类型只能一个用户只能绑定一次, 而非 aff code, 发福利等方式可使用礼品码, 可在头像下拉菜单中的礼品码中兑换
- 兑换码一种类型可以多个用户绑定, 可作为正常购买和发卡使用, 可在用户管理中的兑换码管理中批量生成, 在头像下拉菜单的点数(菜单第一个)内输入兑换码进行兑换。
- 一个例子:比如我发了一个类型为 *新年快乐* 的福利, 此时推荐使用礼品码, 假设发放 100 个 66 点数, 如果为兑换码, 手快的一个用户就批量把所有兑换码的 6600 点数都用完了, 而礼品码则可以保证每个用户只能使用一次 (获得 66 点数)。
- 而搭建发卡的时, 如果用礼品码, 因为一个类型只能兑换一次, 购买多个礼品码会导致兑换失败, 而兑换码则可以在此场景下使用。
9. **该项目支持 Vercel 部署吗?**
- Chat Nio 本身并不支持 Vercel 部署, 但是你可以使用前后端分离模式, Vercel 部署前端部分, 后端部分使用 Docker 部署或编译部署。
10. **前后端分离部署模式是什么?**
Expand Down
24 changes: 19 additions & 5 deletions app/src/components/home/subscription/BuyDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { Plus } from "lucide-react";
import { ToastAction } from "@/components/ui/toast.tsx";
import { deeptrainEndpoint, useDeeptrain } from "@/conf/env.ts";
import { AppDispatch } from "@/store";
import { openDialog } from "@/store/quota.ts";
import { openDialog, quotaSelector } from "@/store/quota.ts";
import { getPlanPrice } from "@/conf/subscription.tsx";
import { Plans } from "@/api/types.tsx";
import { subscriptionDataSelector } from "@/store/globals.ts";
Expand All @@ -52,7 +52,7 @@ function countUpgradePrice(
): number {
const bias = getPlanPrice(data, target) - getPlanPrice(data, level);
const v = (bias / 30) * days;
return v > 0 ? v + 1 : 0; // time count offset
return (v > 0 ? v + 1 : 0) + 1; // time count offset
}

type UpgradeProps = {
Expand All @@ -66,6 +66,7 @@ async function callBuyAction(
dispatch: AppDispatch,
month: number,
level: number,
current: number,
): Promise<boolean> {
const res = await buySubscription(month, level);
if (res.status) {
Expand All @@ -78,7 +79,11 @@ async function callBuyAction(
} else {
toast({
title: t("sub.failed"),
description: t("sub.failed-prompt"),
description: useDeeptrain
? t("sub.failed-prompt")
: t("sub.failed-quota-prompt", {
quota: current.toFixed(2),
}),
action: (
<ToastAction
altText={t("buy.go")}
Expand Down Expand Up @@ -116,7 +121,7 @@ async function callMigrateAction(
} else {
toast({
title: t("sub.migrate-failed"),
description: t("sub.migrate-failed-prompt"),
description: t("sub.sub-migrate-failed-prompt", { reason: res.error }),
});
}
return res.status;
Expand All @@ -130,6 +135,8 @@ export function Upgrade({ level, current }: UpgradeProps) {
const dispatch = useDispatch();
const { toast } = useToast();

const quota = useSelector(quotaSelector);

const subscriptionData = useSelector(subscriptionDataSelector);

const isCurrent = useMemo(() => current === level, [current, level]);
Expand Down Expand Up @@ -199,7 +206,14 @@ export function Upgrade({ level, current }: UpgradeProps) {
<Button
className={`mb-1.5`}
onClick={async () => {
const res = await callBuyAction(t, toast, dispatch, month, level);
const res = await callBuyAction(
t,
toast,
dispatch,
month,
level,
quota,
);
if (res) {
setOpen(false);
await refreshSubscription(dispatch);
Expand Down
15 changes: 8 additions & 7 deletions app/src/resources/i18n/cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,9 @@
"migrate-success-prompt": "您已成功变更订阅计划。",
"failed": "订阅失败",
"failed-prompt": "订阅失败,请确保您有足够的余额。",
"failed-quota-prompt": "订阅失败,您的余额不足 ({{quota}} 点数)",
"migrate-failed": "变更失败",
"migrate-failed-prompt": "您的订阅变更失败"
"sub-migrate-failed-prompt": "您的订阅变更失败,原因:{{reason}}"
},
"cancel": "取消",
"confirm": "确认",
Expand Down Expand Up @@ -340,8 +341,8 @@
},
"invitation": {
"title": "兑换码",
"invitation": "邀请码",
"input-placeholder": "请输入邀请码",
"invitation": "礼品码",
"input-placeholder": "请输入礼品码",
"cancel": "取消",
"check": "验证",
"check-success": "兑换成功",
Expand Down Expand Up @@ -410,7 +411,7 @@
"model-chart-tip": "Token 用量",
"model-usage-chart": "模型使用占比",
"user-type-chart": "用户类型占比",
"user-type-chart-tip": "其他付费用户:指订阅过期用户或点数超过当前初始点数的用户(使用邀请码等操作也会被算作点数增加的变更",
"user-type-chart-tip": "其他付费用户:指订阅过期用户或点数超过当前初始点数的用户(使用礼品码等操作也会被算作点数增加的变更",
"user-type-chart-info": "总共 {{total}} 用户",
"request-chart": "请求量统计",
"billing-chart": "收入统计",
Expand All @@ -422,9 +423,9 @@
"confirm": "确认",
"invitation": "兑换码管理",
"code": "兑换码",
"invitation-code": "邀请码",
"invitation-manage": "邀请码管理",
"invitation-tips": "邀请码用于兑换点数,每一类邀请码一个用户只能使用一次(可作宣传使用)",
"invitation-code": "礼品码",
"invitation-manage": "礼品码管理",
"invitation-tips": "礼品码用于兑换点数,每一类礼品码一个用户只能使用一次(可作宣传使用)",
"redeem-tips": "兑换码用于兑换点数,可用于支付发卡等",
"quota": "点数",
"type": "类型",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@
"plan-tip": "Callable Model",
"disable": "This site's subscription feature has been turned off",
"plan-unlimited-usage": "{{name}} has unlimited uses",
"plan-not-support-relay": "Site subscription quota does not cover staging API, please use flexible billing credits for staging API"
"plan-not-support-relay": "Site subscription quota does not cover staging API, please use flexible billing credits for staging API",
"failed-quota-prompt": "Subscription failed, your balance is insufficient ({{quota}} credits)",
"sub-migrate-failed-prompt": "Your subscription change failed for {{reason}}"
},
"cancel": "Cancel",
"confirm": "Confirm",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@
"plan-tip": "呼び出し可能なモデル",
"disable": "このサイトのサブスクリプション機能はオフになっています",
"plan-unlimited-usage": "{{name}}は無制限に使用できます",
"plan-not-support-relay": "サイトサブスクリプションクォータはステージングAPIをカバーしていません。ステージングAPIに柔軟な請求クレジットを使用してください"
"plan-not-support-relay": "サイトサブスクリプションクォータはステージングAPIをカバーしていません。ステージングAPIに柔軟な請求クレジットを使用してください",
"failed-quota-prompt": "サブスクリプションに失敗しました。残高が不足しています({{ quota}}クレジット)",
"sub-migrate-failed-prompt": "サブスクリプションの変更が{{reason}}で失敗しました"
},
"cancel": "キャンセル",
"confirm": "確認",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@
"plan-tip": "Вызываемая модель",
"disable": "Функция подписки на этом сайте отключена",
"plan-unlimited-usage": "{{name}} имеет неограниченное количество пользователей",
"plan-not-support-relay": "Квота подписки на сайт не распространяется на промежуточный API, пожалуйста, используйте гибкие биллинговые кредиты для промежуточного API"
"plan-not-support-relay": "Квота подписки на сайт не распространяется на промежуточный API, пожалуйста, используйте гибкие биллинговые кредиты для промежуточного API",
"failed-quota-prompt": "Не удалось оформить подписку, недостаточно средств ({{quota}} кредитов)",
"sub-migrate-failed-prompt": "Изменение подписки не выполнено по {{reason}}"
},
"cancel": "Отмена",
"confirm": "Подтвердить",
Expand Down
6 changes: 5 additions & 1 deletion middleware/throttle.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ func ThrottleMiddleware() gin.HandlerFunc {

limiter := GetPrefixMap[Limiter](path, limits)
if limiter != nil && limiter.RateLimit(cache, ip, path) {
c.JSON(200, gin.H{"status": false, "reason": "You have sent too many requests. Please try again later."})
c.JSON(200, gin.H{
"status": false,
"reason": "You have sent too many requests. Please try again later.",
"error": "request_throttled",
})
c.Abort()
return
}
Expand Down

0 comments on commit 6136a10

Please sign in to comment.