mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-21 13:59:03 +08:00
Merge pull request #18 from PANDAJSR/tauri
修复了 Tauri 版本的亿些bug到可以正常运行的程度
This commit is contained in:
@@ -6,15 +6,22 @@ node_modules
|
|||||||
# Build outputs
|
# Build outputs
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
|
out
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
# Tauri
|
# Tauri
|
||||||
src-tauri/target
|
src-tauri/target
|
||||||
src-tauri/Cargo.lock
|
src-tauri/Cargo.lock
|
||||||
src-tauri/gen
|
src-tauri/gen
|
||||||
|
.cargo-local/
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
data.sql
|
data.sql
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite3
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<title>SecScore</title>
|
<title>SecScore</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<rect width="64" height="64" rx="12" fill="#0052D9" />
|
||||||
|
<path
|
||||||
|
d="M16 22c0-3.314 2.686-6 6-6h20c3.314 0 6 2.686 6 6v20c0 3.314-2.686 6-6 6H22c-3.314 0-6-2.686-6-6V22z"
|
||||||
|
fill="#ffffff"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M24 28h16a2 2 0 110 4H24a2 2 0 110-4zm0 8h10a2 2 0 110 4H24a2 2 0 110-4z"
|
||||||
|
fill="#0052D9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 379 B |
@@ -1,5 +1,4 @@
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use chrono::{Datelike, Duration, TimeZone, Timelike, Utc};
|
use chrono::{Datelike, Duration, Timelike, Utc};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect, Set,
|
ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect, Set,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryOrder, Set};
|
use sea_orm::{ActiveModelTrait, EntityTrait, QueryOrder, Set};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ use tauri::{AppHandle, Manager};
|
|||||||
|
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
|
|
||||||
use super::response::IpcResponse;
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn window_minimize(
|
pub async fn window_minimize(
|
||||||
app: AppHandle,
|
app: AppHandle,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pub fn setup_app(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_database(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
fn setup_database(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let handle = app.handle();
|
let handle = app.handle().clone();
|
||||||
let db_path = if cfg!(debug_assertions) {
|
let db_path = if cfg!(debug_assertions) {
|
||||||
std::path::PathBuf::from("data.sql")
|
std::path::PathBuf::from("data.sql")
|
||||||
} else {
|
} else {
|
||||||
@@ -52,7 +52,7 @@ fn setup_database(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
match create_sqlite_connection(&db_path_str).await {
|
match create_sqlite_connection(&db_path_str).await {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
let state = handle.state::<crate::state::SafeAppState>();
|
let state = handle.state::<crate::state::SafeAppState>();
|
||||||
let mut state_guard = state.write();
|
let state_guard = state.write();
|
||||||
let mut db_guard = state_guard.db.write();
|
let mut db_guard = state_guard.db.write();
|
||||||
*db_guard = Some(conn);
|
*db_guard = Some(conn);
|
||||||
eprintln!("Database connected to: {}", db_path_str);
|
eprintln!("Database connected to: {}", db_path_str);
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ fn main() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
setup_app(app)?;
|
|
||||||
let state = AppState::new(app.handle().clone());
|
let state = AppState::new(app.handle().clone());
|
||||||
app.manage(Arc::new(RwLock::new(state)));
|
app.manage(Arc::new(RwLock::new(state)));
|
||||||
|
setup_app(app)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
|||||||
+27
-9
@@ -15,16 +15,34 @@ function MainContent(): React.JSX.Element {
|
|||||||
const [messageApi, contextHolder] = message.useMessage()
|
const [messageApi, contextHolder] = message.useMessage()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!(window as any).api) return
|
const api = (window as any).api
|
||||||
const unlisten = (window as any).api.onNavigate((route: string) => {
|
if (!api) return
|
||||||
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
|
||||||
const targetPath = route === "/" ? "/home" : route
|
|
||||||
|
|
||||||
if (currentPath !== targetPath) {
|
let disposed = false
|
||||||
navigate(route)
|
let unlisten: (() => void) | null = null
|
||||||
}
|
|
||||||
})
|
api
|
||||||
return () => unlisten()
|
.onNavigate((route: string) => {
|
||||||
|
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
||||||
|
const targetPath = route === "/" ? "/home" : route
|
||||||
|
|
||||||
|
if (currentPath !== targetPath) {
|
||||||
|
navigate(route)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposed = true
|
||||||
|
if (unlisten) unlisten()
|
||||||
|
}
|
||||||
}, [navigate, location.pathname])
|
}, [navigate, location.pathname])
|
||||||
|
|
||||||
const [wizardVisible, setWizardVisible] = useState(false)
|
const [wizardVisible, setWizardVisible] = useState(false)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { Suspense, lazy } from "react"
|
|||||||
import { Layout, Space, Button, Tag, Spin } from "antd"
|
import { Layout, Space, Button, Tag, Spin } from "antd"
|
||||||
import { Routes, Route, Navigate } from "react-router-dom"
|
import { Routes, Route, Navigate } from "react-router-dom"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { WindowControls } from "./WindowControls"
|
||||||
|
|
||||||
const Home = lazy(() => import("./Home").then((m) => ({ default: m.Home })))
|
const Home = lazy(() => import("./Home").then((m) => ({ default: m.Home })))
|
||||||
const StudentManager = lazy(() =>
|
const StudentManager = lazy(() =>
|
||||||
@@ -67,6 +68,7 @@ export function ContentArea({
|
|||||||
background: "var(--ss-header-bg)",
|
background: "var(--ss-header-bg)",
|
||||||
borderBottom: "1px solid var(--ss-border-color)",
|
borderBottom: "1px solid var(--ss-border-color)",
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
WebkitAppRegion: "drag",
|
||||||
} as React.CSSProperties
|
} as React.CSSProperties
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -76,7 +78,8 @@ export function ContentArea({
|
|||||||
{
|
{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
paddingRight: "12px",
|
paddingRight: "8px",
|
||||||
|
WebkitAppRegion: "no-drag",
|
||||||
} as React.CSSProperties
|
} as React.CSSProperties
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -94,6 +97,7 @@ export function ContentArea({
|
|||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
|
<WindowControls />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Content style={{ flex: 1, overflowY: "auto" }}>
|
<Content style={{ flex: 1, overflowY: "auto" }}>
|
||||||
|
|||||||
+28
-12
@@ -95,20 +95,36 @@ export const Settings: React.FC<{ permission: permissionLevel }> = ({ permission
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadAll()
|
loadAll()
|
||||||
if (!(window as any).api) return
|
const api = (window as any).api
|
||||||
const unsubscribe = (window as any).api.onSettingChanged((change: any) => {
|
if (!api) return
|
||||||
setSettings((prev) => {
|
|
||||||
if (change?.key === "log_level") return { ...prev, log_level: change.value }
|
let disposed = false
|
||||||
if (change?.key === "is_wizard_completed")
|
let unlisten: (() => void) | null = null
|
||||||
return { ...prev, is_wizard_completed: change.value }
|
|
||||||
if (change?.key === "window_zoom") return { ...prev, window_zoom: change.value }
|
api
|
||||||
if (change?.key === "auto_score_enabled")
|
.onSettingChanged((change: any) => {
|
||||||
return { ...prev, auto_score_enabled: change.value }
|
setSettings((prev) => {
|
||||||
return prev
|
if (change?.key === "log_level") return { ...prev, log_level: change.value }
|
||||||
|
if (change?.key === "is_wizard_completed")
|
||||||
|
return { ...prev, is_wizard_completed: change.value }
|
||||||
|
if (change?.key === "window_zoom") return { ...prev, window_zoom: change.value }
|
||||||
|
if (change?.key === "auto_score_enabled")
|
||||||
|
return { ...prev, auto_score_enabled: change.value }
|
||||||
|
return prev
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (typeof unsubscribe === "function") unsubscribe()
|
disposed = true
|
||||||
|
if (unlisten) unlisten()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|||||||
@@ -39,15 +39,30 @@ export function Sidebar({ activeMenu, permission, onMenuChange }: SidebarProps):
|
|||||||
const handleStatusChange = () => {
|
const handleStatusChange = () => {
|
||||||
loadDbStatus()
|
loadDbStatus()
|
||||||
}
|
}
|
||||||
if ((window as any).api) {
|
const api = (window as any).api
|
||||||
const unsubscribe = (window as any).api.onSettingChanged(
|
if (!api) return
|
||||||
(change: { key: string; value: any }) => {
|
|
||||||
if (change.key === "pg_connection_status") {
|
let disposed = false
|
||||||
handleStatusChange()
|
let unlisten: (() => void) | null = null
|
||||||
}
|
|
||||||
|
api
|
||||||
|
.onSettingChanged((change: { key: string; value: any }) => {
|
||||||
|
if (change.key === "pg_connection_status") {
|
||||||
|
handleStatusChange()
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
return unsubscribe
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposed = true
|
||||||
|
if (unlisten) unlisten()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,34 @@ export function TitleBar({ children }: TitleBarProps): React.JSX.Element {
|
|||||||
const [isMaximized, setIsMaximized] = useState(false)
|
const [isMaximized, setIsMaximized] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!(window as any).api) return
|
const api = (window as any).api
|
||||||
;(window as any).api.windowIsMaximized().then((v: boolean) => setIsMaximized(v))
|
if (!api) return
|
||||||
|
|
||||||
const cleanup = (window as any).api.onWindowMaximizedChanged((maximized: boolean) => {
|
let disposed = false
|
||||||
setIsMaximized(maximized)
|
let unlisten: (() => void) | null = null
|
||||||
})
|
|
||||||
return cleanup
|
api
|
||||||
|
.windowIsMaximized()
|
||||||
|
.then((v: boolean) => setIsMaximized(v))
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
api
|
||||||
|
.onWindowMaximizedChanged((maximized: boolean) => {
|
||||||
|
setIsMaximized(maximized)
|
||||||
|
})
|
||||||
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposed = true
|
||||||
|
if (unlisten) unlisten()
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const minimize = () => {
|
const minimize = () => {
|
||||||
|
|||||||
@@ -11,13 +11,34 @@ export function WindowControls(): React.JSX.Element {
|
|||||||
const [isMaximized, setIsMaximized] = useState(false)
|
const [isMaximized, setIsMaximized] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!(window as any).api) return
|
const api = (window as any).api
|
||||||
;(window as any).api.windowIsMaximized().then((v: boolean) => setIsMaximized(v))
|
if (!api) return
|
||||||
|
|
||||||
const cleanup = (window as any).api.onWindowMaximizedChanged((maximized: boolean) => {
|
let disposed = false
|
||||||
setIsMaximized(maximized)
|
let unlisten: (() => void) | null = null
|
||||||
})
|
|
||||||
return cleanup
|
api
|
||||||
|
.windowIsMaximized()
|
||||||
|
.then((v: boolean) => setIsMaximized(v))
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
api
|
||||||
|
.onWindowMaximizedChanged((maximized: boolean) => {
|
||||||
|
setIsMaximized(maximized)
|
||||||
|
})
|
||||||
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposed = true
|
||||||
|
if (unlisten) unlisten()
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const minimize = () => {
|
const minimize = () => {
|
||||||
|
|||||||
@@ -120,23 +120,36 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ childre
|
|||||||
}, [applyThemeConfig])
|
}, [applyThemeConfig])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!(window as any).api) return
|
const api = (window as any).api
|
||||||
|
if (!api) return
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await loadThemes()
|
await loadThemes()
|
||||||
await loadCurrentTheme()
|
await loadCurrentTheme()
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const unsubscribe = (window as any).api.onThemeChanged((theme: themeConfig) => {
|
let disposed = false
|
||||||
setCurrentTheme(theme)
|
let unlisten: (() => void) | null = null
|
||||||
currentThemeRef.current = theme
|
|
||||||
applyThemeConfig(theme)
|
api
|
||||||
loadThemes()
|
.onThemeChanged((theme: themeConfig) => {
|
||||||
})
|
setCurrentTheme(theme)
|
||||||
|
currentThemeRef.current = theme
|
||||||
|
applyThemeConfig(theme)
|
||||||
|
loadThemes()
|
||||||
|
})
|
||||||
|
.then((fn: () => void) => {
|
||||||
|
if (disposed) {
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch(() => void 0)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (typeof unsubscribe === "function") {
|
disposed = true
|
||||||
unsubscribe()
|
if (unlisten) unlisten()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [applyThemeConfig, loadCurrentTheme, loadThemes])
|
}, [applyThemeConfig, loadCurrentTheme, loadThemes])
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -7,6 +7,11 @@ import App from "./App"
|
|||||||
import { ClientContext } from "./ClientContext"
|
import { ClientContext } from "./ClientContext"
|
||||||
import { StudentService } from "./services/StudentService"
|
import { StudentService } from "./services/StudentService"
|
||||||
import { ServiceProvider } from "./contexts/ServiceContext"
|
import { ServiceProvider } from "./contexts/ServiceContext"
|
||||||
|
import { api } from "./preload/types"
|
||||||
|
|
||||||
|
if (!(window as any).api) {
|
||||||
|
;(window as any).api = api
|
||||||
|
}
|
||||||
|
|
||||||
const ctx = new ClientContext()
|
const ctx = new ClientContext()
|
||||||
new StudentService(ctx)
|
new StudentService(ctx)
|
||||||
@@ -19,7 +24,7 @@ const safeWriteLog = (payload: {
|
|||||||
try {
|
try {
|
||||||
const api = (window as any).api
|
const api = (window as any).api
|
||||||
if (!api?.writeLog) return
|
if (!api?.writeLog) return
|
||||||
api.writeLog(payload)
|
Promise.resolve(api.writeLog(payload)).catch(() => void 0)
|
||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-3
@@ -173,6 +173,9 @@ const api = {
|
|||||||
windowMaximize: (): Promise<boolean> => invoke("window_maximize"),
|
windowMaximize: (): Promise<boolean> => invoke("window_maximize"),
|
||||||
windowClose: (): Promise<void> => invoke("window_close"),
|
windowClose: (): Promise<void> => invoke("window_close"),
|
||||||
windowIsMaximized: (): Promise<boolean> => invoke("window_is_maximized"),
|
windowIsMaximized: (): Promise<boolean> => invoke("window_is_maximized"),
|
||||||
|
toggleDevTools: (): Promise<void> => invoke("toggle_devtools"),
|
||||||
|
windowResize: (width: number, height: number): Promise<void> =>
|
||||||
|
invoke("window_resize", { width, height }),
|
||||||
onWindowMaximizedChanged: (callback: (maximized: boolean) => void): Promise<UnlistenFn> => {
|
onWindowMaximizedChanged: (callback: (maximized: boolean) => void): Promise<UnlistenFn> => {
|
||||||
return listen<boolean>("window:maximized-changed", (event) => {
|
return listen<boolean>("window:maximized-changed", (event) => {
|
||||||
callback(event.payload)
|
callback(event.payload)
|
||||||
@@ -185,15 +188,19 @@ const api = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
queryLogs: (params?: { lines?: number }): Promise<{ success: boolean; data: string[] }> =>
|
queryLogs: (
|
||||||
invoke("log_query", { params }),
|
input?: number | { lines?: number }
|
||||||
|
): Promise<{ success: boolean; data: string[] }> => {
|
||||||
|
const lines = typeof input === "number" ? input : input?.lines
|
||||||
|
return invoke("log_query", { lines })
|
||||||
|
},
|
||||||
clearLogs: (): Promise<{ success: boolean }> => invoke("log_clear"),
|
clearLogs: (): Promise<{ success: boolean }> => invoke("log_clear"),
|
||||||
setLogLevel: (level: string): Promise<{ success: boolean }> => invoke("log_set_level", { level }),
|
setLogLevel: (level: string): Promise<{ success: boolean }> => invoke("log_set_level", { level }),
|
||||||
writeLog: (payload: {
|
writeLog: (payload: {
|
||||||
level: string
|
level: string
|
||||||
message: string
|
message: string
|
||||||
meta?: any
|
meta?: any
|
||||||
}): Promise<{ success: boolean }> => invoke("log_write", payload),
|
}): Promise<{ success: boolean }> => invoke("log_write", { payload }),
|
||||||
|
|
||||||
// Database Connection
|
// Database Connection
|
||||||
dbTestConnection: (
|
dbTestConnection: (
|
||||||
@@ -291,6 +298,28 @@ const api = {
|
|||||||
ruleIds: number[]
|
ruleIds: number[]
|
||||||
): Promise<{ success: boolean; data?: boolean; message?: string }> =>
|
): Promise<{ success: boolean; data?: boolean; message?: string }> =>
|
||||||
invoke("auto_score_sort_rules", { ruleIds }),
|
invoke("auto_score_sort_rules", { ruleIds }),
|
||||||
|
|
||||||
|
// Generic invoke wrapper for backward compatibility with callers using `api.invoke`
|
||||||
|
invoke: async (channel: string, ...args: any[]): Promise<any> => {
|
||||||
|
switch (channel) {
|
||||||
|
case "auto-score:getRules":
|
||||||
|
return api.autoScoreGetRules()
|
||||||
|
case "auto-score:addRule":
|
||||||
|
return api.autoScoreAddRule(args[0])
|
||||||
|
case "auto-score:updateRule":
|
||||||
|
return api.autoScoreUpdateRule(args[0])
|
||||||
|
case "auto-score:deleteRule":
|
||||||
|
return api.autoScoreDeleteRule(args[0])
|
||||||
|
case "auto-score:toggleRule":
|
||||||
|
return api.autoScoreToggleRule(args[0])
|
||||||
|
case "auto-score:sortRules":
|
||||||
|
return api.autoScoreSortRules(args[0])
|
||||||
|
case "auto-score:getStatus":
|
||||||
|
return api.autoScoreGetStatus()
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported legacy invoke channel: ${channel}`)
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ export default defineConfig({
|
|||||||
"@": resolve(__dirname, "src"),
|
"@": resolve(__dirname, "src"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
// Avoid scanning legacy `old-ss` entries under project root.
|
||||||
|
entries: ["index.html"],
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: "dist",
|
outDir: "dist",
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user