添加(main/db/config.ts):引入数据库配置文件以支持指定数据库目录

🔧 更新(main/db/connect.ts):改进数据库连接方式以支持配置文件设置的数据库目录
🔧 更新(main/db/ipc.ts):添加设置数据库目录和初始化表格的IPC事件处理
♻️ 重构(main/db/query.ts):优化数据库查询函数以适应新的数据库连接方式
📝 更新(main/db/tables.ts):更新数据库表格初始化逻辑以支持新的数据库连接方式
🔧 更新(main/windows.ts):调整窗口初始化配置以适应数据库目录设置变化
🌐 更新(preload/index.d.ts):增加设置数据库目录和初始化表格的全局类型声明
📝 更新(preload/index.ts):更新设置数据库目录和初始化表格的preload事件处理逻辑
🔧 更新(renderer/src/components/Result/index.tsx):修复结果组件显示内容问题
🔧 更新(renderer/src/hooks/useSearch.ts):优化搜索逻辑以支持新的数据查询方式
🔧 更新(renderer/src/layouts/Home/index.tsx):调整初始化逻辑以应用新的数据库目录设置和表格初始化
♻️ 更新(renderer/src/store/useStore.ts):调整存储数据类型以更好地支持内容类型数据存储
This commit is contained in:
yuruo
2024-06-24 08:58:25 +08:00
parent a7d06b43cb
commit 70b662b575
13 changed files with 70 additions and 35 deletions

View File

@@ -0,0 +1,3 @@
export default {
databaseDirectory: ""
}

View File

@@ -1,7 +1,17 @@
import Database, * as BetterSqlite3 from 'better-sqlite3';
import { app } from 'electron';
import {resolve} from 'node:path'
const file = resolve(app.getPath('home'), 'autoMate.db')
const db: BetterSqlite3.Database = new Database(file, {});
db.pragma('journal_mode = WAL');
export {db};
import { resolve } from 'node:path'
import config from './config';
import { existsSync } from 'node:fs';
const db = (): BetterSqlite3.Database => {
let dir = resolve(app.getPath('home'))
if (config.databaseDirectory && existsSync(config.databaseDirectory)) {
dir = config.databaseDirectory
}
const db: BetterSqlite3.Database = new Database(dir + '/autoMate.db', {});
db.pragma('journal_mode = WAL');
return db
}
export { db };

View File

@@ -1,2 +1,2 @@
import './tables'
// import './tables'
import './ipc'

View File

@@ -1,5 +1,7 @@
import { IpcMainInvokeEvent, dialog, ipcMain } from "electron";
import * as query from './query'
import config from "./config";
import { initTable } from "./tables";
ipcMain.handle('sql', (_event: IpcMainInvokeEvent, sql: string, type: SqlActionType, params={}) => {
return query[type](sql, params)
})
@@ -11,4 +13,12 @@ ipcMain.handle('selectDatabaseDirectory', async () => {
properties: ['openDirectory', 'createDirectory']
})
return ret.canceled?'' : ret.filePaths[0]
})
ipcMain.on('setDatabaseDirectory', (_event: IpcMainInvokeEvent, path: string) => {
config.databaseDirectory = path
})
ipcMain.on('initTable', () => {
initTable()
})

View File

