feat: 初始化
This commit is contained in:
parent
d94f215467
commit
98c937e079
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"is_init": true,
|
||||
"db_type": "sqlite",
|
||||
"db_host": "localhost",
|
||||
"db_port": 3306,
|
||||
"db_user": "root",
|
||||
"db_password": "12345",
|
||||
"db_name": "your_workflow",
|
||||
"admin_password": "12345"
|
||||
}
|
||||
|
|
@ -6,8 +6,14 @@ CONFIG_PATH = Path(__file__).parent.parent / "config" / "init.json"
|
|||
|
||||
|
||||
def _sync_load_config() -> dict:
|
||||
with CONFIG_PATH.open("r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
with CONFIG_PATH.open("r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
default_config = {"is_init": False}
|
||||
_sync_save_config(default_config)
|
||||
return default_config
|
||||
|
||||
|
||||
def _sync_save_config(config_data: dict):
|
||||
|
|
|
|||
|
|
@ -95,12 +95,12 @@ async def lifespan(app: FastAPI):
|
|||
init_config = await load_init_config()
|
||||
await init_tortoise(init_config["db_type"], init_config, init_config.get("admin_password"))
|
||||
logger.info("初始化数据库")
|
||||
# 读取上一次登录状态
|
||||
await load_session_from_file(app)
|
||||
# 定时器
|
||||
scheduler.add_job(clear_session, "interval", seconds=30, misfire_grace_time=10)
|
||||
scheduler.start()
|
||||
logger.info("初始化定时器")
|
||||
# 读取上一次登录状态
|
||||
await load_session_from_file(app)
|
||||
|
||||
yield
|
||||
|
||||
|
|
@ -173,6 +173,8 @@ def create_app():
|
|||
|
||||
@app.get("/api/current_user", tags=["User"], description="当前用户信息", response_model=LoginResponse)
|
||||
async def current_user(user: DB.User = Depends(get_current_user)):
|
||||
if not await is_init():
|
||||
return LoginResponse(success=False)
|
||||
return LoginResponse(data=user.json(del_columns=["password"]))
|
||||
|
||||
@app.post("/api/run", tags=["Flow"], description="执行任务", response_model=BaseResponse)
|
||||
|
|
|
|||
|
|
@ -4,3 +4,6 @@ export const isInit = async () => {
|
|||
return request("/api/check_init", "GET")
|
||||
}
|
||||
|
||||
export const initSystem = async (data) => {
|
||||
return request("/api/init_system", "POST", data)
|
||||
}
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
import { login as loginToServer, currentUser } from "../api/user";
|
||||
import { isInit } from '../api/system';
|
||||
const AuthContext = createContext(null);
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export function AuthProvider({ children }) {
|
||||
const navigate = useNavigate();
|
||||
const token = localStorage.getItem('_token')
|
||||
const [user, setUser] = useState(null);
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(token?.length > 0);
|
||||
const [systemStatus, setSystemStatus] = useState(-1);
|
||||
|
||||
const getUserInfoFromToken = async () => {
|
||||
try {
|
||||
|
|
@ -24,6 +26,11 @@ export function AuthProvider({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
|
||||
const checkSystemStatus = async () => {
|
||||
const res = await isInit();
|
||||
setSystemStatus(res?.data ? 1 : 0);
|
||||
}
|
||||
|
||||
const login = async (username, password) => {
|
||||
const res = await loginToServer(username, password);
|
||||
if (res?.success) {
|
||||
|
|
@ -42,11 +49,22 @@ export function AuthProvider({ children }) {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
token && getUserInfoFromToken();
|
||||
}, [token])
|
||||
systemStatus === 1 && token && getUserInfoFromToken();
|
||||
|
||||
if (systemStatus === 0) {
|
||||
navigate("/init");
|
||||
}
|
||||
else if (!token) {
|
||||
navigate("/login")
|
||||
}
|
||||
}, [token, systemStatus])
|
||||
|
||||
useEffect(() => {
|
||||
checkSystemStatus();
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, login, logout, loading }}>
|
||||
<AuthContext.Provider value={{ user, login, logout, loading, systemStatus }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,32 @@
|
|||
import { ProForm, ProFormSelect, ProFormText } from "@ant-design/pro-components";
|
||||
import { Card, Divider } from "antd";
|
||||
import { ProForm, ProFormDependency, ProFormDigit, ProFormGroup, ProFormSelect, ProFormText } from "@ant-design/pro-components";
|
||||
import { App, Card, Divider } from "antd";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { initSystem } from "../api/system";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import { useEffect } from "react";
|
||||
const rules = [{required: true}]
|
||||
const InitPage = () => {
|
||||
const { systemStatus } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { message } = App.useApp();
|
||||
useEffect(() => {
|
||||
if (systemStatus === 1) {
|
||||
navigate("/login");
|
||||
}
|
||||
}, [systemStatus])
|
||||
return (
|
||||
<div style={{ width: '100vw', height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f2f3f5' }}>
|
||||
<Card title='初始化' style={{ width: 400}}>
|
||||
<ProForm layout='horizontal'>
|
||||
<Divider orientation="left">超级帐号</Divider>
|
||||
<Card style={{ width: 600}} title="系统初始化">
|
||||
<ProForm onFinish={async values => {
|
||||
const res = await initSystem(values);
|
||||
if (res?.success) {
|
||||
message.success("初始化成功");
|
||||
navigate("/login");
|
||||
} else {
|
||||
message.error(res.message);
|
||||
}
|
||||
}}>
|
||||
<Divider orientation="left" plain>超级帐号</Divider>
|
||||
<ProFormText
|
||||
name="account"
|
||||
label="帐号"
|
||||
|
|
@ -17,14 +37,29 @@ const InitPage = () => {
|
|||
label="密码"
|
||||
rules={rules}
|
||||
/>
|
||||
<Divider orientation="left">数据库配置</Divider>
|
||||
<Divider orientation="left" plain>数据库配置</Divider>
|
||||
<ProFormSelect
|
||||
name="db_type"
|
||||
options={[{ label: 'SQLite', value: 'sqlite' }, { label: 'MySql', value: 'mysql' }]}
|
||||
label="数据库"
|
||||
rules={rules}
|
||||
/>
|
||||
|
||||
<ProFormDependency name={['db_type']}>
|
||||
{({ db_type }) => {
|
||||
if (db_type === 'mysql') return <>
|
||||
<ProFormGroup>
|
||||
<ProFormText name="db_host" label="地址" rules={rules} />
|
||||
<ProFormDigit name="db_port" label="端口" rules={rules} />
|
||||
<ProFormText name="db_name" label="数据库" rules={rules} />
|
||||
<ProFormText name="db_user" label="用户" rules={rules} />
|
||||
<ProFormText.Password name="db_password" label="密码" rules={rules} />
|
||||
</ProFormGroup>
|
||||
</>
|
||||
|
||||
return null;
|
||||
|
||||
}}
|
||||
</ProFormDependency>
|
||||
</ProForm>
|
||||
</Card>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,17 +10,25 @@ import FlowDetail from "./pages/Flow/Detail";
|
|||
import LayoutPage from "./pages/Layout";
|
||||
import ClientPage from "./pages/Client";
|
||||
import LogPage from "./pages/Log";
|
||||
import InitPage from "./pages/InitPage";
|
||||
|
||||
// 受保护的路由:没登录就跳转到登录页
|
||||
function PrivateRoute() {
|
||||
const { user, loading } = useAuth();
|
||||
return (user || loading) ? <Outlet /> : <Navigate to="/login" replace />;
|
||||
const { user, loading, systemStatus } = useAuth();
|
||||
if (systemStatus === 0) {
|
||||
return <Navigate to="/init" replace />
|
||||
}
|
||||
if (user || loading || systemStatus != 0) {
|
||||
return <Outlet />;
|
||||
}
|
||||
return <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
const routes = [
|
||||
// 登录页公开访问
|
||||
{ path: "/", element: <Loading /> },
|
||||
{ path: "/login", element: <Login /> },
|
||||
{ path: "/init", element: <InitPage /> },
|
||||
|
||||
// 需要登录才能访问的路由
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue