Commit c0152a50 authored by web's avatar web

init

parent 0ce5adcb
Pipeline #736 failed with stages
File added
node_modules
build
dist
.vscode
\ No newline at end of file
const webpack = require("webpack");
module.exports = function override(config) {
const fallback = config.resolve.fallback || {};
Object.assign(fallback, {
crypto: false, // require.resolve("crypto-browserify") can be polyfilled here if needed
stream: false, // require.resolve("stream-browserify") can be polyfilled here if needed
assert: false, // require.resolve("assert") can be polyfilled here if needed
http: false, // require.resolve("stream-http") can be polyfilled here if needed
https: false, // require.resolve("https-browserify") can be polyfilled here if needed
os: false, // require.resolve("os-browserify") can be polyfilled here if needed
url: false, // require.resolve("url") can be polyfilled here if needed
zlib: false, // require.resolve("browserify-zlib") can be polyfilled here if needed
});
config.resolve.fallback = fallback;
config.plugins = (config.plugins || []).concat([
new webpack.ProvidePlugin({
process: "process/browser",
Buffer: ["buffer", "Buffer"],
}),
]);
config.ignoreWarnings = [/Failed to parse source map/];
config.module.rules.push({
test: /\.(js|mjs|jsx)$/,
enforce: "pre",
loader: require.resolve("source-map-loader"),
resolve: {
fullySpecified: false,
},
});
return config;
};
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "ai",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
"@traptitech/markdown-it-katex": "^3.6.0",
"@wavesurfer/react": "^1.0.4",
"@web3auth/ethereum-provider": "^8.0.1",
"@web3auth/modal": "^7.3.1",
"antd": "^5.15.1",
"antd-style": "^3.6.1",
"autoprefixer": "^10.4.16",
"bootstrap": "^5.3.2",
"clipboard-copy": "^4.0.1",
"crypto-browserify": "^3.12.0",
"jose": "^5.2.3",
"moment": "^2.30.1",
"postcss": "^8.4.32",
"react": "^18.2.0",
"react-bootstrap": "^2.9.2",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.21.1",
"react-scripts": "5.0.1",
"react-slick": "^0.30.2",
"react-syntax-highlighter": "^15.5.0",
"slick-carousel": "^1.8.1",
"stream-browserify": "^3.0.0",
"swiper": "^11.0.5",
"video-react": "^0.16.0",
"vm-browserify": "^1.1.2",
"wavesurfer.js": "^7.7.5",
"web-vitals": "^2.1.0",
"web3": "^4.6.0"
},
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"react-app-rewired": "^2.2.1",
"sass": "^1.69.6",
"sass-loader": "^13.3.3",
"tailwindcss": "^3.4.0"
}
}
<!DOCTYPE html>
<html lang="en" class="h-full">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content=""
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/favicon.ico" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>AIGIC</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
{
"data": [
{
"key": "sdxl",
"icon": "",
"tit": "Stable Diffusion XL",
"content": "Stable Diffusion is a latent text-to-image diffusion model capable of generating photo-realistic images given any text input.",
"tags": ["Image", "text-to-image"]
},
{
"key": "chat",
"icon": "",
"tit": "ChatGLM2-6B",
"content": "ChatGLM2-6B is the second-generation version of the open-source bilingual (Chinese-English) chat model ChatGLM-6B. It retains the smooth conversation flow and low deployment threshold of the first-generation model, while introducing the new features including stronger performance, longer contex and more efficient inference.",
"tags": ["LLM", "text"]
}
]
}
\ No newline at end of file
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
File added
.App {
text-align: center;
position: relative;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
.ant-form-item-extra {
text-align: left;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import { BrowserRouter as Router } from 'react-router-dom';
import Layout from './components/Layout';
import AppRoutes from './routes';
import { ConfigProvider } from 'antd';
import 'video-react/dist/video-react.css';
import './assets/fonts/fonts.scss'
import './index.css';
import './App.css';
import './styles.scss'
import { LoginProvider } from './context/LoginContext';
function App() {
const host = window.location.host;
const hostname = window.location.hostname;
const targetAdminHost = hostname !== 'localhost' ? 'https://console.' + host : 'http://' + host
return (
<div className="App">
<ConfigProvider
theme={
{
token: {
colorPrimary: '#722ED1',
},
components: {
Button: {
borderRadius: 24,
colorPrimary: '#722ED1',
defaultColor: '#722ED1',
defaultBorderColor: '#722ED1',
defaultActiveBg: '#722ED1',
defaultActiveBorderColor: '#722ED1',
defaultActiveColor: '#fff',
primaryShadow: 'none',
colorPrimaryBg: '#722ED1',
},
Select: {
optionSelectedBg: '#722ED1',
},
Table: {
headerBg: '#EFDBFF',
headerColor: '#000',
cellFontSize: 16,
headerBorderRadius: 0,
}
}
}
}
>
<Router basename='/' >
<LoginProvider>
<Layout>
<AppRoutes />
<iframe id="targetFrame" src={`${targetAdminHost}/receiver`} title="Target Frame" style={{ display: 'none' }} />
</Layout>
</LoginProvider>
</Router>
</ConfigProvider>
</div>
);
}
export default App;
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
@font-face {
font-family: 'SourceHanSansSC-Bold';
src: url('./SourceHanSansSC-Bold.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'SourceHanSansSC-Heavy';
src: url('./SourceHanSansSC-Heavy.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'SourceHanSansSC-Medium';
src: url('./SourceHanSansSC-Medium.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'SourceHanSansSC-Regular';
src: url('./SourceHanSansSC-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
$font_sc_Bold: 'SourceHanSansSC-Bold';
$font_sc_Heavy: 'SourceHanSansSC-Heavy';
$font_sc_Medium: 'SourceHanSansSC-Medium';
$font_sc_Regular: 'SourceHanSansSC-Regular';
\ No newline at end of file
import React, { useCallback, useRef } from 'react';
import { useWavesurfer } from '@wavesurfer/react'
const formatTime = (seconds) => [seconds / 60, seconds % 60].map((v) => `0${Math.floor(v)}`.slice(-2)).join(':')
const AudioPlayer = ({ audioUrl }) => {
const containerRef = useRef(null)
const { wavesurfer, isPlaying, currentTime } = useWavesurfer({
container: containerRef,
height: 150,
waveColor: '#fff',
progressColor: '#722ED1',
url: audioUrl,
})
const onPlayPause = useCallback(() => {
try {
wavesurfer && wavesurfer.playPause()
} catch (error) {
console.log(error)
}
}, [wavesurfer])
return (
<>
{(
<>
<div
className="playIcon"
onClick={() => {
if (!wavesurfer?.getDuration()) {
return
}
onPlayPause()
}}>
{!isPlaying ? <img className="handleBtn" src={require('../assets/images/home/play-fill.png')} alt="" /> : <img className="handleBtn" src={require('../assets/images/home/pause.png')} alt="" />}
</div>
<div className="times">{formatTime(currentTime)}</div>
<div className="process">
<div ref={containerRef}></div>
{!wavesurfer?.getDuration() && <div className="process_null"></div>}
</div>
<div className="times">{formatTime(wavesurfer?.getDuration())}</div>
</>
)}
</>
);
};
export default AudioPlayer;
// CodeSnippet.js
import React, { useState } from 'react';
import { message } from 'antd';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { duotoneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { CopyToClipboard } from 'react-copy-to-clipboard';
const CodeSnippet = ({ code, isHome, lang }) => {
const handleCopy = (e) => {
navigator.clipboard.writeText(e)
.then(() => {
message.success('Copied');
})
.catch(() => {
message.error('Copied Failed');
});
};
return (
<div className='overflow-auto' style={!isHome ? { height: '23.02vw' } : {}}>
<CopyToClipboard text={code} onCopy={handleCopy}>
<img className='absolute top-2 right-4 cursor-pointer' style={{height: '1.25vw', width: '1.25vw'}} src={require('../assets/images/playground/copy.png')} alt="" />
</CopyToClipboard>
<SyntaxHighlighter language={lang} customStyle={{ margin: 0, height: '100%', backgroundColor: '#22075E', fontSize: '.83vw', fontWeight: 400, color: '#fff', textShadow: 'none', fontFamily: 'SourceHanSansSC-Regular' }}>
{code && code.length ? code : "Stay tuned, we'll be here soon"}
</SyntaxHighlighter>
</div>
);
};
export default CodeSnippet;
const Footer = () => {
return (
<footer className="flex-0 relative px-8 py-3 bg-zinc-900 border-t border-zinc-800">
<div className="flex flex-row items-center justify-between gap-5">
<div className="flex gap-6">
<p className="text-xs text-zinc-400">© AIGIC Labs</p>
</div>
</div>
</footer>
)
}
export default Footer
\ No newline at end of file
import { useLocation } from 'react-router-dom';
import './styles/header_dark.scss'
import { useState } from "react";
const Header = () => {
const location = useLocation();
const pathname = location.pathname;
const host = window.location.host;
const hostname = window.location.hostname;
const targetDocsHost = hostname !== 'localhost' ? 'https://docs.' + host.replace('www.', '') : 'http://' + host
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpand = () => {
setIsExpanded(!isExpanded);
};
return (
<header style={isExpanded || pathname !== '/' ? { backgroundColor: '#22075E' } : {}}>
<nav className='flex flex-row items-center justify-between'>
<a href="/">
<div className="logo">
<img src={require('../assets/images/logo_.png')} alt="" />
</div>
</a>
<div className="menu">
<img className='menuIcon' src={require(`../assets/images/headers/${isExpanded ? 'close' : 'menu'}.png`)} onClick={toggleExpand} alt="" />
<ul className={isExpanded ? 'expanded' : 'collapsed'}>
<li>
<a href="/playground" onClick={toggleExpand}>
<span>Built with AIGIC</span>
<img src={require('../assets/images/headers/right.png')} alt="" />
</a>
</li>
<li>
<a href={targetDocsHost} target='_blank' onClick={toggleExpand}>
<span>Docs</span>
<img src={require('../assets/images/headers/right.png')} alt="" />
</a>
</li>
</ul>
</div>
</nav>
</header>
);
};
export default Header;
\ No newline at end of file
import { Dropdown } from 'antd';
import React from 'react';
const HeaderDropdown = ({ ...restProps }) => {
return <Dropdown {...restProps} />;
};
export default HeaderDropdown;
\ No newline at end of file
import React from 'react';
import Header from './Header';
import Footer from './Footer';
const Layout = ({ children }) => {
return (
<div className='relative flex min-h-screen flex-col overflow-hidden text-zinc-100'>
<Header></Header>
<div className="flex flex-1 flex-col content">
{children}
</div>
{/* <Footer></Footer> */}
</div>
);
};
export default Layout;
import React from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
const CodeBlock = ({ language, children }) => {
return (
<SyntaxHighlighter language={language} style={vscDarkPlus}>
{children}
</SyntaxHighlighter>
);
};
const MarkdownRenderer = ({ markdownContent }) => {
return (
<ReactMarkdown
components={{
code: CodeBlock,
}}
>
{markdownContent}
</ReactMarkdown>
);
};
export default MarkdownRenderer;
header {
background: #000;
padding: 3.08vw 6.15vw;
width: 100%;
color: #fff;
position: fixed;
top: 0;
left: 0;
z-index: 100;
nav {
.logo img {
width: 23.59vw;
height: 8.21vw;
}
.menu {
.menuIcon {
height: 6.15vw;
width: 6.15vw;
}
.expanded {
height: calc(100vh - 14.36vw);
display: flex;
opacity: 1;
transition: all 0.3s ease;
position: fixed;
top: 14.36vw;
left: 0;
padding: 2.05vw 0;
}
.collapsed {
height: 0;
padding: 0;
position: absolute;
left: 0;
top: 14.36vw;
}
ul {
overflow: hidden;
height: 0;
opacity: 0;
width: 100%;
z-index: 99;
display: flex;
flex-direction: column;
background-color: #22075E;
li {
width: 100%;
a {
padding: 2.05vw 6.15vw;
font-size: 2.56vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
display: flex;
flex-direction: row;
justify-content: space-between;
img {
height: 4.1vw;
width: 4.1vw;
}
}
}
}
}
}
}
\ No newline at end of file
import React, { createContext,useContext, useState } from 'react';
import { doLogin, doLogout } from '../utils/login';
const LoginContext = createContext();
export const LoginProvider = ({ children }) => {
const [isLogin, setIsLogin] = useState(false);
const login = (callbak) => {
// 登录逻辑...
doLogin((res,error) => {
console.log("doLogin",res,error)
if (error == null) {
setIsLogin(true)
}
callbak(res,error)
})
};
const logout = (callbak) => {
// 登出逻辑...
doLogout((res,error) => {
console.log("doLogout",res,error)
if (error == null) {
setIsLogin(false)
}
callbak(res,error)
})
};
return (
<LoginContext.Provider value={{ isLogin, setIsLogin,login, logout }}>
{children}
</LoginContext.Provider>
);
};
export const useLoginContext = () => useContext(LoginContext);
\ No newline at end of file
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
font-family: SourceHanSansSC-Regular;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
} */
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
// document.documentElement.classList.add('dark');
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
\ No newline at end of file
import React, { useState, useEffect } from "react";
import { Button, Input, message } from "antd";
import { Link } from 'react-router-dom';
import Slider from 'react-slick';
import Stable_Diffusion_XL from '../assets/images/home/model_icon1.png'
import LLAMA from '../assets/images/home/model_icon2.png'
import Musicgen from '../assets/images/home/model_icon3.png'
import StyleTTS_2 from '../assets/images/home/model_icon4.png'
import LoadingGif from '../assets/images/playground/loading.gif'
// import './styles/home.scss'
import './styles/home_dark.scss'
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import { useLoginContext } from '../context/LoginContext';
import Fetch_ from "../utils/fetch";
const Home = () => {
const [activeModel, setActiveModel] = useState({})
const [activeModelIndex, setActiveModelIndex] = useState(1)
const [play, setPlay] = useState(false)
const [activeModelImg, setActiveModelImg] = useState(Stable_Diffusion_XL)
const [activeModelType, setActiveModelType] = useState(1)
const [models, setModels] = useState([])
const { isLogin, setIsLogin } = useLoginContext();
const [currentApiKey, setCurrentApiKey] = useState('');
const [loading, setLoading] = useState(false);
const [resCon, setResCon] = useState('');
const [resTask, setResTask] = useState({});
const [prompt, setPrompt] = useState('')
const [countDown, setCountDown] = useState(60);
const [remainingHours, setRemainingHours] = useState(0);
const [remainingMinutes, setRemainingMinutes] = useState(0);
const [remainingSeconds, setRemainingSeconds] = useState(0);
useEffect(() => {
switch (activeModelIndex) {
case 1:
setActiveModelImg(Stable_Diffusion_XL)
setActiveModelType(1)
break;
case 2:
setActiveModelImg(LLAMA)
setActiveModelType(2)
break;
case 3:
setActiveModelImg(Musicgen)
setActiveModelType(3)
break;
case 4:
setActiveModelImg(StyleTTS_2)
setActiveModelType(4)
break;
default:
break;
}
setResTask(null)
}, [activeModelIndex])
useEffect(() => {
if (isLogin) {
queryApiKeys()
} else {
setCurrentApiKey('')
}
}, [isLogin]);
useEffect(() => {
fetchData()
}, []);
const fetchData = async () => {
const token = localStorage.getItem("token")
if (token) {
setIsLogin(true)
await queryApiKeys()
}
try {
let images = [Stable_Diffusion_XL, LLAMA, Musicgen, StyleTTS_2]
let models = await getModels()
if (models && models.length) {
images.map((item, index) => {
if (index < models.length) {
let model = models[index]
model.image = item
}
})
}
setModels(models)
initFirstSelectModel(models)
} catch (error) {
console.log(error)
}
}
const getModels = async () => {
const res = await fetch('/admin/api/task/examples', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
page: 1,
size: 4
}),
});
const jsonData = await res.json()
if (jsonData.code === 200 && jsonData.data && jsonData.data.data && jsonData.data.data.length) {
return jsonData.data.data
}
return []
}
const initFirstSelectModel = async (models) => {
if (models && models.length) {
let model = models[0]
if (model.examples && model.examples.length) {
let example = model.examples[0]
if (example.input && example.input.length) {
let input = JSON.parse(example.input)
setPrompt(input.prompt)
}
}
setActiveModel(model)
}
}
const switchModel = async (data, index) => {
if (data.examples && data.examples.length) {
let example = data.examples[0]
if (example.input && example.input.length) {
let input = JSON.parse(example.input)
setPrompt(input.prompt)
return input.prompt
}
}
setActiveModelIndex(index + 1)
setActiveModel(data)
}
async function queryApiKeys() {
try {
const result = await Fetch_("/admin/api/app/apikeysfront", {
method: "GET",
})
const res = await result.json();
if (res.code === 200) {
let data = res.data.data
if (data && data.length > 0) {
setCurrentApiKey(data[0].api_key)
}
} else if (res.code === 401) {
// message.error(res.msg)
setIsLogin(false)
}
} catch (error) {
console.log(error)
// setIsLogin(false)
}
}
const queryApi = async (data) => {
let timing = null
try {
if (activeModel.estimat_exe_time && activeModel.estimat_exe_time > 0) {
let count = Number(activeModel.estimat_exe_time) + Number(activeModel.start_up_time)
setCountDown(count)
timing = setInterval(() => {
const hours = Math.floor(count / 3600);
const minutes = Math.floor((count % 3600) / 60);
const seconds = count % 60;
setRemainingHours(hours);
setRemainingMinutes(minutes);
setRemainingSeconds(seconds);
count -= 1;
setCountDown(count)
if (count === 0) {
clearInterval(timing)
setRemainingHours(0);
setRemainingMinutes(0);
setRemainingSeconds(0);
}
}, 1000)
}
const response = await fetch('/api/v1' + activeModel['api_path'], {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': isLogin ? currentApiKey : '4oipB83LZCpkrVN3i12f38WcBUYH5MR9',
'async': false,
},
body: JSON.stringify(data),
});
if (response.ok) {
if (response.status === 200) {
try {
const resultJson = await response.json();
const isResultTask = resultJson && resultJson.task
if (isResultTask && resultJson.task.is_success === false) {
setLoading(false)
setResTask({ ...resultJson.task, output: resultJson.output })
if (resultJson.task.exec_code == 409) {
message.error('Already running a prediction')
return
}
if (resultJson.task.api_error && resultJson.task.api_error.message) {
message.error(resultJson.task.api_error.message)
} else if (resultJson.task.task_error) {
message.error(resultJson.task.task_error)
}
}
if (resultJson && resultJson.task.is_success && resultJson.output) {
setResTask(null)
setLoading(false)
message.success('Success')
if (Array.isArray(resultJson.output) && resultJson.output.length > 0) {
// const output = [].concat(...resultJson.output)
const outputArr = resultJson.output.filter(item => Array.isArray(item)).flat() || []
const outputArrStr = resultJson.output.filter(item => typeof (item) === 'string').flat() || []
setResCon(outputArrStr.length > 0 ? outputArrStr : outputArr)
}
}
} catch (error) {
setResTask(null)
if (response.url) {
setResCon(response.url)
setLoading(false)
} else {
setLoading(false)
message.error(response.statusText)
}
}
}
clearInterval(timing)
setRemainingHours(0);
setRemainingMinutes(0);
setRemainingSeconds(0);
} else {
message.error(`Request failed with status ${response.status}`)
setResTask(null)
setLoading(false)
clearInterval(timing)
setRemainingHours(0);
setRemainingMinutes(0);
setRemainingSeconds(0);
}
} catch (error) {
setLoading(false)
setResTask(null)
clearInterval(timing)
setRemainingHours(0);
setRemainingMinutes(0);
setRemainingSeconds(0);
console.error('Error posting data:', error)
}
}
const optSubmit = async (values) => {
setActiveModel(values)
if (loading) return
if (activeModel.publish_status !== 1) {
message.warning("This model isn't open yet.")
return
}
setResCon('')
setLoading(true)
let input = {
prompt: prompt
}
if (values.examples && values.examples.length) {
let example = values.examples[0]
if (example.input && example.input.length) {
input = JSON.parse(example.input)
input.prompt = prompt
}
}
const postData = {
input: input
}
queryApi(postData)
}
const models_settings = {
className: "center variable-width",
arrows: false,
centerMode: true,
infinite: true,
variableWidth: true,
// slidesToShow: 1,
speed: 300
};
const settings = {
className: "slider variable-width",
arrows: false,
infinite: true,
variableWidth: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1
};
return (
<div className="home">
<div className="large_bg">
<section className="first_page">
<div className="banner_text">
<p>Run your own AI Application</p>
<p>Just One Line Of Code</p>
</div>
<p className="banner_text_des">You don't need high configuration hardware or complex local deployment.</p>
<p className="banner_text_des">On AIGIC, you only need to copy a line of code to create your own AI application.</p>
<Link to="/playground"><div className="start_btn">Get Free Computility</div></Link>
<img src={require('../assets/images/home/cloud1.png')} alt="" className="cloudIcon cloud1" />
<img src={require('../assets/images/home/cloud2.png')} alt="" className="cloudIcon cloud2" />
<img src={require('../assets/images/home/cloud3.png')} alt="" className="cloudIcon cloud3" />
</section>
<section className="second_page">
<div className="slider-container">
<Slider {...models_settings}>
{
models && models.length && models.map((item, index) => {
return (
<div key={index}>
{
index === 0 ? (
<div className="">
<div className="top_generate">
<p className="modelName">{item.tit}</p>
<div className="playground" style={resCon || loading ? { background: '#270966' } : { backgroundImage: `url(${Stable_Diffusion_XL})` }}>
{
loading ?
(<div className="generating">
<img src={LoadingGif} alt="" />
{countDown > 0 ? <p>ETA: {`${remainingHours.toString().padStart(2, '0')}:${remainingMinutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`}</p> : <p>Accelerating generation...</p>}
</div>)
:
!loading && resTask && resTask.is_success === false ?
<div className="error_text">
{resTask?.api_error && resTask?.api_error.message && <div>
<span>api_error: </span><span>{resTask?.api_error.message}</span>
</div>}
{resTask?.task_error && <div>
<span>task_error: </span><span>{resTask?.task_error}</span>
</div>}
{resTask?.exec_error && <div>
<span>exec_error: </span><span>{resTask?.exec_error}</span>
</div>}
{resTask?.output && <div>
<span>output: </span><span>{resTask?.output}</span>
</div>}
</div>
:
resCon && Array.isArray(resCon) && resCon.length > 1 ? resCon.map((item, index) => {
return (
<img key={index} data-state="closer" loading="lazy" decoding="async" data-nimg="1" className="resImg cursor-pointer z-10 w-auto h-auto max-w-full max-h-full m-5" src={item} />
)
}) : (
resCon
?
<img data-state="closed" loading="lazy" decoding="async" data-nimg="1" className="resImg" src={resCon && resCon} />
:
<div></div>
)
}
</div>
<div className="handles">
<Input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Outer space, universe, movie lightingcinematic" />
<Button onClick={() => optSubmit(item)} >Generate</Button>
</div>
</div>
</div>
) : index === 1 ? (
<div className="">
<div className="top_generate">
<p className="modelName">{item.tit}</p>
<div className="playground" style={{ padding: '0 4.1vw' }}>
{
loading ?
(<div className="generating">
<img src={LoadingGif} alt="" />
{countDown > 0 ? <p>ETA: {`${remainingHours.toString().padStart(2, '0')}:${remainingMinutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`}</p> : <p>Accelerating generation...</p>}
</div>)
:
!loading && resTask && resTask.is_success === false ?
<div className="error_text">
{resTask?.api_error && resTask?.api_error.message && <div>
<span>api_error: </span><span>{resTask?.api_error.message}</span>
</div>}
{resTask?.task_error && <div>
<span>task_error: </span><span>{resTask?.task_error}</span>
</div>}
{resTask?.exec_error && <div>
<span>exec_error: </span><span>{resTask?.exec_error}</span>
</div>}
{resTask?.output && <div>
<span>output: </span><span>{resTask?.output}</span>
</div>}
</div>
:
<div className="textToText">
<div className="sender">Tell Me About 《a Farewell To Arms》</div>
<div className="res_message">
s a youth of 18, ernest hemingway was eager to fight in the great war. poor vision kept him out of the army, so he joined the ambulance corps instead and was sent to france. then he transferred to italy where he became the first american wounded in that country during world war i. hemingway came out of the european battlefields with a medal for valor and a wealth of experience that he would, 10 years later, spin into literary gold with a farewell to arms. this is the story of lieutenant henry, an american, and catherine barkley, a british nurse. the two meet in italy, and almost immediately hemingway sets up the central tension of the novel: the tenuous nature of love in a time of war. during their first encounter, catherine tells henry about her fiancé of eight years who had been killed the year before in the somme. explaining why she hadn't married him, she says she was afraid marriage would be bad for him, then admits: i wanted to do something for him. you see, i didn't care about the other thing and he could have had it all. he could have had anything he wanted if i would have known. i would have married him or anything. i know all about it now. but then he wanted to go to war and i didn't know. the two begin an affair, with henry quite convinced that he "did not love catherine barkley nor had any idea of loving her. this was a game, like bridge, in which you said things instead of playing cards." soon enough, however, the game turns serious for both of them and ultimately henry ends up deserting to be with catherine.
</div>
</div>
}
</div>
<div className="handles">
<Input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Outer space, universe, movie lightingcinematic" />
<Button onClick={() => optSubmit(item)} >Generate</Button>
</div>
</div>
</div>
) : index === 2 ? (
<div className="">
<div className="top_generate">
<p className="modelName">{item.tit}</p>
<div className="playground" style={{ backgroundImage: `url(${Musicgen})` }}>
{
loading ?
(<div className="generating">
<img src={LoadingGif} alt="" />
{countDown > 0 ? <p>ETA: {`${remainingHours.toString().padStart(2, '0')}:${remainingMinutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`}</p> : <p>Accelerating generation...</p>}
</div>)
:
!loading && resTask && resTask.is_success === false ?
<div className="error_text">
{resTask?.api_error && resTask?.api_error.message && <div>
<span>api_error: </span><span>{resTask?.api_error.message}</span>
</div>}
{resTask?.task_error && <div>
<span>task_error: </span><span>{resTask?.task_error}</span>
</div>}
{resTask?.exec_error && <div>
<span>exec_error: </span><span>{resTask?.exec_error}</span>
</div>}
{resTask?.output && <div>
<span>output: </span><span>{resTask?.output}</span>
</div>}
</div>
:
<div className="textToAudio">
<div className="playIcon" onClick={() => setPlay(!play)}>
{!play ? <img className="handleBtn" src={require('../assets/images/home/play-fill.png')} alt="" /> : <img className="handleBtn" src={require('../assets/images/home/pause.png')} alt="" />}
</div>
<div className="processCon">
<div className="times">00'00</div>
{!play ? <div className="process"></div> : <img className="processImg" src={require('../assets/images/home/sound.png')} alt="" />}
<div className="times">01'01</div>
</div>
</div>
}
</div>
<div className="handles">
<Input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Outer space, universe, movie lightingcinematic" />
<Button onClick={() => optSubmit(item)} >Generate</Button>
</div>
</div>
</div>
) : (
<div className="">
<div className="top_generate">
<p className="modelName">{item.tit}</p>
<div className="playground" style={{ backgroundImage: `url(${StyleTTS_2})` }}>
{
loading ?
(<div className="generating">
<img src={LoadingGif} alt="" />
{countDown > 0 ? <p>ETA: {`${remainingHours.toString().padStart(2, '0')}:${remainingMinutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`}</p> : <p>Accelerating generation...</p>}
</div>)
:
!loading && resTask && resTask.is_success === false ?
<div className="error_text">
{resTask?.api_error && resTask?.api_error.message && <div>
<span>api_error: </span><span>{resTask?.api_error.message}</span>
</div>}
{resTask?.task_error && <div>
<span>task_error: </span><span>{resTask?.task_error}</span>
</div>}
{resTask?.exec_error && <div>
<span>exec_error: </span><span>{resTask?.exec_error}</span>
</div>}
{resTask?.output && <div>
<span>output: </span><span>{resTask?.output}</span>
</div>}
</div>
:
<div className="textToAudio">
<div className="playIcon" onClick={() => setPlay(!play)}>
{!play ? <img className="handleBtn" src={require('../assets/images/home/play-fill.png')} alt="" /> : <img className="handleBtn" src={require('../assets/images/home/pause.png')} alt="" />}
</div>
<div className="processCon">
<div className="times">00'00</div>
{!play ? <div className="process"></div> : <img className="processImg" src={require('../assets/images/home/sound.png')} alt="" />}
<div className="times">01'01</div>
</div>
</div>
}
</div>
<div className="handles">
<Input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Outer space, universe, movie lightingcinematic" />
<Button onClick={() => optSubmit(item)} >Generate</Button>
</div>
</div>
</div>
)
}
</div>
)
})
}
</Slider>
</div>
<Link to="/playground" className={`moreModels`}>
<span>{`Explore more models>>`}</span>
</Link>
</section>
<section className="third_page">
<div className="left"></div>
<div className="right">
<div className="top_tit">
<span className="white_text">WHY</span>
<span className="white_text">CHOOSE TO USE AIGIC</span>
</div>
<div className="right_item">
<span className="tit">Always Use AI Open-source Models</span>
<span className="right_item_content">You don't need expensive GPUs and hardware, you can run over 1000 open-source models on AIGIC at any time and copy the code into your own project.</span>
</div>
<div className="right_item item2">
<span className="tit">The Lowest Usage Price.</span>
<span className="right_item_content">AIGIC utilizes the most advanced aggregated AI Computility network, allowing your application to run at the lowest cost and achieve the highest returns.</span>
</div>
<div className="right_item item3">
<span className="tit">Full Encryption To Protect Privacy</span>
<span className="right_item_content">AIGIC uses advanced modeling and data transmission encryption technology to protect user model data and copyright, as well as user privacy and trade secrets.</span>
</div>
<div className="right_item item4">
<span className="tit">Deploy Custom AI Models.</span>
<span className="right_item_content">In addition to the models in the existing model library, you can also deploy your own custom models, which are stored on cloud servers and you only need to pay fees when using them.</span>
</div>
</div>
</section>
<section className="fifth_page">
<div className="fifth_page_tit">
<p>PAY ONLY</p>
<p>WHEN RUNNING CODE</p>
</div>
<div className="fifth_page_con">
<img src={require('../assets/images/home/adminPage.png')} alt="" />
<div className="adminHomeImg"></div>
<span>There is no need to pay any fees for the model and hardware, AIGIC will only calculate traffic and charge when the code is copied into your application project and runs. During use, AIGIC will provide you with a complete traffic monitoring system to help you keep track of your account usage at all times.</span>
<span>At the same time, AIGIC will give a certain amount of computing power to registered users every day, which allows you to complete the testing phase of a small number of users with almost no cost until the project is officially launched and has a large number of users.</span>
<Link to={'/info'}><button>Get Free Computility</button></Link>
</div>
</section>
</div>
<section className="sixth_page">
<div className="sixth_page_tit">
<p>AIGIC is working with AI</p>
<p>developers</p>
<p>Realize countless</p>
<p>imaginations</p>
</div>
<div className="sixth_page_con">
<div className="middle_info">
<Slider {...settings}>
<div className="ava_message" style={{ width: '67.44vw' }}>
<div className="ava_message_top">
<img src={require('../assets/images/home/sixth_ava.png')} alt="" />
<div className="ava_message_top_right">
<p>Rosario</p>
<p>Music software developer</p>
</div>
</div>
<div className="bottom_content">
<span>Now, I can create a plugin in DAW, just write the melody, and AI can help me complete the harmony 🎶 and beat 🥁.</span>
</div>
</div>
<div className="ava_message" style={{ width: '67.44vw' }}>
<div className="ava_message_top">
<img src={require('../assets/images/home/sixth_ava2.png')} alt="" />
<div className="ava_message_top_right">
<p>Liam Heath</p>
<p>Freelancing</p>
</div>
</div>
<div className="bottom_content">
<span>I don't need a GPU, I can work anytime and anywhere with my laptop, and I can find any model I need on AIGIC!!</span>
</div>
</div>
<div className="ava_message" style={{ width: '67.44vw' }}>
<div className="ava_message_top">
<img src={require('../assets/images/home/sixth_ava3.png')} alt="" />
<div className="ava_message_top_right">
<p>Tina LEEEEEEEEE</p>
<p>Vlogger</p>
</div>
</div>
<div className="bottom_content">
<span>Now I can dub my videos in various tones 🎙️🎙️, and it's almost free of charge!🎉</span>
</div>
</div>
</Slider>
</div>
{/* <div className="sixth_p_bottom">
<img src={require('../assets/images/home/sixth_btmIcon.png')} alt="" />
<img src={require('../assets/images/home/sixth_btmIcon2.png')} alt="" />
<img src={require('../assets/images/home/sixth_btmIcon3.png')} alt="" />
</div> */}
</div>
</section>
<footer className="flex flex-row items-center justify-between">
<Link className="footer_logo" to={'/'}><img src={require('../assets/images/home/footer_logo.png')} alt="" /></Link>
<p>{`AIGIC ©️ 2024`}</p>
</footer>
</div>
);
};
export default Home;
\ No newline at end of file
import './styles/info.scss'
import { Link } from 'react-router-dom'
const Info = () => {
return (
<div className="info">
<img src={require('../assets/images/home/info.png')} alt="" />
<p>Please Login With Your Computer To Use Full Functionality</p>
<p className='info_text'>Using your computer to log in to AIGIC, not only can you use the complete functions of all models, copy model codes to your application with just one click, but you can also receive free Computility every day.</p>
<Link to="/playground"><button className="exploreBtn">Explore Other</button></Link>
</div>
)
}
export default Info;
\ No newline at end of file
import { Row, Col, Button, Tabs, Input, Flex, Spin, message } from 'antd'
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import Fetch_ from "../utils/fetch";
import { useLoginContext } from '../context/LoginContext';
import './styles/playground_list.scss'
const PlaygroundList = () => {
const { isLogin, login } = useLoginContext();
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
async function handleCollect(event, type, id) {
event.stopPropagation()
if (!isLogin) {
login((res, error) => {
if (error == null) handleCollect()
})
return
}
type = type === 0 ? 'add' : 'cancel'
try {
const result = await Fetch_(`/admin/api/favorite/${type}`, {
method: "post",
body: JSON.stringify({ task_type_id: Number(id) }),
})
const res = await result.json();
if (res.code === 200) {
message.success(type === 'add' ? 'Collection successful' : 'Cancel collection successful')
fetchData('collect')
}
} catch (error) {
console.log(error)
}
}
async function getData(params, eventIn) {
try {
if(!eventIn) setLoading(true)
const res = await Fetch_('/admin/api/task/models', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ ...params, size: 100 }),
});
const jsonData = await res.json()
return jsonData
} catch (error) {
setLoading(false)
console.log(error)
}
}
async function getCategorys(params) {
const res = await fetch('/admin/api/task/allcategorys', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
const jsonData = await res.json()
return jsonData
}
const [dataArr, setDataArr] = useState([])
const [activeTab, setActiveTab] = useState(0);
const [categorys, setCategorys] = useState([])
const [keyword, setKeyword] = useState('')
const handleTabClick = async (tab) => {
console.log("handleTabClick", tab)
tab = parseInt(tab)
setActiveTab(tab);
const data = await getData({ keyword: keyword, category: tab });
setDataArr(data.data.data)
setLoading(false)
};
const handleSearch = async () => {
const data = await getData({ keyword });
setDataArr(data.data.data)
setLoading(false)
}
const goPlayground = (item) => {
navigate(`/info`)
}
async function fetchData(eventIn) {
const data = await getData({}, eventIn)
if (data && data.data && data.data.data) {
setDataArr(data.data.data)
setLoading(false)
const categoryData = await getCategorys()
if (categoryData && categoryData.data && categoryData.data.length) {
let categorys = categoryData.data.map(item => {
item.key = item.id + ""
item.label = item.en_desc
return item
})
categorys.unshift({
key: "0",
label: "All",
id: 0,
desc: "All",
en_desc: "All",
sort: 0,
})
setCategorys(categorys)
}
}
}
useEffect(() => {
fetchData()
}, [])
return (
<div className="playground_list">
<div className="list_content">
<div className="search">
<Input allowClear onChange={e => setKeyword(e.target.value)} placeholder="Search" prefix={<img style={{ height: '4.1vw', width: '4.1vw' }} src={require('../assets/images/playground/search.png')} />} />
<button onClick={()=> handleSearch()}>Search</button>
{/* <Button icon={<img src={require('../assets/images/playground/collect_filter.png')} />}> default collation</Button> */}
</div>
<div className="list">
{loading ? <Spin size='large' spinning={loading} />
: !dataArr || dataArr.length <= 0 && !loading ? (
<div className="no_data">
<img src={require('../assets/images/playground/no_data.png')} alt="" />
<span>You haven't collected the model yet</span>
</div>
) : (
<Flex wrap="wrap" className="list_items">
{
dataArr && dataArr.length > 0 && dataArr.map((item, index) => {
return (
<div key={index} className="item" onClick={() => goPlayground(item)}>
<div className="item_top">
{/* 2 4 7 11 text */}
<div className="tags">
{
item.type === 1 || item.type === 6 || item.type === 8 ?
<img className='typeIcon' src={require('../assets/images/playground/type_img.png')} alt="" />
: item.type === 2 || item.type === 4 || item.type === 7 || item.type === 11 ?
<img className='typeIcon' src={require('../assets/images/playground/type_chat.png')} alt="" />
: item.type === 3 || item.type === 5 || item.type === 9 ?
<img className='typeIcon' src={require('../assets/images/playground/type_mv.png')} alt="" />
: item.type === 10 ?
<img className='typeIcon' src={require('../assets/images/playground/type_video.png')} alt="" />
: <img className='typeIcon' src={require('../assets/images/playground/type_img.png')} alt="" />
}
{item.tags && item.tags.map((tag, index) => {
return (
<span key={index} className="tag">
{tag}
</span>
)
})}
</div>
</div>
<div className="item_con">
<span className='name'>{item.tit}</span>
<span className='desc'>{item.content}</span>
</div>
</div>
)
})
}
</Flex>
)}
</div>
</div>
</div>
)
}
export default PlaygroundList
\ No newline at end of file
import { useEffect } from "react";
const ReceiveMessage = () => {
const handleMessage = (event) => {
const data = event.data;
if (data.token) localStorage.setItem('token', data.token)
// 验证消息来源
if (event.origin !== window.location.origin) {
console.log('(Web)Received message from invalid origin:', event.origin, window.location.origin);
return;
}
// 处理收到的消息
console.log('(Web)Received message:', event.data);
};
useEffect(()=> {
window.addEventListener('message', handleMessage);
}, [])
return <div></div>
}
export default ReceiveMessage;
\ No newline at end of file
import { useState ,useEffect} from "react";
import { Space, Switch, Table } from 'antd';
import { far } from "react-syntax-highlighter/dist/esm/styles/hljs";
const Playground_API = ({data}) => {
const [currentNav, setCurrentNav] = useState(1);
const headercolumns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Value',
dataIndex: 'value',
// width: '40%',
},
{
title: 'Required',
dataIndex: 'required_show',
// width: '30%',
},
{
title: 'Required',
dataIndex: 'required',
hideInTable:true,
// width: '30%',
},
{
title: 'Example',
dataIndex: 'example',
// width: '30%',
},
{
title: 'Remark',
dataIndex: 'remark',
// width: '30%',
}
];
const columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Type',
dataIndex: 'type',
// width: '40%',
},
{
title: 'Required',
dataIndex: 'required',
// width: '30%',
},
{
title: 'Default',
dataIndex: 'default',
// width: '30%',
},
{
title: 'Remark',
dataIndex: 'remark',
// width: '30%',
},
{
title: 'Other',
dataIndex: 'other',
// width: '30%',
},
];
const testdata = [
{
key: 1,
name: 'John Brown sr.',
age: 60,
address: 'New York No. 1 Lake Park',
children: [
{
key: 11,
name: 'John Brown',
age: 42,
address: 'New York No. 2 Lake Park',
},
{
key: 12,
name: 'John Brown jr.',
age: 30,
address: 'New York No. 3 Lake Park',
children: [
{
key: 121,
name: 'Jimmy Brown',
age: 16,
address: 'New York No. 3 Lake Park',
},
],
},
{
key: 13,
name: 'Jim Green sr.',
age: 72,
address: 'London No. 1 Lake Park',
children: [
{
key: 131,
name: 'Jim Green',
age: 42,
address: 'London No. 2 Lake Park',
children: [
{
key: 1311,
name: 'Jim Green jr.',
age: 25,
address: 'London No. 3 Lake Park',
},
{
key: 1312,
name: 'Jimmy Green sr.',
age: 18,
address: 'London No. 4 Lake Park',
},
],
},
],
},
],
},
{
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sydney No. 1 Lake Park',
},
];
const [headers, setHeaders] = useState([]);
const [body, setBody] = useState([]);
const [response, setResponse] = useState([]);
const [errorCode, setErrorCode] = useState([]);
const [interfaceData, setInterfaceData] = useState({});
const [apiPtah, setApiPtah] = useState('');
const [basePath, setBasePath] = useState('');
useEffect(() => {
init()
}, []);
async function init() {
if (typeof data == 'string') {
data = JSON.parse(data)
}
console.log("Playground_API",data)
setBasePath(data.info.basePath)
let paths = data && data.paths ? Object.keys(data.paths) : []
let interfaceData = null
console.log("Playground_API paths",paths)
if (paths && paths.length) {
paths.map((item) => {
interfaceData = data.paths[item].post
if (interfaceData && interfaceData.summary && interfaceData.summary === 'Predict') {
setApiPtah(item)
setInterfaceData(interfaceData)
return false
}
})
}
if (interfaceData && interfaceData.parameters && interfaceData.parameters.length) {
let content_types = []
if (interfaceData && interfaceData.requestBody && interfaceData.requestBody.content) {
content_types = Object.keys(interfaceData.requestBody.content)
}
let headsers = []
content_types.map((item) => {
let header = {
name:"Content-Type",
required:true,
required_show:"Yes",
value:item,
example:item.example,
remark:item.remark,
}
headsers.push(header)
})
interfaceData.parameters.map((item) => {
if (item.in === 'header') {
let header = {
name:item.name,
required:item.required,
required_show: item.required ? "Yes" : "No",
value:item.value,
example:item.example,
remark:item.remark,
}
headsers.push(header)
}
})
setHeaders(headsers)
}
if (interfaceData && interfaceData.requestBody && interfaceData.requestBody.content) {
let content_types = []
if (interfaceData && interfaceData.requestBody && interfaceData.requestBody.content) {
content_types = Object.keys(interfaceData.requestBody.content)
}
let content = null
if (content_types && content_types.length) {
content = interfaceData.requestBody.content[content_types[0]]
}
let request = null
if (content) {
let ref = content.schema['$ref']
request = data['components.schemas.PredictionRequest']
}
console.log("init",request)
let bodys = []
// interfaceData.parameters.map((item) => {
// if (item.in === 'header') {
// let header = {
// name:item.name,
// required:item.required,
// required_show: item.required ? "Yes" : "No",
// value:item.value,
// example:item.example,
// remark:item.remark,
// }
// headsers.push(header)
// }
// })
// setHeaders(headsers)
}
}
return (
<div className="built_content">
<div className="api_content">
<div className="leftNav">
<ul>
<li className={`${currentNav === 1 && 'li_active'}`} onClick={() => setCurrentNav(1)}><a href="#Basic">Basic Information</a></li>
<li className={`${currentNav === 2 && 'li_active'}`} onClick={() => setCurrentNav(2)}><a href="#Headers">Headers</a></li>
<li className={`${currentNav === 3 && 'li_active'}`} onClick={() => setCurrentNav(3)}><a href="#Body">Body</a></li>
<li className={`${currentNav === 4 && 'li_active'}`} onClick={() => setCurrentNav(4)}><a href="#Response">Response</a></li>
<li className={`${currentNav === 5 && 'li_active'}`} onClick={() => setCurrentNav(5)}><a href="#ErrorCode">ErrorCode</a></li>
</ul>
</div>
<div className="rightContent">
<p className="module_tit" id="Basic">Basic Information</p>
<div className="info">
<div className="info_item">
<p className="item_label">Interface Name:</p>
<p className="item_con">{interfaceData.summary}</p>
</div>
<div className="info_item">
<p className="item_label">Interface Path:</p>
<p className="item_con">{`${basePath}${apiPtah}`}</p>
</div>
<div className="info_item">
<p className="item_label">Multiline Text Title:</p>
<p className="item_con">{interfaceData.description}</p>
{/* <p className="item_con">The following examples all expect your Replicate access token to be available from the command line. Because tokens are secrets, they should not be in your code. They should instead be stored in environment variables. Replicate clients look for the REPLICATE_API_TOKEN environment variable and use it if available.</p> */}
</div>
</div>
<p className="module_tit" id="Headers">Headers</p>
<div className="info">
<div className="info_item">
<p className="item_label">Multiline Text Title:</p>
<Table
className="item_table"
columns={headercolumns}
rowSelection={false}
dataSource={headers}
pagination={false}
bordered={false}
/>
</div>
</div>
<p className="module_tit" id="Body">Body</p>
<div className="info">
<div className="info_item">
<p className="item_label">Multiline Text Title:</p>
<Table
className="item_table"
columns={columns}
rowSelection={false}
dataSource={testdata}
pagination={false}
bordered={false}
/>
</div>
</div>
<p className="module_tit" id="Response">Response</p>
<div className="info">
<div className="info_item">
<p className="item_label">Multiline Text Title:</p>
<Table
className="item_table"
columns={columns}
rowSelection={false}
dataSource={testdata}
pagination={false}
bordered={false}
/>
</div>
</div>
<p className="module_tit" id="ErrorCode">ErrorCode</p>
<div className="info">
<div className="info_item">
<p className="item_label">Multiline Text Title:</p>
<Table
className="item_table"
columns={columns}
rowSelection={false}
dataSource={testdata}
pagination={false}
bordered={false}
/>
</div>
</div>
</div>
</div>
</div>
)
}
export default Playground_API;
\ No newline at end of file
import { useState, useEffect } from "react";
import { Timeline } from 'antd';
import '../styles/playground_version.scss'
import moment from 'moment'
const Playground_Version = ({ data }) => {
const [versions, setVersions] = useState([]);
useEffect(() => {
init()
}, [data]);
function compareVersion(v1, v2) {
// 将版本号字符串按 "." 分割为数组
const v1Parts = v1.split(".");
const v2Parts = v2.split(".");
// 比较每个部分的数字大小
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const num1 = parseInt(v1Parts[i] || 0);
const num2 = parseInt(v2Parts[i] || 0);
if (num1 < num2) {
return 1;
} else if (num1 > num2) {
return -1;
}
}
// 版本号相同
return 0;
}
async function init() {
console.log("init", data);
let keys = Object.keys(data);
keys = keys.sort((a, b) => compareVersion(a, b));
let versions = []
console.log("init keys", keys)
keys.map((key, index) => {
let version = data[key]
console.log("init version", version)
let created_time = (version && version.length) ? version[0].created_time : ''
created_time = moment(created_time).format("YYYY-MM-DD HH:mm:ss")
let version_show = {
label: created_time
}
let version_code = <p><span style={{ marginRight: '10px', fontWeight: 'bold' }}>Version:</span> {key}</p>
let hashArr = version.map(item => {
return <p key={item.os + index}><span style={{ marginRight: '10px', fontWeight: 'bold' }}>{item.os}:</span>{item.hash}</p>
})
// let descArr = version.map((item, index) => {
// return item.desc ? <p key={item.desc+index}>{item.desc}</p> : null
// })
let Desc = <>
<p>
<span style={{ marginRight: '10px', fontWeight: 'bold' }}>Change log:</span>
{
version && version.length > 0 && version.map((item, index) => {
return item.desc ? <p key={item.desc + index}>{item.desc}</p> : null
})
}
</p>
</>
version_show.children = [version_code, ...hashArr, Desc]
versions.push(version_show)
})
setVersions(versions)
console.log("init versions", versions)
}
return (
<div className="built_content">
<div className="version_content">
<div className="version_timeline">
<Timeline
mode={'left'}
items={versions}
/>
</div>
</div>
</div>
)
}
export default Playground_Version;
\ No newline at end of file
.home {
&>section {
display: flex;
}
.large_bg {
height: 100%;
background: radial-gradient(circle at 50% 50%, #22075E 0%, #000000 100%);
&>section {
display: flex;
}
}
.first_page {
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
.banner_text {
padding: 0 6.15vw;
font-size: 5.13vw;
font-family: SourceHanSansSC-Heavy;
font-weight: 800;
text-align: center;
color: #fff;
line-height: 8.21vw;
text-shadow: 0px 6px 16px rgba(0, 0, 0, 0.28);
margin-top: 6.15vw;
margin-bottom: 4.1vw;
p:last-child {
background: linear-gradient(to right, #9254DE 0%, #EB8E71 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-fill-color: transparent;
}
}
.banner_text_des {
padding: 0 6.15vw;
font-size: 2.05vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: center;
color: #FFFFFF;
line-height: 4.1vw;
}
.start_btn {
height: 6.15vw;
background: linear-gradient(180deg, #D3ADF7 0%, #722ED1 100%);
box-shadow: 0px 2.05vw 4.1vw .26vw rgba(34, 7, 94, 0.32);
border-radius: 26.04vw;
border: .26vw solid #722ED1;
font-size: 2.56vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #ffffff;
cursor: pointer;
margin-top: 6.15vw;
display: flex;
justify-content: center;
align-items: center;
padding: 1.03vw 4.1vw;
}
.cloudIcon {
position: absolute;
z-index: 10;
}
.cloud1 {
left: 0;
top: 8.21vw;
height: 9.23vw;
width: 9.23vw;
}
.cloud2 {
right: -2.05vw;
top: 17.4vw;
height: 11.28vw;
width: 12.82vw;
}
.cloud3 {
right: 19.49vw;
top: 2.56vw;
width: 3.59vw;
height: 2.56vw;
}
}
.second_page {
width: 100%;
margin-top: 10.26vw;
position: relative;
flex-direction: column;
.top_generate {
height: 66.67vw;
width: 60.51vw;
opacity: .8;
transition: .6s;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
border: .26vw solid #fff;
border-radius: .83vw;
padding: 4.1vw 0;
padding-bottom: 6.15vw;
box-shadow: 2.05vw 2.05vw 4.1vw .26vw rgba(34, 7, 94, 0.32);
margin: 0 6.41vw;
background-color: #000000;
.modelName {
width: 100%;
font-size: 2.56vw;
color: #fff;
text-align: left;
margin-bottom: 4.1vw;
padding: 0 4.1vw;
}
.playground {
width: 100%;
height: 42.05vw;
overflow: hidden;
z-index: 11;
position: relative;
background-size: 100% 100%;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.resImg {
height: 22.14vw;
width: 39.38vw;
margin-bottom: 1.67vw;
}
.generating {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
margin-top: 2.08vw;
width: 18.04vw;
height: 18.04vw;
}
p {
font-size: 2.56vw;
font-weight: 800;
text-align: center;
color: #ffffff;
}
}
.error_text {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
justify-content: center;
align-items: center;
font-size: 2.56vw;
&>div>span:first-child {
font-weight: bold;
font-size: 2.82vw;
}
}
.textToText {
width: 100%;
height: 100%;
overflow: scroll;
border-radius: 6px;
.sender {
width: 100%;
height: auto;
background: #531dab;
border-radius: .77vw;
padding: 1.03vw 2.05vw;
font-size: 2.56vw;
line-height: 4.1vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #bfbfbf;
margin-bottom: 4.1vw;
}
.res_message {
width: 100%;
height: auto;
background: #9254de;
border-radius: 6px;
padding: 1.03vw 2.05vw;
font-size: 2.56vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #bfbfbf;
line-height: 4.1vw;
}
}
.textToAudio {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
width: 100%;
height: 100%;
.playIcon {
.handleBtn {
height: 8.21vw;
width: 8.21vw;
margin: 0;
margin-top: 2.56vw;
}
}
.processCon {
height: 12.82vw;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
.process {
width: 45.13vw;
height: .26vw;
background: #ffffff;
margin: 0 2.05vw;
}
.processImg {
height: 100%;
width: 45.13vw;
margin: 0 2.05vw;
}
.times {
font-size: 2.05vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #ffffff;
}
}
}
}
.handles {
position: relative;
z-index: 11;
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 0 4.1vw;
.ant-input {
width: 100%;
height: 6.15vw;
border-radius: 64.1vw;
border: none;
padding: 1.03vw 2.05vw;
font-size: 2.56vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #22075e;
margin-bottom: 4.1vw;
margin-top: 6.15vw;
border: .26vw solid #722ED1;
}
.ant-input::placeholder {
color: #22075e;
}
.ant-input-affix-wrapper {
padding: .42vw .83vw;
font-size: .83vw;
color: #000000;
height: 3.33vw;
border-radius: 1.72vw;
}
.ant-btn {
height: 6.15vw;
background: #722ED1;
border: .26vw solid #722ED1;
border-radius: 64.1vw;
padding: 1.03vw 4.1vw;
display: flex;
justify-content: center;
align-items: center;
font-size: 2.56vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #fff;
}
}
}
.slider-container{
min-height: 83.08vw;
}
.slick-slide, .modes_item, .modes_item .modes_item_active{
outline: none;
user-select: none;
}
.slick-track{
display: flex;
align-items: center;
}
.slick-center {
.top_generate {
height: 83.08vw;
width: 75.38vw;
opacity: 1;
margin: 0;
}
}
.moreModels {
font-size: 2.56vw;
font-family: SourceHanSansSC-Bold;
font-weight: 500;
margin: 0 auto;
color: #FFFFFF;
position: relative;
text-decoration-line: underline;
margin-top: 4.1vw;
}
}
.third_page {
padding-top: 6.15vw;
display: flex;
flex-direction: row;
position: relative;
.left {
position: absolute;
left: -48.21vw;
height: 112.31vw;
width: 99.49vw;
z-index: 9;
background-image: url('../../assets/images/home/third_left_bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.right {
position: relative;
z-index: 10;
width: 100%;
padding: 6.15vw;
.top_tit {
display: flex;
flex-direction: column;
height: 17.5vw;
line-height: 8.21vw;
margin-bottom: 6.15vw;
.white_text {
font-size: 5.13vw;
font-family: SourceHanSansSC-Heavy;
font-weight: 800;
text-align: left;
color: #fff;
text-shadow:
-1px -1px 0 black,
1px -1px 0 black,
-1px 1px 0 black,
1px 1px 0 black;
}
}
.right_item {
height: 27.69vw;
width: 100%;
background: url('../../assets/images/home/third_text_bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 4.1vw;
margin-bottom: 6.15vw;
border-radius: .42vw;
box-shadow: 2.05vw 2.05vw 4.1vw .26vw rgba(34, 7, 94, 0.32);
.tit {
font-size: 3.08vw;
font-family: SourceHanSansSC-Bold;
font-weight: bold;
text-align: left;
color: #ffffff;
}
.right_item_content {
font-size: 2.56vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
text-align: left;
color: #ffffff;
line-height: 4.1vw;
}
}
.item2 {
background: url('../../assets/images/home/third_text_bg2.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.item3 {
background: url('../../assets/images/home/third_text_bg3.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.item4 {
background: url('../../assets/images/home/third_text_bg4.png');
background-repeat: no-repeat;
background-size: 100% 100%;
margin-bottom: 0;
}
}
}
.fifth_page {
margin-top: 4.1vw;
height: 162.95vw;
flex-direction: column;
padding: 6.15vw;
background-image: url('../../assets/images/home/fifth_bg.png');
background-size: 100% 100%;
position: relative;
.fifth_page_tit {
font-size: 5.13vw;
line-height: 8.21vw;
font-family: SourceHanSansSC-Heavy;
font-weight: 800;
text-align: left;
color: #ffffff;
text-align: left;
}
.fifth_page_con {
display: flex;
flex-direction: column;
align-items: flex-start;
img {
position: absolute;
top: 26.67vw;
left: 6.15vw;
height: 60vw;
width: 106.67vw;
max-width: 106.67vw;
box-shadow: 2.05vw 2.05vw 4.1vw 2px rgba(34, 7, 94, 0.32);
border-radius: 1.03vw;
}
.adminHomeImg {
height: 60vw;
width: 100%;
margin-top: 4.1vw;
}
&>span {
font-size: 2.56vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
text-align: left;
color: #ffffff;
line-height: 4.1vw;
margin-top: 6.15vw;
}
button {
height: 6.15vw;
background: #ffffff;
border: .26vw solid #722ED1;
border-radius: 64.1vw;
background: linear-gradient(180deg, #FFFFFF 0%, #D3ADF7 100%);
box-shadow: 0px 16px 32px 2px rgba(34, 7, 94, 0.32);
padding: 1.03vw 4.1vw;
display: flex;
justify-content: center;
align-items: center;
font-size: 2.56vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #722ED1;
margin-top: 5.73vw;
}
}
}
.sixth_page {
flex-direction: column;
justify-content: center;
padding: 6.15vw;
padding-bottom: 10.26vw;
padding-right: 0;
background: linear-gradient(180deg, #000000 0%, #22075E 100%);
.sixth_page_tit {
font-size: 5.13vw;
line-height: 8.21vw;
font-family: SourceHanSansSC-Heavy;
font-weight: 800;
text-align: left;
color: #FFFFFF;
text-transform: uppercase;
}
.sixth_page_con {
display: flex;
flex-direction: column;
margin-top: 3.65vw;
.middle_info {
width: 100%;
position: relative;
.slick-initialized .slick-slide {
margin-right: 6.15vw !important;
}
.middle_info_img {
height: 25.31vw;
width: 100%;
border-radius: .42vw;
}
.ava_message {
height: 22.56vw;
width: 67.44vw;
margin-right: 6.15vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #fff;
background: #FFFFFF;
box-shadow: 8px 8px 16px 1px rgba(34, 7, 94, 0.32);
border-radius: 8px 8px 8px 8px;
padding: 2.56vw;
padding-right: 2.82vw;
.ava_message_top {
display: flex;
flex-direction: row;
img {
height: 3.33vw;
width: 3.33vw;
margin-right: .83vw;
}
.ava_message_top_right {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
p:first-child {
font-family: SourceHanSansSC-Bold;
font-size: 2.05vw;
color: #000000;
}
p:last-child {
font-family: SourceHanSansSC-Regular;
font-weight: 400;
font-size: 1.54vw;
color: #531DAB;
}
}
}
.bottom_content {
font-family: SourceHanSansSC-Regular;
font-weight: 400;
font-size: 2.05vw;
color: #000000;
line-height: 4.1vw;
text-align: left;
}
}
}
.sixth_p_bottom {
width: 100%;
padding: 10.77vw 6.15vw 13.33vw;
display: flex;
justify-content: space-around;
img {
width: 23.59vw;
height: 7.18vw;
}
img:nth-child(2) {
margin: 0 5.51vw;
width: 23.08vw;
}
img:nth-child(3) {
width: 24.62vw;
height: 6.15vw;
}
}
}
}
footer {
width: 100%;
height: 10.26vw;
background: linear-gradient(180deg, #531DAB 0%, #9254DE 100%);
padding: 2.56vw 6.15vw;
display: flex;
flex-direction: row;
justify-content: flex-start;
img {
width: 15.38vw;
height: 5.13vw;
margin-right: 4.1vw;
}
p {
font-family: SourceHanSansSC-Bold;
font-size: 2.05vw;
color: #FFFFFF;
}
}
// footer {
// width: 100%;
// height: 31.67vw;
// background-image: url('../../assets/images/home/footer_bg.png');
// background-size: 100% 100%;
// padding: 4.38vw 3.33vw;
// .footer_container {
// display: flex;
// flex-direction: row;
// .footer_left {
// display: flex;
// text-align: left;
// flex-direction: column;
// margin-right: 5vw;
// .footer_logo {
// height: 3.23vw;
// width: 9.06vw;
// margin-bottom: 1.77vw;
// }
// span {
// width: 21.67vw;
// height: 5vw;
// font-size: 1.25vw;
// font-family: SourceHanSansSC-Medium;
// font-weight: 500;
// text-align: left;
// color: #ffffff;
// line-height: 2.4vw;
// text-shadow: 0px 6px 16px rgba(0, 0, 0, 0.28);
// }
// }
// .footer_right {
// display: flex;
// flex-direction: row;
// .links {
// text-align: left;
// margin-right: 1.67vw;
// .links_top {
// margin-bottom: 1.51vw;
// span {
// font-size: 1.25vw;
// font-family: SourceHanSansSC-Heavy;
// font-weight: 800;
// color: #b37feb;
// }
// .line {
// width: 16.67vw;
// height: .83vw;
// border-radius: 2px;
// margin-top: .42vw;
// img {
// height: 100%;
// width: 100%;
// }
// }
// }
// nav {
// ul {
// li {
// margin-bottom: 1.09vw;
// font-size: 1.25vw;
// font-family: SourceHanSansSC-Medium;
// font-weight: 500;
// text-align: left;
// color: #ffffff;
// }
// li a:hover {
// color: #b37feb;
// }
// }
// }
// }
// }
// }
// }
}
\ No newline at end of file
.info {
height: calc(100vh - 14.36vw);
width: 100%;
background-color: #22075E;
display: flex;
flex-direction: column;
align-items: center;
padding: 10.26vw;
// justify-content: center;
img {
width: 62.05vw;
height: 49.23vw;
margin-bottom: 8.21vw;
}
p {
font-size: 4.1vw;
line-height: 6.67vw;
color: #fff;
text-align: left;
font-family: SourceHanSansSC-Bold;
}
.info_text {
font-size: 2.56vw;
font-family: SourceHanSansSC-Regular;
line-height: 5.13vw;
margin-top: 6.15vw;
}
.exploreBtn {
height: 6.15vw;
width: 34.87vw;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
margin-top: 6.15vw;
background-color: #722ED1;
border-radius: 64.1vw;
font-size: 2.56vw;
font-weight: 500;
background: linear-gradient(180deg, #D3ADF7 0%, #722ED1 100%);
box-shadow: 0px 2.05vw 4.1vw .26vw rgba(34, 7, 94, 0.32);
border-radius: 64.1vw;
border: .26vw solid #722ED1;
}
}
\ No newline at end of file
.playground_built {
min-height: calc(100vh - 5vw);
background-color: #22075E;
.built_top {
background-color: #130337;
padding: 0 3.33vw;
padding-top: .83vw;
.built_top_left {
display: flex;
flex-direction: column;
align-items: flex-start;
.model_name {
font-size: 1.25vw;
font-family: SourceHanSansSC-Bold;
font-weight: bold;
color: #FFFFFF;
}
.tags {
margin-top: .83vw;
.tag {
display: inline-flex;
align-items: center;
justify-content: center;
background: #391085;
border-radius: 2px;
padding: .21vw;
font-size: 12px;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
color: #FFFFFF;
margin-right: .42vw;
}
}
}
.built_top_right {
height: 100%;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
.collect {
height: 2.08vw;
width: 2.08vw;
border: 1px solid #722ED1;
background-color: #fff;
border-radius: 50%;
margin-right: 1.25vw;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
img {
height: 1.25vw;
width: 1.25vw;
}
}
.ant-select {
height: 2.08vw !important;
width: 11.19vw;
margin-right: 1.25vw;
}
.ant-select-single .ant-select-selector {
font-size: .83vw;
padding: 0;
font-family: SourceHanSansSC-Medium;
}
.ant-select .ant-select-selection-item {
font-weight: 500;
flex-grow: 0.8,
}
.ant-select .ant-select-arrow {
inset-inline-end: 1.04vw;
font-size: .73vw;
}
.ant-select-single.ant-select-show-arrow .ant-select-selection-item,
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
padding-inline: .94vw;
text-align: left;
}
button {
width: auto;
height: 2.08vw;
font-size: .83vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
border-radius: 1.67vw;
background-color: #fff;
color: #722ED1;
padding: 0 .94vw;
}
}
.tabs {
margin-top: 1.67vw;
.ant-tabs-top>.ant-tabs-nav::before,
.ant-tabs-bottom>.ant-tabs-nav::before,
.ant-tabs-top>div>.ant-tabs-nav::before,
.ant-tabs-bottom>div>.ant-tabs-nav::before {
display: none !important;
}
.ant-tabs-top>.ant-tabs-nav {
margin: 0;
}
.ant-tabs .ant-tabs-tab {
font-size: 1.04vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
padding: .21vw 0 .31vw;
color: #FFFFFF;
}
.ant-tabs .ant-tabs-tab:hover{
color: #722ED1;
}
.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
color: #FFFFFF;
}
.ant-tabs .ant-tabs-ink-bar {
background-color: #fff;
}
}
}
.built_content {
display: flex;
flex-direction: row;
padding: 1.67vw;
background-color: #22075E;
.con_left_form {
width: 23.33vw;
background-color: #130337;
position: relative;
.form_top_con {
height: 31.67vw;
padding: .83vw 1.25vw;
padding-bottom: 3.65vw;
overflow-y: scroll;
.ant-form-item .ant-form-item-label>label {
font-size: .83vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #FFFFFF;
}
.ant-input {
border-radius: 2px;
height: 2.19vw;
}
.ant-form-item-control-input-content textarea {
height: auto;
}
.ant-select {
height: 2.19vw;
}
.ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer):hover .ant-select-selector,
.ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector,
.ant-input-outlined {
border: none;
background: #22075E;
}
.ant-select .ant-select-selection-item {
text-align: left;
}
.ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector,
.ant-input-affix-wrapper {
border-radius: 2px;
}
.ant-select-single .ant-select-selector {
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
}
.ant-select .ant-select-selection-item {
font-weight: 400;
}
.ant-select-single.ant-select-show-arrow .ant-select-selection-item,
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
padding-inline: .42vw;
text-align: left;
}
.ant-select-focused .ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer) .ant-select-selector {
box-shadow: none;
}
.ant-select-single .ant-select-selector,
.ant-select .ant-select-arrow {
color: #fff;
outline: none;
}
.ant-input {
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
color: #FFFFFF;
}
.ant-input-number {
height: 2.19vw;
width: 4.48vw;
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
color: #FFFFFF;
}
.ant-col-6 {
text-align: left;
}
.ant-input-number-outlined {
border: none;
background: #22075E;
color: #FFFFFF;
}
.ant-input-number .ant-input-number-input {
line-height: 2.19vw;
padding-block: 0;
color: #FFFFFF;
}
.ant-upload-wrapper .ant-upload-drag {
border: none;
background-color: #22075E;
}
.ant-upload-wrapper .ant-upload-list .ant-upload-list-item .ant-upload-icon .anticon {
color: #FFFFFF;
}
.ant-upload-list-item{
color: #FFFFFF;
}
.ant-upload-list-item a:hover{
color: #722ed1;
}
.ant-upload-wrapper .ant-upload-drag .ant-upload-drag-container {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.ant-upload-wrapper .ant-upload-drag p.ant-upload-drag-icon {
margin: 0;
margin-right: .42vw;
}
.ant-upload-wrapper .ant-upload-drag p.ant-upload-drag-icon .anticon {
font-size: .94vw;
}
.ant-upload-wrapper .ant-upload-drag p.ant-upload-text {
font-size: .83vw;
color: #FFFFFF;
}
.ant-slider .ant-slider-rail {
background-color: #D3ADF7;
border: 1px solid #722ed1;
height: .42vw;
border-radius: .26vw;
}
.ant-slider .ant-slider-track {
background-color: #722ED1;
border-radius: .26vw;
height: .42vw;
}
.ant-slider-horizontal .ant-slider-step {
height: .42vw;
}
.ant-slider .ant-slider-handle::after {
box-shadow: 0 0 0 2px #722ED1;
}
.ant-slider-horizontal .ant-slider-handle {
inset-block-start: .16vw;
}
.ant-checkbox .ant-checkbox-inner {
height: .83vw;
width: .83vw;
}
.ant-checkbox-wrapper {
font-family: SourceHanSansSC-Regular;
font-size: .83vw;
color: #FFFFFF;
}
.form_bottom_btn {
position: absolute;
bottom: 0;
left: 0;
padding: .78vw 1.25vw;
width: 100%;
z-index: 10;
background: #130337;
box-shadow: 0px -6px 16px 1px rgba(239,219,255,0.08);
display: flex;
justify-content: flex-end;
.ant-btn {
margin-left: 1.25vw;
min-width: 3.96vw;
height: 2.08vw;
border-radius: 1.67vw;
font-size: .83vw;
font-family: SourceHanSansSC-Bold;
background-color: #fff;
color: #722ED1;
}
.ant-btn-primary {
width: 7.71vw;
height: 2.08vw;
background-color: #722ED1;
color: #fff;
}
}
}
}
.con_right_result {
margin-left: 1.67vw;
background-color: #130337;
padding: 1.67vw;
display: flex;
flex-direction: row;
flex-wrap: wrap;
.result_con_box {
height: 33.13vw;
width: 36.46vw;
padding: .83vw;
background: url('../../assets/images/playground/res_bg.png');
background-repeat: no-repeat;
background-size: cover;
overflow: scroll;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
.download {
position: absolute;
top: .83vw;
right: .83vw;
height: 1.88vw;
width: 1.88vw;
background: #722ed1;
border-radius: 50%;
box-shadow: 8px 8px 16px 0px #22075e;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
img {
height: 1.04vw;
width: 1.04vw;
}
}
.generating {
img {
width: 18.04vw;
height: 18.04vw;
}
p {
font-size: 1.25vw;
font-weight: 800;
text-align: center;
color: #ffffff;
}
}
.error_text {
font-size: 1.15vw;
}
.textToText {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
padding-bottom: .52vw;
overflow: scroll;
border-radius: 6px;
.sender {
width: 100%;
min-height: 2.5vw;
background: #531dab;
border-radius: 6px;
padding: .52vw .83vw .68vw;
font-size: 1.04vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #bfbfbf;
margin-bottom: .73vw;
}
.res_message {
width: 100%;
height: auto;
margin-bottom: .73vw;
background: #9254de;
border-radius: 6px;
padding: .52vw .83vw .68vw;
font-size: 1.04vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #bfbfbf;
line-height: 1.88vw;
}
}
.imgToText {
height: 100%;
width: 100%;
}
.textToMedia {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
width: 100%;
height: 100%;
audio {
width: 100%;
/* 设置播放器宽度为100% */
background-color: transparent;
}
.playIcon {
.handleBtn {
height: 2.08vw;
width: 2.08vw;
margin: 0;
}
}
.process {
width: 22.71vw;
position: relative;
.process_null{
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: .21vw;
background: #ffffff;
}
}
.times {
font-size: 1.04vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-align: left;
color: #ffffff;
}
}
.textToVideo {
width: 100%;
height: 19.58vw;
border: none;
.video-react {
padding: 0 !important;
height: 100%;
width: 100%;
background-color: transparent;
.video-react-big-play-button {
height: 1.98vw;
width: 1.98vw;
background-color: #fff;
line-height: 1.98vw;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
color: #000;
}
.video-react-control-bar {
bottom: -1.82vw;
background-color: rgba(8, 8, 8, 0.5);
border-radius: .78vw;
align-items: center;
}
.video-react-slider {
background-color: #e5e7eb;
}
.video-react-time-control {
display: flex;
align-items: center;
line-height: normal;
font-size: .73vw;
}
}
video {
height: 100%;
width: 100%;
outline: none;
}
}
.resImg {
max-height: 100%;
max-width: 100%;
}
.more_img {
height: 100%;
width: 100%;
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: center;
gap: 1.04vw;
overflow: scroll;
.more_img_large {
height: 24.38vw;
max-width: 100%;
display: flex;
justify-content: center;
align-items: center;
.img_large {
max-height: 24.38vw;
max-width: 100%;
}
}
.more_img_item {
width: 100%;
overflow: scroll;
display: flex;
flex-direction: row;
justify-content: space-around;
gap: .83vw;
margin: 0 2.6vw;
img {
height: 5.21vw;
width: 5.21vw;
max-height: 5.21vw;
max-width: 5.21vw;
border-radius: 2px;
cursor: pointer;
// transform-origin: left top;
transition: transform 0.3s ease;
}
img:hover {
transform: scale(1.1);
}
}
}
}
.result_apiKeyOrCodes {
display: flex;
flex-direction: column;
width: 29.79vw;
margin-left: 1.25vw;
.itemLabel {
font-size: .83vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #fff;
display: flex;
flex-direction: row;
justify-content: space-between;
img {
height: 1.25vw;
width: 1.25vw;
}
}
.top_apikey {
width: 100%;
.apikey_con {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: .42vw;
background-color: #22075E;
padding: .89vw .83vw;
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
color: #fff;
.apikey_text {
display: inline-block;
max-width: 100%;
overflow: scroll;
}
.toLogin {
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
text-decoration: underline;
text-align: left;
color: #fff;
line-height: 1.35vw;
}
img {
height: 1.25vw;
width: 1.25vw;
}
}
}
.bottom_codes {
margin-top: 1.25vw;
.code {
// border: 1px solid #f5f5f5;
margin-top: .78vw;
.ant-tabs-top>.ant-tabs-nav::before,
.ant-tabs-bottom>.ant-tabs-nav::before,
.ant-tabs-top>div>.ant-tabs-nav::before,
.ant-tabs-bottom>div>.ant-tabs-nav::before {
display: none !important;
}
.ant-tabs>.ant-tabs-nav .ant-tabs-nav-list {
width: 100%;
justify-content: space-between;
background-color: #391085;
}
.ant-tabs .ant-tabs-tab {
font-size: .83vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
color: #fff;
padding: .31vw 1.15vw .42vw;
}
.ant-tabs .ant-tabs-tab+.ant-tabs-tab {
margin: 0;
}
// .ant-tabs .ant-tabs-tab:hover{
// color: #722ED1;
// }
.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
color: #FFFFFF;
}
.ant-tabs .ant-tabs-ink-bar {
background-color: #fff;
}
// .ant-tabs >.ant-tabs-nav .ant-tabs-nav-list{
// width: 100%;
// justify-content: space-around;
// }
.ant-tabs-top>.ant-tabs-nav {
margin: 0;
}
.tab_con {
height: 23.02vw;
}
}
}
}
}
}
}
code, code span{
color: #fff !important;
text-shadow: none !important;
}
\ No newline at end of file
.playground_list {
min-height: calc(100vh - 14.36vw);
background-color: #22075E;
.list_content {
display: flex;
flex-direction: column;
padding: 4.1vw 6.15vw;
background-color: #22075E;
.search {
display: flex;
flex-direction: row;
justify-content: space-between;
.ant-input-affix-wrapper {
padding: 1.03vw 2.05vw;
font-size: 2.56vw;
color: #722ED1;
height: 6.15vw;
width: 61.03vw;
border-radius: 64.1vw;
line-height: normal;
}
.ant-btn {
margin-left: 1.25vw;
height: 2.08vw;
}
.ant-btn-icon {
display: inline-block;
height: 4.1vw;
width: 4.1vw;
}
button {
display: flex;
justify-content: center;
align-items: center;
padding: 1.03vw 5.38vw;
height: 6.15vw;
font-size: 2.56vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
display: inline-flex;
align-items: center;
background-color: #722ED1;
border-radius: 64.1vw;
}
}
.list {
.ant-spin{
margin-top: 50%;
}
.no_data {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 50%;
img {
height: 25.64vw;
width: 25.64vw;
margin-bottom: 4.1vw;
}
span {
font-size: 2.56vw;
font-family: SourceHanSansSC-Regular;
font-weight: 400;
color: #bfbfbf;
}
}
.list_items {
// gap: 4.1vw;
margin-top: 6.15vw;
.item {
display: flex;
flex-direction: column;
justify-content: flex-start;
padding: 4.1vw;
width: 100%;
height: 34.36vw;
margin-bottom: 4.1vw;
border-radius: 1.03vw;
background: #130337;
box-shadow: 2.05vw 2.05vw 4.1vw .26vw rgba(34,7,94,0.32);
overflow: hidden;
cursor: pointer;
.item_top {
display: flex;
flex-direction: row;
justify-content: space-between;
.tags {
display: flex;
flex-direction: row;
.typeIcon {
height: 5.13vw;
width: 5.13vw;
}
.tag {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 1.03vw;
font-size: 2.05vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
color: #FFFFFF;
background: #391085;
border-radius: 1.03vw;
margin-left: 2.05vw;
}
}
}
.item_con {
display: flex;
flex-direction: column;
align-items: flex-start;
.name {
font-size: 4.1vw;
font-family: SourceHanSansSC-Bold;
font-weight: 700;
color: #FFFFFF;
margin: 4.1vw 0 2.05vw;
display: inline-block;
white-space: nowrap;
max-width: 100%;
height: 6.67vw;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
}
.desc {
font-size: 2.56vw;
font-family: SourceHanSansSC-Medium;
font-weight: 500;
color: #FFFFFF;
display: -webkit-box;
/* 使用flex布局 */
-webkit-box-orient: vertical;
/* 垂直排列 */
-webkit-line-clamp: 2;
/* 最多显示两行 */
height: 8.21vw;
line-height: 4.1vw;
width: 100%;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
}
}
}
}
}
}
}
\ No newline at end of file
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
// routes.js
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Playground from './pages/Playground_list';
import Home from './pages/Home';
import Info from './pages/Info';
import ReceiveMessage from './pages/ReceiveMessage';
const AppRoutes = () => {
return (
<Routes>
<Route
path="/"
element={<Home />}
/>
<Route
path="/playground"
element={<Playground />}
/>
<Route
path="/info"
element={<Info />}
/>
<Route
path="/receive-message"
element={<ReceiveMessage />}
/>
</Routes>
);
};
export default AppRoutes;
const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/xxl-job-admin',
createProxyMiddleware({
target: 'http://jobs.ap-northeast-1.elasticbeanstalk.com:8080',
changeOrigin: true,
pathRewrite: {'^': ''},
}),
);
app.use(
'/admin/',
createProxyMiddleware({
// target: 'https://console.agicoin.ai/', //演示
target: 'https://console.dev.aigic.ai/', //开发
// target: 'http://192.168.1.121:8087/',
// target: 'http://172.20.10.6:8087/',
// target: 'http://localhost:8087/',
changeOrigin: true,
pathRewrite: {'^': ''},
}),
);
app.use(
'/api/',
createProxyMiddleware({
target: 'https://dev.aigic.ai/',
// target: 'http://43.198.252.255:8000/',
// target: 'http://192.168.1.108:8087/',
changeOrigin: true,
pathRewrite: {'^': ''},
}),
);
};
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
// $dark: #18181b;
$bodyColor: #fafafa;
$white: #fff;
$themeColor: #722ED1;
body {
font-family: SourceHanSansSC-Regular;
background: #000000;
color: #fff;
}
.content {
padding-top: 14.36vw;
}
// .ant-btn {
// border: none;
// box-shadow: none;
// background-color: $themeColor;
// border-radius: 25px;
// color: #fff;
// height: auto;
// }
// .ant-btn-default:not(:disabled):not(.ant-btn-disabled):hover,
// :where(.css-dev-only-do-not-override-djtmh8).ant-btn-default:not(:disabled):not(.ant-btn-disabled):active {
// background: $themeColor;
// border: none;
// color: #fff;
// }
// .btn-light {
// background-color: #fff;
// border: 1px solid $themeColor !important;
// color: $themeColor !important;
// }
// .btn-light:hover,
// .btn-light:focus {
// background: #fff !important;
// border: 1px solid $themeColor;
// color: themeColor;
// }
// .btn-light:active {
// background-color: $themeColor;
// border: 1px solid $themeColor;
// color: #fff;
// }
// .ant-btn-primary {
// background-color: $themeColor;
// border: none;
// color: #fff;
// }
.ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer):hover .ant-select-selector,
.ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector,
.ant-input-outlined {
border: 1px solid #722ED1;
}
.ant-input-affix-wrapper {
color: #722ED1;
}
.ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector,
.ant-input-affix-wrapper {
border-radius: 1.09vw;
}
.ant-select-single .ant-select-selector,
.ant-select .ant-select-arrow {
color: #722ED1;
outline: none;
}
.ant-select-dropdown{
box-shadow: 0 6px 16px 0 rgba(83,29,171,0.06),0 3px 6px -4px rgba(83,29,171,0.12),0 9px 28px 8px rgba(83,29,171,0.05)
}
.ant-select-dropdown .ant-select-item-option-selected:not(.ant-select-item-option-disabled){
background-color: #722ED1;
color: #fff;
}
.ant-select-dropdown {
padding: .42vw !important;
}
.ant-select-dropdown .ant-select-item{
font-size: .83vw !important;
}
.ant-select-focused .ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer) .ant-select-selector{
border-color: #722ED1;
box-shadow: none;
}
.ant-form-item-control-input {
outline: none;
}
.w3a-parent-container #w3a-modal div.w3a-header__subtitle,
.w3a-parent-container #w3a-modal div.w3a-social__policy,
.w3a-parent-container #w3a-modal .w3a-modal__footer,
.w3a-parent-container #w3a-modal .w3a-spinner-power {
display: none !important;
}
.w3a-parent-container #w3a-modal .w3a-modal__inner {
min-height: 27.08vw !important;
}
\ No newline at end of file
export default async function Fetch_(url, options = {}) {
try {
// 从 localStorage 中获取 token,你也可以从其他地方获取
const token = localStorage.getItem('token');
// 设置请求头部,将 token 添加到 Authorization 头中
const headers = {
'Content-Type': 'application/json',
'Authorization': token || null,
...options.headers, // 可以合并传入的 headers
};
const fetchOptions = {
...options,
headers,
}
// 发送请求
const response = await fetch(url, fetchOptions);
// 检查是否请求成功
if (!response.ok) {
if(response.status === 401){
localStorage.removeItem('token');
// logout()
// setIsLogin(false)
}
// throw new Error(`Request failed with status ${response.status}`);
}
// 从 response headers 中获取 token
const resToken = response.headers.get('Authorization');
// 将 token 存储到 localStorage 中
if (resToken) {
localStorage.setItem('token', resToken);
}
// 解析响应体并返回
return response;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
import { Web3Auth } from "@web3auth/modal";
import Web3 from "web3";
import { WALLET_ADAPTERS } from "@web3auth/base";
import { getPublicCompressed } from "@toruslabs/eccrypto";
import Fetch_ from "../utils/fetch";
import React from "react";
const loginContext = React.createContext();
const clientId = 'BHFvULiKBqRN0Em-14M-bDO2eAvHL4F19hLxR4s7dkksiIx8cIk5VlZvJeJbf8WwT5bX3FMhil45HjVbmd1Wmk4'
const doLogout = async (callback) => {
try {
await Fetch_('/admin/api/user/logout', { method: "POST", })
} catch (error) {
console.log(error)
callback(null, error.message)
}
try {
localStorage.removeItem('token');
const web3auth = initWeb3auth();
await web3auth.initModal();
if (web3auth.connected) {
await web3auth.logout();
}
callback(200, null)
} catch (error) {
console.log(error)
callback(null, error.message)
}
}
const doLogin = async (callback) => {
const web3auth = initWeb3auth();
const temp = {
modalConfig: {
[WALLET_ADAPTERS.OPENLOGIN]: {
label: "openlogin",
loginMethods: {
facebook: {
name: "facebook",
showOnModal: false,
},
twitter: {
// it will hide the facebook option from the Web3Auth modal.
name: "twitter",
showOnModal: false,
},
reddit: {
// it will hide the facebook option from the Web3Auth modal.
name: "reddit",
showOnModal: false,
},
discord: {
// it will hide the facebook option from the Web3Auth modal.
name: "discord",
showOnModal: false,
},
twitch: {
// it will hide the facebook option from the Web3Auth modal.
name: "twitch",
showOnModal: false,
},
apple: {
// it will hide the facebook option from the Web3Auth modal.
name: "apple",
showOnModal: false,
},
line: {
// it will hide the facebook option from the Web3Auth modal.
name: "line",
showOnModal: false,
},
kakao: {
// it will hide the facebook option from the Web3Auth modal.
name: "kakao",
showOnModal: false,
},
weibo: {
// it will hide the facebook option from the Web3Auth modal.
name: "weibo",
showOnModal: false,
},
wechat: {
// it will hide the facebook option from the Web3Auth modal.
name: "wechat",
showOnModal: false,
},
sms_passwordless: {
// it will hide the facebook option from the Web3Auth modal.
name: "sms_passwordless",
showOnModal: false,
},
farcaster: {
name: 'farcaster',
showOnModal: false,
}
},
// setting it to false will hide all social login methods from modal.
showOnModal: true,
},
[WALLET_ADAPTERS.WALLET_CONNECT_V2]: {
label: "wallet_connect",
showOnModal: false,
},
// Disable Metamask
[WALLET_ADAPTERS.METAMASK]: {
label: "metamask",
showOnModal: false,
},
[WALLET_ADAPTERS.COINBASE]: {
label: "coinbase",
showOnModal: false,
},
[WALLET_ADAPTERS.TORUS_SOLANA]: {
label: "torus-solana",
showOnModal: false,
},
[WALLET_ADAPTERS.PHANTOM]: {
label: "phantom",
showOnModal: false,
},
[WALLET_ADAPTERS.SOLFLARE]: {
label: "solflare",
showOnModal: false,
},
[WALLET_ADAPTERS.SLOPE]: {
label: "slope",
showOnModal: false,
},
[WALLET_ADAPTERS.TORUS_EVM]: {
label: "torus-evm",
showOnModal: false,
},
},
}
await web3auth.initModal(temp);
handleLogin(web3auth, callback)
}
const handleLogin = async (web3auth, callback) => {
if (!web3auth) {
callback(null, "web3auth not initialized yet")
return;
}
try {
let provider = await web3auth.connect();
if (web3auth.connected) {
const user = await web3auth.getUserInfo();
const app_scoped_privkey = await provider.request({
method: "eth_private_key", // use "private_key" for other non-evm chains
});
const app_pub_key = getPublicCompressed(
Buffer.from(app_scoped_privkey.padStart(64, "0"), "hex")
).toString("hex");
const web3 = new Web3(provider);
const address = await web3.eth.getAccounts();
let requestUser = {
user: {
mail: user.email,
chain_account: (address && address.length && address[0]) || "",
register_from_desc: user.typeOfLogin,
name: user.name,
type: 0,
},
id_token: user.idToken,
web3auth_public_key: app_pub_key,
};
loginRequest(requestUser, web3auth, callback);
}
} catch (error) {
console.log("login", error.message);
callback(null, error)
}
};
const loginRequest = async (user, web3auth, callback) => {
try {
const result = await Fetch_("/admin/api/user/login", {
method: "POST",
body: JSON.stringify(user)
})
const response = result
const res = await result.json();
if (res.code === 200) {
callback(200, null)
} else {
callback(null, res.err)
await web3auth.connect();
};
} catch (error) {
callback(null, error.message)
await web3auth.connect();
}
};
const initWeb3auth = () => {
const web3auth = new Web3Auth({
uiConfig: {
appName: "AIGIC",
theme: {
primary: "#722ed1",
},
mode: "dark",
appUrl: "",
appLogo: '/favicon.ico',
logoLight: '/favicon.ico',
useLogoLoader: false,
defaultLanguage: "en",
loginGridCol: 2,
loginMethodsOrder: ["github", "google", "linkedin", "email_passwordless"],
},
chainConfig: {
chainNamespace: "eip155",
chainId: "0x1",
rpcTarget: "https://rpc.ankr.com/eth",
displayName: "Ethereum Mainnet",
blockExplorer: "https://goerli.etherscan.io",
ticker: "ETH",
tickerName: "Ethereum",
},
clientId,
web3AuthNetwork: "sapphire_devnet", // Web3Auth Network
});
return web3auth;
}
export {
loginContext,
doLogin,
doLogout
}
\ No newline at end of file
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: 'selector',
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
dark: {
// Your dark theme configurations go here
textColor: '#ffffff', // Example: White text
backgroundColor: '#18181b', // Example: Dark gray background
// ... add more styles as needed
},
screens: {
'sm': '640px',
// => @media (min-width: 640px) { ... }
'md': '768px',
// => @media (min-width: 768px) { ... }
'lg': '1024px',
// => @media (min-width: 1024px) { ... }
'xl': '1280px',
// => @media (min-width: 1280px) { ... }
'2xl': '1536px',
// => @media (min-width: 1536px) { ... }
}
},
},
plugins: [],
}
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 to comment