@@ -1,25 +1,25 @@
import {db} from './connect'
export const findAll = (sql: string, params={}) => {
return db.prepare(sql).all(params);
return db().prepare(sql).all(params);
}
export const findOne = (sql: string) => {
return db.prepare(sql).get();
return db().prepare(sql).get();
}
export const create = (sql: string) => {
return db.prepare(sql).run().lastInsertRowid;
return db().prepare(sql).run().lastInsertRowid;
}
//使用 params 是为了防止 sql 注入
export const update = (sql: string, params: Record<string, any>) => {
return db.prepare(sql).run(params).changes;
return db().prepare(sql).run(params).changes;
}
export const del = (sql: string, params={}) => {
return db.prepare(sql).run(params).changes;
return db().prepare(sql).run(params).changes;
}
export const config = () => {

View File

@@ -1,8 +1,11 @@
import { Random } from "mockjs";
// import { Random } from "mockjs";
import { db } from "./connect";
import { findOne } from "./query";
db.exec(`
export function initTable() {
db().exec(`
CREATE TABLE IF NOT EXISTS categories (
id INTEGER PRIMARY KEY AUTOINCREMENT not null,
name TEXT not null,
@@ -11,7 +14,7 @@ CREATE TABLE IF NOT EXISTS categories (
`)
db.exec(`
db().exec(`
CREATE TABLE IF NOT EXISTS contents (
id INTEGER PRIMARY KEY AUTOINCREMENT not null,
title TEXT not null,
@@ -22,34 +25,36 @@ CREATE TABLE IF NOT EXISTS contents (
`)
db.exec(`
db().exec(`
CREATE TABLE IF NOT EXISTS config (
id INTEGER PRIMARY KEY AUTOINCREMENT not null,
content TEXT not null
);
`)
initData()
}
function initData() {
const initData = findOne('select * from config')
if (initData) return
db.exec(`insert into config (id, content) values(1,'{"shortCut":"Alt+Space","databaseDirectory":""}')`)
db().exec(`insert into config (id, content) values(1,'{"shortCut":"Alt+Space","databaseDirectory":""}')`)
}
initData()
// for (let i = 0; i < 20; i++) {
// const name = Random.title(5, 10)
// db.exec(`insert into config (content) values('${name}')`)
// db().exec(`insert into config (content) values('${name}')`)
// }
// for (let i = 0; i < 20; i++) {
// const name = Random.title(5, 10)
// db.exec(`insert into categories (name, created_at) values('${name}', datetime())`)
// db().exec(`insert into categories (name, created_at) values('${name}', datetime())`)
// }
// for (let i = 1; i < 20; i++) {
// const title = Random.title(5, 10)
// const content = Random.paragraph(5, 10)
// db.exec(`insert into contents (title, content, category_id, created_at) values('${title}', '${content}', ${i}, datetime())`)
// db().exec(`insert into contents (title, content, category_id, created_at) values('${title}', '${content}', ${i}, datetime())`)
// }

View File

@@ -25,7 +25,7 @@ export const config = {
config: {
id: 0,
options: {
initShow: false,
initShow: true,
width: 600,
height: 400,
openDevTools: true,

View File

@@ -10,7 +10,9 @@ declare global {
sql: <T>(sql: string, type: SqlActionType, params?: Record<string, any>) => Promise<T>
openWindow: (name: WindowNameType) => void,
closeWindow: (name: WindowNameType) => void,
selectDatabaseDirectory: () => Promise<string>
selectDatabaseDirectory: () => Promise<string>,
setDatabaseDirectory: (path: string) => void,
initTable: () => void,
}
}
}

View File

@@ -23,8 +23,13 @@ const api = {
},
selectDatabaseDirectory: () => {
return ipcRenderer.invoke("selectDatabaseDirectory")
},
setDatabaseDirectory: (path: string) => {
ipcRenderer.send("setDatabaseDirectory", path)
},
initTable: () => {
ipcRenderer.send("initTable")
}
}
// Use `contextBridge` APIs to expose Electron APIs to

View File

@@ -10,7 +10,7 @@ export default function Result() {
className={item.id == selectId? styles.active : ''}
onClick={()=>select(item.id)}
>
<p>{item.content}</p>
<p>{item.title}</p>
</div>
))}

View File

@@ -1,20 +1,17 @@
// import useCode from "@renderer/hooks/useCode"
import { ChangeEvent } from "react"
import { codes } from "@renderer/data"
import { useStore } from "@renderer/store/useStore"
export default()=>{
// const {setData} = useCode()
const setData = useStore((state)=>state.setData)
// const [search, setSearch] = useState('')
const search = useStore((state)=>state.search)
const setSearch = useStore((state)=>state.setSearch)
const handleSearch = (e: ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value)
setData(
codes.filter((code) =>
code.content.toLowerCase().includes(e.target.value.toLowerCase() || '@@@@@@')
).slice(0, 8)
)
const handleSearch = async (e: ChangeEvent<HTMLInputElement>) => {
const data = await window.api.sql(
`select * from contents where title like @content`,
'findAll',
{content: `%${e.target.value}%`})
setData(data as ContentType[])
}
return {search, handleSearch}
}

View File

@@ -12,6 +12,8 @@ function Home(): JSX.Element {
const {setIgnoreMouseEvents} = useIgnoreMouseEvents()
const config = useStore(state => state.config)
window.api.shortCut(config.shortCut)
window.api.setDatabaseDirectory(config.databaseDirectory)
window.api.initTable()
useEffect(()=>{
setIgnoreMouseEvents(mainRef as MutableRefObject<HTMLDivElement>)
// //为开发方便,临时代码

View File

@@ -4,7 +4,7 @@ interface StateProps{
config: ConfigDataType,
setConfig: (config: ConfigDataType) => void,
data: DataType[],
setData: (data: DataType[]) => void,
setData: (data: ContentType[]) => void,
search: string,
setSearch: (search: string) => void,
error: string,
@@ -15,7 +15,7 @@ interface StateProps{
setEditCategoryId: (id: number) => void
}
export const useStore = create<StateProps>((set) => ({
config: {shortCut: "", databaseDirectory: ""},
config: {shortCut: "alt+d", databaseDirectory: ""},
setConfig: (config) => set({config}),
data: [],
setData: (data) => set({data}),
@@ -29,3 +29,4 @@ export const useStore = create<StateProps>((set) => ({
setEditCategoryId: (editCategoryId) => set({editCategoryId})
}))