mirror of
https://github.com/linux-do/new-api.git
synced 2025-11-18 11:33:42 +08:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b63d9bba6 | ||
|
|
b99b24f271 | ||
|
|
ac11f4bc0e | ||
|
|
44465a398b | ||
|
|
4f0419c7bc | ||
|
|
07b4a8f5d2 | ||
|
|
348e5a0df3 |
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 项目群聊
|
||||
url: https://openai.justsong.cn/
|
||||
about: QQ 群:828520184,自动审核,备注 One API
|
||||
- name: 赞赏支持
|
||||
url: https://iamazing.cn/page/reward
|
||||
about: 请作者喝杯咖啡,以激励作者持续开发
|
||||
url: https://private-user-images.githubusercontent.com/61247483/283011625-de536a8a-0161-47a7-a0a2-66ef6de81266.jpeg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDIyMjQzOTAsIm5iZiI6MTcwMjIyNDA5MCwicGF0aCI6Ii82MTI0NzQ4My8yODMwMTE2MjUtZGU1MzZhOGEtMDE2MS00N2E3LWEwYTItNjZlZjZkZTgxMjY2LmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBSVdOSllBWDRDU1ZFSDUzQSUyRjIwMjMxMjEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDIzMTIxMFQxNjAxMzBaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT02MGIxYmM3ZDQyYzBkOTA2ZTYyYmVmMzQ1NjY4NjM1YjY0NTUzNTM5NjE1NDZkYTIzODdhYTk4ZjZjODJmYzY2JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.TJ8CTfOSwR0-CHS1KLfomqgL0e4YH1luy8lSLrkv5Zg
|
||||
about: QQ 群:629454374
|
||||
|
||||
@@ -155,7 +155,7 @@ func EpayNotify(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
log.Printf("易支付回调更新用户成功 %v", topUp)
|
||||
model.RecordLog(topUp.UserId, model.LogTypeTopup, fmt.Sprintf("使用在线充值成功,充值金额: %v,支付金额:%d", common.LogQuota(topUp.Amount*500000), topUp.Money))
|
||||
model.RecordLog(topUp.UserId, model.LogTypeTopup, fmt.Sprintf("使用在线充值成功,充值金额: %v,支付金额:%f", common.LogQuota(topUp.Amount*500000), topUp.Money))
|
||||
}
|
||||
} else {
|
||||
log.Printf("易支付异常回调: %v", verifyInfo)
|
||||
|
||||
@@ -190,6 +190,10 @@ func SyncChannelCache(frequency int) {
|
||||
}
|
||||
|
||||
func CacheGetRandomSatisfiedChannel(group string, model string) (*Channel, error) {
|
||||
if strings.HasPrefix(model, "gpt-4-gizmo") {
|
||||
model = "gpt-4-gizmo-*"
|
||||
}
|
||||
|
||||
if !common.MemoryCacheEnabled {
|
||||
return GetRandomSatisfiedChannel(group, model)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '../helpers';
|
||||
|
||||
import {CHANNEL_OPTIONS, ITEMS_PER_PAGE} from '../constants';
|
||||
import {renderGroup, renderNumber, renderQuota, renderQuotaWithPrompt} from '../helpers/render';
|
||||
import {renderGroup, renderNumber, renderNumberWithPoint, renderQuota, renderQuotaWithPrompt} from '../helpers/render';
|
||||
import {
|
||||
Avatar,
|
||||
Tag,
|
||||
@@ -142,8 +142,8 @@ const ChannelsTable = () => {
|
||||
<Tooltip content={'已用额度'}>
|
||||
<Tag color='white' type='ghost' size='large'>{renderQuota(record.used_quota)}</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip content={'剩余额度,点击更新'}>
|
||||
<Tag color='white' type='ghost' size='large' onClick={() => {updateChannelBalance(record)}}>${record.balance}</Tag>
|
||||
<Tooltip content={'剩余额度' + record.balance + ',点击更新'}>
|
||||
<Tag color='white' type='ghost' size='large' onClick={() => {updateChannelBalance(record)}}>${renderNumberWithPoint(record.balance)}</Tag>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, {useContext, useEffect, useState} from 'react';
|
||||
import {Form, Image, Message} from 'semantic-ui-react';
|
||||
import {Link, useNavigate} from 'react-router-dom';
|
||||
import {API, copy, isRoot, showError, showInfo, showNotice, showSuccess} from '../helpers';
|
||||
import Turnstile from 'react-turnstile';
|
||||
@@ -10,7 +9,7 @@ import {
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
Divider,
|
||||
Divider, Image,
|
||||
Input, InputNumber,
|
||||
Layout,
|
||||
Modal,
|
||||
@@ -267,7 +266,7 @@ const PersonalSetting = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{lineHeight: '40px'}}>
|
||||
<div>
|
||||
<Layout>
|
||||
<Layout.Content>
|
||||
<Modal
|
||||
@@ -426,8 +425,7 @@ const PersonalSetting = () => {
|
||||
</Space>
|
||||
|
||||
{systemToken && (
|
||||
<Form.Input
|
||||
fluid
|
||||
<Input
|
||||
readOnly
|
||||
value={systemToken}
|
||||
onClick={handleSystemTokenClick}
|
||||
@@ -451,24 +449,21 @@ const PersonalSetting = () => {
|
||||
visible={showWeChatBindModal}
|
||||
size={'mini'}
|
||||
>
|
||||
<Image src={status.wechat_qrcode} fluid/>
|
||||
<Image src={status.wechat_qrcode}/>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<p>
|
||||
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
|
||||
</p>
|
||||
</div>
|
||||
<Form size='large'>
|
||||
<Form.Input
|
||||
fluid
|
||||
placeholder='验证码'
|
||||
name='wechat_verification_code'
|
||||
value={inputs.wechat_verification_code}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Button color='' fluid size='large' onClick={bindWeChat}>
|
||||
绑定
|
||||
</Button>
|
||||
</Form>
|
||||
<Input
|
||||
placeholder='验证码'
|
||||
name='wechat_verification_code'
|
||||
value={inputs.wechat_verification_code}
|
||||
onChange={(v)=>handleInputChange('wechat_verification_code', v)}
|
||||
/>
|
||||
<Button color='' fluid size='large' onClick={bindWeChat}>
|
||||
绑定
|
||||
</Button>
|
||||
</Modal>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, {useContext, useState} from 'react';
|
||||
import {Link, useNavigate} from 'react-router-dom';
|
||||
import {UserContext} from '../context/User';
|
||||
|
||||
import {Button, Container, Icon, Menu, Segment} from 'semantic-ui-react';
|
||||
import {API, getLogo, getSystemName, isAdmin, isMobile, showSuccess} from '../helpers';
|
||||
import '../index.css';
|
||||
|
||||
|
||||
@@ -4,7 +4,22 @@ import {API, copy, isAdmin, showError, showSuccess, showWarning, timestamp2strin
|
||||
|
||||
import {ITEMS_PER_PAGE} from '../constants';
|
||||
import {renderQuota, stringToColor} from '../helpers/render';
|
||||
import {Avatar, Tag, Table, Button, Popover, Form, Modal, Popconfirm} from "@douyinfe/semi-ui";
|
||||
import {
|
||||
Avatar,
|
||||
Tag,
|
||||
Table,
|
||||
Button,
|
||||
Popover,
|
||||
Form,
|
||||
Modal,
|
||||
Popconfirm,
|
||||
SplitButtonGroup,
|
||||
Dropdown
|
||||
} from "@douyinfe/semi-ui";
|
||||
|
||||
import {
|
||||
IconTreeTriangleDown,
|
||||
} from '@douyinfe/semi-icons';
|
||||
import EditToken from "../pages/Token/EditToken";
|
||||
|
||||
const {Column} = Table;
|
||||
@@ -44,6 +59,13 @@ function renderStatus(status) {
|
||||
}
|
||||
|
||||
const TokensTable = () => {
|
||||
|
||||
const link_menu = [
|
||||
{node: 'item', key: 'next', name: 'ChatGPT Next Web', onClick: () => {onOpenLink('next')}},
|
||||
{node: 'item', key: 'ama', name: 'AMA 问天', value: 'ama'},
|
||||
{node: 'item', key: 'opencat', name: 'OpenCat', value: 'opencat'},
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
@@ -124,6 +146,19 @@ const TokensTable = () => {
|
||||
await copyText('sk-' + record.key)
|
||||
}}
|
||||
>复制</Button>
|
||||
<SplitButtonGroup style={{marginRight: 1}} aria-label="项目操作按钮组">
|
||||
<Button theme="light" style={{ color: 'rgba(var(--semi-teal-7), 1)' }} onClick={()=>{onOpenLink('next', record.key)}}>聊天</Button>
|
||||
<Dropdown trigger="click" position="bottomRight" menu={
|
||||
[
|
||||
{node: 'item', key: 'next', name: 'ChatGPT Next Web', onClick: () => {onOpenLink('next', record.key)}},
|
||||
{node: 'item', key: 'ama', name: 'AMA 问天(BotGrem)', onClick: () => {onOpenLink('ama', record.key)}},
|
||||
{node: 'item', key: 'opencat', name: 'OpenCat', onClick: () => {onOpenLink('opencat', record.key)}},
|
||||
]
|
||||
}
|
||||
>
|
||||
<Button style={ { padding: '8px 4px', color: 'rgba(var(--semi-teal-7), 1)' }} type="primary" icon={<IconTreeTriangleDown />}></Button>
|
||||
</Dropdown>
|
||||
</SplitButtonGroup>
|
||||
<Popconfirm
|
||||
title="确定是否要删除此令牌?"
|
||||
content="此修改将不可逆"
|
||||
@@ -301,7 +336,8 @@ const TokensTable = () => {
|
||||
if (chatLink) {
|
||||
defaultUrl = chatLink + `/#/?settings={"key":"sk-${key}","url":"${serverAddress}"}`;
|
||||
} else {
|
||||
defaultUrl = `https://chat.oneapi.pro/#/?settings={"key":"sk-${key}","url":"${serverAddress}"}`;
|
||||
showError('管理员未设置聊天链接')
|
||||
return
|
||||
}
|
||||
let url;
|
||||
switch (type) {
|
||||
|
||||
@@ -42,6 +42,34 @@ export function renderNumber(num) {
|
||||
}
|
||||
}
|
||||
|
||||
export function renderNumberWithPoint(num) {
|
||||
num = num.toFixed(2);
|
||||
if (num >= 100000) {
|
||||
// Convert number to string to manipulate it
|
||||
let numStr = num.toString();
|
||||
// Find the position of the decimal point
|
||||
let decimalPointIndex = numStr.indexOf('.');
|
||||
|
||||
let wholePart = numStr;
|
||||
let decimalPart = '';
|
||||
|
||||
// If there is a decimal point, split the number into whole and decimal parts
|
||||
if (decimalPointIndex !== -1) {
|
||||
wholePart = numStr.slice(0, decimalPointIndex);
|
||||
decimalPart = numStr.slice(decimalPointIndex);
|
||||
}
|
||||
|
||||
// Take the first two and last two digits of the whole number part
|
||||
let shortenedWholePart = wholePart.slice(0, 2) + '..' + wholePart.slice(-2);
|
||||
|
||||
// Return the formatted number
|
||||
return shortenedWholePart + decimalPart;
|
||||
}
|
||||
|
||||
// If the number is less than 100,000, return it unmodified
|
||||
return num;
|
||||
}
|
||||
|
||||
export function getQuotaPerUnit() {
|
||||
let quotaPerUnit = localStorage.getItem('quota_per_unit');
|
||||
quotaPerUnit = parseFloat(quotaPerUnit);
|
||||
|
||||
@@ -253,6 +253,7 @@ const EditChannel = (props) => {
|
||||
return (
|
||||
<>
|
||||
<SideSheet
|
||||
maskClosable={false}
|
||||
placement={isEdit ? 'right' : 'left'}
|
||||
title={<Title level={3}>{isEdit ? '更新渠道信息' : '创建新的渠道'}</Title>}
|
||||
headerStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
|
||||
|
||||
Reference in New Issue
Block a user