feat: implement user type-based UI access control

Restrict settings interface and material validation features based on user type:

- SettingsTab: User type only sees "Test ERP Connection" and "Test Database Connection" buttons; Admin sees full configuration interface
- MaterialValidationTab: Hide manager filter and data source options from non-admin users; default to database_filtered mode
- test_db_connection(): Read from config directly to support User type without UI variables
- Add backward compatibility: no session_manager defaults to full interface

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-02-10 17:30:26 +08:00
parent db461e39f9
commit d18bedcd77
4 changed files with 219 additions and 79 deletions

View File

@@ -16,21 +16,26 @@ from config.schema import DatabaseType
class SettingsTab(ttk.Frame):
"""设置标签页"""
def __init__(self, parent, config: ConfigManager):
def __init__(self, parent, config: ConfigManager, session_manager=None):
"""
初始化设置标签页
Args:
parent: 父容器
config: 配置管理器
session_manager: 会话管理器,用于获取用户类型
"""
super().__init__(parent)
self.config = config
self.session_manager = session_manager
self.create_widgets()
self.load_settings()
def create_widgets(self):
"""创建界面组件"""
# 判断用户类型
is_user_only = self.session_manager and self.session_manager.get_user_type() == 'User'
# 创建主容器,带滚动条
canvas = tk.Canvas(self)
scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
@@ -43,40 +48,42 @@ class SettingsTab(ttk.Frame):
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
# ERP 配置组
self._create_erp_group(scrollable_frame)
# 根据用户类型创建配置组
if not is_user_only:
# 管理员显示所有配置组
self._create_erp_group(scrollable_frame)
self._create_database_group(scrollable_frame)
self._create_browser_group(scrollable_frame)
self._create_paths_group(scrollable_frame)
self._create_extraction_group(scrollable_frame)
self._create_validation_group(scrollable_frame)
# 数据库配置组
self._create_database_group(scrollable_frame)
# 浏览器配置组
self._create_browser_group(scrollable_frame)
# 路径配置组
self._create_paths_group(scrollable_frame)
# 处理配置组
self._create_extraction_group(scrollable_frame)
# 校验配置组
self._create_validation_group(scrollable_frame)
# 按钮区域
# 按钮区域 - 根据用户类型显示不同按钮
button_frame = ttk.Frame(scrollable_frame)
button_frame.grid(row=6, column=0, columnspan=2, pady=20, sticky="ew")
ttk.Button(
button_frame, text="测试 ERP 连接", command=self.test_erp_connection
).pack(side="left", padx=5)
ttk.Button(
button_frame, text="测试数据库连接", command=self.test_db_connection
).pack(side="left", padx=5)
ttk.Button(button_frame, text="保存设置", command=self.save_settings).pack(
side="left", padx=5
)
ttk.Button(button_frame, text="恢复默认", command=self.reset_defaults).pack(
side="left", padx=5
)
if is_user_only:
# 普通用户只显示测试按钮
ttk.Button(
button_frame, text="测试 ERP 连接", command=self.test_erp_connection
).pack(side="left", padx=5)
ttk.Button(
button_frame, text="测试数据库连接", command=self.test_db_connection
).pack(side="left", padx=5)
else:
# 管理员显示所有按钮
ttk.Button(
button_frame, text="测试 ERP 连接", command=self.test_erp_connection
).pack(side="left", padx=5)
ttk.Button(
button_frame, text="测试数据库连接", command=self.test_db_connection
).pack(side="left", padx=5)
ttk.Button(button_frame, text="保存设置", command=self.save_settings).pack(
side="left", padx=5
)
ttk.Button(button_frame, text="恢复默认", command=self.reset_defaults).pack(
side="left", padx=5
)
# 布局
canvas.grid(row=0, column=0, sticky="nsew")
@@ -326,6 +333,15 @@ class SettingsTab(ttk.Frame):
def load_settings(self):
"""从配置加载设置到界面"""
# 判断是否为仅测试用户模式
is_user_only = self.session_manager and self.session_manager.get_user_type() == 'User'
if is_user_only:
# 普通用户模式 - 只需要加载测试连接所需的配置
# 不需要加载设置到界面,因为界面没有配置输入框
return
# 管理员模式 - 加载所有配置
# ERP 设置
self.erp_url_var.set(self.config.get("erp.url", ""))
self.erp_username_var.set(self.config.get("erp.username", ""))
@@ -431,7 +447,8 @@ class SettingsTab(ttk.Frame):
def test_db_connection(self):
"""测试数据库连接"""
db_type = self.db_type_var.get()
# 从配置读取而不是从 UI 变量(支持 User 类型用户)
db_type = self.config.get("database.db_type", "sqlserver")
try:
if db_type == "mysql":
@@ -439,11 +456,11 @@ class SettingsTab(ttk.Frame):
from mysql.connector import Error
conn = mysql.connector.connect(
host=self.mysql_host_var.get(),
port=self.mysql_port_var.get(),
database=self.db_name_var.get(),
user=self.db_username_var.get(),
password=self.db_password_var.get(),
host=self.config.get("database.mysql.host", ""),
port=self.config.get("database.mysql.port", 3306),
database=self.config.get("database.database", ""),
user=self.config.get("database.username", ""),
password=self.config.get("database.password", ""),
connection_timeout=5
)
conn.close()
@@ -451,10 +468,10 @@ class SettingsTab(ttk.Frame):
else:
conn_str = (
f"DRIVER={{ODBC Driver 18 for SQL Server}};"
f"SERVER={self.db_server_var.get()};"
f"DATABASE={self.db_name_var.get()};"
f"UID={self.db_username_var.get()};"
f"PWD={self.db_password_var.get()};"
f"SERVER={self.config.get('database.server', '')};"
f"DATABASE={self.config.get('database.database', '')};"
f"UID={self.config.get('database.username', '')};"
f"PWD={self.config.get('database.password', '')};"
f"TrustServerCertificate=yes;"
)
conn = pyodbc.connect(conn_str, timeout=5)