Merge branch 'main' into telegram-login

This commit is contained in:
Ehco
2024-03-03 19:42:06 +08:00
committed by GitHub
27 changed files with 233 additions and 116 deletions

View File

@@ -257,6 +257,7 @@ const ChannelsTable = () => {
const [idSort, setIdSort] = useState(false);
const [searchKeyword, setSearchKeyword] = useState('');
const [searchGroup, setSearchGroup] = useState('');
const [searchModel, setSearchModel] = useState('');
const [searching, setSearching] = useState(false);
const [updatingBalance, setUpdatingBalance] = useState(false);
const [pageSize, setPageSize] = useState(ITEMS_PER_PAGE);
@@ -440,15 +441,15 @@ const ChannelsTable = () => {
}
};
const searchChannels = async (searchKeyword, searchGroup) => {
if (searchKeyword === '' && searchGroup === '') {
const searchChannels = async (searchKeyword, searchGroup, searchModel) => {
if (searchKeyword === '' && searchGroup === '' && searchModel === '') {
// if keyword is blank, load files instead.
await loadChannels(0, pageSize, idSort);
setActivePage(1);
return;
}
setSearching(true);
const res = await API.get(`/api/channel/search?keyword=${searchKeyword}&group=${searchGroup}`);
const res = await API.get(`/api/channel/search?keyword=${searchKeyword}&group=${searchGroup}&model=${searchModel}`);
const {success, message, data} = res.data;
if (success) {
setChannels(data);
@@ -625,13 +626,12 @@ const ChannelsTable = () => {
return (
<>
<EditChannel refresh={refresh} visible={showEdit} handleClose={closeEdit} editingChannel={editingChannel}/>
<Form onSubmit={() => {searchChannels(searchKeyword, searchGroup)}} labelPosition='left'>
<Form onSubmit={() => {searchChannels(searchKeyword, searchGroup, searchModel)}} labelPosition='left'>
<div style={{display: 'flex'}}>
<Space>
<Form.Input
field='search'
label='关键词'
field='search_keyword'
label='搜索渠道关键词'
placeholder='ID名称和密钥 ...'
value={searchKeyword}
loading={searching}
@@ -639,10 +639,22 @@ const ChannelsTable = () => {
setSearchKeyword(v.trim())
}}
/>
<Form.Input
field='search_model'
label='模型'
placeholder='模型关键字'
value={searchModel}
loading={searching}
onChange={(v)=>{
setSearchModel(v.trim())
}}
/>
<Form.Select field="group" label='分组' optionList={groupOptions} onChange={(v) => {
setSearchGroup(v)
searchChannels(searchKeyword, v)
searchChannels(searchKeyword, v, searchModel)
}}/>
<Button label='查询' type="primary" htmlType="submit" className="btn-margin-right"
style={{marginRight: 8}}>查询</Button>
</Space>
</div>
</Form>

View File

@@ -27,6 +27,7 @@ const OperationSetting = () => {
DataExportEnabled: '',
DataExportDefaultTime: 'hour',
DataExportInterval: 5,
DefaultCollapseSidebar: '', // 默认折叠侧边栏
RetryTimes: 0
});
const [originInputs, setOriginInputs] = useState({});
@@ -65,6 +66,10 @@ const OperationSetting = () => {
if (key.endsWith('Enabled')) {
value = inputs[key] === 'true' ? 'false' : 'true';
}
if (key === 'DefaultCollapseSidebar') {
value = inputs[key] === 'true' ? 'false' : 'true';
}
console.log(key, value)
const res = await API.put('/api/option/', {
key,
value
@@ -79,7 +84,7 @@ const OperationSetting = () => {
};
const handleInputChange = async (e, {name, value}) => {
if (name.endsWith('Enabled') || name === 'DataExportInterval' || name === 'DataExportDefaultTime') {
if (name.endsWith('Enabled') || name === 'DataExportInterval' || name === 'DataExportDefaultTime' || name === 'DefaultCollapseSidebar') {
if (name === 'DataExportDefaultTime') {
localStorage.setItem('data_export_default_time', value);
}
@@ -243,6 +248,12 @@ const OperationSetting = () => {
name='DrawingEnabled'
onChange={handleInputChange}
/>
<Form.Checkbox
checked={inputs.DefaultCollapseSidebar === 'true'}
label='默认折叠侧边栏'
name='DefaultCollapseSidebar'
onChange={handleInputChange}
/>
</Form.Group>
<Form.Button onClick={() => {
submitConfig('general').then();

View File

@@ -1,8 +1,8 @@
import React, {useContext, useMemo, useState} from 'react';
import React, { useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {UserContext} from '../context/User';
import {API, getLogo, getSystemName, isAdmin, isMobile, showSuccess} from '../helpers';
import { API, getLogo, getSystemName, isAdmin, isMobile, showError, showSuccess } from '../helpers';
import '../index.css';
import {
@@ -24,11 +24,14 @@ import {Nav, Avatar, Dropdown, Layout} from '@douyinfe/semi-ui';
const SiderBar = () => {
const [userState, userDispatch] = useContext(UserContext);
const defaultIsCollapsed = isMobile() || localStorage.getItem('default_collapse_sidebar') === 'true';
let navigate = useNavigate();
const [selectedKeys, setSelectedKeys] = useState(['home']);
const [showSidebar, setShowSidebar] = useState(false);
const systemName = getSystemName();
const logo = getLogo();
const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed);
const headerButtons = useMemo(() => [
{
text: '首页',
@@ -110,15 +113,41 @@ const SiderBar = () => {
// }
], [localStorage.getItem('enable_data_export'), localStorage.getItem('enable_drawing'), localStorage.getItem('chat_link'), isAdmin()]);
const loadStatus = async () => {
const res = await API.get('/api/status');
const { success, data } = res.data;
if (success) {
localStorage.setItem('status', JSON.stringify(data));
// statusDispatch({ type: 'set', payload: data });
localStorage.setItem('system_name', data.system_name);
localStorage.setItem('logo', data.logo);
localStorage.setItem('footer_html', data.footer_html);
localStorage.setItem('quota_per_unit', data.quota_per_unit);
localStorage.setItem('display_in_currency', data.display_in_currency);
localStorage.setItem('enable_drawing', data.enable_drawing);
localStorage.setItem('enable_data_export', data.enable_data_export);
localStorage.setItem('data_export_default_time', data.data_export_default_time);
localStorage.setItem('default_collapse_sidebar', data.default_collapse_sidebar);
if (data.chat_link) {
localStorage.setItem('chat_link', data.chat_link);
} else {
localStorage.removeItem('chat_link');
}
if (data.chat_link2) {
localStorage.setItem('chat_link2', data.chat_link2);
} else {
localStorage.removeItem('chat_link2');
}
} else {
showError('无法正常连接至服务器!');
}
};
async function logout() {
setShowSidebar(false);
await API.get('/api/user/logout');
showSuccess('注销成功!');
userDispatch({type: 'logout'});
localStorage.removeItem('user');
navigate('/login');
}
useEffect(() => {
loadStatus().then(() => {
setIsCollapsed(isMobile() || localStorage.getItem('default_collapse_sidebar') === 'true');
});
},[])
return (
<>
@@ -127,7 +156,12 @@ const SiderBar = () => {
<Nav
// mode={'horizontal'}
// bodyStyle={{ height: 100 }}
defaultIsCollapsed={isMobile()}
defaultIsCollapsed={isMobile() || localStorage.getItem('default_collapse_sidebar') === 'true'}
isCollapsed={isCollapsed}
onCollapseChange={collapsed => {
console.log(collapsed);
setIsCollapsed(collapsed);
}}
selectedKeys={selectedKeys}
renderWrapper={({itemElement, isSubNav, isInSubNav, props}) => {
const routerMap = {

View File

@@ -20,8 +20,10 @@ const SystemSetting = () => {
EpayId: '',
EpayKey: '',
Price: 7.3,
MinTopUp: 1,
TopupGroupRatio: '',
PayAddress: '',
CustomCallbackAddress: '',
Footer: '',
WeChatAuthEnabled: '',
WeChatServerAddress: '',
@@ -292,8 +294,8 @@ const SystemSetting = () => {
<Form.Button onClick={submitServerAddress}>
更新服务器地址
</Form.Button>
<Divider />
<Header as='h3'>支付设置当前仅支持易支付接口使用上方服务器地址作为回调地址</Header>
<Divider/>
<Header as='h3'>支付设置当前仅支持易支付接口默认使用上方服务器地址作为回调地址</Header>
<Form.Group widths='equal'>
<Form.Input
label='支付地址,不填写则不启用在线支付'
@@ -316,14 +318,31 @@ const SystemSetting = () => {
name='EpayKey'
onChange={handleInputChange}
/>
<Form.Input
label='充值价格x元/美金)'
placeholder='例如7就是7元/美金'
value={inputs.Price}
name='Price'
min={0}
onChange={handleInputChange}
</Form.Group>
<Form.Group widths='equal'>
<Form.Input
label='回调地址,不填写则使用上方服务器地址作为回调地址'
placeholder='例如https://yourdomain.com'
value={inputs.CustomCallbackAddress}
name='CustomCallbackAddress'
onChange={handleInputChange}
/>
<Form.Input
label='充值价格x元/美金)'
placeholder='例如7就是7元/美金'
value={inputs.Price}
name='Price'
min={0}
onChange={handleInputChange}
/>
<Form.Input
label='最低充值数量'
placeholder='例如2就是最低充值2$'
value={inputs.MinTopUp}
name='MinTopUp'
min={1}
onChange={handleInputChange}
/>
</Form.Group>
<Form.Group widths='equal'>

View File

@@ -153,7 +153,7 @@ const TokensTable = () => {
[
{node: 'item', key: 'next', disabled: !localStorage.getItem('chat_link'), name: 'ChatGPT Next Web', onClick: () => {onOpenLink('next', record.key)}},
{node: 'item', key: 'next-mj', disabled: !localStorage.getItem('chat_link2'), name: 'ChatGPT Web & Midjourney', onClick: () => {onOpenLink('next-mj', record.key)}},
{node: 'item', key: 'ama', name: 'AMA 问天BotGrem', onClick: () => {onOpenLink('ama', record.key)}},
{node: 'item', key: 'ama', name: 'AMA 问天BotGem', onClick: () => {onOpenLink('ama', record.key)}},
{node: 'item', key: 'opencat', name: 'OpenCat', onClick: () => {onOpenLink('opencat', record.key)}},
]
}