diff --git a/README.md b/README.md
index 461963c..71998e8 100644
--- a/README.md
+++ b/README.md
@@ -9,40 +9,9 @@ Telegram交流群:https://t.me/ai_cn2023
## 最新示意图(2023.08.28)
-
-
-
-
-## 更新日志
-### 8月26日更新
-1. 有效检查改为发送请求,不再使用正则;
-
-### 8月22日更新
-
-1. 组织信息增加`userid`和`创建时间`;
-
-### 7月29日更新(点个star吧)
-
-1. 新增GPT-3.5查询、绑卡信息(人名和地址)、组织名称、邮箱、组织ID、是否有效;
-2. 使用sk查询不再整体报错,而是展示可以查询到的内容;
-
-### 7月22日更新后,如要查看完整信息,需登录一次账号,F12查看sess码,使用sess码进行查询
-
-7月22日更新后,已删除key校验规则,需使用sess码进行查询。使用key只能查询部分信息。
-
-
-
-## sess查询示例(120刀4.0key)
-
-
-
-## sk查询示例(120刀4.0key)
-
-
-
-## sk查询示例(5刀未绑卡key)
-
-
+
+
+
## SESS ID获取方法
@@ -55,8 +24,6 @@ Telegram交流群:https://t.me/ai_cn2023
``` html
```
-## 反代代码示例
-
## 怎么部署
下载index.html直接打开就行,除了背景图片,没有任何外部资源。
diff --git a/index.html b/index.html
index 1a2dd56..85aea54 100644
--- a/index.html
+++ b/index.html
@@ -6,365 +6,7 @@
OpenAIAPI 信息查询
-
+
@@ -415,8 +57,9 @@
GPT-4 |
32K |
绑卡 |
- 绑卡信息 |
- 组织信息 |
+ 绑卡信息 |
+ 组织信息 |
+ 速率 |
是否有效 |
@@ -432,439 +75,7 @@
-
-
-
+
diff --git a/static/css.css b/static/css.css
new file mode 100644
index 0000000..e79aba9
--- /dev/null
+++ b/static/css.css
@@ -0,0 +1,357 @@
+:root {
+ --color-primary: #2EA7E0;
+ --color-primary-dark: #2482AD;
+ --color-primary-alpha: #75C2E6;
+ --body-color: #ffffff;
+ --body-bg: #000000;
+ --border-color: #f1ebeb00;
+}
+
+body {
+ background: url('https://cdn-img.czl.net/2023/05/23/pjbczr.webp') no-repeat center center fixed;
+ /* 自定义背景图 */
+ background-size: cover;
+ width: 90%;
+ max-width: 1400px;
+ margin-left: auto;
+ margin-right: auto;
+ padding-left: 2rem;
+ padding-right: 2rem;
+ color: var(--body-color);
+ /* background: var(--body-bg); */
+ font-family: system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ -webkit-tap-highlight-color: rgb(252, 247, 247);
+ text-rendering: optimizelegibility;
+ -webkit-font-smoothing: antialiased;
+}
+
+.query {
+ max-width: 50rem;
+ margin: auto;
+}
+
+a {
+ color: var(--color-primary);
+ text-decoration: none;
+ transition: color .3s;
+}
+
+a:hover {
+ color: var(--color-primary-alpha);
+ text-decoration: underline;
+}
+
+h1 {
+ font-size: 2.5rem;
+ text-align: center;
+}
+
+main[x-cloak] {
+ opacity: 0;
+}
+
+main:not([x-cloak]) {
+ opacity: 1;
+ transition: opacity .3s;
+}
+
+textarea {
+ -webkit-appearance: none;
+ appearance: none;
+ display: block;
+ width: 100%;
+ padding: .5rem 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: .25rem;
+ box-sizing: border-box;
+ color: #33404d;
+ line-height: inherit;
+ font-size: 1rem;
+ transition: border .3s, box-shadow .3s;
+}
+
+textarea:focus {
+ box-shadow: 0 0 0 .25rem var(--color-primary-alpha);
+ border-color: var(--color-primary);
+ outline: 0;
+}
+
+input {
+ -webkit-appearance: none;
+ appearance: none;
+ display: block;
+ width: 100%;
+ padding: .5rem 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: .25rem;
+ box-sizing: border-box;
+ color: #33404d;
+ line-height: inherit;
+ font-size: 1rem;
+ transition: border .3s, box-shadow .3s;
+}
+
+input:focus {
+ box-shadow: 0 0 0 .25rem var(--color-primary-alpha);
+ border-color: var(--color-primary);
+ outline: 0;
+}
+
+details {
+ margin: 1rem 0 2rem;
+ border: 1px solid var(--border-color);
+ border-radius: .25rem;
+ /* transition: background .3s; */
+}
+
+details[open] {
+ background: #fff;
+}
+
+details summary {
+ padding: .5rem 1rem;
+ font-weight: 500;
+ user-select: none;
+ cursor: pointer;
+ opacity: .8;
+ outline: 0;
+}
+
+details div {
+ padding: 1rem;
+ border-top: 1px solid var(--border-color);
+}
+
+details small {
+ margin: 0;
+ font-size: .875rem;
+ line-height: 2;
+}
+
+button {
+ appearance: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ margin: auto;
+ max-width: 50rem;
+ margin-bottom: 1rem;
+ padding: .5rem .75rem;
+ border: 1px solid var(--color-primary);
+ border-radius: .25rem;
+ background: var(--color-primary);
+ color: #fff;
+ font-size: 1rem;
+ font-weight: 500;
+ line-height: inherit;
+ cursor: pointer;
+ user-select: none;
+ transition: border .3s, background .3s, ;
+}
+
+button:hover {
+ border-color: var(--color-primary-dark);
+ background: var(--color-primary-dark);
+}
+
+button:focus {
+ box-shadow: 0 0 0 .25rem var(--color-primary-alpha);
+ border-color: var(--color-primary);
+ outline: 0;
+}
+
+button:disabled {
+ background: var(--color-primary);
+ border-color: var(--color-primary);
+ opacity: .6;
+ cursor: not-allowed;
+}
+
+button.loading::before {
+ content: '';
+ display: inline-block;
+ margin-right: .5rem;
+ border: 2px solid #fff;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ border-radius: 50%;
+ width: .75rem;
+ height: .75rem;
+ animation: rotate .5s linear infinite;
+}
+
+footer {
+ /* padding: 2px; */
+ /* border-top: 1px solid var(--border-color); */
+ text-align: center;
+ /* opacity: .5; */
+ /* position: fixed; */
+ /* bottom: 0; */
+ /* left: 0; */
+ margin-top: 20px;
+ /* width: 100%; */
+ /* background-color:#212121; */
+ line-height: unset !important;
+ line-height: normal;
+}
+
+footer .p {
+ display: flex;
+ margin-block-start: 0 !important;
+ margin-block-end: 0 !important;
+ padding: 0;
+ color: rgb(255, 255, 255);
+}
+
+.success,
+.error {
+ margin-bottom: 1rem;
+ padding: .5rem 1rem;
+ border-radius: .25rem;
+ color: #fff;
+ text-align: center;
+ opacity: 1;
+ transition: opacity .3s;
+}
+
+.success {
+ /* border: 1px solid #12b886; */
+ background: #38d9a9;
+}
+
+.error {
+ /* border: 1px solid #b32142; */
+ background: #b32142;
+}
+
+@keyframes rotate {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* 设置API URL选择器和自定义URL输入框的样式 */
+select#api-url-select,
+input#custom-url-input {
+ width: 100%;
+ height: 2.4rem;
+ font-size: 1rem;
+ background-color: #212121;
+ margin-bottom: .5rem;
+ padding: .5rem .75rem;
+ color: #ffffff;
+ border: none;
+ padding: .5rem .75rem;
+ border-radius: .25rem;
+ margin-right: 10px;
+ margin-top: 2vhpx;
+ /* 添加了顶部边距 */
+}
+
+
+
+/* 隐藏自定义API链接输入框 */
+input#custom-url-input {
+ display: none;
+ height: 50px;
+ /* 添加高度 */
+}
+
+
+
+/* 下面的代码定义了结果表格的样式 */
+#result-table {
+ border-collapse: collapse;
+ width: 100%;
+ margin-top: 20px;
+ font-size: 10px;
+ border-radius: 5px;
+ border: none;
+ overflow: hidden;
+}
+
+/* 下面的代码定义了结果表格表头的样式 */
+#result-table th {
+ background-color: var(--color-primary);
+ color: #ffffff;
+ font-weight: 400;
+ height: 20px;
+ padding: 10px 5px;
+ text-align: left;
+ /* border: 1px solid #dcdcdc; */
+}
+
+/* 下面的代码定义了结果表格数据单元格的样式 */
+#result-table td {
+ height: 20px;
+ text-align: left;
+ padding: 10px 5px;
+ /* border: 1px solid #d3d3d3; */
+}
+
+/* 下面的代码定义了结果表格奇数行的背景颜色 */
+#result-table tbody tr:nth-child(odd) {
+ background-color: #252422;
+}
+
+/* 下面的代码定义了结果表格偶数行的背景颜色 */
+#result-table tbody tr:nth-child(even) {
+ background-color: #31302d;
+}
+
+/* 下面的代码定义了结果表格表头的宽度 */
+#result-table .table-header {
+ width: 25%;
+}
+
+/* 下面的代码定义了结果表格数据单元格的宽度、字体加粗和颜色 */
+#result-table .table-data {
+ width: 25%;
+ font-weight: bold;
+ color: #1c248b;
+}
+
+/* 下面的代码定义了结果表格数据单元格的样式 */
+#result-table .status-error {
+ height: 20px;
+ text-align: left;
+ padding: 10px 5px;
+ /* border: 1px solid #dcdcdc; */
+}
+
+/* 下面的代码定义了一个类名为status-ok的样式,用于设置成功状态的文本颜色 */
+.status-ok {
+ color: #2d8d2d;
+}
+
+/* 下面的代码定义了一个类名为status-error的样式,用于设置错误状态的文本颜色 */
+.status-error {
+ color: #ed0808;
+}
+
+#api-key-input {
+ width: 100%;
+ height: 100px;
+ /* border: 1px solid #999; */
+ background-color: #fff;
+}
+
+.emoji {
+ font-size: 30px;
+ /* 调整为适当的大小 */
+}
+
+button.loading::before {
+ content: "";
+ display: inline-block;
+ margin-right: .5rem;
+ border: 2px solid #fff;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ border-radius: 50%;
+ width: .75rem;
+ height: .75rem;
+ animation: rotate .5s linear infinite;
+}
\ No newline at end of file
diff --git a/static/js.js b/static/js.js
new file mode 100644
index 0000000..f89c8bd
--- /dev/null
+++ b/static/js.js
@@ -0,0 +1,456 @@
+let queriedApiKeys = [];
+let serialNumber = 1;
+
+
+async function checkBilling(apiKey, apiUrl) {
+ const now = new Date();
+ let startDate = new Date(now - 90 * 24 * 60 * 60 * 1000);
+ const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
+ const subDate = new Date(now);
+ subDate.setDate(1);
+
+ const headers = {
+ "Authorization": "Bearer " + apiKey,
+ "Content-Type": "application/json"
+ };
+ const modelsCheck = `${apiUrl}/v1/models`;
+ const urlSubscription = `${apiUrl}/v1/dashboard/billing/subscription`;
+ let urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`;
+ const urlsetid = apiUrl + '/v1/organizations';
+ const urlPaymentmethods = `${apiUrl}/v1/dashboard/billing/payment_methods`;
+ const urlRatelimits = `${apiUrl}/v1/dashboard/rate_limits`;
+
+ try {
+ let totalAmount, totalUsage, remaining, GPT35CheckResult, GPT4CheckResult, GPT432kCheckResult, setid, isSubscrible;
+ let SubscribleInformation = {};
+ let SubInformation;
+ let errors = {};
+
+ let response = await fetch(urlSubscription, { headers });
+
+ let currentDate = new Date();
+ const subscriptionData = await response.json();
+ const expiryDate = new Date(subscriptionData.access_until * 1000 + 8 * 60 * 60 * 1000);
+ const formattedDate = `${expiryDate.getFullYear()}-${(expiryDate.getMonth() + 1).toString().padStart(2, '0')}-${expiryDate.getDate().toString().padStart(2, '0')}`;
+
+ try {
+ totalAmount = subscriptionData.system_hard_limit_usd;
+
+ if (totalAmount > 20) {
+ startDate = subDate;
+ urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`;
+ response = await fetch(urlUsage, { headers });
+ const usageData = await response.json();
+ }
+ response = await fetch(urlUsage, { headers });
+ const usageData = await response.json();
+ totalUsage = usageData.total_usage / 100;
+ remaining = currentDate > expiryDate ? "❌过期" : (totalAmount - totalUsage).toFixed(3);
+ } catch (error) {
+ console.error(error);
+ errors['subscription'] = error.message;
+ }
+ //获取是否绑卡
+ try {
+ if (subscriptionData.plan.id.includes('payg')) {
+ switch (subscriptionData.billing_mechanism) {
+ case 'advance':
+ isSubscrible = '✅预付费';
+ break;
+ case 'arrears':
+ isSubscrible = '✅已欠费';
+ break;
+ case null:
+ isSubscrible = '✅后付费';
+ break;
+ default:
+ isSubscrible = '✅';
+ }
+ } else {
+ isSubscrible = '❌';
+ }
+ } catch (error) {
+ console.error(error);
+ }
+
+ //获取绑卡信息
+ try {
+ // 从 subscriptionData 中获取 SubscribleInformation 的值...
+ SubscribleInformation.account_name = subscriptionData.account_name;
+ SubscribleInformation.po_number = subscriptionData.po_number;
+ SubscribleInformation.billing_email = subscriptionData.billing_email;
+ SubscribleInformation.tax_ids = subscriptionData.tax_ids;
+
+ let billingAddress = subscriptionData.billing_address; // 定义并赋值 billingAddress
+ let businessAddress = subscriptionData.business_address; // 定义并赋值 businessAddress
+
+ SubInformation = "名称: " + SubscribleInformation.account_name + "\n";
+ SubInformation += "PO号: " + SubscribleInformation.po_number + "\n";
+ SubInformation += "帐单邮箱: " + SubscribleInformation.billing_email + "\n";
+ SubInformation += "税号: " + SubscribleInformation.tax_ids + "\n";
+ //使用 JavaScript 的可选链式调用来确定是否为null,避免异常控制台报错
+ SubInformation += "账单地址: " + (billingAddress?.line1 ? billingAddress.line1 : '') + ", " + (billingAddress?.city ? billingAddress.city : '') + ", " + (billingAddress?.state ? billingAddress.state : '') + ", " + (billingAddress?.country ? billingAddress.country : '') + ", " + (billingAddress?.postal_code ? billingAddress.postal_code : '') + "\n";
+ SubInformation += "商业地址: " + (businessAddress?.line1 ? businessAddress.line1 : '') + ", " + (businessAddress?.city ? businessAddress.city : '') + ", " + (businessAddress?.state ? businessAddress.state : '') + ", " + (businessAddress?.country ? businessAddress.country : '') + ", " + (businessAddress?.postal_code ? businessAddress.postal_code : '\n');
+
+ // 获取付款方法信息
+ response = await fetch(urlPaymentmethods, { headers });
+ const paymentMethodsData = await response.json();
+
+ if (paymentMethodsData.data && paymentMethodsData.data.length > 0) {
+ paymentMethodsData.data.forEach((paymentMethod, index) => {
+ if (paymentMethod.type === 'card' && paymentMethod.card) {
+ const cardInfo = paymentMethod.card;
+ SubInformation += `\n\n付款方式 ${index + 1}: \n`;
+ SubInformation += paymentMethod.is_default ? "默认卡:\n" : "非默认卡:\n"; // Add default label
+ SubInformation += `卡种: ${cardInfo.brand} \n`; // Card Brand
+ SubInformation += `后4位: ${cardInfo.last4} \n`; // Card Last4
+ SubInformation += `卡日期: ${cardInfo.exp_month}/${cardInfo.exp_year} \n`; // Card Expiry
+ SubInformation += `卡国家: ${cardInfo.country}`; // Card Country
+ }
+ });
+ }
+
+ }
+ catch (error) {
+ console.error(error);
+ }
+
+ //组织信息
+ try {
+ response = await fetch(urlsetid, { headers });
+ const setiddata = await response.json();
+ setid = '';
+ const emailStartIndex = setiddata.data[0].description.lastIndexOf(' ') + 1;
+ const email = setiddata.data[0].description.substring(emailStartIndex);
+ const title = setiddata.data[0].title;
+ const id1 = setiddata.data[0].id;
+ const name = setiddata.data[0].name;
+ const description = setiddata.data[0].description;
+ const createdTimestamp = setiddata.data[0].created;
+ const createdDate = new Date(createdTimestamp * 1000);
+
+ // 格式化日期
+ const formattedDate = `${createdDate.getFullYear()}.${(createdDate.getMonth() + 1).toString().padStart(2, '0')}.${createdDate.getDate().toString().padStart(2, '0')}`;
+
+ const timeAndZone = createdDate.toString().match(/\d{2}:\d{2}:\d{2} \w+/)[0];
+
+ if (typeof setiddata.data[1] !== 'undefined') {
+ const id2 = setiddata.data[1].id;
+ setid = `${title}\n${email}\n${id1}\n${id2}\n${name}\n${description}\n${formattedDate} ${timeAndZone}`;
+ } else {
+ setid = `${title}\n${email}\n${id1}\n${name}\n${description}\n${formattedDate} ${timeAndZone}`;
+ }
+ if (typeof setiddata.data[1] !== 'undefined') {
+ const id2 = setiddata.data[1].id;
+ setid = `人名: ${title}\n邮箱: ${email}\n组织: ${id1} ${id2}\nUserID:${name}\n\n注册时间:${formattedDate} ${timeAndZone}`;
+ } else {
+ setid = `人名: ${title}\n邮箱: ${email}\n组织: ${id1} \nUserID:${name}\n注册时间:${formattedDate} ${timeAndZone}`;
+ }
+
+ } catch (error) {
+ console.error(error);
+ errors['setid'] = error.message;
+ }
+
+ //获取速率
+ let rateLimits;
+ try {
+ const response = await fetch(urlRatelimits, { headers });
+ const rateLimitsData = await response.json();
+ rateLimits = {
+ 'gpt-3.5-turbo': rateLimitsData['gpt-3.5-turbo'],
+ 'gpt-3.5-turbo-16k': rateLimitsData['gpt-3.5-turbo-16k'],
+ 'gpt-4': rateLimitsData['gpt-4'],
+ 'gpt-4-32k': rateLimitsData['gpt-4-32k']
+ };
+ } catch (error) {
+ console.error(error);
+ errors['rateLimits'] = error.message;
+ }
+
+
+
+ // 初始化模型查询结果
+ GPT35CheckResult = '❌';
+ GPT4CheckResult = '❌';
+ GPT432kCheckResult = '❌';
+ //3.5模型查询
+ let GPT35CheckSuccess = false; // 初始化为 false
+ try {
+ const modelsCheckResponse = await fetch(modelsCheck, { headers });
+ const modelsCheckData = await modelsCheckResponse.json();
+ GPT35CheckSuccess = GPT35CheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-3.5-turbo')) ? '✅' : '❌';
+ } catch (error) {
+ console.error(error);
+ errors['modelsCheck'] = error.message;
+ }
+ //4模型查询
+ try {
+ const modelsCheckResponse = await fetch(modelsCheck, { headers });
+ const modelsCheckData = await modelsCheckResponse.json();
+ GPT4CheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-4')) ? '✅' : '❌';
+ GPT432kCheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-4-32k')) ? '✅' : '❌';
+ } catch (error) {
+ console.error(error);
+ errors['modelsCheck'] = error.message;
+ }
+ // 是否有效查询
+ async function checkCompletion(apiKey, apiUrl) {
+ const urlCompletion = `${apiUrl}/v1/chat/completions`;
+ const headers = {
+ "Authorization": "Bearer " + apiKey,
+ "Content-Type": "application/json"
+ };
+ const postBody = JSON.stringify({
+ "model": "gpt-3.5-turbo",
+ "messages": [{
+ "role": "user",
+ "content": "Hello"
+ }],
+ "max_tokens": 5
+ });
+
+ let response = await fetch(urlCompletion, {
+ method: 'POST',
+ headers: headers,
+ body: postBody
+ });
+
+ let data = await response.json();
+ // 判断请求是否成功
+ if (response.status === 200) {
+ return ['✅', data.usage.total_tokens]; // 返回状态和 total_tokens
+ } else {
+ return ['❌', null];
+ }
+ }
+ // 调用 checkCompletion 函数并获取结果
+ let completionCheckResult = await checkCompletion(apiKey, apiUrl);
+ //返回值
+ return [totalAmount, totalUsage, remaining, formattedDate, GPT35CheckResult, GPT4CheckResult, GPT432kCheckResult, isSubscrible, SubInformation, setid, errors, GPT35CheckSuccess, completionCheckResult, rateLimits];
+ } catch (error) {
+ return ["Error", null, null, null, null, null, null, null, null, null];
+ }
+}
+
+
+
+
+function formatDate(date) {
+ const year = date.getFullYear();
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
+ const day = date.getDate().toString().padStart(2, '0');
+
+ return `${year}-${month}-${day}`;
+}
+
+//查询函数
+function sendRequest() {
+ let button = document.querySelector("button");
+ button.textContent = "加载中...";
+ button.disabled = true;
+ button.classList.add("loading")
+
+ let apiKeyInput = document.getElementById("api-key-input");
+ let apiUrlSelect = document.getElementById("api-url-select");
+ let customUrlInput = document.getElementById("custom-url-input");
+ let table = document.getElementById("result-table");
+ let h2 = document.getElementById("result-head");
+ h2.style.visibility = "visible";
+ table.style.visibility = "visible";
+
+ if (apiKeyInput.value.trim() === "") {
+ alert("请填写API KEY");
+ return;
+ }
+
+ document.getElementById("result-table").getElementsByTagName('tbody')[0].innerHTML = "";
+
+ let apiUrl = "";
+ if (apiUrlSelect.value === "custom") {
+ if (customUrlInput.value.trim() === "") {
+ alert("请设置API链接");
+ return;
+ } else {
+ apiUrl = customUrlInput.value.trim();
+ if (!apiUrl.startsWith("http://") && !apiUrl.startsWith("https://")) {
+ apiUrl = "https://" + apiUrl;
+ }
+ }
+ } else {
+ apiUrl = apiUrlSelect.value;
+ }
+
+ let apiKeys = apiKeyInput.value.split(/[,\s,\n]+/);
+
+ if (apiKeys.length === 0) {
+ alert("未匹配到 API-KEY,请检查输入内容");
+ return;
+ }
+
+ alert("成功匹配到 API Key,确认后开始查询:" + apiKeys);
+
+ let tableBody = document.querySelector("#result-table tbody");
+ for (let i = 0; i < apiKeys.length; i++) {
+ let apiKey = apiKeys[i].trim();
+
+ if (queriedApiKeys.includes(apiKey)) {
+ console.log(`API KEY ${apiKey} 已查询过,跳过此次查询`);
+ continue;
+ }
+ queriedApiKeys.push(apiKey);
+
+ checkBilling(apiKey, apiUrl).then((data) => {
+ data = data.map(item => {
+ if (item === undefined) {
+ return 'Not Found.'
+ } else {
+ return item
+ }
+ }
+ )
+
+ let row = document.createElement("tr");
+
+ let serialNumberCell = document.createElement("td"); // 创建序列号单元格
+ serialNumberCell.textContent = serialNumber; // 设置序列号文本
+ row.appendChild(serialNumberCell); // 将序列号单元格添加到行中
+
+ let apiKeyCell = document.createElement("td");
+ apiKeyCell.textContent = apiKey.replace(/^(.{5}).*(.{4})$/, "$1***$2");
+ row.appendChild(apiKeyCell);
+
+ console.log('查看查询结果', data); // 添加 console.log 以查看 data 的值
+
+ if (data[0] === undefined) {
+ let errorMessageCell = document.createElement("td");
+ errorMessageCell.colSpan = "8";
+ errorMessageCell.classList.add("status-error");
+ errorMessageCell.textContent = "不正确或已失效的API-KEY";
+ row.appendChild(errorMessageCell);
+ } else {
+ let totalAmount = document.createElement("td");
+ totalAmount.textContent = data[0];
+ row.appendChild(totalAmount);
+
+ let totalUsedCell = document.createElement("td");
+ if (!isNaN(data[1])) {
+ totalUsedCell.textContent = data[1].toFixed(3);
+ } else {
+ totalUsedCell.textContent = '❌'
+ }
+ row.appendChild(totalUsedCell);
+
+ let totalAvailableCell = document.createElement("td");
+ totalAvailableCell.textContent = typeof data[2] === 'number' ? data[2] : data[2];
+ row.appendChild(totalAvailableCell);
+ let progressCell = document.createElement("td");
+ let progressContainer = document.createElement("div"); // 添加一个新的容器元素
+ progressContainer.style.width = "100%";
+ progressContainer.style.height = "20px";
+ progressContainer.style.backgroundColor = "#f3f3f3"; // 设置容器的背景色为灰白色
+ let progressBar = document.createElement("div");
+ progressBar.style.width = (data[1] / data[0] * 100).toFixed(2) + "%";
+ progressBar.style.height = "20px";
+ progressBar.style.backgroundColor = "#4CAF50";
+ progressBar.style.position = "relative"; // 设置进度条的 position 为 relative
+ progressBar.textContent = (data[1] / data[0] * 100).toFixed(2) + "%"; // 显示百分比
+ progressBar.style.textAlign = "right"; // 设置文本对齐方式为右对齐
+ progressBar.style.paddingRight = "5px"; // 设置右边距以确保文本不超出边界
+ progressBar.style.color = "black"; // 设置文本颜色为白色
+ progressContainer.appendChild(progressBar); // 将进度条添加到容器中
+ progressCell.appendChild(progressContainer); // 将容器添加到单元格中
+ row.appendChild(progressCell);
+
+
+
+ let expireTime = document.createElement("td");
+ expireTime.textContent = data[3];
+ row.appendChild(expireTime);
+
+ let GPT35CheckResult = document.createElement("td");
+ GPT35CheckResult.textContent = data[4];
+ row.appendChild(GPT35CheckResult);
+
+ let GPT4CheckResult = document.createElement("td");
+ GPT4CheckResult.textContent = data[5];
+ row.appendChild(GPT4CheckResult);
+
+ let GPT432kCheckResult = document.createElement("td");
+ GPT432kCheckResult.textContent = data[6];
+ row.appendChild(GPT432kCheckResult);
+
+ let isSubscribe = document.createElement("td");
+ isSubscribe.style.whiteSpace = "pre"; // 添加这一行来保留换行
+ isSubscribe.textContent = data[7];
+ row.appendChild(isSubscribe);
+
+ let SubInformation = document.createElement("td");
+ let SubInformationContainer = document.createElement("div");
+ SubInformationContainer.style.whiteSpace = "pre-wrap";
+ SubInformationContainer.textContent = data[8];
+ SubInformation.appendChild(SubInformationContainer);
+ row.appendChild(SubInformation);
+
+
+ let setidCell = document.createElement("td");
+ let setidCellContainer = document.createElement("div");
+ setidCellContainer.style.whiteSpace = "pre-wrap";
+ setidCellContainer.textContent = data[9];
+ setidCell.appendChild(setidCellContainer);
+ row.appendChild(setidCell);
+
+ let rateLimitsDataCell = document.createElement("td");
+ let rateLimitsDataContainer = document.createElement("div");
+ rateLimitsDataContainer.style.whiteSpace = "pre-wrap";
+ if (data[13]) { // checking if rateLimits data exists
+ let rateLimitsData = data[13];
+ let models = ['gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-4', 'gpt-4-32k'];
+ for (let model of models) {
+ if (rateLimitsData[model]) {
+ rateLimitsDataContainer.textContent += `${model}:\n\tRPM: ${rateLimitsData[model].max_requests_per_1_minute}\n\tTPM: ${rateLimitsData[model].max_tokens_per_1_minute}\n\n`;
+ } else {
+ rateLimitsDataContainer.textContent += model + ": ❌\n";
+ }
+ }
+ }
+
+ rateLimitsDataCell.appendChild(rateLimitsDataContainer);
+ row.appendChild(rateLimitsDataCell);
+
+
+ // 是否有效列
+ let completionCheckResultCell = document.createElement("td");
+ completionCheckResultCell.innerHTML = `${data[12][0]}
消耗${data[12][1]} tokens`; // 使用 innerHTML 添加两行内容
+ row.appendChild(completionCheckResultCell);
+
+
+ }
+ tableBody.appendChild(row);
+
+ if (i === apiKeys.length - 1) {
+ queriedApiKeys = [];
+ }
+ serialNumber++; // 增加序列号
+ h2.style.display = 'block';
+ table.style.display = 'table';
+
+ button.textContent = "查询";
+ button.disabled = false;
+ button.classList.remove("loading")
+ })
+
+ }
+}
+
+let apiUrlSelect = document.getElementById("api-url-select");
+let customUrlInput = document.getElementById("custom-url-input");
+
+apiUrlSelect.addEventListener("change", function () {
+ if (apiUrlSelect.value === "custom") {
+ customUrlInput.style.display = "inline-block";
+ customUrlInput.style.marginTop = "5px";
+ } else {
+ customUrlInput.style.display = "none";
+ }
+});
\ No newline at end of file