Commit add3b05d by CaIon

chore: reformat code

parent 7c547cbc
......@@ -13,7 +13,7 @@ import (
// TODO: when a new api is enabled, check the pricing here
// 1 === $0.002 / 1K tokens
// 1 === ¥0.014 / 1k tokens
var ModelRatio = map[string]float64{
var DefaultModelRatio = map[string]float64{
//"midjourney": 50,
"gpt-4-gizmo-*": 15,
"gpt-4": 15,
......@@ -115,6 +115,7 @@ var DefaultModelPrice = map[string]float64{
}
var ModelPrice = map[string]float64{}
var ModelRatio = map[string]float64{}
func ModelPrice2JSONString() string {
if len(ModelPrice) == 0 {
......@@ -150,6 +151,9 @@ func GetModelPrice(name string, printErr bool) float64 {
}
func ModelRatio2JSONString() string {
if len(ModelRatio) == 0 {
ModelRatio = DefaultModelRatio
}
jsonBytes, err := json.Marshal(ModelRatio)
if err != nil {
SysError("error marshalling model ratio: " + err.Error())
......@@ -163,6 +167,9 @@ func UpdateModelRatioByJSONString(jsonStr string) error {
}
func GetModelRatio(name string) float64 {
if len(ModelRatio) == 0 {
ModelRatio = DefaultModelRatio
}
if strings.HasPrefix(name, "gpt-4-gizmo") {
name = "gpt-4-gizmo-*"
}
......
......@@ -49,7 +49,7 @@
]
},
"devDependencies": {
"prettier": "^2.7.1",
"prettier": "2.8.8",
"typescript": "4.4.2"
},
"prettier": {
......
......@@ -8,12 +8,11 @@ import LoginForm from './components/LoginForm';
import NotFound from './pages/NotFound';
import Setting from './pages/Setting';
import EditUser from './pages/User/EditUser';
import { API, getLogo, getSystemName, showError, showNotice } from './helpers';
import { getLogo, getSystemName } from './helpers';
import PasswordResetForm from './components/PasswordResetForm';
import GitHubOAuth from './components/GitHubOAuth';
import PasswordResetConfirm from './components/PasswordResetConfirm';
import { UserContext } from './context/User';
import { StatusContext } from './context/Status';
import Channel from './pages/Channel';
import Token from './pages/Token';
import EditChannel from './pages/Channel/EditChannel';
......@@ -21,12 +20,13 @@ import Redemption from './pages/Redemption';
import TopUp from './pages/TopUp';
import Log from './pages/Log';
import Chat from './pages/Chat';
import {Layout} from "@douyinfe/semi-ui";
import Midjourney from "./pages/Midjourney";
import Detail from "./pages/Detail";
import { Layout } from '@douyinfe/semi-ui';
import Midjourney from './pages/Midjourney';
import Detail from './pages/Detail';
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
function App() {
const [userState, userDispatch] = useContext(UserContext);
// const [statusState, statusDispatch] = useContext(StatusContext);
......@@ -47,7 +47,7 @@ function App() {
}
let logo = getLogo();
if (logo) {
let linkElement = document.querySelector("link[rel~='icon']");
let linkElement = document.querySelector('link[rel~=\'icon\']');
if (linkElement) {
linkElement.href = logo;
}
......@@ -59,7 +59,7 @@ function App() {
<Layout.Content>
<Routes>
<Route
path='/'
path="/"
element={
<Suspense fallback={<Loading></Loading>}>
<Home />
......@@ -67,7 +67,7 @@ function App() {
}
/>
<Route
path='/channel'
path="/channel"
element={
<PrivateRoute>
<Channel />
......@@ -75,7 +75,7 @@ function App() {
}
/>
<Route
path='/channel/edit/:id'
path="/channel/edit/:id"
element={
<Suspense fallback={<Loading></Loading>}>
<EditChannel />
......@@ -83,7 +83,7 @@ function App() {
}
/>
<Route
path='/channel/add'
path="/channel/add"
element={
<Suspense fallback={<Loading></Loading>}>
<EditChannel />
......@@ -91,7 +91,7 @@ function App() {
}
/>
<Route
path='/token'
path="/token"
element={
<PrivateRoute>
<Token />
......@@ -99,7 +99,7 @@ function App() {
}
/>
<Route
path='/redemption'
path="/redemption"
element={
<PrivateRoute>
<Redemption />
......@@ -107,7 +107,7 @@ function App() {
}
/>
<Route
path='/user'
path="/user"
element={
<PrivateRoute>
<User />
......@@ -115,7 +115,7 @@ function App() {
}
/>
<Route
path='/user/edit/:id'
path="/user/edit/:id"
element={
<Suspense fallback={<Loading></Loading>}>
<EditUser />
......@@ -123,7 +123,7 @@ function App() {
}
/>
<Route
path='/user/edit'
path="/user/edit"
element={
<Suspense fallback={<Loading></Loading>}>
<EditUser />
......@@ -131,7 +131,7 @@ function App() {
}
/>
<Route
path='/user/reset'
path="/user/reset"
element={
<Suspense fallback={<Loading></Loading>}>
<PasswordResetConfirm />
......@@ -139,7 +139,7 @@ function App() {
}
/>
<Route
path='/login'
path="/login"
element={
<Suspense fallback={<Loading></Loading>}>
<LoginForm />
......@@ -147,7 +147,7 @@ function App() {
}
/>
<Route
path='/register'
path="/register"
element={
<Suspense fallback={<Loading></Loading>}>
<RegisterForm />
......@@ -155,7 +155,7 @@ function App() {
}
/>
<Route
path='/reset'
path="/reset"
element={
<Suspense fallback={<Loading></Loading>}>
<PasswordResetForm />
......@@ -163,7 +163,7 @@ function App() {
}
/>
<Route
path='/oauth/github'
path="/oauth/github"
element={
<Suspense fallback={<Loading></Loading>}>
<GitHubOAuth />
......@@ -171,7 +171,7 @@ function App() {
}
/>
<Route
path='/setting'
path="/setting"
element={
<PrivateRoute>
<Suspense fallback={<Loading></Loading>}>
......@@ -181,7 +181,7 @@ function App() {
}
/>
<Route
path='/topup'
path="/topup"
element={
<PrivateRoute>
<Suspense fallback={<Loading></Loading>}>
......@@ -191,7 +191,7 @@ function App() {
}
/>
<Route
path='/log'
path="/log"
element={
<PrivateRoute>
<Log />
......@@ -199,7 +199,7 @@ function App() {
}
/>
<Route
path='/detail'
path="/detail"
element={
<PrivateRoute>
<Detail />
......@@ -207,7 +207,7 @@ function App() {
}
/>
<Route
path='/midjourney'
path="/midjourney"
element={
<PrivateRoute>
<Midjourney />
......@@ -215,7 +215,7 @@ function App() {
}
/>
<Route
path='/about'
path="/about"
element={
<Suspense fallback={<Loading></Loading>}>
<About />
......@@ -223,14 +223,14 @@ function App() {
}
/>
<Route
path='/chat'
path="/chat"
element={
<Suspense fallback={<Loading></Loading>}>
<Chat />
</Suspense>
}
/>
<Route path='*' element={
<Route path="*" element={
<NotFound />
} />
</Routes>
......
import React, { useEffect, useState } from 'react';
import { getFooterHTML, getSystemName } from '../helpers';
import {Layout} from "@douyinfe/semi-ui";
import { Layout } from '@douyinfe/semi-ui';
const Footer = () => {
const systemName = getSystemName();
......@@ -29,30 +29,30 @@ const Footer = () => {
return (
<Layout>
<Layout.Content style={{textAlign: 'center'}}>
<Layout.Content style={{ textAlign: 'center' }}>
{footer ? (
<div
className='custom-footer'
className="custom-footer"
dangerouslySetInnerHTML={{ __html: footer }}
></div>
) : (
<div className='custom-footer'>
<div className="custom-footer">
<a
href='https://github.com/Calcium-Ion/new-api'
target='_blank'
href="https://github.com/Calcium-Ion/new-api"
target="_blank" rel="noreferrer"
>
New API {process.env.REACT_APP_VERSION}{' '}
</a>
{' '}
<a href='https://github.com/Calcium-Ion' target='_blank'>
<a href="https://github.com/Calcium-Ion" target="_blank" rel="noreferrer">
Calcium-Ion
</a>{' '}
开发,基于{' '}
<a href='https://github.com/songquanpeng/one-api' target='_blank'>
<a href="https://github.com/songquanpeng/one-api" target="_blank" rel="noreferrer">
One API v0.5.4
</a>{' '}
,本项目根据{' '}
<a href='https://opensource.org/licenses/mit-license.php'>
<a href="https://opensource.org/licenses/mit-license.php">
MIT 许可证
</a>{' '}
授权
......
......@@ -49,7 +49,7 @@ const GitHubOAuth = () => {
return (
<Segment style={{ minHeight: '300px' }}>
<Dimmer active inverted>
<Loader size='large'>{prompt}</Loader>
<Loader size="large">{prompt}</Loader>
</Dimmer>
</Segment>
);
......
import React, {useContext, useEffect, useRef, useState} from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {UserContext} from '../context/User';
import React, { useContext, useEffect, 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, showSuccess } from '../helpers';
import '../index.css';
import fireworks from 'react-fireworks';
import {
IconKey,
IconUser,
IconHelpCircle
} from '@douyinfe/semi-icons';
import {Nav, Avatar, Dropdown, Layout, Switch} from '@douyinfe/semi-ui';
import {stringToColor} from "../helpers/render";
import { IconHelpCircle, IconKey, IconUser } from '@douyinfe/semi-icons';
import { Avatar, Dropdown, Layout, Nav, Switch } from '@douyinfe/semi-ui';
import { stringToColor } from '../helpers/render';
// HeaderBar Buttons
let headerButtons = [
......@@ -21,8 +17,8 @@ let headerButtons = [
text: '关于',
itemKey: 'about',
to: '/about',
icon: <IconHelpCircle/>
},
icon: <IconHelpCircle />
}
];
if (localStorage.getItem('chat_link')) {
......@@ -50,13 +46,13 @@ const HeaderBar = () => {
setShowSidebar(false);
await API.get('/api/user/logout');
showSuccess('注销成功!');
userDispatch({type: 'logout'});
userDispatch({ type: 'logout' });
localStorage.removeItem('user');
navigate('/login');
}
const handleNewYearClick = () => {
fireworks.init("root",{});
fireworks.init('root', {});
fireworks.start();
setTimeout(() => {
fireworks.stop();
......@@ -89,19 +85,19 @@ const HeaderBar = () => {
return (
<>
<Layout>
<div style={{width: '100%'}}>
<div style={{ width: '100%' }}>
<Nav
mode={'horizontal'}
// bodyStyle={{ height: 100 }}
renderWrapper={({itemElement, isSubNav, isInSubNav, props}) => {
renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
const routerMap = {
about: "/about",
login: "/login",
register: "/register",
about: '/about',
login: '/login',
register: '/register'
};
return (
<Link
style={{textDecoration: "none"}}
style={{ textDecoration: 'none' }}
to={routerMap[props.itemKey]}
>
{itemElement}
......@@ -125,7 +121,7 @@ const HeaderBar = () => {
</Dropdown.Menu>
}
>
<Nav.Item itemKey={'new-year'} text={'🏮'}/>
<Nav.Item itemKey={'new-year'} text={'🏮'} />
</Dropdown>
}
<Nav.Item itemKey={'about'} icon={<IconHelpCircle />} />
......
import React from 'react';
import { Segment, Dimmer, Loader } from 'semantic-ui-react';
import { Dimmer, Loader, Segment } from 'semantic-ui-react';
const Loading = ({ prompt: name = 'page' }) => {
return (
......
import React, { useContext, useEffect, useState } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import { UserContext } from '../context/User';
import { API, getLogo, isMobile, showError, showInfo, showSuccess, showWarning } from '../helpers';
import { API, getLogo, showError, showInfo, showSuccess } from '../helpers';
import { onGitHubOAuthClicked } from './utils';
import Turnstile from "react-turnstile";
import { Layout, Card, Image, Form, Button, Divider, Modal, Icon } from '@douyinfe/semi-ui';
import Title from "@douyinfe/semi-ui/lib/es/typography/title";
import Text from "@douyinfe/semi-ui/lib/es/typography/text";
import Turnstile from 'react-turnstile';
import { Button, Card, Divider, Form, Icon, Layout, Modal } from '@douyinfe/semi-ui';
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
import TelegramLoginButton from 'react-telegram-login';
import { IconGithubLogo } from '@douyinfe/semi-icons';
......@@ -104,7 +104,7 @@ const LoginForm = () => {
// 添加Telegram登录处理函数
const onTelegramLoginClicked = async (response) => {
const fields = ["id", "first_name", "last_name", "username", "photo_url", "auth_date", "hash", "lang"];
const fields = ['id', 'first_name', 'last_name', 'username', 'photo_url', 'auth_date', 'hash', 'lang'];
const params = {};
fields.forEach((field) => {
if (response[field]) {
......@@ -129,7 +129,7 @@ const LoginForm = () => {
<Layout.Header>
</Layout.Header>
<Layout.Content>
<div style={{ justifyContent: 'center', display: "flex", marginTop: 120 }}>
<div style={{ justifyContent: 'center', display: 'flex', marginTop: 120 }}>
<div style={{ width: 500 }}>
<Card>
<Title heading={2} style={{ textAlign: 'center' }}>
......@@ -139,41 +139,41 @@ const LoginForm = () => {
<Form.Input
field={'username'}
label={'用户名'}
placeholder='用户名'
name='username'
placeholder="用户名"
name="username"
onChange={(value) => handleChange('username', value)}
/>
<Form.Input
field={'password'}
label={'密码'}
placeholder='密码'
name='password'
type='password'
placeholder="密码"
name="password"
type="password"
onChange={(value) => handleChange('password', value)}
/>
<Button theme='solid' style={{ width: '100%' }} type={'primary'} size='large'
<Button theme="solid" style={{ width: '100%' }} type={'primary'} size="large"
htmlType={'submit'} onClick={handleSubmit}>
登录
</Button>
</Form>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 20 }}>
<Text>
没有账号请先 <Link to='/register'>注册账号</Link>
没有账号请先 <Link to="/register">注册账号</Link>
</Text>
<Text>
忘记密码 <Link to='/reset'>点击重置</Link>
忘记密码 <Link to="/reset">点击重置</Link>
</Text>
</div>
{status.github_oauth || status.wechat_login || status.telegram_oauth ? (
<>
<Divider margin='12px' align='center'>
<Divider margin="12px" align="center">
第三方登录
</Divider>
<div style={{ display: 'flex', justifyContent: 'center', marginTop: 20 }}>
{status.github_oauth ? (
<Button
type='primary'
type="primary"
icon={<IconGithubLogo />}
onClick={() => onGitHubOAuthClicked(status.github_client_id)}
/>
......@@ -182,8 +182,8 @@ const LoginForm = () => {
)}
{status.wechat_login ? (
<Button
type='primary'
style={{color: 'rgba(var(--semi-green-5), 1)'}}
type="primary"
style={{ color: 'rgba(var(--semi-green-5), 1)' }}
icon={<Icon svg={<WeChatIcon />} />}
onClick={onWeChatLoginClicked}
/>
......@@ -212,17 +212,17 @@ const LoginForm = () => {
centered={true}
>
<div style={{ display: 'flex', alignItem: 'center', flexDirection: 'column' }}>
<img src={status.wechat_qrcode}/>
<img src={status.wechat_qrcode} />
</div>
<div style={{textAlign: 'center'}}>
<div style={{ textAlign: 'center' }}>
<p>
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
</p>
</div>
<Form size='large'>
<Form size="large">
<Form.Input
field={'wechat_verification_code'}
placeholder='验证码'
placeholder="验证码"
label={'验证码'}
value={inputs.wechat_verification_code}
onChange={(value) => handleChange('wechat_verification_code', value)}
......
import React, { useEffect, useRef, useState } from 'react';
import { Col, Row , Form, Button, Banner } from '@douyinfe/semi-ui';
import { Banner, Button, Col, Form, Row } from '@douyinfe/semi-ui';
import { API, showError, showSuccess } from '../helpers';
import { marked } from 'marked';
......@@ -57,8 +57,8 @@ const OtherSetting = () => {
await updateOption('Notice', inputs.Notice);
showSuccess('公告已更新');
} catch (error) {
console.error("公告更新失败", error);
showError("公告更新失败")
console.error('公告更新失败', error);
showError('公告更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, Notice: false }));
}
......@@ -72,8 +72,8 @@ const OtherSetting = () => {
await updateOption('SystemName', inputs.SystemName);
showSuccess('系统名称已更新');
} catch (error) {
console.error("系统名称更新失败", error);
showError("系统名称更新失败")
console.error('系统名称更新失败', error);
showError('系统名称更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, SystemName: false }));
}
......@@ -86,8 +86,8 @@ const OtherSetting = () => {
await updateOption('Logo', inputs.Logo);
showSuccess('Logo 已更新');
} catch (error) {
console.error("Logo 更新失败", error);
showError("Logo 更新失败")
console.error('Logo 更新失败', error);
showError('Logo 更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, Logo: false }));
}
......@@ -99,8 +99,8 @@ const OtherSetting = () => {
await updateOption(key, inputs[key]);
showSuccess('首页内容已更新');
} catch (error) {
console.error("首页内容更新失败", error);
showError("首页内容更新失败")
console.error('首页内容更新失败', error);
showError('首页内容更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, HomePageContent: false }));
}
......@@ -112,8 +112,8 @@ const OtherSetting = () => {
await updateOption('About', inputs.About);
showSuccess('关于内容已更新');
} catch (error) {
console.error("关于内容更新失败", error);
showError("关于内容更新失败");
console.error('关于内容更新失败', error);
showError('关于内容更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, About: false }));
}
......@@ -125,16 +125,14 @@ const OtherSetting = () => {
await updateOption('Footer', inputs.Footer);
showSuccess('页脚内容已更新');
} catch (error) {
console.error("页脚内容更新失败", error);
showError("页脚内容更新失败");
console.error('页脚内容更新失败', error);
showError('页脚内容更新失败');
} finally {
setLoadingInput((loadingInput) => ({ ...loadingInput, Footer: false }));
}
};
const openGitHubRelease = () => {
window.location =
'https://github.com/songquanpeng/one-api/releases/latest';
......@@ -173,16 +171,17 @@ const OtherSetting = () => {
}
};
useEffect( () => {
useEffect(() => {
getOptions();
}, []);
return (
<Row >
<Row>
<Col span={24}>
{/* 通用设置 */}
<Form values={inputs} getFormApi={formAPI => formAPISettingGeneral.current = formAPI} style={{marginBottom: 15}}>
<Form values={inputs} getFormApi={formAPI => formAPISettingGeneral.current = formAPI}
style={{ marginBottom: 15 }}>
<Form.Section text={'通用设置'}>
<Form.TextArea
label={'公告'}
......@@ -196,7 +195,8 @@ const OtherSetting = () => {
</Form.Section>
</Form>
{/* 个性化设置 */}
<Form values={inputs} getFormApi={formAPI => formAPIPersonalization.current = formAPI} style={{marginBottom: 15}}>
<Form values={inputs} getFormApi={formAPI => formAPIPersonalization.current = formAPI}
style={{ marginBottom: 15 }}>
<Form.Section text={'个性化设置'}>
<Form.Input
label={'系统名称'}
......@@ -220,7 +220,8 @@ const OtherSetting = () => {
style={{ fontFamily: 'JetBrains Mono, Consolas' }}
autosize={{ minRows: 6, maxRows: 12 }}
/>
<Button onClick={() => submitOption('HomePageContent')} loading={loadingInput['HomePageContent']}>设置首页内容</Button>
<Button onClick={() => submitOption('HomePageContent')}
loading={loadingInput['HomePageContent']}>设置首页内容</Button>
<Form.TextArea
label={'关于'}
placeholder={'在此输入新的关于内容,支持 Markdown & HTML 代码。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为关于页面。'}
......
import React, { useEffect, useState } from 'react';
import { Button, Form, Grid, Header, Image, Segment } from 'semantic-ui-react';
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
import { API, copy, showError, showNotice } from '../helpers';
import { useSearchParams } from 'react-router-dom';
const PasswordResetConfirm = () => {
const [inputs, setInputs] = useState({
email: '',
token: '',
token: ''
});
const { email, token } = inputs;
......@@ -23,7 +23,7 @@ const PasswordResetConfirm = () => {
let email = searchParams.get('email');
setInputs({
token,
email,
email
});
}, []);
......@@ -46,7 +46,7 @@ const PasswordResetConfirm = () => {
setLoading(true);
const res = await API.post(`/api/user/reset`, {
email,
token,
token
});
const { success, message } = res.data;
if (success) {
......@@ -61,29 +61,29 @@ const PasswordResetConfirm = () => {
}
return (
<Grid textAlign='center' style={{ marginTop: '48px' }}>
<Grid textAlign="center" style={{ marginTop: '48px' }}>
<Grid.Column style={{ maxWidth: 450 }}>
<Header as='h2' color='' textAlign='center'>
<Image src='/logo.png' /> 密码重置确认
<Header as="h2" color="" textAlign="center">
<Image src="/logo.png" /> 密码重置确认
</Header>
<Form size='large'>
<Form size="large">
<Segment>
<Form.Input
fluid
icon='mail'
iconPosition='left'
placeholder='邮箱地址'
name='email'
icon="mail"
iconPosition="left"
placeholder="邮箱地址"
name="email"
value={email}
readOnly
/>
{newPassword && (
<Form.Input
fluid
icon='lock'
iconPosition='left'
placeholder='新密码'
name='newPassword'
icon="lock"
iconPosition="left"
placeholder="新密码"
name="newPassword"
value={newPassword}
readOnly
onClick={(e) => {
......@@ -94,9 +94,9 @@ const PasswordResetConfirm = () => {
/>
)}
<Button
color='green'
color="green"
fluid
size='large'
size="large"
onClick={handleSubmit}
loading={loading}
disabled={disableButton}
......
......@@ -56,19 +56,19 @@ const PasswordResetForm = () => {
}
return (
<Grid textAlign='center' style={{ marginTop: '48px' }}>
<Grid textAlign="center" style={{ marginTop: '48px' }}>
<Grid.Column style={{ maxWidth: 450 }}>
<Header as='h2' color='' textAlign='center'>
<Image src='/logo.png' /> 密码重置
<Header as="h2" color="" textAlign="center">
<Image src="/logo.png" /> 密码重置
</Header>
<Form size='large'>
<Form size="large">
<Segment>
<Form.Input
fluid
icon='mail'
iconPosition='left'
placeholder='邮箱地址'
name='email'
icon="mail"
iconPosition="left"
placeholder="邮箱地址"
name="email"
value={email}
onChange={handleChange}
/>
......@@ -83,9 +83,9 @@ const PasswordResetForm = () => {
<></>
)}
<Button
color='green'
color="green"
fluid
size='large'
size="large"
onClick={handleSubmit}
loading={loading}
disabled={disableButton}
......
......@@ -5,7 +5,7 @@ import { history } from '../helpers';
function PrivateRoute({ children }) {
if (!localStorage.getItem('user')) {
return <Navigate to='/login' state={{ from: history.location }} />;
return <Navigate to="/login" state={{ from: history.location }} />;
}
return children;
}
......
......@@ -98,49 +98,49 @@ const RegisterForm = () => {
};
return (
<Grid textAlign='center' style={{ marginTop: '48px' }}>
<Grid textAlign="center" style={{ marginTop: '48px' }}>
<Grid.Column style={{ maxWidth: 450 }}>
<Header as='h2' color='' textAlign='center'>
<Header as="h2" color="" textAlign="center">
<Image src={logo} /> 新用户注
</Header>
<Form size='large'>
<Form size="large">
<Segment>
<Form.Input
fluid
icon='user'
iconPosition='left'
placeholder='输入用户名,最长 12 位'
icon="user"
iconPosition="left"
placeholder="输入用户名,最长 12 位"
onChange={handleChange}
name='username'
name="username"
/>
<Form.Input
fluid
icon='lock'
iconPosition='left'
placeholder='输入密码,最短 8 位,最长 20 位'
icon="lock"
iconPosition="left"
placeholder="输入密码,最短 8 位,最长 20 位"
onChange={handleChange}
name='password'
type='password'
name="password"
type="password"
/>
<Form.Input
fluid
icon='lock'
iconPosition='left'
placeholder='输入密码,最短 8 位,最长 20 位'
icon="lock"
iconPosition="left"
placeholder="输入密码,最短 8 位,最长 20 位"
onChange={handleChange}
name='password2'
type='password'
name="password2"
type="password"
/>
{showEmailVerification ? (
<>
<Form.Input
fluid
icon='mail'
iconPosition='left'
placeholder='输入邮箱地址'
icon="mail"
iconPosition="left"
placeholder="输入邮箱地址"
onChange={handleChange}
name='email'
type='email'
name="email"
type="email"
action={
<Button onClick={sendVerificationCode} disabled={loading}>
获取验证码
......@@ -149,11 +149,11 @@ const RegisterForm = () => {
/>
<Form.Input
fluid
icon='lock'
iconPosition='left'
placeholder='输入验证码'
icon="lock"
iconPosition="left"
placeholder="输入验证码"
onChange={handleChange}
name='verification_code'
name="verification_code"
/>
</>
) : (
......@@ -170,9 +170,9 @@ const RegisterForm = () => {
<></>
)}
<Button
color='green'
color="green"
fluid
size='large'
size="large"
onClick={handleSubmit}
loading={loading}
>
......@@ -182,7 +182,7 @@ const RegisterForm = () => {
</Form>
<Message>
已有账户?
<Link to='/login' className='btn btn-link'>
<Link to="/login" className="btn btn-link">
点击登录
</Link>
</Message>
......
import React, { useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {UserContext} from '../context/User';
import React, { useContext, useEffect, useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { UserContext } from '../context/User';
import { StatusContext } from '../context/Status';
import { API, getLogo, getSystemName, isAdmin, isMobile, showError, showSuccess } from '../helpers';
import { API, getLogo, getSystemName, isAdmin, isMobile, showError } from '../helpers';
import '../index.css';
import {
IconCalendarClock,
IconHistogram,
IconComment,
IconCreditCard,
IconGift,
IconHistogram,
IconHome,
IconImage,
IconKey,
IconUser,
IconLayers,
IconSetting,
IconCreditCard,
IconComment,
IconHome,
IconImage
IconUser
} from '@douyinfe/semi-icons';
import {Nav, Avatar, Dropdown, Layout} from '@douyinfe/semi-ui';
import { Layout, Nav } from '@douyinfe/semi-ui';
// HeaderBar Buttons
......@@ -39,74 +39,74 @@ const SiderBar = () => {
text: '首页',
itemKey: 'home',
to: '/',
icon: <IconHome/>
icon: <IconHome />
},
{
text: '渠道',
itemKey: 'channel',
to: '/channel',
icon: <IconLayers/>,
className: isAdmin()?'semi-navigation-item-normal':'tableHiddle',
icon: <IconLayers />,
className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '聊天',
itemKey: 'chat',
to: '/chat',
icon: <IconComment />,
className: localStorage.getItem('chat_link')?'semi-navigation-item-normal':'tableHiddle',
className: localStorage.getItem('chat_link') ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '令牌',
itemKey: 'token',
to: '/token',
icon: <IconKey/>
icon: <IconKey />
},
{
text: '兑换码',
itemKey: 'redemption',
to: '/redemption',
icon: <IconGift/>,
className: isAdmin()?'semi-navigation-item-normal':'tableHiddle',
icon: <IconGift />,
className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '钱包',
itemKey: 'topup',
to: '/topup',
icon: <IconCreditCard/>
icon: <IconCreditCard />
},
{
text: '用户管理',
itemKey: 'user',
to: '/user',
icon: <IconUser/>,
className: isAdmin()?'semi-navigation-item-normal':'tableHiddle',
icon: <IconUser />,
className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '日志',
itemKey: 'log',
to: '/log',
icon: <IconHistogram/>
icon: <IconHistogram />
},
{
text: '数据看板',
itemKey: 'detail',
to: '/detail',
icon: <IconCalendarClock />,
className: localStorage.getItem('enable_data_export') === 'true'?'semi-navigation-item-normal':'tableHiddle',
className: localStorage.getItem('enable_data_export') === 'true' ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '绘图',
itemKey: 'midjourney',
to: '/midjourney',
icon: <IconImage/>,
className: localStorage.getItem('enable_drawing') === 'true'?'semi-navigation-item-normal':'tableHiddle',
icon: <IconImage />,
className: localStorage.getItem('enable_drawing') === 'true' ? 'semi-navigation-item-normal' : 'tableHiddle'
},
{
text: '设置',
itemKey: 'setting',
to: '/setting',
icon: <IconSetting/>
},
icon: <IconSetting />
}
// {
// text: '关于',
// itemKey: 'about',
......@@ -149,12 +149,12 @@ const SiderBar = () => {
loadStatus().then(() => {
setIsCollapsed(isMobile() || localStorage.getItem('default_collapse_sidebar') === 'true');
});
},[])
}, []);
return (
<>
<Layout>
<div style={{height: '100%'}}>
<div style={{ height: '100%' }}>
<Nav
// bodyStyle={{ maxWidth: 200 }}
style={{ maxWidth: 200 }}
......@@ -164,24 +164,24 @@ const SiderBar = () => {
setIsCollapsed(collapsed);
}}
selectedKeys={selectedKeys}
renderWrapper={({itemElement, isSubNav, isInSubNav, props}) => {
renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
const routerMap = {
home: "/",
channel: "/channel",
token: "/token",
redemption: "/redemption",
topup: "/topup",
user: "/user",
log: "/log",
midjourney: "/midjourney",
setting: "/setting",
about: "/about",
chat: "/chat",
detail: "/detail",
home: '/',
channel: '/channel',
token: '/token',
redemption: '/redemption',
topup: '/topup',
user: '/user',
log: '/log',
midjourney: '/midjourney',
setting: '/setting',
about: '/about',
chat: '/chat',
detail: '/detail'
};
return (
<Link
style={{textDecoration: "none"}}
style={{ textDecoration: 'none' }}
to={routerMap[props.itemKey]}
>
{itemElement}
......@@ -193,8 +193,8 @@ const SiderBar = () => {
setSelectedKeys([key.itemKey]);
}}
header={{
logo: <img src={logo} alt='logo' style={{marginRight: '0.75em'}}/>,
text: systemName,
logo: <img src={logo} alt="logo" style={{ marginRight: '0.75em' }} />,
text: systemName
}}
// footer={{
// text: '© 2021 NekoAPI',
......
......@@ -3,14 +3,14 @@ import { Icon } from '@douyinfe/semi-ui';
const WeChatIcon = () => {
function CustomIcon() {
return <svg t='1709714447384' className='icon' viewBox='0 0 1024 1024' version='1.1'
xmlns='http://www.w3.org/2000/svg' p-id='5091' width='16' height='16'>
return <svg t="1709714447384" className="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="5091" width="16" height="16">
<path
d='M690.1 377.4c5.9 0 11.8 0.2 17.6 0.5-24.4-128.7-158.3-227.1-319.9-227.1C209 150.8 64 271.4 64 420.2c0 81.1 43.6 154.2 111.9 203.6 5.5 3.9 9.1 10.3 9.1 17.6 0 2.4-0.5 4.6-1.1 6.9-5.5 20.3-14.2 52.8-14.6 54.3-0.7 2.6-1.7 5.2-1.7 7.9 0 5.9 4.8 10.8 10.8 10.8 2.3 0 4.2-0.9 6.2-2l70.9-40.9c5.3-3.1 11-5 17.2-5 3.2 0 6.4 0.5 9.5 1.4 33.1 9.5 68.8 14.8 105.7 14.8 6 0 11.9-0.1 17.8-0.4-7.1-21-10.9-43.1-10.9-66 0-135.8 132.2-245.8 295.3-245.8z m-194.3-86.5c23.8 0 43.2 19.3 43.2 43.1s-19.3 43.1-43.2 43.1c-23.8 0-43.2-19.3-43.2-43.1s19.4-43.1 43.2-43.1z m-215.9 86.2c-23.8 0-43.2-19.3-43.2-43.1s19.3-43.1 43.2-43.1 43.2 19.3 43.2 43.1-19.4 43.1-43.2 43.1z'
p-id='5092'></path>
d="M690.1 377.4c5.9 0 11.8 0.2 17.6 0.5-24.4-128.7-158.3-227.1-319.9-227.1C209 150.8 64 271.4 64 420.2c0 81.1 43.6 154.2 111.9 203.6 5.5 3.9 9.1 10.3 9.1 17.6 0 2.4-0.5 4.6-1.1 6.9-5.5 20.3-14.2 52.8-14.6 54.3-0.7 2.6-1.7 5.2-1.7 7.9 0 5.9 4.8 10.8 10.8 10.8 2.3 0 4.2-0.9 6.2-2l70.9-40.9c5.3-3.1 11-5 17.2-5 3.2 0 6.4 0.5 9.5 1.4 33.1 9.5 68.8 14.8 105.7 14.8 6 0 11.9-0.1 17.8-0.4-7.1-21-10.9-43.1-10.9-66 0-135.8 132.2-245.8 295.3-245.8z m-194.3-86.5c23.8 0 43.2 19.3 43.2 43.1s-19.3 43.1-43.2 43.1c-23.8 0-43.2-19.3-43.2-43.1s19.4-43.1 43.2-43.1z m-215.9 86.2c-23.8 0-43.2-19.3-43.2-43.1s19.3-43.1 43.2-43.1 43.2 19.3 43.2 43.1-19.4 43.1-43.2 43.1z"
p-id="5092"></path>
<path
d='M866.7 792.7c56.9-41.2 93.2-102 93.2-169.7 0-124-120.8-224.5-269.9-224.5-149 0-269.9 100.5-269.9 224.5S540.9 847.5 690 847.5c30.8 0 60.6-4.4 88.1-12.3 2.6-0.8 5.2-1.2 7.9-1.2 5.2 0 9.9 1.6 14.3 4.1l59.1 34c1.7 1 3.3 1.7 5.2 1.7 2.4 0 4.7-0.9 6.4-2.6 1.7-1.7 2.6-4 2.6-6.4 0-2.2-0.9-4.4-1.4-6.6-0.3-1.2-7.6-28.3-12.2-45.3-0.5-1.9-0.9-3.8-0.9-5.7 0.1-5.9 3.1-11.2 7.6-14.5zM600.2 587.2c-19.9 0-36-16.1-36-35.9 0-19.8 16.1-35.9 36-35.9s36 16.1 36 35.9c0 19.8-16.2 35.9-36 35.9z m179.9 0c-19.9 0-36-16.1-36-35.9 0-19.8 16.1-35.9 36-35.9s36 16.1 36 35.9c-0.1 19.8-16.2 35.9-36 35.9z'
p-id='5093'></path>
d="M866.7 792.7c56.9-41.2 93.2-102 93.2-169.7 0-124-120.8-224.5-269.9-224.5-149 0-269.9 100.5-269.9 224.5S540.9 847.5 690 847.5c30.8 0 60.6-4.4 88.1-12.3 2.6-0.8 5.2-1.2 7.9-1.2 5.2 0 9.9 1.6 14.3 4.1l59.1 34c1.7 1 3.3 1.7 5.2 1.7 2.4 0 4.7-0.9 6.4-2.6 1.7-1.7 2.6-4 2.6-6.4 0-2.2-0.9-4.4-1.4-6.6-0.3-1.2-7.6-28.3-12.2-45.3-0.5-1.9-0.9-3.8-0.9-5.7 0.1-5.9 3.1-11.2 7.6-14.5zM600.2 587.2c-19.9 0-36-16.1-36-35.9 0-19.8 16.1-35.9 36-35.9s36 16.1 36 35.9c0 19.8-16.2 35.9-36 35.9z m179.9 0c-19.9 0-36-16.1-36-35.9 0-19.8 16.1-35.9 36-35.9s36 16.1 36 35.9c-0.1 19.8-16.2 35.9-36 35.9z"
p-id="5093"></path>
</svg>;
}
......
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import {API, downloadTextAsFile, isMobile, showError, showSuccess} from '../../helpers';
import { renderQuota, renderQuotaWithPrompt } from '../../helpers/render';
import {SideSheet, Space, Spin, Button, Input, Typography, AutoComplete, Modal} from "@douyinfe/semi-ui";
import Title from "@douyinfe/semi-ui/lib/es/typography/title";
import {Divider} from "semantic-ui-react";
import { useNavigate, useParams } from 'react-router-dom';
import { API, downloadTextAsFile, isMobile, showError, showSuccess } from '../../helpers';
import { renderQuotaWithPrompt } from '../../helpers/render';
import { AutoComplete, Button, Input, Modal, SideSheet, Space, Spin, Typography } from '@douyinfe/semi-ui';
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
import { Divider } from 'semantic-ui-react';
const EditRedemption = (props) => {
const isEdit = props.editingRedemption.id !== undefined;
const [loading, setLoading] = useState(isEdit);
const params = useParams();
const navigate = useNavigate()
const navigate = useNavigate();
const originInputs = {
name: '',
quota: 100000,
......@@ -22,7 +22,7 @@ const EditRedemption = (props) => {
const handleCancel = () => {
props.handleClose();
}
};
const handleInputChange = (name, value) => {
setInputs((inputs) => ({ ...inputs, [name]: value }));
......@@ -82,9 +82,9 @@ const EditRedemption = (props) => {
showError(message);
}
if (!isEdit && data) {
let text = "";
let text = '';
for (let i = 0; i < data.length; i++) {
text += data[i] + "\n";
text += data[i] + '\n';
}
// downloadTextAsFile(text, `${inputs.name}.txt`);
Modal.confirm({
......@@ -108,14 +108,14 @@ const EditRedemption = (props) => {
<SideSheet
placement={isEdit ? 'right' : 'left'}
title={<Title level={3}>{isEdit ? '更新兑换码信息' : '创建新的兑换码'}</Title>}
headerStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
bodyStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
headerStyle={{ borderBottom: '1px solid var(--semi-color-border)' }}
bodyStyle={{ borderBottom: '1px solid var(--semi-color-border)' }}
visible={props.visiable}
footer={
<div style={{display: 'flex', justifyContent: 'flex-end'}}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Space>
<Button theme='solid' size={'large'} onClick={submit}>提交</Button>
<Button theme='solid' size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
<Button theme="solid" size={'large'} onClick={submit}>提交</Button>
<Button theme="solid" size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
</Space>
</div>
}
......@@ -126,49 +126,49 @@ const EditRedemption = (props) => {
<Spin spinning={loading}>
<Input
style={{ marginTop: 20 }}
label='名称'
name='name'
label="名称"
name="name"
placeholder={'请输入名称'}
onChange={value => handleInputChange('name', value)}
value={name}
autoComplete='new-password'
autoComplete="new-password"
required={!isEdit}
/>
<Divider/>
<Divider />
<div style={{ marginTop: 20 }}>
<Typography.Text>{`额度${renderQuotaWithPrompt(quota)}`}</Typography.Text>
</div>
<AutoComplete
style={{ marginTop: 8 }}
name='quota'
name="quota"
placeholder={'请输入额度'}
onChange={(value) => handleInputChange('quota', value)}
value={quota}
autoComplete='new-password'
type='number'
autoComplete="new-password"
type="number"
position={'bottom'}
data={[
{value: 500000, label: '1$'},
{value: 5000000, label: '10$'},
{value: 25000000, label: '50$'},
{value: 50000000, label: '100$'},
{value: 250000000, label: '500$'},
{value: 500000000, label: '1000$'},
{ value: 500000, label: '1$' },
{ value: 5000000, label: '10$' },
{ value: 25000000, label: '50$' },
{ value: 50000000, label: '100$' },
{ value: 250000000, label: '500$' },
{ value: 500000000, label: '1000$' }
]}
/>
{
!isEdit && <>
<Divider/>
<Divider />
<Typography.Text>生成数量</Typography.Text>
<Input
style={{ marginTop: 8 }}
label='生成数量'
name='count'
label="生成数量"
name="count"
placeholder={'请输入生成数量'}
onChange={value => handleInputChange('count', value)}
value={count}
autoComplete='new-password'
type='number'
autoComplete="new-password"
type="number"
/>
</>
}
......
import React, {useState} from 'react';
import {API, isMobile, showError, showSuccess} from '../../helpers';
import Title from "@douyinfe/semi-ui/lib/es/typography/title";
import {Button, SideSheet, Space, Input, Spin} from "@douyinfe/semi-ui";
import React, { useState } from 'react';
import { API, isMobile, showError, showSuccess } from '../../helpers';
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
import { Button, Input, SideSheet, Space, Spin } from '@douyinfe/semi-ui';
const AddUser = (props) => {
const originInputs = {
username: '',
display_name: '',
password: '',
password: ''
};
const [inputs, setInputs] = useState(originInputs);
const [loading, setLoading] = useState(false);
const {username, display_name, password} = inputs;
const { username, display_name, password } = inputs;
const handleInputChange = (name, value) => {
setInputs((inputs) => ({...inputs, [name]: value}));
setInputs((inputs) => ({ ...inputs, [name]: value }));
};
const submit = async () => {
setLoading(true);
if (inputs.username === '' || inputs.password === '') return;
const res = await API.post(`/api/user/`, inputs);
const {success, message} = res.data;
const { success, message } = res.data;
if (success) {
showSuccess('用户账户创建成功!');
setInputs(originInputs);
......@@ -35,21 +35,21 @@ const AddUser = (props) => {
const handleCancel = () => {
props.handleClose();
}
};
return (
<>
<SideSheet
placement={'left'}
title={<Title level={3}>{'添加用户'}</Title>}
headerStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
bodyStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
headerStyle={{ borderBottom: '1px solid var(--semi-color-border)' }}
bodyStyle={{ borderBottom: '1px solid var(--semi-color-border)' }}
visible={props.visible}
footer={
<div style={{display: 'flex', justifyContent: 'flex-end'}}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Space>
<Button theme='solid' size={'large'} onClick={submit}>提交</Button>
<Button theme='solid' size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
<Button theme="solid" size={'large'} onClick={submit}>提交</Button>
<Button theme="solid" size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
</Space>
</div>
}
......@@ -59,7 +59,7 @@ const AddUser = (props) => {
>
<Spin spinning={loading}>
<Input
style={{marginTop: 20}}
style={{ marginTop: 20 }}
label="用户名"
name="username"
addonBefore={'用户名'}
......@@ -69,7 +69,7 @@ const AddUser = (props) => {
autoComplete="off"
/>
<Input
style={{marginTop: 20}}
style={{ marginTop: 20 }}
addonBefore={'显示名'}
label="显示名称"
name="display_name"
......@@ -79,7 +79,7 @@ const AddUser = (props) => {
value={display_name}
/>
<Input
style={{marginTop: 20}}
style={{ marginTop: 20 }}
label="密 码"
name="password"
type={'password'}
......
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { API, isMobile, showError, showSuccess } from '../../helpers';
import { renderQuota, renderQuotaWithPrompt } from '../../helpers/render';
import Title from "@douyinfe/semi-ui/lib/es/typography/title";
import { SideSheet, Space, Button, Spin, Input, Typography, Select, Divider } from "@douyinfe/semi-ui";
import { renderQuotaWithPrompt } from '../../helpers/render';
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
import { Button, Divider, Input, Select, SideSheet, Space, Spin, Typography } from '@douyinfe/semi-ui';
const EditUser = (props) => {
const userId = props.editingUser.id;
......@@ -29,7 +29,7 @@ const EditUser = (props) => {
let res = await API.get(`/api/group/`);
setGroupOptions(res.data.data.map((group) => ({
label: group,
value: group,
value: group
})));
} catch (error) {
showError(error.message);
......@@ -38,7 +38,7 @@ const EditUser = (props) => {
const navigate = useNavigate();
const handleCancel = () => {
props.handleClose();
}
};
const loadUser = async () => {
setLoading(true);
let res = undefined;
......@@ -98,8 +98,8 @@ const EditUser = (props) => {
footer={
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Space>
<Button theme='solid' size={'large'} onClick={submit}>提交</Button>
<Button theme='solid' size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
<Button theme="solid" size={'large'} onClick={submit}>提交</Button>
<Button theme="solid" size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
</Space>
</div>
}
......@@ -112,35 +112,35 @@ const EditUser = (props) => {
<Typography.Text>用户名</Typography.Text>
</div>
<Input
label='用户名'
name='username'
label="用户名"
name="username"
placeholder={'请输入新的用户名'}
onChange={value => handleInputChange('username', value)}
value={username}
autoComplete='new-password'
autoComplete="new-password"
/>
<div style={{ marginTop: 20 }}>
<Typography.Text>密码</Typography.Text>
</div>
<Input
label='密码'
name='password'
label="密码"
name="password"
type={'password'}
placeholder={'请输入新的密码,最短 8 位'}
onChange={value => handleInputChange('password', value)}
value={password}
autoComplete='new-password'
autoComplete="new-password"
/>
<div style={{ marginTop: 20 }}>
<Typography.Text>显示名称</Typography.Text>
</div>
<Input
label='显示名称'
name='display_name'
label="显示名称"
name="display_name"
placeholder={'请输入新的显示名称'}
onChange={value => handleInputChange('display_name', value)}
value={display_name}
autoComplete='new-password'
autoComplete="new-password"
/>
{
userId && <>
......@@ -149,7 +149,7 @@ const EditUser = (props) => {
</div>
<Select
placeholder={'请选择分组'}
name='group'
name="group"
fluid
search
selection
......@@ -157,19 +157,19 @@ const EditUser = (props) => {
additionLabel={'请在系统设置页面编辑分组倍率以添加新的分组:'}
onChange={value => handleInputChange('group', value)}
value={inputs.group}
autoComplete='new-password'
autoComplete="new-password"
optionList={groupOptions}
/>
<div style={{ marginTop: 20 }}>
<Typography.Text>{`剩余额度${renderQuotaWithPrompt(quota)}`}</Typography.Text>
</div>
<Input
name='quota'
name="quota"
placeholder={'请输入新的剩余额度'}
onChange={value => handleInputChange('quota', value)}
value={quota}
type={'number'}
autoComplete='new-password'
autoComplete="new-password"
/>
</>
}
......@@ -178,37 +178,37 @@ const EditUser = (props) => {
<Typography.Text>已绑定的 GitHub 账户</Typography.Text>
</div>
<Input
name='github_id'
name="github_id"
value={github_id}
autoComplete='new-password'
placeholder='此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改'
autoComplete="new-password"
placeholder="此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改"
readonly
/>
<div style={{ marginTop: 20 }}>
<Typography.Text>已绑定的微信账户</Typography.Text>
</div>
<Input
name='wechat_id'
name="wechat_id"
value={wechat_id}
autoComplete='new-password'
placeholder='此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改'
autoComplete="new-password"
placeholder="此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改"
readonly
/>
<Input
name='telegram_id'
name="telegram_id"
value={telegram_id}
autoComplete='new-password'
placeholder='此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改'
autoComplete="new-password"
placeholder="此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改"
readonly
/>
<div style={{ marginTop: 20 }}>
<Typography.Text>已绑定的邮箱账户</Typography.Text>
</div>
<Input
name='email'
name="email"
value={email}
autoComplete='new-password'
placeholder='此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改'
autoComplete="new-password"
placeholder="此项只读,需要用户通过个人设置页面的相关绑定按钮进行绑定,不可直接修改"
readonly
/>
</Spin>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment