Compare commits

..

7 Commits

Author SHA1 Message Date
CaIon
3b63d9bba6 优化渠道余额显示 2023-12-11 20:42:51 +08:00
CaIon
b99b24f271 令牌界面添加聊天按钮 2023-12-11 20:11:26 +08:00
CaIon
ac11f4bc0e 优化前端代码 2023-12-11 19:52:41 +08:00
CaIon
44465a398b support gpts 2023-12-11 19:50:43 +08:00
CaIon
4f0419c7bc update ISSUE_TEMPLATE 2023-12-11 00:02:41 +08:00
CaIon
07b4a8f5d2 修复日志充值显示问题 2023-12-10 18:49:17 +08:00
CaIon
348e5a0df3 渠道余额改为保留两位小数 2023-12-10 18:34:44 +08:00
9 changed files with 90 additions and 30 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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';

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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)'}}