mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	feat: able to customize home page now (#24)
This commit is contained in:
		@@ -56,7 +56,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
 | 
			
		||||
5. 支持设置令牌的过期时间和使用次数。
 | 
			
		||||
6. 支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
 | 
			
		||||
7. 支持为新用户设置初始配额。
 | 
			
		||||
8. 支持发布公告,在线修改关于页面,设置充值链接,自定义页脚。
 | 
			
		||||
8. 支持自定义首页,发布公告,自定义关于页面,设置充值链接,自定义页脚。
 | 
			
		||||
9. 支持通过系统访问令牌访问管理 API。
 | 
			
		||||
10. 多种用户登录注册方式:
 | 
			
		||||
    + 邮箱登录注册以及通过邮箱进行密码重置。
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,17 @@ func GetAbout(c *gin.Context) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetHomePageContent(c *gin.Context) {
 | 
			
		||||
	common.OptionMapRWMutex.RLock()
 | 
			
		||||
	defer common.OptionMapRWMutex.RUnlock()
 | 
			
		||||
	c.JSON(http.StatusOK, gin.H{
 | 
			
		||||
		"success": true,
 | 
			
		||||
		"message": "",
 | 
			
		||||
		"data":    common.OptionMap["HomePageContent"],
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SendEmailVerification(c *gin.Context) {
 | 
			
		||||
	email := c.Query("email")
 | 
			
		||||
	if err := common.Validate.Var(email, "required,email"); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ func InitOptionMap() {
 | 
			
		||||
	common.OptionMap["SMTPToken"] = ""
 | 
			
		||||
	common.OptionMap["Notice"] = ""
 | 
			
		||||
	common.OptionMap["About"] = ""
 | 
			
		||||
	common.OptionMap["HomePageContent"] = ""
 | 
			
		||||
	common.OptionMap["Footer"] = common.Footer
 | 
			
		||||
	common.OptionMap["ServerAddress"] = ""
 | 
			
		||||
	common.OptionMap["GitHubClientId"] = ""
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ func SetApiRouter(router *gin.Engine) {
 | 
			
		||||
		apiRouter.GET("/status", controller.GetStatus)
 | 
			
		||||
		apiRouter.GET("/notice", controller.GetNotice)
 | 
			
		||||
		apiRouter.GET("/about", controller.GetAbout)
 | 
			
		||||
		apiRouter.GET("/home_page_content", controller.GetHomePageContent)
 | 
			
		||||
		apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification)
 | 
			
		||||
		apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail)
 | 
			
		||||
		apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ const OtherSetting = () => {
 | 
			
		||||
    Footer: '',
 | 
			
		||||
    Notice: '',
 | 
			
		||||
    About: '',
 | 
			
		||||
    HomePageContent: '',
 | 
			
		||||
  });
 | 
			
		||||
  let originInputs = {};
 | 
			
		||||
  let [loading, setLoading] = useState(false);
 | 
			
		||||
@@ -69,6 +70,10 @@ const OtherSetting = () => {
 | 
			
		||||
    await updateOption('About', inputs.About);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const submitOption = async (key) => {
 | 
			
		||||
    await updateOption(key, inputs[key]);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const openGitHubRelease = () => {
 | 
			
		||||
    window.location =
 | 
			
		||||
      'https://github.com/songquanpeng/one-api/releases/latest';
 | 
			
		||||
@@ -109,6 +114,17 @@ const OtherSetting = () => {
 | 
			
		||||
          <Form.Button onClick={submitNotice}>保存公告</Form.Button>
 | 
			
		||||
          <Divider />
 | 
			
		||||
          <Header as='h3'>个性化设置</Header>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
            <Form.TextArea
 | 
			
		||||
              label='首页内容'
 | 
			
		||||
              placeholder='在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示'
 | 
			
		||||
              value={inputs.HomePageContent}
 | 
			
		||||
              name='HomePageContent'
 | 
			
		||||
              onChange={handleInputChange}
 | 
			
		||||
              style={{ minHeight: 300, fontFamily: 'JetBrains Mono, Consolas' }}
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Group>
 | 
			
		||||
          <Form.Button onClick={()=>submitOption('HomePageContent')}>保存首页内容</Form.Button>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
            <Form.TextArea
 | 
			
		||||
              label='关于'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
import React, { useContext, useEffect } from 'react';
 | 
			
		||||
import React, { useContext, useEffect, useState } from 'react';
 | 
			
		||||
import { Card, Grid, Header, Segment } from 'semantic-ui-react';
 | 
			
		||||
import { API, showError, showNotice, timestamp2string } from '../../helpers';
 | 
			
		||||
import { StatusContext } from '../../context/Status';
 | 
			
		||||
import { marked } from 'marked';
 | 
			
		||||
 | 
			
		||||
const Home = () => {
 | 
			
		||||
  const [statusState, statusDispatch] = useContext(StatusContext);
 | 
			
		||||
  const [homePageContent, setHomePageContent] = useState('');
 | 
			
		||||
 | 
			
		||||
  const displayNotice = async () => {
 | 
			
		||||
    const res = await API.get('/api/notice');
 | 
			
		||||
@@ -20,6 +22,19 @@ const Home = () => {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const displayHomePageContent = async () => {
 | 
			
		||||
    const res = await API.get('/api/home_page_content');
 | 
			
		||||
    const { success, message, data } = res.data;
 | 
			
		||||
    if (success) {
 | 
			
		||||
      let HTMLContent = marked.parse(data);
 | 
			
		||||
      localStorage.setItem('home_page_content', HTMLContent);
 | 
			
		||||
      setHomePageContent(HTMLContent);
 | 
			
		||||
    } else {
 | 
			
		||||
      showError(message);
 | 
			
		||||
      setHomePageContent('加载首页内容失败...');
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const getStartTimeString = () => {
 | 
			
		||||
    const timestamp = statusState?.status?.start_time;
 | 
			
		||||
    return timestamp2string(timestamp);
 | 
			
		||||
@@ -27,69 +42,76 @@ const Home = () => {
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    displayNotice().then();
 | 
			
		||||
    displayHomePageContent().then();
 | 
			
		||||
  }, []);
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Segment>
 | 
			
		||||
        <Header as='h3'>系统状况</Header>
 | 
			
		||||
        <Grid columns={2} stackable>
 | 
			
		||||
          <Grid.Column>
 | 
			
		||||
            <Card fluid>
 | 
			
		||||
              <Card.Content>
 | 
			
		||||
                <Card.Header>系统信息</Card.Header>
 | 
			
		||||
                <Card.Meta>系统信息总览</Card.Meta>
 | 
			
		||||
                <Card.Description>
 | 
			
		||||
                  <p>名称:{statusState?.status?.system_name}</p>
 | 
			
		||||
                  <p>版本:{statusState?.status?.version}</p>
 | 
			
		||||
                  <p>
 | 
			
		||||
                    源码:
 | 
			
		||||
                    <a
 | 
			
		||||
                      href='https://github.com/songquanpeng/one-api'
 | 
			
		||||
                      target='_blank'
 | 
			
		||||
                    >
 | 
			
		||||
                      https://github.com/songquanpeng/one-api
 | 
			
		||||
                    </a>
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <p>启动时间:{getStartTimeString()}</p>
 | 
			
		||||
                </Card.Description>
 | 
			
		||||
              </Card.Content>
 | 
			
		||||
            </Card>
 | 
			
		||||
          </Grid.Column>
 | 
			
		||||
          <Grid.Column>
 | 
			
		||||
            <Card fluid>
 | 
			
		||||
              <Card.Content>
 | 
			
		||||
                <Card.Header>系统配置</Card.Header>
 | 
			
		||||
                <Card.Meta>系统配置总览</Card.Meta>
 | 
			
		||||
                <Card.Description>
 | 
			
		||||
                  <p>
 | 
			
		||||
                    邮箱验证:
 | 
			
		||||
                    {statusState?.status?.email_verification === true
 | 
			
		||||
                      ? '已启用'
 | 
			
		||||
                      : '未启用'}
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <p>
 | 
			
		||||
                    GitHub 身份验证:
 | 
			
		||||
                    {statusState?.status?.github_oauth === true
 | 
			
		||||
                      ? '已启用'
 | 
			
		||||
                      : '未启用'}
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <p>
 | 
			
		||||
                    微信身份验证:
 | 
			
		||||
                    {statusState?.status?.wechat_login === true
 | 
			
		||||
                      ? '已启用'
 | 
			
		||||
                      : '未启用'}
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <p>
 | 
			
		||||
                    Turnstile 用户校验:
 | 
			
		||||
                    {statusState?.status?.turnstile_check === true
 | 
			
		||||
                      ? '已启用'
 | 
			
		||||
                      : '未启用'}
 | 
			
		||||
                  </p>
 | 
			
		||||
                </Card.Description>
 | 
			
		||||
              </Card.Content>
 | 
			
		||||
            </Card>
 | 
			
		||||
          </Grid.Column>
 | 
			
		||||
        </Grid>
 | 
			
		||||
        {
 | 
			
		||||
          homePageContent  === '' ? <>
 | 
			
		||||
          <Header as='h3'>系统状况</Header>
 | 
			
		||||
          <Grid columns={2} stackable>
 | 
			
		||||
            <Grid.Column>
 | 
			
		||||
              <Card fluid>
 | 
			
		||||
                <Card.Content>
 | 
			
		||||
                  <Card.Header>系统信息</Card.Header>
 | 
			
		||||
                  <Card.Meta>系统信息总览</Card.Meta>
 | 
			
		||||
                  <Card.Description>
 | 
			
		||||
                    <p>名称:{statusState?.status?.system_name}</p>
 | 
			
		||||
                    <p>版本:{statusState?.status?.version}</p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                      源码:
 | 
			
		||||
                      <a
 | 
			
		||||
                        href='https://github.com/songquanpeng/one-api'
 | 
			
		||||
                        target='_blank'
 | 
			
		||||
                      >
 | 
			
		||||
                        https://github.com/songquanpeng/one-api
 | 
			
		||||
                      </a>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p>启动时间:{getStartTimeString()}</p>
 | 
			
		||||
                  </Card.Description>
 | 
			
		||||
                </Card.Content>
 | 
			
		||||
              </Card>
 | 
			
		||||
            </Grid.Column>
 | 
			
		||||
            <Grid.Column>
 | 
			
		||||
              <Card fluid>
 | 
			
		||||
                <Card.Content>
 | 
			
		||||
                  <Card.Header>系统配置</Card.Header>
 | 
			
		||||
                  <Card.Meta>系统配置总览</Card.Meta>
 | 
			
		||||
                  <Card.Description>
 | 
			
		||||
                    <p>
 | 
			
		||||
                      邮箱验证:
 | 
			
		||||
                      {statusState?.status?.email_verification === true
 | 
			
		||||
                        ? '已启用'
 | 
			
		||||
                        : '未启用'}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                      GitHub 身份验证:
 | 
			
		||||
                      {statusState?.status?.github_oauth === true
 | 
			
		||||
                        ? '已启用'
 | 
			
		||||
                        : '未启用'}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                      微信身份验证:
 | 
			
		||||
                      {statusState?.status?.wechat_login === true
 | 
			
		||||
                        ? '已启用'
 | 
			
		||||
                        : '未启用'}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                      Turnstile 用户校验:
 | 
			
		||||
                      {statusState?.status?.turnstile_check === true
 | 
			
		||||
                        ? '已启用'
 | 
			
		||||
                        : '未启用'}
 | 
			
		||||
                    </p>
 | 
			
		||||
                  </Card.Description>
 | 
			
		||||
                </Card.Content>
 | 
			
		||||
              </Card>
 | 
			
		||||
            </Grid.Column>
 | 
			
		||||
          </Grid>
 | 
			
		||||
          </> : <>
 | 
			
		||||
          <div dangerouslySetInnerHTML={{ __html: homePageContent}}></div>
 | 
			
		||||
          </>
 | 
			
		||||
        }
 | 
			
		||||
      </Segment>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user