mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	fix: #463 add subscrption total amount
This commit is contained in:
		@@ -96,26 +96,18 @@ export function Settings(props: { closeSettings: () => void }) {
 | 
			
		||||
 | 
			
		||||
  const [usage, setUsage] = useState<{
 | 
			
		||||
    used?: number;
 | 
			
		||||
    subscription?: number;
 | 
			
		||||
  }>();
 | 
			
		||||
  const [loadingUsage, setLoadingUsage] = useState(false);
 | 
			
		||||
  function checkUsage() {
 | 
			
		||||
    setLoadingUsage(true);
 | 
			
		||||
    requestUsage()
 | 
			
		||||
      .then((res) =>
 | 
			
		||||
        setUsage({
 | 
			
		||||
          used: res,
 | 
			
		||||
        }),
 | 
			
		||||
      )
 | 
			
		||||
      .then((res) => setUsage(res))
 | 
			
		||||
      .finally(() => {
 | 
			
		||||
        setLoadingUsage(false);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    checkUpdate();
 | 
			
		||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const accessStore = useAccessStore();
 | 
			
		||||
  const enabledAccessControl = useMemo(
 | 
			
		||||
    () => accessStore.enabledAccessControl(),
 | 
			
		||||
@@ -127,12 +119,13 @@ export function Settings(props: { closeSettings: () => void }) {
 | 
			
		||||
  const builtinCount = SearchService.count.builtin;
 | 
			
		||||
  const customCount = promptStore.prompts.size ?? 0;
 | 
			
		||||
 | 
			
		||||
  const showUsage = accessStore.token !== "";
 | 
			
		||||
  const showUsage = !!accessStore.token || !!accessStore.accessCode;
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (showUsage) {
 | 
			
		||||
      checkUsage();
 | 
			
		||||
    }
 | 
			
		||||
  }, [showUsage]);
 | 
			
		||||
    checkUpdate();
 | 
			
		||||
    showUsage && checkUsage();
 | 
			
		||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <ErrorBoundary>
 | 
			
		||||
@@ -392,7 +385,10 @@ export function Settings(props: { closeSettings: () => void }) {
 | 
			
		||||
              showUsage
 | 
			
		||||
                ? loadingUsage
 | 
			
		||||
                  ? Locale.Settings.Usage.IsChecking
 | 
			
		||||
                  : Locale.Settings.Usage.SubTitle(usage?.used ?? "[?]")
 | 
			
		||||
                  : Locale.Settings.Usage.SubTitle(
 | 
			
		||||
                      usage?.used ?? "[?]",
 | 
			
		||||
                      usage?.subscription ?? "[?]",
 | 
			
		||||
                    )
 | 
			
		||||
                : Locale.Settings.Usage.NoAccess
 | 
			
		||||
            }
 | 
			
		||||
          >
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { SubmitKey } from "../store/app";
 | 
			
		||||
const cn = {
 | 
			
		||||
  WIP: "该功能仍在开发中……",
 | 
			
		||||
  Error: {
 | 
			
		||||
    Unauthorized: "现在是未授权状态,请在设置页输入授权码。",
 | 
			
		||||
    Unauthorized: "现在是未授权状态,请在设置页输入访问密码。",
 | 
			
		||||
  },
 | 
			
		||||
  ChatItem: {
 | 
			
		||||
    ChatItemCount: (count: number) => `${count} 条对话`,
 | 
			
		||||
@@ -104,22 +104,22 @@ const cn = {
 | 
			
		||||
    },
 | 
			
		||||
    Token: {
 | 
			
		||||
      Title: "API Key",
 | 
			
		||||
      SubTitle: "使用自己的 Key 可绕过授权访问限制",
 | 
			
		||||
      SubTitle: "使用自己的 Key 可绕过密码访问限制",
 | 
			
		||||
      Placeholder: "OpenAI API Key",
 | 
			
		||||
    },
 | 
			
		||||
    Usage: {
 | 
			
		||||
      Title: "账户余额",
 | 
			
		||||
      SubTitle(used: any) {
 | 
			
		||||
        return `本月已使用 $${used}`;
 | 
			
		||||
      Title: "余额查询",
 | 
			
		||||
      SubTitle(used: any, total: any) {
 | 
			
		||||
        return `本月已使用 $${used},订阅总额 $${total}`;
 | 
			
		||||
      },
 | 
			
		||||
      IsChecking: "正在检查…",
 | 
			
		||||
      Check: "重新检查",
 | 
			
		||||
      NoAccess: "输入API Key查看余额",
 | 
			
		||||
      NoAccess: "输入 API Key 或访问密码查看余额",
 | 
			
		||||
    },
 | 
			
		||||
    AccessCode: {
 | 
			
		||||
      Title: "授权码",
 | 
			
		||||
      Title: "访问密码",
 | 
			
		||||
      SubTitle: "现在是未授权访问状态",
 | 
			
		||||
      Placeholder: "请输入授权码",
 | 
			
		||||
      Placeholder: "请输入访问密码",
 | 
			
		||||
    },
 | 
			
		||||
    Model: "模型 (model)",
 | 
			
		||||
    Temperature: {
 | 
			
		||||
 
 | 
			
		||||
@@ -112,8 +112,8 @@ const en: LocaleType = {
 | 
			
		||||
    },
 | 
			
		||||
    Usage: {
 | 
			
		||||
      Title: "Account Balance",
 | 
			
		||||
      SubTitle(used: any) {
 | 
			
		||||
        return `Used this month $${used}`;
 | 
			
		||||
      SubTitle(used: any, total: any) {
 | 
			
		||||
        return `Used this month $${used}, subscription $${total}`;
 | 
			
		||||
      },
 | 
			
		||||
      IsChecking: "Checking...",
 | 
			
		||||
      Check: "Check Again",
 | 
			
		||||
 
 | 
			
		||||
@@ -112,8 +112,8 @@ const es: LocaleType = {
 | 
			
		||||
    },
 | 
			
		||||
    Usage: {
 | 
			
		||||
      Title: "Saldo de la cuenta",
 | 
			
		||||
      SubTitle(used: any) {
 | 
			
		||||
        return `Usado $${used}`;
 | 
			
		||||
      SubTitle(used: any, total: any) {
 | 
			
		||||
        return `Usado $${used}, subscription $${total}`;
 | 
			
		||||
      },
 | 
			
		||||
      IsChecking: "Comprobando...",
 | 
			
		||||
      Check: "Comprobar de nuevo",
 | 
			
		||||
 
 | 
			
		||||
@@ -113,8 +113,8 @@ const it: LocaleType = {
 | 
			
		||||
    },
 | 
			
		||||
    Usage: {
 | 
			
		||||
      Title: "Bilancio Account",
 | 
			
		||||
      SubTitle(used: any) {
 | 
			
		||||
        return `Usato in questo mese $${used}`;
 | 
			
		||||
      SubTitle(used: any, total: any) {
 | 
			
		||||
        return `Usato in questo mese $${used}, subscription $${total}`;
 | 
			
		||||
      },
 | 
			
		||||
      IsChecking: "Controllando...",
 | 
			
		||||
      Check: "Controlla ancora",
 | 
			
		||||
 
 | 
			
		||||
@@ -109,8 +109,8 @@ const tw: LocaleType = {
 | 
			
		||||
    },
 | 
			
		||||
    Usage: {
 | 
			
		||||
      Title: "帳戶餘額",
 | 
			
		||||
      SubTitle(used: any) {
 | 
			
		||||
        return `本月已使用 $${used}`;
 | 
			
		||||
      SubTitle(used: any, total: any) {
 | 
			
		||||
        return `本月已使用 $${used},订阅总额 $${total}`;
 | 
			
		||||
      },
 | 
			
		||||
      IsChecking: "正在檢查…",
 | 
			
		||||
      Check: "重新檢查",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import type { ChatRequest, ChatReponse } from "./api/openai/typing";
 | 
			
		||||
import { Message, ModelConfig, useAccessStore, useChatStore } from "./store";
 | 
			
		||||
import Locale from "./locales";
 | 
			
		||||
import { showToast } from "./components/ui-lib";
 | 
			
		||||
 | 
			
		||||
const TIME_OUT_MS = 30000;
 | 
			
		||||
@@ -83,19 +82,26 @@ export async function requestUsage() {
 | 
			
		||||
  const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
 | 
			
		||||
  const startDate = formatDate(startOfMonth);
 | 
			
		||||
  const endDate = formatDate(now);
 | 
			
		||||
  const res = await requestOpenaiClient(
 | 
			
		||||
    `dashboard/billing/usage?start_date=${startDate}&end_date=${endDate}`,
 | 
			
		||||
  )(null, "GET");
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const response = (await res.json()) as {
 | 
			
		||||
      total_usage: number;
 | 
			
		||||
  const [used, subs] = await Promise.all([
 | 
			
		||||
    requestOpenaiClient(
 | 
			
		||||
      `dashboard/billing/usage?start_date=${startDate}&end_date=${endDate}`,
 | 
			
		||||
    )(null, "GET"),
 | 
			
		||||
    requestOpenaiClient("dashboard/billing/subscription")(null, "GET"),
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
  const response = (await used.json()) as {
 | 
			
		||||
    total_usage?: number;
 | 
			
		||||
    error?: {
 | 
			
		||||
      type: string;
 | 
			
		||||
      message: string;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const total = (await subs.json()) as {
 | 
			
		||||
    hard_limit_usd?: number;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (response.error && response.error.type) {
 | 
			
		||||
    showToast(response.error.message);
 | 
			
		||||
    return;
 | 
			
		||||
@@ -104,10 +110,11 @@ export async function requestUsage() {
 | 
			
		||||
  if (response.total_usage) {
 | 
			
		||||
    response.total_usage = Math.round(response.total_usage) / 100;
 | 
			
		||||
  }
 | 
			
		||||
    return response.total_usage;
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error("[Request usage] ", error, res.body);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    used: response.total_usage,
 | 
			
		||||
    subscription: total.hard_limit_usd,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function requestChatStream(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user