From e9f94db1d647431e53bbe46ae3d7cfe227b5de87 Mon Sep 17 00:00:00 2001 From: zhu-mengmeng <15588200382@163.com> Date: Fri, 13 Jun 2025 17:14:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E6=95=B0=E6=8D=AE=E6=BA=90=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/app_config.json | 30 ++- main.py | 12 +- ui/settings_ui.py | 34 ++-- .../__pycache__/config_loader.cpython-310.pyc | Bin 4192 -> 6491 bytes utils/__pycache__/sql_utils.cpython-310.pyc | Bin 2678 -> 5714 bytes utils/config_loader.py | 153 ++++++++++++++- utils/init_db.py | 13 +- utils/sql_utils.py | 165 ++++++++++++++-- .../__pycache__/login_widget.cpython-310.pyc | Bin 3474 -> 3456 bytes widgets/login_widget.py | 6 +- widgets/settings_widget.py | 182 ++++++++++++++---- 11 files changed, 505 insertions(+), 90 deletions(-) diff --git a/config/app_config.json b/config/app_config.json index 7e456a2..33a27f1 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -9,13 +9,29 @@ } }, "database": { - "type": "sqlite", - "path": "db/jtDB.db", - "host": "", - "port": "", - "user": "", - "password": "", - "name": "" + "default": "sqlite", + "sources": { + "sqlite": { + "path": "db/jtDB.db", + "description": "默认SQLite数据库" + }, + "postgresql": { + "host": "localhost", + "port": "5432", + "user": "postgres", + "password": "", + "name": "jtDB", + "description": "PostgreSQL数据库" + }, + "mysql": { + "host": "localhost", + "port": "3306", + "user": "root", + "password": "", + "name": "jtDB", + "description": "MySQL数据库" + } + } }, "camera": { "enabled": false, diff --git a/main.py b/main.py index 59eca21..7d3ee9f 100644 --- a/main.py +++ b/main.py @@ -179,8 +179,13 @@ def main(): # 创建db目录(如果不存在) os.makedirs('db', exist_ok=True) + # 从配置获取SQLite数据库路径 + config_loader = ConfigLoader.get_instance() + sqlite_config = config_loader.get_database_config('sqlite') + sqlite_db_path = sqlite_config.get('path', 'db/jtDB.db') + # 检查数据库是否存在,如果不存在则初始化 - if not os.path.exists('db/jtDB.db'): + if not os.path.exists(sqlite_db_path): from utils.init_db import init_database init_database() logging.info("初始化数据库完成") @@ -190,6 +195,11 @@ def main(): exit_code = app.exec() logging.info(f"应用程序退出,退出码: {exit_code}") + + # 关闭所有数据库连接 + from utils.sql_utils import SQLUtils + SQLUtils.close_all_connections() + sys.exit(exit_code) except Exception as e: diff --git a/ui/settings_ui.py b/ui/settings_ui.py index 5ad530a..622fe21 100644 --- a/ui/settings_ui.py +++ b/ui/settings_ui.py @@ -205,25 +205,31 @@ class SettingsUI(QWidget): self.database_layout = QVBoxLayout(self.database_tab) self.database_layout.setContentsMargins(20, 20, 20, 20) - # 数据库类型选择 - self.db_type_group = QGroupBox("数据库类型") + # 数据源类型选择 + self.db_type_group = QGroupBox("数据源类型") self.db_type_group.setFont(self.normal_font) self.db_type_layout = QHBoxLayout() - self.sqlite_radio = QCheckBox("SQLite") - self.sqlite_radio.setFont(self.normal_font) - self.sqlite_radio.setChecked(True) + self.db_type_combo = QComboBox() + self.db_type_combo.setFont(self.normal_font) + self.db_type_combo.addItem("SQLite") + self.db_type_combo.addItem("PostgreSQL") + self.db_type_combo.addItem("MySQL") - self.pgsql_radio = QCheckBox("PostgreSQL") - self.pgsql_radio.setFont(self.normal_font) - - self.mysql_radio = QCheckBox("MySQL") - self.mysql_radio.setFont(self.normal_font) - - self.db_type_layout.addWidget(self.sqlite_radio) - self.db_type_layout.addWidget(self.pgsql_radio) - self.db_type_layout.addWidget(self.mysql_radio) + self.db_type_layout.addWidget(QLabel("当前配置类型:")) + self.db_type_layout.addWidget(self.db_type_combo) self.db_type_layout.addStretch(1) + + # 添加当前使用的数据源选择 + self.current_source_label = QLabel("当前使用的数据源:") + self.current_source_label.setFont(self.normal_font) + self.current_source_combo = QComboBox() + self.current_source_combo.setFont(self.normal_font) + self.current_source_combo.addItems(["SQLite", "PostgreSQL", "MySQL"]) + + self.db_type_layout.addWidget(self.current_source_label) + self.db_type_layout.addWidget(self.current_source_combo) + self.db_type_group.setLayout(self.db_type_layout) self.database_layout.addWidget(self.db_type_group) diff --git a/utils/__pycache__/config_loader.cpython-310.pyc b/utils/__pycache__/config_loader.cpython-310.pyc index b0dd2df2521dd8fb951de060fbab575e7cdaee4d..871a615370ce2fe79cf1dc38d49691f0cc5f2b5e 100644 GIT binary patch delta 2982 zcmaJ@Ym5`u6`p%%Jf0n|$7X?L*%t-^&S;54*(@QHrWFJ=646G@l9!3(diM^F!Pw5V zCuBF?II5s538alCkTx;tT6rRc6?B_~>=L#8QAMg$sY?25TB-f9_OgA5R(<@S1$xfR z*eomB8O@n{&pnTO&OPUw`9tKlTeMs-s0wiX{EvH{{ngsIknn@&Ks5=ji^^mRTaUYX zQ#eDbq_G)ED7KD%NQ7}pgs}}E6=ZjmXhY_n!D%P&>ek!U#|2i|Jg}Zpq|El9{J-g`zDD+|$1$uH<2y;zq$1Yzb|im8~A% z+A?2*x>A4t=B>8GbGf1}@-Ael4TWbiao?fQ!ZR72+Wrxfb0b@{{e_&#M~p%`G6>tk z5?Sa4qD!{ljf2I*%-EkaGsT4Q9GEh>0oCDgQpt2Sz6@t&6xh$5n2SbS8rZyLvrhR2 zu*Ek5i7N+<(cxT@v$4P)V>Fgeri_G{*J(UZg2B_tjM)RywNHLrn|QNk?eh(2;P5Nxa0^<|tk-?_cdiB}DV}6- z9=YuPbSjbFpU4^pGnn-o-|q5DAW5l4+K5KFZ?sWOq&`Y0g@;Jjq-#{AB8;v(T;MtU ztF*-(xijhSu-@sd{fGK*$^-v~@};u11FVM$l|W{(Wl96+285*R?fRbMaywJSU;@Xzth$ZBDnFj^wO8D}EA2_G*)-!TbmyF?~MMwzcl$7zYCq2(%c zTr2_SAmszjDzspgvKDARS`wMKT425%Lbear%Gi%pFb+n7prnD)E*8oX7WTN%q237k z)Eli}E5TqpHV<2M2D?;t4VUN+Fz$|Fn>nXvp0%<*f90QTkX{m6QnU_EbUB$%epx$$EhgaY2TD#WZhB_^%!PHLgCcPx@G|V*_)b zfgMtYxVx)_^+Mb~b5s|Z2Mk*~gh+N<3UDHi{srJf0yqhQD?f{rqz0TkE<6c(TRs=xhW{iBy_6XzGJG(o1Jd!l~s?ONpn z*KsTsbFe}$12TBM?HF_biFc#vJAlm1zS1=6YQk=opcqH^aQi-jBW!-&hh!}h9Z3|) zIwW@@=|Hj`h*?H(ysa0r1y-6-aNG^Y_BYX8lkY|ckWioae(j|nxqIZBQ1}59?gvsk z|J^0>a~ID+98rM8GGb!1{@SN=7iXegBBGET+m}xPaGLl0KYd4}p?ni`QQwT9qIbwk z&$#x^h08yAcY9<|SIS%gLB1WySAp1K$|&-$Iiq|o&+o^DuLIG2JPfaR3mf);4GwNN zft3&sW{ty%CZF#_9mExv$T->oj{%_oaw-XnDrqf?2vYKOMOFc*!q-)~ov7Ze zU2O#>B^q!Q;Gu#>6cT}VJJF~DGx_tjeog5m%8T^I*v4HB;y#oE^yRVtiNhm+a*b>H zxO^A+=DjfGK_uIN*b*}j<(DMpW+wPIP;g0nn6a7ZYyLkGpL6im-&!`2UrhI^r^z<> z&IyAHH{gOVW3^msuwf-FFA@;P|x{tK;0pJgwC5|e5b?_|s zqt*+-Uh~n!z*WFR z0l-`YFh{790F}bb2V>;RC4%UZ7OMC|<~RQhifY8WF2C|g?R%%|Cyv#o-k85ITYKwe zsPLO*Z_T#q-}dTdd!)&CC9hmMQG4$@QK)zLJBeJXE%$#3{=={0kAUAjMr0b(L z@x!^#emei!2kxJZ(}&iKwyDh0BgI7?+y-rKb8sx&_{hf^xPw0}d^ZwAjj?4-0q;*G zrW1~3+erI^D0=Jp+smPC5~#Qv{~x>#>3~8j;Kx-7v=T*>NSinoxur%MT8or)GN^|w zGxYEp>=~yO9q;@JoW_ytL-Ldr3$L>N8dCcaEfql`5;TiS6j=!oM_9CzXrINxsR;d}oJN!*4Q delta 741 zcmZ9K&ubGw6vyYyZnBfz>^46(H8l#YqIOMepr}-|rH!G2LOir8L{t(cVq(Ow-3pDV zUUJJp%0N9dLUZg<@{f34FTIN5#e)cKxxvG2DC*qgR+|(JKE@+Bhk2C8a5gzzA&&j|$0`*c%#eM67R`qq zslhI7k($y2cUC-63hy5guC5RsmF+<6~WHe5SR?uHGX+JhmI+ z5oxtUKG7Zk89AxMGd4DXY*HZ26sqt>EqbisvHwp}svtV*S%`~0^$k!l8OVyKf%B=R z&db@Fm(R`cvQHe%SG|o!#WnCd#C~8Z>QG-PH5xwSC9hO2tyRRY;F9K^!@6UNoVFl# zwEXfiE-AGj1{RzdBq4VZT`-iMj|-Ww`%OXAeY`rTZN-19vW< zpKD57MEELSf7NiATu)0l5^0Hy#1)Ca34$`ajJVrBvc5ye*LdZ5X}#`=pOFka=%=FF zFn0~>g>M5Kj^bXI9YcHB<^F=a#r6`xiI7GwsS(G8Yhr^7LqV$o4u`4bNxZS+zU8&8SFiPT>dhMv*@ diff --git a/utils/__pycache__/sql_utils.cpython-310.pyc b/utils/__pycache__/sql_utils.cpython-310.pyc index a1332ee6721597b8551b654da373c3299670a65b..a3bc11cda7dce61260774948859039070534eed2 100644 GIT binary patch literal 5714 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 literal 2678 zcmZ`*&2Jk;6rY)0uQwYzbwZM+Egz;I6jP}dAOWgS)l%B3fQ%q56~3%CI}_K5z3a}b zNxgDW)#gN{!kG$WOO;Sg+zSW(j=j=U;+z`?%6qd}%W0go=FQvL_h#PjeT~Cn(IN2s zmA`oFcbkyE@n!shHF5!lS^>fdr!7(^v86d$r#DG3Z4$wH3zXoG!`inbpc|QtQ8z|1 zr$;hIDsz=^#*IzFjR&l5a=J_^=09)_srg999|K-4z)-6|1gTR_>Wov)Hc8#!1~*|g z`C)GH{3fmEfV24&a28+U)4Z^0*7Lv>`3!J2aEEvaxG6r%=Rnipukd-8r}+Y3gt@?T zV9SxjUjFKf8&R{Rd!;AcmFZeN*J%LUy3+|&)Q|%B_((_f{IJt_uiRASAdJe*Kt*1wC3s@N_huxL zd^*1$FYPk>MQ!dy-ioJ0Y@ch3b|`!2;)NT5>UKJzj07+52J~E6$EV`xkR^6@crtyh zjgpt845gd`=jm`t^rysFBt}C-iSv!u>WWk-535^LVvO{jDJkG9>Mz1j^FZdQNo~4F z(|L)OSc%4^Q7Cs)spezmW)Jcv3>`|H#gMmMA}vnuLgucK0qxU18#0Q)V*?}0;tH#! z08NSZC3$g2_}xfoAdtslyWNDe)mA44xHGXjp7h%4B?w7zSJA!Q6|#2%_EMPNHh`Id zU%WU1ut#tY3PgbJ(I~C}6CXOr_M5r}O%j>CiaUZJpuJOIG0o_ZY zcPf?!DACPnlnw)zOkKX?i%!%GgT$6$tF_|!>lHH%(h`auK`AO;hC7p?=yo8JL#!MGVDZrr(tV=) zKw`&5kUJU30mY0&Pym<864zM^01X6-cZml1{Kuc3J$;gblx5i9IzrJ!hv7^?y@}i; z409>IaS$JY><%WX!yHRS~ZG06i(~dvT#`!D@ z$E`e%dZ&QIuZ^smBzK^FJ6KkjOz7w3-HKpo$=jn<_8bMxdg4*Nys#S`3D+gX%xNhRO zZad`N7V-rbnxofBzsMrUrWc1U!q@TjI1(%g`4$rNy+p5QJH{$f*QUNXFe+H;3j3N3 z?bgmaMaOb%C+}FcWg7)UqD&GEy%@0ktZ9-b3v=Thni^YSW9>rskpdib#yJ;3;Qf4wb5+ z^0k-;yNB0tEhawr^c75KLXW{`avK`A`4HMwOZa>8fqn!a zZSs)#e8La7ukZe|Mld2RLmt6K@e@2MM1!I50;lgjk>B7Hs`4FuZ0BhiOk8;=LK(Mt zNdE|18mwWzP)L{NNRU8=bc@y7wS+391Pl3^uXXqw@D2hp1gvI&dcw{C7h`n=YfRVy zL)7fdP)+%THRTWX+*Q+QaZ$oURFqs$a#2ZjF3V`8)?N@h!zd6=*zXKh&=u8CD9uxB z1{Vh%+fvP~&YD}r-`<-_b^4ue0uR z+OXl~^u*v4R;HhG4`62<<5C_6PvcaJViE3(4fT>Lw=r@>KkV-bTe%cU%DbT-2uto1 zu3c6&Q_~Y+9C~gq?Wyc5*zzV+CmT-Pq~#+@#0OW5-jMl$=fv1kkq#uqhS+z z@S^BJUoRp;d-SL|cr5-2-emt1MZ`B-EfKm8zHess&CF-!u>7`c^-VKH)c0g-r~Nhi z$x1<~r`%E5CmcBC+G{$d0X+uJ-B8FVE?KU6Tt-i1a2Wro*SDPLs7=_aGUGgr}mQ`ZNeD|pz#ynqi4#WzU zq8LsL9ntIb_C*mx$QH78hr7a(YsNJ&dK^~kl%?n+^Z~ diff --git a/widgets/login_widget.py b/widgets/login_widget.py index 7007981..1a88fea 100644 --- a/widgets/login_widget.py +++ b/widgets/login_widget.py @@ -10,7 +10,8 @@ import threading def check_user_login(user_id, password): """验证用户登录""" try: - db = SQLUtils('sqlite', database='db/jtDB.db') + # 始终使用SQLite数据源验证登录 + db = SQLUtils(source_name='sqlite') db.execute_query("SELECT id FROM user WHERE username = ? AND password = ? AND is_deleted = 0", (user_id, password)) result = db.fetchone() db.close() @@ -22,7 +23,8 @@ def check_user_login(user_id, password): def get_user_info(user_id): """获取用户信息""" try: - db = SQLUtils('sqlite', database='db/jtDB.db') + # 始终使用SQLite数据源获取用户信息 + db = SQLUtils(source_name='sqlite') db.execute_query("SELECT username, 'Default Corp', 1, 1 FROM user WHERE username = ?", (user_id,)) result = db.fetchone() db.close() diff --git a/widgets/settings_widget.py b/widgets/settings_widget.py index d15f8b7..784dc81 100644 --- a/widgets/settings_widget.py +++ b/widgets/settings_widget.py @@ -1,9 +1,12 @@ from PySide6.QtWidgets import QMessageBox, QVBoxLayout import logging +import json +import os from ui.settings_ui import SettingsUI from utils.sql_utils import SQLUtils from widgets.inspection_settings_widget import InspectionSettingsWidget from widgets.pallet_type_settings_widget import PalletTypeSettingsWidget +from utils.config_loader import ConfigLoader class SettingsWidget(SettingsUI): def __init__(self, parent=None): @@ -52,19 +55,23 @@ class SettingsWidget(SettingsUI): else: logging.error("无法找到pallet_type_layout布局") + # 加载配置文件 + self.config_loader = ConfigLoader.get_instance() + # 连接信号和槽 self.connect_signals() # 初始化数据库类型UI状态 - self.update_db_ui_state() + self.load_db_config() logging.info("SettingsWidget初始化完成") def connect_signals(self): # 数据库类型选择 - self.sqlite_radio.toggled.connect(self.update_db_ui_state) - self.pgsql_radio.toggled.connect(self.update_db_ui_state) - self.mysql_radio.toggled.connect(self.update_db_ui_state) + self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state) + + # 更新当前使用的数据源 + self.current_source_combo.currentTextChanged.connect(self.update_default_source) # 按钮动作 self.test_conn_button.clicked.connect(self.test_connection) @@ -80,10 +87,67 @@ class SettingsWidget(SettingsUI): if hasattr(self, 'back_button'): self.back_button.clicked.connect(self.back_to_main) + def load_db_config(self): + """加载数据库配置""" + try: + # 获取默认数据源 + default_source = self.config_loader.get_value('database.default', 'sqlite').lower() + + # 设置当前使用的数据源组合框 + self._update_source_combo_items() # 更新组合框项目 + + index = self.current_source_combo.findText(default_source.capitalize(), Qt.MatchFixedString) + if index >= 0: + self.current_source_combo.setCurrentIndex(index) + + # 默认选择当前使用的数据源类型 + index = self.db_type_combo.findText(default_source.capitalize(), Qt.MatchFixedString) + if index >= 0: + self.db_type_combo.setCurrentIndex(index) + + # 更新UI状态 + self.update_db_ui_state() + + except Exception as e: + logging.error(f"加载数据库配置失败: {e}") + + def _update_source_combo_items(self): + """更新数据源下拉框项目""" + try: + # 清空当前项目 + self.current_source_combo.clear() + + # 获取所有配置的数据源 + sources = self.config_loader.get_value('database.sources', {}) + + # 添加数据源到下拉框 + for source_name in sources.keys(): + # 处理特殊情况:postgresql显示为PostgreSQL + display_name = source_name.capitalize() + self.current_source_combo.addItem(display_name, source_name) + + except Exception as e: + logging.error(f"更新数据源下拉框失败: {e}") + # 添加默认项 + self.current_source_combo.addItem("SQLite", "sqlite") + def update_db_ui_state(self): """根据选择的数据库类型更新UI状态""" - if self.sqlite_radio.isChecked(): - # SQLite模式下,只需要数据库文件路径 + db_type = self.db_type_combo.currentText().lower() + + # 处理特殊情况:PostgreSQL对应postgresql + if db_type == "postgresql": + db_type = "postgresql" + + # 加载选定类型的数据源配置 + config_path = f"database.sources.{db_type}" + db_config = {} + + if db_type == "sqlite": + # SQLite模式下,只需要数据库文件路径和说明 + path = self.config_loader.get_value(f"{config_path}.path", "db/jtDB.db") + description = self.config_loader.get_value(f"{config_path}.description", "") + self.host_input.setEnabled(False) self.host_input.setText("") self.user_input.setEnabled(False) @@ -93,41 +157,60 @@ class SettingsWidget(SettingsUI): self.port_input.setEnabled(False) self.port_input.setText("") self.database_input.setEnabled(True) - self.database_input.setText("db/jtDB.db") - elif self.pgsql_radio.isChecked(): + self.database_input.setText(path) + self.desc_input.setText(description) + + elif db_type == "postgresql": # PostgreSQL模式下,需要完整的连接信息 + host = self.config_loader.get_value(f"{config_path}.host", "localhost") + port = self.config_loader.get_value(f"{config_path}.port", "5432") + user = self.config_loader.get_value(f"{config_path}.user", "postgres") + password = self.config_loader.get_value(f"{config_path}.password", "") + name = self.config_loader.get_value(f"{config_path}.name", "jtDB") + description = self.config_loader.get_value(f"{config_path}.description", "") + self.host_input.setEnabled(True) - self.host_input.setText("localhost") + self.host_input.setText(host) self.user_input.setEnabled(True) - self.user_input.setText("postgres") + self.user_input.setText(user) self.password_input.setEnabled(True) - self.password_input.setText("") + self.password_input.setText(password) self.port_input.setEnabled(True) - self.port_input.setText("5432") + self.port_input.setText(port) self.database_input.setEnabled(True) - self.database_input.setText("jtDB") - elif self.mysql_radio.isChecked(): + self.database_input.setText(name) + self.desc_input.setText(description) + + elif db_type == "mysql": # MySQL模式下,需要完整的连接信息 + host = self.config_loader.get_value(f"{config_path}.host", "localhost") + port = self.config_loader.get_value(f"{config_path}.port", "3306") + user = self.config_loader.get_value(f"{config_path}.user", "root") + password = self.config_loader.get_value(f"{config_path}.password", "") + name = self.config_loader.get_value(f"{config_path}.name", "jtDB") + description = self.config_loader.get_value(f"{config_path}.description", "") + self.host_input.setEnabled(True) - self.host_input.setText("localhost") + self.host_input.setText(host) self.user_input.setEnabled(True) - self.user_input.setText("root") + self.user_input.setText(user) self.password_input.setEnabled(True) - self.password_input.setText("") + self.password_input.setText(password) self.port_input.setEnabled(True) - self.port_input.setText("3306") + self.port_input.setText(port) self.database_input.setEnabled(True) - self.database_input.setText("jtDB") + self.database_input.setText(name) + self.desc_input.setText(description) + + def update_default_source(self): + """更新默认使用的数据源""" + default_source = self.current_source_combo.currentText().lower() + self.config_loader.set_value('database.default', default_source) + logging.info(f"已更新默认使用的数据源为: {default_source}") def get_db_type(self): """获取当前选择的数据库类型""" - if self.sqlite_radio.isChecked(): - return "sqlite" - elif self.pgsql_radio.isChecked(): - return "pgsql" - elif self.mysql_radio.isChecked(): - return "mysql" - return "sqlite" # 默认返回sqlite + return self.db_type_combo.currentText().lower() def get_connection_params(self): """获取数据库连接参数""" @@ -174,19 +257,42 @@ class SettingsWidget(SettingsUI): params = self.get_connection_params()[1] desc = self.desc_input.text().strip() - # 这里应该将设置保存到配置文件中 - # 为了简单起见,这里只显示一个消息框 - settings_info = f"数据库类型: {db_type}\n" - for key, value in params.items(): - if key != "password": - settings_info += f"{key}: {value}\n" + try: + # 构建要保存的配置数据 + config_path = f"database.sources.{db_type}" + + if db_type == "sqlite": + self.config_loader.set_value(f"{config_path}.path", params["database"]) + self.config_loader.set_value(f"{config_path}.description", desc) else: - settings_info += f"{key}: {'*' * len(value)}\n" - - settings_info += f"说明: {desc}" - - QMessageBox.information(self, "设置已保存", f"数据库设置已保存!\n\n{settings_info}") - logging.info(f"数据库设置已保存,类型: {db_type}") + self.config_loader.set_value(f"{config_path}.host", params["host"]) + self.config_loader.set_value(f"{config_path}.port", params["port"]) + self.config_loader.set_value(f"{config_path}.user", params["user"]) + self.config_loader.set_value(f"{config_path}.password", params["password"]) + self.config_loader.set_value(f"{config_path}.name", params["database"]) + self.config_loader.set_value(f"{config_path}.description", desc) + + # 更新数据源下拉框 + self._update_source_combo_items() + + # 构建要显示的消息 + settings_info = f"数据库类型: {db_type}\n" + for key, value in params.items(): + if key != "password": + settings_info += f"{key}: {value}\n" + else: + settings_info += f"{key}: {'*' * len(value)}\n" + + settings_info += f"说明: {desc}" + + # 显示成功消息 + QMessageBox.information(self, "设置已保存", f"数据库设置已保存!\n\n{settings_info}") + logging.info(f"数据库设置已保存,类型: {db_type}") + + except Exception as e: + # 显示错误消息 + QMessageBox.critical(self, "保存失败", f"保存数据库设置失败!\n\n错误: {str(e)}") + logging.error(f"保存数据库设置失败: {str(e)}") def handle_inspection_configs_changed(self): """处理检验配置变更"""