style: format all Python files with Black
Apply Black formatter to the entire codebase for consistent code style. Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
This commit is contained in:
@@ -12,10 +12,10 @@ from .delete_progress_window import DeleteProgressWindow
|
||||
from .checkbox_treeview import CheckboxTreeview
|
||||
|
||||
__all__ = [
|
||||
'FileSelector',
|
||||
'LogText',
|
||||
'ProductionIdInput',
|
||||
'GuiTextHandler',
|
||||
'DeleteProgressWindow',
|
||||
'CheckboxTreeview'
|
||||
"FileSelector",
|
||||
"LogText",
|
||||
"ProductionIdInput",
|
||||
"GuiTextHandler",
|
||||
"DeleteProgressWindow",
|
||||
"CheckboxTreeview",
|
||||
]
|
||||
|
||||
@@ -39,10 +39,10 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
self.on_checkbox_change = on_checkbox_change # checkbox 状态改变回调
|
||||
|
||||
# 排序状态
|
||||
self.sort_column = None # 当前排序列的列标识符
|
||||
self.sort_direction = None # 'asc', 'desc', 或 None
|
||||
self.sort_column = None # 当前排序列的列标识符
|
||||
self.sort_direction = None # 'asc', 'desc', 或 None
|
||||
self.sortable_columns = ["选择", "材料名称"] # 可排序的列白名单
|
||||
self.original_headings = {} # 存储原始列标题文本(不含箭头)
|
||||
self.original_headings = {} # 存储原始列标题文本(不含箭头)
|
||||
|
||||
# 存储原始列标题(延迟执行以确保标题已设置)
|
||||
self.after(100, self._store_original_headings)
|
||||
@@ -121,7 +121,7 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
|
||||
# 初始化 checkbox 状态为未选中
|
||||
checkbox_char = values[0] if values else "☐"
|
||||
self.checkboxes[item] = (checkbox_char == "☑")
|
||||
self.checkboxes[item] = checkbox_char == "☑"
|
||||
|
||||
return item
|
||||
|
||||
@@ -134,8 +134,8 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
|
||||
def _store_original_headings(self):
|
||||
"""存储原始列标题文本(不含箭头)"""
|
||||
for col in self['columns']:
|
||||
self.original_headings[col] = self.heading(col, 'text')
|
||||
for col in self["columns"]:
|
||||
self.original_headings[col] = self.heading(col, "text")
|
||||
|
||||
def _get_column_id_from_column_index(self, column_index):
|
||||
"""将列索引 ('#1', '#2') 转换为列标识符
|
||||
@@ -147,7 +147,7 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
列标识符,如 '选择', '材料名称'
|
||||
"""
|
||||
index = int(column_index[1:]) - 1
|
||||
columns = self['columns']
|
||||
columns = self["columns"]
|
||||
if 0 <= index < len(columns):
|
||||
return columns[index]
|
||||
return None
|
||||
@@ -173,15 +173,15 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
# 确定新的排序方向
|
||||
if self.sort_column == column_id:
|
||||
# 同一列:asc -> desc -> None
|
||||
if self.sort_direction == 'asc':
|
||||
new_direction = 'desc'
|
||||
elif self.sort_direction == 'desc':
|
||||
if self.sort_direction == "asc":
|
||||
new_direction = "desc"
|
||||
elif self.sort_direction == "desc":
|
||||
new_direction = None
|
||||
else:
|
||||
new_direction = 'asc'
|
||||
new_direction = "asc"
|
||||
else:
|
||||
# 不同列:从升序开始
|
||||
new_direction = 'asc'
|
||||
new_direction = "asc"
|
||||
|
||||
# 应用排序
|
||||
if new_direction:
|
||||
@@ -208,35 +208,33 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
for item in self.get_children():
|
||||
values = self.item(item, "values")
|
||||
checkbox_state = self.checkboxes.get(item, False)
|
||||
items_data.append({
|
||||
'item_id': item,
|
||||
'values': values,
|
||||
'checked': checkbox_state
|
||||
})
|
||||
items_data.append(
|
||||
{"item_id": item, "values": values, "checked": checkbox_state}
|
||||
)
|
||||
|
||||
# 根据列和方向排序
|
||||
if column_id == "选择":
|
||||
# 按复选框状态排序(选中在前,未选中在后)
|
||||
items_data.sort(key=lambda x: x['checked'], reverse=(direction == 'desc'))
|
||||
items_data.sort(key=lambda x: x["checked"], reverse=(direction == "desc"))
|
||||
elif column_id == "材料名称":
|
||||
# 按材料名称排序
|
||||
items_data.sort(
|
||||
key=lambda x: str(x['values'][1]) if len(x['values']) > 1 else "",
|
||||
reverse=(direction == 'desc')
|
||||
key=lambda x: str(x["values"][1]) if len(x["values"]) > 1 else "",
|
||||
reverse=(direction == "desc"),
|
||||
)
|
||||
|
||||
# 重新排列项目顺序(使用 detach 和 move 保留项目ID和状态)
|
||||
for item_data in items_data:
|
||||
self.move(item_data['item_id'], '', 'end')
|
||||
self.move(item_data["item_id"], "", "end")
|
||||
|
||||
def _update_heading_display(self):
|
||||
"""更新列标题显示(添加/移除排序箭头)"""
|
||||
for col in self['columns']:
|
||||
for col in self["columns"]:
|
||||
original = self.original_headings.get(col, col)
|
||||
if col == self.sort_column:
|
||||
# 添加排序箭头
|
||||
arrow = " ↑" if self.sort_direction == 'asc' else " ↓"
|
||||
arrow = " ↑" if self.sort_direction == "asc" else " ↓"
|
||||
self.heading(col, text=original + arrow)
|
||||
else:
|
||||
# 移除箭头,显示原始标题
|
||||
self.heading(col, text=original)
|
||||
self.heading(col, text=original)
|
||||
|
||||
@@ -14,12 +14,14 @@ from datetime import datetime
|
||||
# 尝试导入 tkinterweb 和 markdown2
|
||||
try:
|
||||
from tkinterweb import HtmlFrame
|
||||
|
||||
HAS_TKINTERWEB = True
|
||||
except ImportError:
|
||||
HAS_TKINTERWEB = False
|
||||
|
||||
try:
|
||||
import markdown2
|
||||
|
||||
HAS_MARKDOWN2 = True
|
||||
except ImportError:
|
||||
HAS_MARKDOWN2 = False
|
||||
@@ -34,7 +36,7 @@ class DeleteProgressWindow:
|
||||
title: str = "执行删除",
|
||||
managers: str = "",
|
||||
dryrun: bool = False,
|
||||
on_cancel: Optional[Callable] = None
|
||||
on_cancel: Optional[Callable] = None,
|
||||
):
|
||||
"""
|
||||
初始化删除进度窗口
|
||||
@@ -100,14 +102,13 @@ class DeleteProgressWindow:
|
||||
self.progress_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
self.progress_var = tk.StringVar(value="准备中...")
|
||||
self.progress_label = ttk.Label(self.progress_frame, textvariable=self.progress_var)
|
||||
self.progress_label = ttk.Label(
|
||||
self.progress_frame, textvariable=self.progress_var
|
||||
)
|
||||
self.progress_label.pack(anchor="w")
|
||||
|
||||
self.progress_bar = ttk.Progressbar(
|
||||
self.progress_frame,
|
||||
mode='determinate',
|
||||
length=660,
|
||||
maximum=100
|
||||
self.progress_frame, mode="determinate", length=660, maximum=100
|
||||
)
|
||||
self.progress_bar.pack(fill=tk.X, pady=5)
|
||||
|
||||
@@ -120,15 +121,15 @@ class DeleteProgressWindow:
|
||||
height=10,
|
||||
wrap=tk.WORD,
|
||||
state=tk.DISABLED,
|
||||
font=('Consolas', 9)
|
||||
font=("Consolas", 9),
|
||||
)
|
||||
self.log_text.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# 配置日志标签颜色
|
||||
self.log_text.tag_configure('info', foreground='black')
|
||||
self.log_text.tag_configure('success', foreground='green')
|
||||
self.log_text.tag_configure('warning', foreground='orange')
|
||||
self.log_text.tag_configure('error', foreground='red')
|
||||
self.log_text.tag_configure("info", foreground="black")
|
||||
self.log_text.tag_configure("success", foreground="green")
|
||||
self.log_text.tag_configure("warning", foreground="orange")
|
||||
self.log_text.tag_configure("error", foreground="red")
|
||||
|
||||
# 报告区域(完成后显示)- 初始隐藏
|
||||
self.report_frame = ttk.LabelFrame(self.main_frame, text="执行报告", padding=5)
|
||||
@@ -145,7 +146,7 @@ class DeleteProgressWindow:
|
||||
height=20,
|
||||
wrap=tk.WORD,
|
||||
state=tk.DISABLED,
|
||||
font=('Consolas', 9)
|
||||
font=("Consolas", 9),
|
||||
)
|
||||
self.report_text.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
@@ -154,18 +155,12 @@ class DeleteProgressWindow:
|
||||
button_frame.pack(fill=tk.X)
|
||||
|
||||
self.cancel_button = ttk.Button(
|
||||
button_frame,
|
||||
text="取消执行",
|
||||
command=self._on_cancel
|
||||
button_frame, text="取消执行", command=self._on_cancel
|
||||
)
|
||||
self.cancel_button.pack(side=tk.RIGHT)
|
||||
|
||||
# 关闭按钮(初始隐藏)
|
||||
self.close_button = ttk.Button(
|
||||
button_frame,
|
||||
text="关闭",
|
||||
command=self.close
|
||||
)
|
||||
self.close_button = ttk.Button(button_frame, text="关闭", command=self.close)
|
||||
|
||||
def _on_cancel(self):
|
||||
"""处理取消操作"""
|
||||
@@ -187,7 +182,7 @@ class DeleteProgressWindow:
|
||||
"""
|
||||
if total > 0:
|
||||
percentage = int((current / total) * 100)
|
||||
self.progress_bar['value'] = percentage
|
||||
self.progress_bar["value"] = percentage
|
||||
self.progress_var.set(message)
|
||||
else:
|
||||
self.progress_var.set(message)
|
||||
@@ -263,8 +258,7 @@ class DeleteProgressWindow:
|
||||
"""
|
||||
# 使用 markdown2 转换
|
||||
html_body = markdown2.markdown(
|
||||
markdown_content,
|
||||
extras=['tables', 'fenced-code-blocks']
|
||||
markdown_content, extras=["tables", "fenced-code-blocks"]
|
||||
)
|
||||
|
||||
# 添加样式
|
||||
@@ -340,59 +334,65 @@ class DeleteProgressWindow:
|
||||
Returns:
|
||||
HTML 内容
|
||||
"""
|
||||
lines = markdown_content.split('\n')
|
||||
html_parts = ['<!DOCTYPE html><html><head><meta charset="UTF-8">',
|
||||
'<style>',
|
||||
'body { font-family: "Microsoft YaHei", Arial, sans-serif; font-size: 12px; padding: 10px; }',
|
||||
'h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }',
|
||||
'h2 { color: #34495e; border-bottom: 1px solid #bdc3c7; margin-top: 20px; }',
|
||||
'table { border-collapse: collapse; width: 100%; margin: 10px 0; }',
|
||||
'th, td { border: 1px solid #bdc3c7; padding: 8px; text-align: left; }',
|
||||
'th { background-color: #3498db; color: white; }',
|
||||
'</style></head><body>']
|
||||
lines = markdown_content.split("\n")
|
||||
html_parts = [
|
||||
'<!DOCTYPE html><html><head><meta charset="UTF-8">',
|
||||
"<style>",
|
||||
'body { font-family: "Microsoft YaHei", Arial, sans-serif; font-size: 12px; padding: 10px; }',
|
||||
"h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }",
|
||||
"h2 { color: #34495e; border-bottom: 1px solid #bdc3c7; margin-top: 20px; }",
|
||||
"table { border-collapse: collapse; width: 100%; margin: 10px 0; }",
|
||||
"th, td { border: 1px solid #bdc3c7; padding: 8px; text-align: left; }",
|
||||
"th { background-color: #3498db; color: white; }",
|
||||
"</style></head><body>",
|
||||
]
|
||||
|
||||
in_table = False
|
||||
for line in lines:
|
||||
if line.startswith('# '):
|
||||
html_parts.append(f'<h1>{line[2:]}</h1>')
|
||||
elif line.startswith('## '):
|
||||
html_parts.append(f'<h2>{line[3:]}</h2>')
|
||||
elif line.startswith('| '):
|
||||
if line.startswith("# "):
|
||||
html_parts.append(f"<h1>{line[2:]}</h1>")
|
||||
elif line.startswith("## "):
|
||||
html_parts.append(f"<h2>{line[3:]}</h2>")
|
||||
elif line.startswith("| "):
|
||||
if not in_table:
|
||||
html_parts.append('<table>')
|
||||
html_parts.append("<table>")
|
||||
in_table = True
|
||||
# 检查是否是表头分隔行
|
||||
if '|--' in line or '|-' in line:
|
||||
if "|--" in line or "|-" in line:
|
||||
continue
|
||||
cells = [cell.strip() for cell in line.split('|')[1:-1]]
|
||||
cells = [cell.strip() for cell in line.split("|")[1:-1]]
|
||||
if cells:
|
||||
# 第一行作为表头
|
||||
if html_parts[-1] == '<table>':
|
||||
html_parts.append('<tr>' + ''.join(f'<th>{c}</th>' for c in cells) + '</tr>')
|
||||
if html_parts[-1] == "<table>":
|
||||
html_parts.append(
|
||||
"<tr>" + "".join(f"<th>{c}</th>" for c in cells) + "</tr>"
|
||||
)
|
||||
else:
|
||||
html_parts.append('<tr>' + ''.join(f'<td>{c}</td>' for c in cells) + '</tr>')
|
||||
elif line.startswith('- '):
|
||||
html_parts.append(
|
||||
"<tr>" + "".join(f"<td>{c}</td>" for c in cells) + "</tr>"
|
||||
)
|
||||
elif line.startswith("- "):
|
||||
if in_table:
|
||||
html_parts.append('</table>')
|
||||
html_parts.append("</table>")
|
||||
in_table = False
|
||||
html_parts.append(f'<li>{line[2:]}</li>')
|
||||
elif line.strip() == '':
|
||||
html_parts.append(f"<li>{line[2:]}</li>")
|
||||
elif line.strip() == "":
|
||||
if in_table:
|
||||
html_parts.append('</table>')
|
||||
html_parts.append("</table>")
|
||||
in_table = False
|
||||
html_parts.append('<br>')
|
||||
html_parts.append("<br>")
|
||||
else:
|
||||
if in_table:
|
||||
html_parts.append('</table>')
|
||||
html_parts.append("</table>")
|
||||
in_table = False
|
||||
if line.strip():
|
||||
html_parts.append(f'<p>{line}</p>')
|
||||
html_parts.append(f"<p>{line}</p>")
|
||||
|
||||
if in_table:
|
||||
html_parts.append('</table>')
|
||||
html_parts.append("</table>")
|
||||
|
||||
html_parts.append('</body></html>')
|
||||
return '\n'.join(html_parts)
|
||||
html_parts.append("</body></html>")
|
||||
return "\n".join(html_parts)
|
||||
|
||||
def _markdown_to_text(self, markdown_content: str) -> str:
|
||||
"""
|
||||
@@ -404,34 +404,34 @@ class DeleteProgressWindow:
|
||||
Returns:
|
||||
格式化后的文本
|
||||
"""
|
||||
lines = markdown_content.split('\n')
|
||||
lines = markdown_content.split("\n")
|
||||
result = []
|
||||
|
||||
for line in lines:
|
||||
# 标题
|
||||
if line.startswith('# '):
|
||||
result.append('=' * 60)
|
||||
if line.startswith("# "):
|
||||
result.append("=" * 60)
|
||||
result.append(line[2:])
|
||||
result.append('=' * 60)
|
||||
elif line.startswith('## '):
|
||||
result.append('')
|
||||
result.append("=" * 60)
|
||||
elif line.startswith("## "):
|
||||
result.append("")
|
||||
result.append(line[3:])
|
||||
result.append('-' * 40)
|
||||
elif line.startswith('| '):
|
||||
result.append("-" * 40)
|
||||
elif line.startswith("| "):
|
||||
# 表格行 - 保持原样
|
||||
result.append(line)
|
||||
elif line.startswith('|--') or line.startswith('|-'):
|
||||
elif line.startswith("|--") or line.startswith("|-"):
|
||||
# 表格分隔线 - 跳过
|
||||
continue
|
||||
elif line.startswith('- '):
|
||||
elif line.startswith("- "):
|
||||
# 列表项
|
||||
result.append(' ' + line)
|
||||
elif line.strip() == '':
|
||||
result.append('')
|
||||
result.append(" " + line)
|
||||
elif line.strip() == "":
|
||||
result.append("")
|
||||
else:
|
||||
result.append(line)
|
||||
|
||||
return '\n'.join(result)
|
||||
return "\n".join(result)
|
||||
|
||||
def close(self):
|
||||
"""关闭窗口"""
|
||||
@@ -444,4 +444,4 @@ class DeleteProgressWindow:
|
||||
def set_completed(self):
|
||||
"""设置为完成状态"""
|
||||
self.cancel_button.pack_forget()
|
||||
self.close_button.pack(side=tk.RIGHT)
|
||||
self.close_button.pack(side=tk.RIGHT)
|
||||
|
||||
@@ -21,7 +21,7 @@ class FileSelector(ttk.Frame):
|
||||
file_type: str = "file",
|
||||
file_types: list = None,
|
||||
initial_dir: str = "",
|
||||
on_change: Optional[Callable] = None
|
||||
on_change: Optional[Callable] = None,
|
||||
):
|
||||
"""
|
||||
初始化文件选择器
|
||||
@@ -64,15 +64,10 @@ class FileSelector(ttk.Frame):
|
||||
|
||||
if self.file_type == "file":
|
||||
path = filedialog.askopenfilename(
|
||||
title="选择文件",
|
||||
initialdir=current_path,
|
||||
filetypes=self.file_types
|
||||
title="选择文件", initialdir=current_path, filetypes=self.file_types
|
||||
)
|
||||
else: # directory
|
||||
path = filedialog.askdirectory(
|
||||
title="选择目录",
|
||||
initialdir=current_path
|
||||
)
|
||||
path = filedialog.askdirectory(title="选择目录", initialdir=current_path)
|
||||
|
||||
if path:
|
||||
self.entry_var.set(path)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"""
|
||||
自定义 logging Handler,将日志输出到 LogText 组件
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from typing import Optional
|
||||
@@ -29,11 +30,11 @@ class GuiTextHandler(logging.Handler):
|
||||
|
||||
# 映射 logging 级别到 LogText 级别
|
||||
self.level_map = {
|
||||
logging.INFO: 'INFO',
|
||||
logging.WARNING: 'WARNING',
|
||||
logging.ERROR: 'ERROR',
|
||||
logging.DEBUG: 'DEBUG',
|
||||
logging.CRITICAL: 'ERROR'
|
||||
logging.INFO: "INFO",
|
||||
logging.WARNING: "WARNING",
|
||||
logging.ERROR: "ERROR",
|
||||
logging.DEBUG: "DEBUG",
|
||||
logging.CRITICAL: "ERROR",
|
||||
}
|
||||
|
||||
def set_log_text(self, log_text: LogText):
|
||||
@@ -57,7 +58,7 @@ class GuiTextHandler(logging.Handler):
|
||||
|
||||
try:
|
||||
# 获取日志级别
|
||||
level = self.level_map.get(record.levelno, 'INFO')
|
||||
level = self.level_map.get(record.levelno, "INFO")
|
||||
|
||||
# 只获取消息内容,不包含时间戳和级别(LogText.log() 会添加)
|
||||
message = record.getMessage()
|
||||
@@ -78,6 +79,7 @@ class GuiTextHandler(logging.Handler):
|
||||
|
||||
# 尝试使用 after 确保在主线程更新
|
||||
import tkinter as tk
|
||||
|
||||
try:
|
||||
# 尝试获取主窗口
|
||||
widget = self.log_text
|
||||
@@ -112,9 +114,9 @@ class GuiTextHandler(logging.Handler):
|
||||
清理后的消息
|
||||
"""
|
||||
# 常见的日志级别标记模式
|
||||
level_pattern = r'^\[(?:INFO|WARNING|ERROR|DEBUG|CRITICAL|WARN|SUCCESS)\]\s*'
|
||||
level_pattern = r"^\[(?:INFO|WARNING|ERROR|DEBUG|CRITICAL|WARN|SUCCESS)\]\s*"
|
||||
match = re.match(level_pattern, message)
|
||||
if match:
|
||||
# 移除匹配到的级别前缀
|
||||
return message[match.end():]
|
||||
return message[match.end() :]
|
||||
return message
|
||||
|
||||
@@ -15,11 +15,11 @@ class LogText(tk.Frame):
|
||||
|
||||
# 日志级别颜色配置
|
||||
LOG_COLORS = {
|
||||
'INFO': '#000000', # 黑色
|
||||
'SUCCESS': '#008000', # 绿色
|
||||
'WARNING': '#FF8C00', # 深橙色
|
||||
'ERROR': '#FF0000', # 红色
|
||||
'DEBUG': '#808080', # 灰色
|
||||
"INFO": "#000000", # 黑色
|
||||
"SUCCESS": "#008000", # 绿色
|
||||
"WARNING": "#FF8C00", # 深橙色
|
||||
"ERROR": "#FF0000", # 红色
|
||||
"DEBUG": "#808080", # 灰色
|
||||
}
|
||||
|
||||
def __init__(self, parent, readonly=True, **kwargs):
|
||||
@@ -67,19 +67,19 @@ class LogText(tk.Frame):
|
||||
def _make_readonly(self):
|
||||
"""通过绑定事件使文本框只读"""
|
||||
# 允许复制、全选等常用操作,阻止其他编辑操作
|
||||
self.text.bind('<Key>', self._handle_key)
|
||||
self.text.bind('<Button-1>', self._allow_click) # 允许左键点击选择
|
||||
self.text.bind("<Key>", self._handle_key)
|
||||
self.text.bind("<Button-1>", self._allow_click) # 允许左键点击选择
|
||||
|
||||
def _handle_key(self, event):
|
||||
"""处理按键事件,允许复制操作,阻止编辑"""
|
||||
# 允许的快捷键
|
||||
allowed_keys = [
|
||||
'Control-c', # 复制
|
||||
'Control-C', # 复制(大写)
|
||||
'Control-a', # 全选
|
||||
'Control-A', # 全选(大写)
|
||||
'Control-x', # 剪切(虽然剪不了,但不报错)
|
||||
'Control-X',
|
||||
"Control-c", # 复制
|
||||
"Control-C", # 复制(大写)
|
||||
"Control-a", # 全选
|
||||
"Control-A", # 全选(大写)
|
||||
"Control-x", # 剪切(虽然剪不了,但不报错)
|
||||
"Control-X",
|
||||
]
|
||||
|
||||
# 检查是否是允许的快捷键
|
||||
@@ -93,14 +93,14 @@ class LogText(tk.Frame):
|
||||
return # 允许执行
|
||||
|
||||
# 其他所有按键都阻止
|
||||
return 'break'
|
||||
return "break"
|
||||
|
||||
def _allow_click(self, event):
|
||||
"""允许点击和选择文本"""
|
||||
# 不打断事件,允许正常的选择操作
|
||||
return
|
||||
|
||||
def log(self, message: str, level: str = 'INFO') -> None:
|
||||
def log(self, message: str, level: str = "INFO") -> None:
|
||||
"""
|
||||
添加日志消息
|
||||
|
||||
@@ -111,46 +111,46 @@ class LogText(tk.Frame):
|
||||
# 确保 tags 已配置
|
||||
self._ensure_tags_configured()
|
||||
|
||||
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
log_message = f"[{timestamp}] [{level}] {message}\n"
|
||||
|
||||
# 插入文本
|
||||
tag = level.lower() if self._tags_configured else None
|
||||
if tag:
|
||||
try:
|
||||
self.text.insert('end', log_message, (tag,))
|
||||
self.text.insert("end", log_message, (tag,))
|
||||
except Exception:
|
||||
# 如果带标签插入失败,尝试不带标签
|
||||
self.text.insert('end', log_message)
|
||||
self.text.insert("end", log_message)
|
||||
else:
|
||||
self.text.insert('end', log_message)
|
||||
self.text.insert("end", log_message)
|
||||
|
||||
# 自动滚动到底部
|
||||
self.text.see('end')
|
||||
self.text.see("end")
|
||||
|
||||
def info(self, message: str) -> None:
|
||||
"""添加 INFO 级别日志"""
|
||||
self.log(message, 'INFO')
|
||||
self.log(message, "INFO")
|
||||
|
||||
def success(self, message: str) -> None:
|
||||
"""添加 SUCCESS 级别日志"""
|
||||
self.log(message, 'SUCCESS')
|
||||
self.log(message, "SUCCESS")
|
||||
|
||||
def warning(self, message: str) -> None:
|
||||
"""添加 WARNING 级别日志"""
|
||||
self.log(message, 'WARNING')
|
||||
self.log(message, "WARNING")
|
||||
|
||||
def error(self, message: str) -> None:
|
||||
"""添加 ERROR 级别日志"""
|
||||
self.log(message, 'ERROR')
|
||||
self.log(message, "ERROR")
|
||||
|
||||
def debug(self, message: str) -> None:
|
||||
"""添加 DEBUG 级别日志"""
|
||||
self.log(message, 'DEBUG')
|
||||
self.log(message, "DEBUG")
|
||||
|
||||
def clear(self) -> None:
|
||||
"""清空日志"""
|
||||
self.text.delete('1.0', 'end')
|
||||
self.text.delete("1.0", "end")
|
||||
|
||||
def save_to_file(self, file_path: str) -> bool:
|
||||
"""
|
||||
@@ -163,8 +163,8 @@ class LogText(tk.Frame):
|
||||
是否成功
|
||||
"""
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(self.text.get('1.0', 'end-1c'))
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
f.write(self.text.get("1.0", "end-1c"))
|
||||
return True
|
||||
except Exception as e:
|
||||
self.error(f"保存日志失败: {e}")
|
||||
@@ -182,5 +182,6 @@ class LogText(tk.Frame):
|
||||
def apply_font(self, font_family: str, font_size: int):
|
||||
"""应用字体设置"""
|
||||
from tkinter import font as tk_font
|
||||
|
||||
font_spec = tk_font.Font(family=font_family, size=font_size)
|
||||
self.text.configure(font=font_spec)
|
||||
|
||||
@@ -35,12 +35,14 @@ class ProductionIdInput(ttk.Frame):
|
||||
justify="center",
|
||||
colors=("black", "#f0f0f0"),
|
||||
bg="#f0f0f0",
|
||||
width=3
|
||||
width=3,
|
||||
)
|
||||
self.line_numbers.pack(fill="both", expand=True)
|
||||
|
||||
# 创建滚动条
|
||||
self.scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.text_widget.yview)
|
||||
self.scrollbar = ttk.Scrollbar(
|
||||
self, orient=tk.VERTICAL, command=self.text_widget.yview
|
||||
)
|
||||
self.text_widget.configure(yscrollcommand=self._on_scroll)
|
||||
|
||||
# 布局:行号 | 文本框 | 滚动条
|
||||
@@ -74,7 +76,10 @@ class ProductionIdInput(ttk.Frame):
|
||||
|
||||
def _on_focus_in(self, event):
|
||||
"""获得焦点时隐藏占位符"""
|
||||
if not self._updating_placeholder and self.text_widget.get("1.0", "end-1c") == self.placeholder:
|
||||
if (
|
||||
not self._updating_placeholder
|
||||
and self.text_widget.get("1.0", "end-1c") == self.placeholder
|
||||
):
|
||||
self.text_widget.delete("1.0", tk.END)
|
||||
# 确保文字颜色为黑色
|
||||
self.text_widget.configure(foreground="black")
|
||||
|
||||
@@ -20,7 +20,7 @@ class ProgressDialog:
|
||||
title: str = "处理中...",
|
||||
message: str = "请稍候",
|
||||
can_cancel: bool = True,
|
||||
on_cancel: Optional[Callable] = None
|
||||
on_cancel: Optional[Callable] = None,
|
||||
):
|
||||
"""
|
||||
初始化进度对话框
|
||||
@@ -66,11 +66,7 @@ class ProgressDialog:
|
||||
self.message_label.pack(pady=(20, 10), padx=20)
|
||||
|
||||
# 进度条
|
||||
self.progress = ttk.Progressbar(
|
||||
self.dialog,
|
||||
mode='indeterminate',
|
||||
length=360
|
||||
)
|
||||
self.progress = ttk.Progressbar(self.dialog, mode="indeterminate", length=360)
|
||||
self.progress.pack(pady=10, padx=20)
|
||||
self.progress.start(10)
|
||||
|
||||
@@ -80,9 +76,7 @@ class ProgressDialog:
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
self.cancel_button = ttk.Button(
|
||||
button_frame,
|
||||
text="取消",
|
||||
command=self._on_cancel
|
||||
button_frame, text="取消", command=self._on_cancel
|
||||
)
|
||||
self.cancel_button.pack()
|
||||
|
||||
@@ -106,8 +100,8 @@ class ProgressDialog:
|
||||
value: 当前进度值
|
||||
maximum: 最大值
|
||||
"""
|
||||
self.progress.config(mode='determinate', maximum=maximum)
|
||||
self.progress['value'] = value
|
||||
self.progress.config(mode="determinate", maximum=maximum)
|
||||
self.progress["value"] = value
|
||||
self.dialog.update_idletasks()
|
||||
|
||||
def close(self):
|
||||
|
||||
Reference in New Issue
Block a user