Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
柴进
/
GoogleNanoBananaApp
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
2fef6a45
authored
2025-12-18 15:55:54 +0800
by
柴进
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
增加使用人的信息记录与日志留存
1 parent
34feac02
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
172 additions
and
12 deletions
image_generator.py
task_queue.py
image_generator.py
View file @
2fef6a4
...
...
@@ -1091,6 +1091,7 @@ class ImageGeneratorWindow(QMainWindow):
self
.
db_config
=
None
self
.
last_user
=
""
self
.
saved_password_hash
=
""
self
.
authenticated_user
=
""
# 当前登录用户名
self
.
load_config
()
self
.
set_window_icon
()
...
...
@@ -1401,21 +1402,21 @@ class ImageGeneratorWindow(QMainWindow):
self
.
image_count_label
=
QLabel
(
"已选择 0 张"
)
upload_header
.
addWidget
(
self
.
image_count_label
)
# Drag and drop hint - 紧凑显示在右侧
hint_label
=
QLabel
(
"💡 拖拽或粘贴图片到下方区域"
)
hint_label
.
setStyleSheet
(
"QLabel { color: #666666; font-size: 11px; margin-left: 10px; }"
)
upload_header
.
addWidget
(
hint_label
)
upload_header
.
addStretch
()
ref_layout
.
addLayout
(
upload_header
)
# Drag and drop hint
hint_label
=
QLabel
(
"💡 提示:可以直接拖拽图片到下方区域,或使用 Ctrl+V 粘贴截图"
)
hint_label
.
setStyleSheet
(
"QLabel { color: #666666; font-size: 11px; margin: 2px 0; }"
)
hint_label
.
setWordWrap
(
True
)
ref_layout
.
addWidget
(
hint_label
)
# Image preview scroll area with drag-and-drop support
self
.
img_scroll
=
DragDropScrollArea
(
self
)
self
.
img_scroll
.
setWidgetResizable
(
True
)
self
.
img_scroll
.
setHorizontalScrollBarPolicy
(
Qt
.
ScrollBarAlwaysOn
)
self
.
img_scroll
.
setVerticalScrollBarPolicy
(
Qt
.
ScrollBarAlwaysOff
)
self
.
img_scroll
.
setFixedHeight
(
18
0
)
self
.
img_scroll
.
setFixedHeight
(
22
0
)
self
.
img_container
=
QWidget
()
self
.
img_layout
=
QHBoxLayout
()
...
...
@@ -2098,6 +2099,7 @@ class ImageGeneratorWindow(QMainWindow):
try
:
# Submit task to queue
import
socket
task_id
=
self
.
task_manager
.
submit_task
(
task_type
=
TaskType
.
IMAGE_GENERATION
,
prompt
=
prompt
,
...
...
@@ -2105,7 +2107,9 @@ class ImageGeneratorWindow(QMainWindow):
reference_images
=
self
.
uploaded_images
.
copy
(),
aspect_ratio
=
self
.
aspect_ratio
.
currentText
(),
image_size
=
self
.
image_size
.
currentText
(),
model
=
"gemini-3-pro-image-preview"
model
=
"gemini-3-pro-image-preview"
,
user_name
=
self
.
authenticated_user
,
device_name
=
socket
.
gethostname
()
)
# Connect to task completion signal
...
...
@@ -3520,6 +3524,7 @@ class StyleDesignerTab(QWidget):
try
:
# Submit task to queue
import
socket
task_id
=
self
.
parent_window
.
task_manager
.
submit_task
(
task_type
=
TaskType
.
STYLE_DESIGN
,
prompt
=
prompt
,
...
...
@@ -3527,7 +3532,9 @@ class StyleDesignerTab(QWidget):
reference_images
=
[],
aspect_ratio
=
aspect_ratio
,
image_size
=
image_size
,
model
=
model
model
=
model
,
user_name
=
self
.
parent_window
.
authenticated_user
,
device_name
=
socket
.
gethostname
()
)
# Connect to task completion signal
...
...
@@ -3861,6 +3868,7 @@ def main():
# Show main window
main_window
=
ImageGeneratorWindow
()
main_window
.
authenticated_user
=
authenticated_user
# 设置登录用户名
main_window
.
show
()
sys
.
exit
(
app
.
exec
())
...
...
task_queue.py
View file @
2fef6a4
...
...
@@ -53,8 +53,12 @@ class Task:
image_size
:
str
model
:
str
# 用户信息 (用于日志记录)
user_name
:
str
=
""
device_name
:
str
=
""
# 时间戳
created_at
:
datetime
created_at
:
datetime
=
field
(
default_factory
=
datetime
.
now
)
started_at
:
Optional
[
datetime
]
=
None
completed_at
:
Optional
[
datetime
]
=
None
...
...
@@ -102,9 +106,28 @@ class TaskQueueManager(QObject):
self
.
_max_queue_size
=
10
self
.
_max_history_size
=
10
# 只保留最近10条完成任务
# 加载数据库配置用于日志记录
self
.
_db_config
=
None
self
.
_load_db_config
()
self
.
_initialized
=
True
self
.
logger
.
info
(
"TaskQueueManager 初始化完成"
)
def
_load_db_config
(
self
):
"""加载数据库配置"""
try
:
import
json
from
pathlib
import
Path
config_file
=
Path
(
"config.json"
)
if
config_file
.
exists
():
with
open
(
config_file
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
config
=
json
.
load
(
f
)
self
.
_db_config
=
config
.
get
(
'db_config'
)
if
self
.
_db_config
:
self
.
logger
.
info
(
"数据库配置已加载"
)
except
Exception
as
e
:
self
.
logger
.
warning
(
f
"加载数据库配置失败: {e}"
)
def
submit_task
(
self
,
task_type
:
TaskType
,
...
...
@@ -113,7 +136,9 @@ class TaskQueueManager(QObject):
reference_images
:
List
[
str
],
aspect_ratio
:
str
,
image_size
:
str
,
model
:
str
model
:
str
,
user_name
:
str
=
""
,
device_name
:
str
=
""
)
->
str
:
"""
提交新任务到队列
...
...
@@ -126,6 +151,8 @@ class TaskQueueManager(QObject):
aspect_ratio: 宽高比
image_size: 图片尺寸
model: 模型名称
user_name: 用户名 (用于日志记录)
device_name: 设备名称 (用于日志记录)
Returns:
task_id: 任务唯一标识
...
...
@@ -148,6 +175,8 @@ class TaskQueueManager(QObject):
aspect_ratio
=
aspect_ratio
,
image_size
=
image_size
,
model
=
model
,
user_name
=
user_name
,
device_name
=
device_name
,
created_at
=
datetime
.
now
()
)
...
...
@@ -225,6 +254,9 @@ class TaskQueueManager(QObject):
elapsed
=
(
task
.
completed_at
-
task
.
started_at
)
.
total_seconds
()
self
.
logger
.
info
(
f
"任务完成: {task_id[:8]} - 耗时 {elapsed:.1f}s"
)
# 记录使用日志
self
.
_log_usage
(
task_id
,
'success'
,
'memory'
,
None
)
self
.
task_completed
.
emit
(
task_id
,
image_bytes
,
prompt
,
reference_images
,
aspect_ratio
,
image_size
,
model
)
...
...
@@ -247,6 +279,9 @@ class TaskQueueManager(QObject):
self
.
logger
.
error
(
f
"任务失败: {task_id[:8]} - {error}"
)
# 记录使用日志
self
.
_log_usage
(
task_id
,
'failure'
,
None
,
error
)
self
.
task_failed
.
emit
(
task_id
,
error
)
# 清理旧任务历史
...
...
@@ -305,11 +340,86 @@ class TaskQueueManager(QObject):
return
sum
(
1
for
t
in
self
.
_tasks
.
values
()
if
t
.
status
==
TaskStatus
.
RUNNING
)
def
cancel_task
(
self
,
task_id
:
str
):
"""取消任务 (仅等待中任务)"""
"""
取消任务 (仅等待中任务)
将任务状态设为 CANCELLED 并从队列中移除
"""
task
=
self
.
_tasks
.
get
(
task_id
)
if
task
and
task
.
status
==
TaskStatus
.
PENDING
:
task
.
status
=
TaskStatus
.
CANCELLED
task
.
completed_at
=
datetime
.
now
()
# 从队列中移除任务 (需要重建队列以移除特定ID)
temp_queue
=
Queue
()
while
not
self
.
_queue
.
empty
():
tid
=
self
.
_queue
.
get
()
if
tid
!=
task_id
:
temp_queue
.
put
(
tid
)
# 替换原队列
self
.
_queue
=
temp_queue
self
.
logger
.
info
(
f
"任务已取消: {task_id[:8]}"
)
self
.
task_failed
.
emit
(
task_id
,
"用户取消"
)
# 发送取消信号以更新 UI
def
_log_usage
(
self
,
task_id
:
str
,
status
:
str
,
result_path
:
Optional
[
str
],
error_message
:
Optional
[
str
]):
"""
记录用户使用日志到数据库
Args:
task_id: 任务ID
status: 'success' 或 'failure'
result_path: 成功时的图片路径,失败时为 None
error_message: 失败时的错误信息,成功时为 None
"""
if
not
self
.
_db_config
:
self
.
logger
.
debug
(
"数据库配置未加载,跳过日志记录"
)
return
task
=
self
.
_tasks
.
get
(
task_id
)
if
not
task
:
self
.
logger
.
warning
(
f
"任务 {task_id[:8]} 不存在,无法记录日志"
)
return
try
:
import
pymysql
# 处理未登录用户
user_name
=
task
.
user_name
if
task
.
user_name
else
"未知用户"
device_name
=
task
.
device_name
if
task
.
device_name
else
"未知设备"
# 连接数据库
connection
=
pymysql
.
connect
(
host
=
self
.
_db_config
[
'host'
],
port
=
self
.
_db_config
[
'port'
],
user
=
self
.
_db_config
[
'user'
],
password
=
self
.
_db_config
[
'password'
],
database
=
self
.
_db_config
[
'database'
]
)
with
connection
.
cursor
()
as
cursor
:
sql
=
"""
INSERT INTO `nano_banana_user_use_log`
(`user_name`, `device_name`, `prompt`, `result_path`, `status`, `error_message`)
VALUES (
%
s,
%
s,
%
s,
%
s,
%
s,
%
s)
"""
cursor
.
execute
(
sql
,
(
user_name
,
device_name
,
task
.
prompt
,
result_path
,
status
,
error_message
))
connection
.
commit
()
connection
.
close
()
self
.
logger
.
info
(
f
"使用日志已记录: {task_id[:8]} - {status}"
)
except
Exception
as
e
:
# 日志记录失败不应影响主流程
self
.
logger
.
error
(
f
"记录使用日志失败: {e}"
,
exc_info
=
False
)
class
TaskQueueWidget
(
QWidget
):
...
...
@@ -338,6 +448,7 @@ class TaskQueueWidget(QWidget):
title
=
QLabel
(
"任务队列"
)
title
.
setStyleSheet
(
"QLabel { font-weight: bold; font-size: 10px; color: #666; }"
)
title
.
setAlignment
(
Qt
.
AlignCenter
)
title
.
setToolTip
(
"鼠标悬停查看详情
\n
右键等待中的任务可取消"
)
layout
.
addWidget
(
title
)
# 分隔线
...
...
@@ -367,6 +478,11 @@ class TaskQueueWidget(QWidget):
}
"""
)
self
.
task_list
.
itemClicked
.
connect
(
self
.
_on_task_item_clicked
)
# 启用右键菜单
self
.
task_list
.
setContextMenuPolicy
(
Qt
.
CustomContextMenu
)
self
.
task_list
.
customContextMenuRequested
.
connect
(
self
.
_show_context_menu
)
layout
.
addWidget
(
self
.
task_list
)
layout
.
addStretch
()
...
...
@@ -426,6 +542,15 @@ class TaskQueueWidget(QWidget):
from
PySide6.QtGui
import
QBrush
,
QColor
item
.
setForeground
(
QBrush
(
QColor
(
color
)))
# 设置 Tooltip - 显示完整的 Prompt 和任务信息
tooltip_text
=
f
"Prompt: {task.prompt}
\n
"
tooltip_text
+=
f
"创建时间: {task.created_at.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')}
\n
"
tooltip_text
+=
f
"宽高比: {task.aspect_ratio}
\n
"
tooltip_text
+=
f
"尺寸: {task.image_size}"
if
task
.
error_message
:
tooltip_text
+=
f
"
\n
错误: {task.error_message}"
item
.
setToolTip
(
tooltip_text
)
# 添加到列表
self
.
task_list
.
addItem
(
item
)
...
...
@@ -434,6 +559,33 @@ class TaskQueueWidget(QWidget):
for
i
in
range
(
self
.
task_list
.
count
()
-
10
):
self
.
task_list
.
takeItem
(
0
)
def
_show_context_menu
(
self
,
position
):
"""显示右键菜单 - 仅为等待中的任务提供取消选项"""
from
PySide6.QtWidgets
import
QMenu
# 获取点击的任务项
item
=
self
.
task_list
.
itemAt
(
position
)
if
not
item
:
return
task_id
=
item
.
data
(
Qt
.
UserRole
)
if
not
task_id
:
return
task
=
self
.
manager
.
get_task
(
task_id
)
if
not
task
:
return
# 仅为 PENDING 状态的任务显示取消选项
if
task
.
status
==
TaskStatus
.
PENDING
:
menu
=
QMenu
()
cancel_action
=
menu
.
addAction
(
"取消任务"
)
action
=
menu
.
exec_
(
self
.
task_list
.
mapToGlobal
(
position
))
if
action
==
cancel_action
:
self
.
manager
.
cancel_task
(
task_id
)
self
.
_update_summary
()
def
_on_task_added
(
self
,
task
:
Task
):
"""任务添加回调"""
...
...
Please
register
or
sign in
to post a comment