Skip to content

Commit 7abcd81

Browse files
committed
feat: add postgres backend and rescan controls
1 parent c6f2313 commit 7abcd81

43 files changed

Lines changed: 2743 additions & 310 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

assets/dist/main.js

Lines changed: 22 additions & 5 deletions
Large diffs are not rendered by default.

assets/dist/styles.css

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/frontend/plugins/comigo_sse.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* 全局 SSE:接收 ui_suggest_reload(整页刷新建议)并转发 log 到设置页日志面板。
2+
* 全局 SSE:接收 ui_suggest_reload(整页刷新通知)并转发 log 到设置页日志面板。
33
*/
44
function shouldEnableComigoSSE() {
55
if (typeof window === 'undefined' || typeof EventSource === 'undefined') {
@@ -10,7 +10,13 @@ function shouldEnableComigoSSE() {
1010
return pathname !== '/login'
1111
}
1212

13-
// 仅在书架与设置页弹出「建议刷新」;阅读页(flip/scroll 等)不打断
13+
const libraryRescanReloadReasons = new Set([
14+
'library_rescan_done',
15+
'auto_library_rescan_done',
16+
'single_store_rescan_done',
17+
])
18+
19+
// 仅在书架与设置页处理整页刷新;阅读页(flip/scroll 等)不打断
1420
function shouldShowUISuggestReloadPrompt() {
1521
const p = window.ComiGoRelativePath ? window.ComiGoRelativePath(window.location.pathname) : window.location.pathname
1622
if (p === '/settings') {
@@ -25,6 +31,10 @@ function shouldShowUISuggestReloadPrompt() {
2531
return false
2632
}
2733

34+
function isLibraryRescanReloadReason(reason) {
35+
return libraryRescanReloadReasons.has(reason)
36+
}
37+
2838
function getReloadPromptMessage(reason) {
2939
const key = 'ui_suggest_reload_reason_' + reason
3040
const translated =
@@ -58,6 +68,14 @@ function showReloadPrompt(reason) {
5868
})
5969
}
6070

71+
function autoReloadAfterLibraryRescan() {
72+
if (!shouldShowUISuggestReloadPrompt() || window.__comigoAutoReloadQueued) {
73+
return
74+
}
75+
window.__comigoAutoReloadQueued = true
76+
window.location.reload()
77+
}
78+
6179
function appendSharedLog(line) {
6280
if (typeof window.__comigoLogAppend === 'function') {
6381
window.__comigoLogAppend(line)
@@ -91,6 +109,10 @@ function comigoAttachSSEListeners(es) {
91109
reason = data.reason
92110
}
93111
} catch (_) {}
112+
if (isLibraryRescanReloadReason(reason)) {
113+
autoReloadAfterLibraryRescan()
114+
return
115+
}
94116
showReloadPrompt(reason)
95117
})
96118

assets/locale/en_US.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@
139139
"enable_database": "Enable a local database to store scanned book data",
140140
"enable_database_description": "Enable local database to save scanned book data. ",
141141
"enable_database_label": "Enable database",
142+
"db_type": "Database type: sqlite or postgres",
143+
"db_dsn": "PostgreSQL connection string",
142144
"enable_file_upload": "Enable file upload",
143145
"enable_funnel": "Enable Funnel",
144146
"enable_plugin": "Enable plugin system",
@@ -639,7 +641,7 @@
639641
"next": "Next",
640642
"next_book": "Next book",
641643
"no_available_stores": "No available stores, please add store paths in settings first",
642-
"no_books_library_path_notice": "No readable books were found. Please configure a library path. When scanning finishes, you will be prompted to refresh the page.",
644+
"no_books_library_path_notice": "No readable books were found. Please configure a library path. The page will reload automatically after scanning finishes.",
643645
"no_config_file_to_delete_in_path": "There is no configuration file to delete in the selected path.",
644646
"no_pages_in_pdf": "No pages in PDF.",
645647
"no_pattern": "Solid Color",
@@ -724,6 +726,7 @@
724726
"register_file_association": "Register archive file association (as a candidate)",
725727
"register_folder_context_menu": "Register folder context menu: Open with Comigo",
726728
"remote_access": "Remote Access",
729+
"rescan_all_stores": "Rescan",
727730
"rescan_store": "Scan",
728731
"rescan_store_in_progress": "Scanning store, please wait...",
729732
"rescan_store_success": "Store scan completed, {0} new books added",
@@ -931,13 +934,13 @@
931934
"tui_url_copied": "URL copied: %s",
932935
"type_or_paste_content": "Type or paste content",
933936
"ui_suggest_reload_default": "Server data has changed. Reload the page to see the latest UI?",
934-
"ui_suggest_reload_reason_auto_library_rescan_done": "Scheduled library scan finished. Reload the page to refresh the shelf and related views?",
937+
"ui_suggest_reload_reason_auto_library_rescan_done": "Scheduled library scan finished. The page will reload automatically.",
935938
"ui_suggest_reload_reason_debug_toggle": "Debug mode changed. Reload the page to show the related settings?",
936-
"ui_suggest_reload_reason_library_rescan_done": "Library scan finished. Reload the page to refresh the shelf and related views?",
939+
"ui_suggest_reload_reason_library_rescan_done": "Library scan finished. The page will reload automatically.",
937940
"ui_suggest_reload_reason_login_settings_changed": "Login settings updated. Reload the page?",
938941
"ui_suggest_reload_reason_plugins_changed": "Plugins changed. Reload the page to apply?",
939942
"ui_suggest_reload_reason_server_config_changed": "Network or server settings changed. Reload the page?",
940-
"ui_suggest_reload_reason_single_store_rescan_done": "This library has been rescanned. Reload the page?",
943+
"ui_suggest_reload_reason_single_store_rescan_done": "This library has been rescanned. The page will reload automatically.",
941944
"unable_to_extract_images_from_pdf": "Unable to extract images from PDF.",
942945
"unknown": "Unknown",
943946
"unregister_context_menu": "Unregister context menu: Open with Comigo",

assets/locale/ja_JP.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@
139139
"enable_database": "スキャンした本をローカルデータベースに保存する",
140140
"enable_database_description": "ローカルデータベースにスキャンした書籍データを保存できるようにします。",
141141
"enable_database_label": "データベースを有効にする",
142+
"db_type": "データベース種別: sqlite または postgres",
143+
"db_dsn": "PostgreSQL 接続文字列",
142144
"enable_file_upload": "ファイルのアップロードを有効にする",
143145
"enable_funnel": "Funnel有効",
144146
"enable_plugin": "プラグインシステムを有効にする",
@@ -639,7 +641,7 @@
639641
"next": "次へ",
640642
"next_book": "次の本",
641643
"no_available_stores": "利用可能な書庫がありません。設定で書庫パスを追加してください",
642-
"no_books_library_path_notice": "閲覧可能な書籍が見つかりません。ライブラリパスを設定してください。スキャン完了後、ページを再読み込みするか確認するダイアログが表示されます",
644+
"no_books_library_path_notice": "閲覧可能な書籍が見つかりません。ライブラリパスを設定してください。スキャン完了後、ページは自動的に再読み込みされます",
643645
"no_config_file_to_delete_in_path": "選択したパスには削除できる設定ファイルがありません。",
644646
"no_pages_in_pdf": "PDF内にページがありません",
645647
"no_pattern": "無地",
@@ -724,6 +726,7 @@
724726
"register_file_association": "圧縮ファイルの関連付けを登録(候補として追加)",
725727
"register_folder_context_menu": "フォルダー右クリックメニューを登録(Comigoで開く)",
726728
"remote_access": "リモートアクセス",
729+
"rescan_all_stores": "再スキャン",
727730
"rescan_store": "書庫スキャン",
728731
"rescan_store_in_progress": "書庫をスキャンしています。お待ちください...",
729732
"rescan_store_success": "書庫のスキャンが完了しました。{0} 冊の新しい書籍が追加されました",
@@ -931,13 +934,13 @@
931934
"tui_url_copied": "URL をコピーしました: %s",
932935
"type_or_paste_content": "入力または貼り付け",
933936
"ui_suggest_reload_default": "サーバー側のデータが更新されました。最新の画面を見るためにページを再読み込みしますか?",
934-
"ui_suggest_reload_reason_auto_library_rescan_done": "定期スキャンが完了しました。本棚などを更新するためにページを再読み込みしますか?",
937+
"ui_suggest_reload_reason_auto_library_rescan_done": "定期スキャンが完了しました。ページは自動的に再読み込みされます。",
935938
"ui_suggest_reload_reason_debug_toggle": "デバッグモードが切り替わりました。関連設定を表示するためにページを再読み込みしますか?",
936-
"ui_suggest_reload_reason_library_rescan_done": "ライブラリのスキャンが完了しました。本棚などを更新するためにページを再読み込みしますか?",
939+
"ui_suggest_reload_reason_library_rescan_done": "ライブラリのスキャンが完了しました。ページは自動的に再読み込みされます。",
937940
"ui_suggest_reload_reason_login_settings_changed": "ログイン設定が更新されました。ページを再読み込みしますか?",
938941
"ui_suggest_reload_reason_plugins_changed": "プラグインの状態が変わりました。反映のためにページを再読み込みしますか?",
939942
"ui_suggest_reload_reason_server_config_changed": "ネットワークまたはサーバー設定が変更されました。ページを再読み込みしますか?",
940-
"ui_suggest_reload_reason_single_store_rescan_done": "このライブラリの再スキャンが完了しました。ページを再読み込みしますか?",
943+
"ui_suggest_reload_reason_single_store_rescan_done": "このライブラリの再スキャンが完了しました。ページは自動的に再読み込みされます。",
941944
"unable_to_extract_images_from_pdf": "PDFから画像を抽出できませんでした。",
942945
"unknown": "不明",
943946
"unregister_context_menu": "右クリックメニューを削除(Comigoで開く)",

assets/locale/zh_CN.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@
139139
"enable_database": "启用本地数据库保存已扫描的书籍数据",
140140
"enable_database_description": "启用本地数据库,保存扫描到的书籍数据。",
141141
"enable_database_label": "启用数据库",
142+
"db_type": "数据库类型:sqlite 或 postgres",
143+
"db_dsn": "PostgreSQL 连接字符串",
142144
"enable_file_upload": "启用文件上传功能",
143145
"enable_funnel": "Funnel模式",
144146
"enable_plugin": "启用插件系统",
@@ -639,7 +641,7 @@
639641
"next": "下一曲",
640642
"next_book": "下一本",
641643
"no_available_stores": "没有可用的书库,请先在设置中添加书库路径",
642-
"no_books_library_path_notice": "未检测到可阅读的书籍,请先配置书库路径。书库扫描完成后,界面会提示您是否刷新页面",
644+
"no_books_library_path_notice": "未检测到可阅读的书籍,请先配置书库路径。书库扫描完成后,页面会自动刷新",
643645
"no_config_file_to_delete_in_path": "当前选择的路径下,没有可删除的配置文件",
644646
"no_pages_in_pdf": "PDF中无页面",
645647
"no_pattern": "纯色",
@@ -724,6 +726,7 @@
724726
"register_file_association": "注册压缩文件类型关联(作为候选打开方式)",
725727
"register_folder_context_menu": "注册文件夹右键菜单(“使用Comigo打开”)",
726728
"remote_access": "远程访问",
729+
"rescan_all_stores": "重新扫描",
727730
"rescan_store": "扫描书库",
728731
"rescan_store_in_progress": "正在扫描书库,请稍候...",
729732
"rescan_store_success": "书库扫描完成,新增 {0} 本书",
@@ -931,13 +934,13 @@
931934
"tui_url_copied": "已复制URL: %s",
932935
"type_or_paste_content": "键入或粘贴内容",
933936
"ui_suggest_reload_default": "服务器端数据已更新,是否刷新页面以查看最新界面?",
934-
"ui_suggest_reload_reason_auto_library_rescan_done": "定时书库扫描已完成,是否刷新页面以更新书架等内容?",
937+
"ui_suggest_reload_reason_auto_library_rescan_done": "定时书库扫描已完成,页面将自动刷新。",
935938
"ui_suggest_reload_reason_debug_toggle": "调试模式已切换,是否刷新页面以加载相关设置项?",
936-
"ui_suggest_reload_reason_library_rescan_done": "书库扫描已完成,是否刷新页面以更新书架等内容?",
939+
"ui_suggest_reload_reason_library_rescan_done": "书库扫描已完成,页面将自动刷新。",
937940
"ui_suggest_reload_reason_login_settings_changed": "登录设置已更新,是否刷新页面?",
938941
"ui_suggest_reload_reason_plugins_changed": "插件状态已变更,是否刷新页面以生效?",
939942
"ui_suggest_reload_reason_server_config_changed": "网络或服务相关设置已变更,是否刷新页面?",
940-
"ui_suggest_reload_reason_single_store_rescan_done": "该书库已重新扫描完成,是否刷新页面?",
943+
"ui_suggest_reload_reason_single_store_rescan_done": "该书库已重新扫描完成,页面将自动刷新。",
941944
"unable_to_extract_images_from_pdf": "无法从PDF中提取图片",
942945
"unknown": "未知",
943946
"unregister_context_menu": "清理右键菜单(“使用Comigo打开”)",

cmd/init_flags.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ func InitFlags() {
5555
RootCmd.PersistentFlags().BoolVar(&cfg.EnableDatabase, "database", false, locale.GetString("enable_database"))
5656
runtimeViper.BindPFlag("EnableDatabase", RootCmd.PersistentFlags().Lookup("database"))
5757

58+
// 数据库类型。未启用数据库时该配置会被忽略。
59+
RootCmd.PersistentFlags().StringVar(&cfg.DBType, "db-type", "sqlite", locale.GetString("db_type"))
60+
runtimeViper.BindPFlag("DBType", RootCmd.PersistentFlags().Lookup("db-type"))
61+
62+
// PostgreSQL 连接字符串。SQLite 模式不使用。
63+
RootCmd.PersistentFlags().StringVar(&cfg.DBDSN, "db-dsn", "", locale.GetString("db_dsn"))
64+
runtimeViper.BindPFlag("DBDSN", RootCmd.PersistentFlags().Lookup("db-dsn"))
65+
5866
// 服务端口
5967
RootCmd.PersistentFlags().IntVarP(&cfg.Port, "port", "p", 1234, locale.GetString("port"))
6068
runtimeViper.BindPFlag("Port", RootCmd.PersistentFlags().Lookup("port"))

cmd/set_metadata.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ func LoadMetadata() {
2121
model.IStore = store.RamStore
2222
return
2323
}
24-
if err := sqlc.OpenDatabase(configDir); err != nil {
24+
if err := sqlc.OpenDatabase(sqlc.DBOptions{
25+
Type: config.GetCfg().DBType,
26+
DSN: config.GetCfg().DBDSN,
27+
ConfigDir: configDir,
28+
}); err != nil {
2529
logger.Infof(locale.GetString("log_open_database_error"), err)
2630
model.IStore = store.RamStore
31+
config.GetCfg().EnableDatabase = false
2732
} else {
2833
model.IStore = sqlc.DbStore
2934
}
@@ -50,7 +55,7 @@ func SaveMetadata() {
5055
}
5156
}
5257
// 启用数据库的时候,同步书籍元数据到RamStore
53-
if config.GetCfg().EnableDatabase {
58+
if config.GetCfg().EnableDatabase && sqlc.DbStore != nil {
5459
allBooks, err := sqlc.DbStore.ListBooks()
5560
if err != nil {
5661
logger.Infof(locale.GetString("log_error_listing_books_from_database"), err)
@@ -63,7 +68,7 @@ func SaveMetadata() {
6368
}
6469
}
6570
// 启用数据库的时候,保存书籍元数据到到数据库
66-
if config.GetCfg().EnableDatabase {
71+
if config.GetCfg().EnableDatabase && sqlc.DbStore != nil {
6772
err := scan.SaveBooksToDatabase(config.GetCfg())
6873
if err != nil {
6974
logger.Infof(locale.GetString("log_failed_savebookstodatabase"), err)

config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ type Config struct {
3535
CustomPlugins []CustomPlugin `json:"-" toml:"-" comment:"用户自定义插件内容列表"`
3636
DisableLAN bool `json:"DisableLAN" comment:"只在本机提供阅读服务,不对外共享"`
3737
EnableDatabase bool `json:"EnableDatabase" comment:"启用本地数据库,保存扫描到的书籍数据。"`
38+
DBType string `json:"DBType" comment:"数据库类型:sqlite 或 postgres。仅启用数据库时生效。"`
39+
DBDSN string `json:"DBDSN" comment:"PostgreSQL 连接字符串。仅 DBType=postgres 时生效。"`
3840
EnableTLS bool `json:"EnableTLS" comment:"是否启用HTTPS协议。需要设置证书于key文件。"`
3941
AutoTLSCertificate bool `json:"AutoTLSCertificate" comment:"自动申请、签发 HTTPS 证书(Let's Encrypt)"`
4042
BasePath string `json:"BasePath" comment:"反向代理基础路径,例如 /some/path。留空表示服务挂载在根路径 /"`

config/get_set.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ import (
1010
"github.com/yumenaka/comigo/tools/logger"
1111
)
1212

13+
// GetCfg 返回当前进程的全局配置指针。
14+
// 调用方可以通过返回值读取或修改配置;并发写入时需要遵守 config.Mutex 的保护约定。
1315
func GetCfg() *Config {
1416
return &cfg
1517
}
1618

19+
// CopyCfg 返回当前全局配置的值拷贝。
20+
// 返回值用于变更前后对比,不会随全局配置后续修改而自动更新。
1721
func CopyCfg() Config {
1822
return cfg
1923
}

0 commit comments

Comments
 (0)