修改获取网页内容代码
This commit is contained in:
parent
036eb90ca0
commit
0792027bea
@ -1,4 +1,4 @@
|
||||
|
||||
import json
|
||||
import sys # 导入sys模块
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import tkinter as tk
|
||||
|
||||
|
||||
from config import *
|
||||
from tkinter import ttk, messagebox, filedialog
|
||||
from tkinter import ttk, messagebox, filedialog, simpledialog
|
||||
from tkinter.scrolledtext import ScrolledText
|
||||
|
||||
import pymysql
|
||||
@ -43,16 +43,31 @@ class ArticleReplaceApp(tk.Tk):
|
||||
# 创建配置页面
|
||||
self.config_frame = ttk.Frame(self.notebook)
|
||||
self.notebook.add(self.config_frame, text="配置")
|
||||
# 初始化主页面
|
||||
self.init_main_frame()
|
||||
# 初始化配置页面
|
||||
self.init_config_frame()
|
||||
|
||||
# 初始化变量
|
||||
self.running = False
|
||||
self.thread = None
|
||||
self.total_links = 0
|
||||
self.processed_links = 0
|
||||
|
||||
# 初始化Coze配置变量
|
||||
self.template_name_var = tk.StringVar()
|
||||
self.coze_workflow_id_var = tk.StringVar(value=CONFIG['Coze']['workflow_id'])
|
||||
self.coze_access_token_var = tk.StringVar(value=CONFIG['Coze']['access_token'])
|
||||
self.coze_is_async_var = tk.StringVar(value=CONFIG['Coze'].get('is_async', 'true'))
|
||||
self.coze_input_data_template_var = tk.StringVar(value=CONFIG['Coze'].get('input_data_template', '{"article": "{article_text}", "link":"{link}", "weijin":"{weijin}"}'))
|
||||
|
||||
# 初始化模板数据结构
|
||||
self.templates = {
|
||||
"短篇": [],
|
||||
"文章": []
|
||||
}
|
||||
|
||||
# 初始化主页面
|
||||
self.init_main_frame()
|
||||
# 初始化配置页面
|
||||
self.init_config_frame()
|
||||
|
||||
# 设置关闭窗口事件
|
||||
self.protocol("WM_DELETE_WINDOW", self.on_close)
|
||||
|
||||
@ -82,14 +97,21 @@ class ArticleReplaceApp(tk.Tk):
|
||||
ai_service_combo = ttk.Combobox(control_frame, textvariable=self.ai_service_var, values=["dify", "coze"], width=10, state="readonly")
|
||||
ai_service_combo.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)
|
||||
|
||||
# 生成类型选择
|
||||
ttk.Label(control_frame, text="生成类型:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.generation_type_var = tk.StringVar(value="短篇")
|
||||
self.generation_type_combo = ttk.Combobox(control_frame, textvariable=self.generation_type_var, values=["短篇", "文章"], width=10, state="readonly")
|
||||
self.generation_type_combo.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)
|
||||
self.generation_type_combo.bind("<<ComboboxSelected>>", self.on_generation_type_changed)
|
||||
|
||||
# 开始按钮
|
||||
self.start_button = ttk.Button(control_frame, text="开始处理", command=self.start_processing)
|
||||
self.start_button.grid(row=3, column=0, columnspan=3, padx=5, pady=20)
|
||||
self.start_button.grid(row=4, column=0, columnspan=3, padx=5, pady=20)
|
||||
|
||||
# 进度条
|
||||
ttk.Label(control_frame, text="处理进度:").grid(row=4, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Label(control_frame, text="处理进度:").grid(row=5, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.progress_var = tk.DoubleVar()
|
||||
ttk.Progressbar(control_frame, variable=self.progress_var, maximum=100).grid(row=4, column=1, columnspan=2,
|
||||
ttk.Progressbar(control_frame, variable=self.progress_var, maximum=100).grid(row=5, column=1, columnspan=2,
|
||||
padx=5, pady=5, sticky=tk.EW)
|
||||
|
||||
# 创建右侧日志面板
|
||||
@ -235,25 +257,77 @@ class ArticleReplaceApp(tk.Tk):
|
||||
ttk.Entry(parent, textvariable=self.dify_input_data_template_var, width=50).grid(row=3, column=1, padx=5, pady=5)
|
||||
|
||||
def init_coze_config(self, parent):
|
||||
# 生成类型选择(与主页面联动)
|
||||
type_frame = ttk.Frame(parent)
|
||||
type_frame.grid(row=0, column=0, columnspan=3, padx=5, pady=5, sticky=tk.EW)
|
||||
ttk.Label(type_frame, text="生成类型:").pack(side=tk.LEFT, padx=5)
|
||||
self.coze_generation_type_var = tk.StringVar(value="短篇")
|
||||
self.coze_generation_type_combo = ttk.Combobox(type_frame, textvariable=self.coze_generation_type_var, values=["短篇", "文章"], width=10, state="readonly")
|
||||
self.coze_generation_type_combo.pack(side=tk.LEFT, padx=5)
|
||||
self.coze_generation_type_combo.bind("<<ComboboxSelected>>", self.on_coze_generation_type_changed)
|
||||
|
||||
# 编辑状态标签
|
||||
self.edit_status_label = ttk.Label(type_frame, text="", foreground="blue")
|
||||
self.edit_status_label.pack(side=tk.LEFT, padx=20)
|
||||
|
||||
# 加载已保存的模板
|
||||
self.load_templates()
|
||||
|
||||
# 初始化变量跟踪
|
||||
self._setup_var_trace()
|
||||
|
||||
# 模板管理框架
|
||||
template_frame = ttk.LabelFrame(parent, text="模板管理")
|
||||
template_frame.grid(row=1, column=0, columnspan=3, padx=5, pady=10, sticky=tk.EW)
|
||||
|
||||
# 模板列表和滚动条
|
||||
list_frame = ttk.Frame(template_frame)
|
||||
list_frame.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Label(template_frame, text="模板列表:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.template_listbox = tk.Listbox(list_frame, height=5, width=30)
|
||||
scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=self.template_listbox.yview)
|
||||
self.template_listbox.configure(yscrollcommand=scrollbar.set)
|
||||
self.template_listbox.pack(side=tk.LEFT, fill=tk.Y)
|
||||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
self.template_listbox.bind("<<ListboxSelect>>", self.on_template_selected)
|
||||
|
||||
# 模板操作按钮
|
||||
button_frame = ttk.Frame(template_frame)
|
||||
button_frame.grid(row=1, column=1, padx=10, pady=5, sticky=tk.N)
|
||||
ttk.Button(button_frame, text="新增模板", command=self.add_template).pack(pady=2)
|
||||
ttk.Button(button_frame, text="删除模板", command=self.delete_template).pack(pady=2)
|
||||
ttk.Button(button_frame, text="重命名模板", command=self.rename_template).pack(pady=2)
|
||||
ttk.Button(button_frame, text="保存模板", command=self.save_template).pack(pady=2)
|
||||
ttk.Button(button_frame, text="复制模板", command=self.duplicate_template).pack(pady=2)
|
||||
ttk.Button(button_frame, text="使用模板", command=self.use_template).pack(pady=2)
|
||||
|
||||
# 当前模板配置
|
||||
config_frame = ttk.LabelFrame(parent, text="当前模板配置")
|
||||
config_frame.grid(row=2, column=0, columnspan=3, padx=5, pady=10, sticky=tk.EW)
|
||||
|
||||
# 模板名称
|
||||
ttk.Label(config_frame, text="模板名称:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Entry(config_frame, textvariable=self.template_name_var, width=30).grid(row=0, column=1, padx=5, pady=5)
|
||||
|
||||
# Coze Workflow ID
|
||||
ttk.Label(parent, text="Workflow ID:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.coze_workflow_id_var = tk.StringVar(value=CONFIG['Coze']['workflow_id'])
|
||||
ttk.Entry(parent, textvariable=self.coze_workflow_id_var, width=50).grid(row=0, column=1, padx=5, pady=5)
|
||||
ttk.Label(config_frame, text="Workflow ID:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Entry(config_frame, textvariable=self.coze_workflow_id_var, width=50).grid(row=1, column=1, padx=5, pady=5)
|
||||
|
||||
# Coze Access Token
|
||||
ttk.Label(parent, text="Access Token:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.coze_access_token_var = tk.StringVar(value=CONFIG['Coze']['access_token'])
|
||||
ttk.Entry(parent, textvariable=self.coze_access_token_var, width=50).grid(row=1, column=1, padx=5, pady=5)
|
||||
ttk.Label(config_frame, text="Access Token:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Entry(config_frame, textvariable=self.coze_access_token_var, width=50).grid(row=2, column=1, padx=5, pady=5)
|
||||
|
||||
# Coze Is Async
|
||||
ttk.Label(parent, text="Is Async:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.coze_is_async_var = tk.StringVar(value=CONFIG['Coze']['is_async'])
|
||||
ttk.Combobox(parent, textvariable=self.coze_is_async_var, values=["true", "false"], width=10, state="readonly").grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Label(config_frame, text="Is Async:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
ttk.Combobox(config_frame, textvariable=self.coze_is_async_var, values=["true", "false"], width=10, state="readonly").grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)
|
||||
|
||||
# Coze Input Data Template
|
||||
ttk.Label(parent, text="Input Data模板:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
self.coze_input_data_template_var = tk.StringVar(value=CONFIG['Coze'].get('input_data_template', '{{"article": "{article_text}", "link":"{link}", "weijin":"{weijin}"}}')) # 添加默认值
|
||||
ttk.Entry(parent, textvariable=self.coze_input_data_template_var, width=50).grid(row=3, column=1, padx=5, pady=5)
|
||||
ttk.Label(config_frame, text="Input Data模板:").grid(row=4, column=0, padx=5, pady=5, sticky=tk.W)
|
||||
# Variable already initialized in __init__
|
||||
ttk.Entry(config_frame, textvariable=self.coze_input_data_template_var, width=50).grid(row=4, column=1, padx=5, pady=5)
|
||||
|
||||
# 更新模板列表
|
||||
self.update_template_list()
|
||||
|
||||
def init_baidu_config(self, parent):
|
||||
# 百度 API Key
|
||||
@ -339,6 +413,468 @@ class ArticleReplaceApp(tk.Tk):
|
||||
CONFIG['Keywords']['banned_words'] = words
|
||||
messagebox.showinfo("保存成功", "违禁词列表已更新")
|
||||
|
||||
def on_generation_type_changed(self, event=None):
|
||||
"""主页面生成类型改变时的处理"""
|
||||
# 同步到coze页面
|
||||
self.coze_generation_type_var.set(self.generation_type_var.get())
|
||||
self.update_template_list()
|
||||
|
||||
def on_coze_generation_type_changed(self, event=None):
|
||||
"""coze页面生成类型改变时的处理"""
|
||||
# 同步到主页面
|
||||
self.generation_type_var.set(self.coze_generation_type_var.get())
|
||||
self.update_template_list()
|
||||
|
||||
def update_template_list(self):
|
||||
"""更新模板列表显示"""
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
self.template_listbox.delete(0, tk.END)
|
||||
|
||||
if current_type in self.templates:
|
||||
for template in self.templates[current_type]:
|
||||
self.template_listbox.insert(tk.END, template['name'])
|
||||
|
||||
def on_template_selected(self, event=None):
|
||||
"""模板选择时的处理"""
|
||||
selection = self.template_listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type in self.templates and index < len(self.templates[current_type]):
|
||||
template = self.templates[current_type][index]
|
||||
self.load_template_config(template)
|
||||
|
||||
def load_template_config(self, template):
|
||||
"""加载模板配置到界面"""
|
||||
# 解绑之前的变量跟踪
|
||||
self._unbind_var_trace()
|
||||
|
||||
self.template_name_var.set(template['name'])
|
||||
self.coze_workflow_id_var.set(template.get('workflow_id', ''))
|
||||
self.coze_access_token_var.set(template.get('access_token', ''))
|
||||
self.coze_is_async_var.set(template.get('is_async', 'true'))
|
||||
self.coze_input_data_template_var.set(template.get('input_data_template', ''))
|
||||
|
||||
self.edit_status_label.config(text="已加载", foreground="blue")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
|
||||
# 重新绑定变量跟踪
|
||||
self._setup_var_trace()
|
||||
|
||||
def _setup_var_trace(self):
|
||||
"""设置变量跟踪以显示编辑状态"""
|
||||
self.var_traces = []
|
||||
for var in [self.template_name_var, self.coze_workflow_id_var,
|
||||
self.coze_access_token_var, self.coze_is_async_var,
|
||||
self.coze_input_data_template_var]:
|
||||
trace_id = var.trace_add('write', lambda *args: self._show_edit_status())
|
||||
self.var_traces.append((var, trace_id))
|
||||
|
||||
def _unbind_var_trace(self):
|
||||
"""解绑变量跟踪"""
|
||||
if hasattr(self, 'var_traces'):
|
||||
for var, trace_id in self.var_traces:
|
||||
try:
|
||||
var.trace_remove('write', trace_id)
|
||||
except Exception:
|
||||
pass
|
||||
self.var_traces = []
|
||||
|
||||
def _show_edit_status(self):
|
||||
"""显示编辑状态"""
|
||||
self.edit_status_label.config(text="未保存", foreground="red")
|
||||
|
||||
def add_template(self):
|
||||
"""添加新模板"""
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
|
||||
# 获取当前模板列表中最大的序号
|
||||
max_num = 0
|
||||
for template in self.templates[current_type]:
|
||||
try:
|
||||
# 尝试将模板名称转换为整数
|
||||
if template['name'].isdigit():
|
||||
num = int(template['name'])
|
||||
max_num = max(max_num, num)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
template_name = f"{max_num + 1}"
|
||||
|
||||
# 获取当前配置作为默认值
|
||||
default_workflow_id = CONFIG['Coze'].get('workflow_id', '')
|
||||
default_access_token = CONFIG['Coze'].get('access_token', '')
|
||||
default_is_async = CONFIG['Coze'].get('is_async', 'true')
|
||||
default_template = CONFIG['Coze'].get('input_data_template',
|
||||
'{"article": "{article_text}", "link":"{link}", "weijin":"{weijin}"}')
|
||||
|
||||
new_template = {
|
||||
'name': template_name,
|
||||
'type': current_type,
|
||||
'workflow_id': default_workflow_id,
|
||||
'access_token': default_access_token,
|
||||
'is_async': default_is_async,
|
||||
'input_data_template': default_template
|
||||
}
|
||||
|
||||
self.templates[current_type].append(new_template)
|
||||
self.update_template_list()
|
||||
self.save_templates()
|
||||
|
||||
# 选中新添加的模板
|
||||
self.template_listbox.selection_clear(0, tk.END)
|
||||
self.template_listbox.selection_set(len(self.templates[current_type]) - 1)
|
||||
self.load_template_config(new_template)
|
||||
self.edit_status_label.config(text="已创建", foreground="green")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text="未保存", foreground="red"))
|
||||
|
||||
def delete_template(self):
|
||||
"""删除选中的模板"""
|
||||
selection = self.template_listbox.curselection()
|
||||
if not selection:
|
||||
messagebox.showwarning("提示", "请先选择要删除的模板")
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type not in self.templates or index >= len(self.templates[current_type]):
|
||||
return
|
||||
|
||||
template_name = self.templates[current_type][index]['name']
|
||||
if messagebox.askyesno("确认删除", f"确定要删除模板 '{template_name}' 吗?"):
|
||||
del self.templates[current_type][index]
|
||||
self.update_template_list()
|
||||
self.save_templates()
|
||||
|
||||
# 清除配置并更新状态
|
||||
self.clear_template_config()
|
||||
self.edit_status_label.config(text=f"已删除 '{template_name}'", foreground="red")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
|
||||
# 如果还有模板,选中最后一个
|
||||
if self.templates[current_type]:
|
||||
last_index = len(self.templates[current_type]) - 1
|
||||
self.template_listbox.selection_set(last_index)
|
||||
self.load_template_config(self.templates[current_type][last_index])
|
||||
|
||||
def validate_template(self):
|
||||
"""验证模板配置"""
|
||||
name = self.template_name_var.get().strip()
|
||||
workflow_id = self.coze_workflow_id_var.get().strip()
|
||||
access_token = self.coze_access_token_var.get().strip()
|
||||
input_template = self.coze_input_data_template_var.get().strip()
|
||||
|
||||
if not name:
|
||||
messagebox.showerror("错误", "模板名称不能为空")
|
||||
return False
|
||||
|
||||
if not workflow_id:
|
||||
messagebox.showerror("错误", "Workflow ID不能为空")
|
||||
return False
|
||||
|
||||
if not access_token:
|
||||
messagebox.showerror("错误", "Access Token不能为空")
|
||||
return False
|
||||
|
||||
if not input_template:
|
||||
messagebox.showerror("错误", "输入数据模板不能为空")
|
||||
return False
|
||||
|
||||
# 验证输入数据模板的JSON格式
|
||||
try:
|
||||
# 替换占位符以便验证JSON格式
|
||||
test_template = input_template.replace('{article_text}', '')\
|
||||
.replace('{link}', '')\
|
||||
.replace('{weijin}', '')
|
||||
json.loads(test_template)
|
||||
except json.JSONDecodeError as e:
|
||||
messagebox.showerror("错误", f"输入数据模板不是有效的JSON格式:\n{str(e)}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
def save_template(self):
|
||||
"""保存当前模板配置"""
|
||||
if not self.validate_template():
|
||||
return
|
||||
|
||||
selection = self.template_listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type in self.templates and index < len(self.templates[current_type]):
|
||||
template = self.templates[current_type][index]
|
||||
template['name'] = self.template_name_var.get().strip()
|
||||
template['workflow_id'] = self.coze_workflow_id_var.get().strip()
|
||||
template['access_token'] = self.coze_access_token_var.get().strip()
|
||||
template['is_async'] = self.coze_is_async_var.get()
|
||||
template['input_data_template'] = self.coze_input_data_template_var.get().strip()
|
||||
|
||||
self.update_template_list()
|
||||
self.save_templates()
|
||||
self.edit_status_label.config(text="已保存", foreground="green")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
else:
|
||||
messagebox.showwarning("未选择模板", "请先选择要保存的模板")
|
||||
|
||||
def rename_template(self):
|
||||
"""重命名当前选中的模板"""
|
||||
selection = self.template_listbox.curselection()
|
||||
if not selection:
|
||||
messagebox.showwarning("未选择模板", "请先选择要重命名的模板")
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type not in self.templates or index >= len(self.templates[current_type]):
|
||||
return
|
||||
|
||||
template = self.templates[current_type][index]
|
||||
old_name = template['name']
|
||||
|
||||
# 弹出重命名对话框
|
||||
new_name = simpledialog.askstring("重命名模板", "请输入新的模板名称:", initialvalue=old_name)
|
||||
if new_name and new_name.strip() and new_name != old_name:
|
||||
template['name'] = new_name.strip()
|
||||
self.update_template_list()
|
||||
self.save_templates()
|
||||
# 重新选中重命名后的模板
|
||||
self.template_listbox.selection_set(index)
|
||||
self.edit_status_label.config(text="已重命名", foreground="green")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
|
||||
def duplicate_template(self):
|
||||
"""复制当前选中的模板"""
|
||||
selection = self.template_listbox.curselection()
|
||||
if not selection:
|
||||
messagebox.showwarning("提示", "请先选择要复制的模板")
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type not in self.templates or index >= len(self.templates[current_type]):
|
||||
return
|
||||
|
||||
template = self.templates[current_type][index]
|
||||
new_template = template.copy()
|
||||
|
||||
# 获取当前模板列表中最大的副本序号
|
||||
base_name = template['name']
|
||||
max_num = 0
|
||||
for t in self.templates[current_type]:
|
||||
if t['name'].startswith(f"{base_name}_副本"):
|
||||
try:
|
||||
num = int(t['name'].split('_副本')[-1]) if t['name'].split('_副本')[-1] else 1
|
||||
max_num = max(max_num, num)
|
||||
except (IndexError, ValueError):
|
||||
pass
|
||||
|
||||
# 设置新的模板名称
|
||||
new_name = f"{base_name}_副本{max_num + 1 if max_num > 0 else ''}"
|
||||
new_template['name'] = new_name
|
||||
|
||||
self.templates[current_type].append(new_template)
|
||||
self.update_template_list()
|
||||
self.save_templates()
|
||||
|
||||
# 选中新复制的模板
|
||||
new_index = len(self.templates[current_type]) - 1
|
||||
self.template_listbox.selection_clear(0, tk.END)
|
||||
self.template_listbox.selection_set(new_index)
|
||||
self.load_template_config(new_template)
|
||||
|
||||
# 更新状态提示
|
||||
self.edit_status_label.config(text=f"已复制为 '{new_name}'", foreground="green")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text="未保存", foreground="red"))
|
||||
|
||||
def use_template(self):
|
||||
"""使用模板功能 - 弹出模板选择对话框并应用所选模板配置"""
|
||||
# 创建模板选择对话框
|
||||
dialog = tk.Toplevel(self)
|
||||
dialog.title("选择模板")
|
||||
dialog.geometry("400x300")
|
||||
dialog.transient(self) # 设置为应用程序的子窗口
|
||||
dialog.grab_set() # 模态对话框
|
||||
dialog.resizable(False, False)
|
||||
|
||||
# 创建说明标签
|
||||
ttk.Label(dialog, text="请选择要使用的模板:", font=("Arial", 10)).pack(pady=10)
|
||||
|
||||
# 创建模板类型选择框架
|
||||
type_frame = ttk.Frame(dialog)
|
||||
type_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||
|
||||
ttk.Label(type_frame, text="模板类型:").pack(side=tk.LEFT, padx=5)
|
||||
dialog_type_var = tk.StringVar(value=self.coze_generation_type_var.get())
|
||||
type_combo = ttk.Combobox(type_frame, textvariable=dialog_type_var, values=["短篇", "文章"], width=10, state="readonly")
|
||||
type_combo.pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# 创建模板列表框架
|
||||
list_frame = ttk.Frame(dialog)
|
||||
list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# 创建模板列表和滚动条
|
||||
template_listbox = tk.Listbox(list_frame, height=10, width=40)
|
||||
scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=template_listbox.yview)
|
||||
template_listbox.configure(yscrollcommand=scrollbar.set)
|
||||
template_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
|
||||
# 填充模板列表
|
||||
def update_dialog_template_list():
|
||||
template_listbox.delete(0, tk.END)
|
||||
current_type = dialog_type_var.get()
|
||||
if current_type in self.templates:
|
||||
for template in self.templates[current_type]:
|
||||
template_listbox.insert(tk.END, template['name'])
|
||||
|
||||
update_dialog_template_list()
|
||||
|
||||
# 绑定类型选择变更事件
|
||||
def on_dialog_type_changed(event=None):
|
||||
update_dialog_template_list()
|
||||
|
||||
type_combo.bind("<<ComboboxSelected>>", on_dialog_type_changed)
|
||||
|
||||
# 创建按钮框架
|
||||
button_frame = ttk.Frame(dialog)
|
||||
button_frame.pack(fill=tk.X, padx=10, pady=10)
|
||||
|
||||
# 定义确定按钮功能
|
||||
def on_confirm():
|
||||
selection = template_listbox.curselection()
|
||||
if not selection:
|
||||
messagebox.showwarning("未选择模板", "请先选择要使用的模板", parent=dialog)
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
current_type = dialog_type_var.get()
|
||||
if current_type not in self.templates or index >= len(self.templates[current_type]):
|
||||
return
|
||||
|
||||
selected_template = self.templates[current_type][index]
|
||||
|
||||
# 应用所选模板的配置
|
||||
self.coze_generation_type_var.set(current_type) # 更新生成类型
|
||||
self.generation_type_var.set(current_type) # 同步到主页面
|
||||
|
||||
# 更新工作流配置
|
||||
self.coze_workflow_id_var.set(selected_template.get('workflow_id', ''))
|
||||
self.coze_access_token_var.set(selected_template.get('access_token', ''))
|
||||
self.coze_is_async_var.set(selected_template.get('is_async', 'true'))
|
||||
self.coze_input_data_template_var.set(selected_template.get('input_data_template', ''))
|
||||
|
||||
# 更新CONFIG配置
|
||||
CONFIG['Coze']['workflow_id'] = selected_template.get('workflow_id', '')
|
||||
CONFIG['Coze']['access_token'] = selected_template.get('access_token', '')
|
||||
CONFIG['Coze']['is_async'] = selected_template.get('is_async', 'true')
|
||||
CONFIG['Coze']['input_data_template'] = selected_template.get('input_data_template', '')
|
||||
|
||||
# 保存配置
|
||||
save_config(CONFIG)
|
||||
|
||||
# 更新模板列表和选中状态
|
||||
self.update_template_list()
|
||||
for i in range(self.template_listbox.size()):
|
||||
if self.template_listbox.get(i) == selected_template['name']:
|
||||
self.template_listbox.selection_set(i)
|
||||
break
|
||||
|
||||
# 显示成功提示
|
||||
self.edit_status_label.config(text=f"已应用模板 '{selected_template['name']}'", foreground="green")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
|
||||
# 关闭对话框
|
||||
dialog.destroy()
|
||||
|
||||
# 添加确定和取消按钮
|
||||
ttk.Button(button_frame, text="确定", command=on_confirm).pack(side=tk.RIGHT, padx=5)
|
||||
ttk.Button(button_frame, text="取消", command=dialog.destroy).pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
# 设置默认选中第一个模板
|
||||
if template_listbox.size() > 0:
|
||||
template_listbox.selection_set(0)
|
||||
|
||||
# 等待对话框关闭
|
||||
self.wait_window(dialog)
|
||||
|
||||
def clear_template_config(self):
|
||||
"""清空模板配置界面"""
|
||||
# 解绑变量跟踪
|
||||
self._unbind_var_trace()
|
||||
|
||||
# 清空所有配置字段
|
||||
self.template_name_var.set('')
|
||||
self.coze_workflow_id_var.set('')
|
||||
self.coze_access_token_var.set('')
|
||||
self.coze_is_async_var.set('true')
|
||||
self.coze_input_data_template_var.set('')
|
||||
|
||||
# 清空状态提示
|
||||
self.edit_status_label.config(text="已清空", foreground="gray")
|
||||
self.after(2000, lambda: self.edit_status_label.config(text=""))
|
||||
|
||||
# 重新绑定变量跟踪
|
||||
self._setup_var_trace()
|
||||
|
||||
def load_templates(self):
|
||||
"""从配置文件加载模板"""
|
||||
try:
|
||||
import json
|
||||
# 检查Templates节是否存在
|
||||
if 'Templates' in CONFIG:
|
||||
templates_section = CONFIG['Templates']
|
||||
for key in templates_section:
|
||||
if key.startswith('templates_'):
|
||||
template_type = key.replace('templates_', '')
|
||||
if template_type in self.templates:
|
||||
value = templates_section[key]
|
||||
# 确保value是字符串类型
|
||||
if isinstance(value, str):
|
||||
self.templates[template_type] = json.loads(value)
|
||||
else:
|
||||
logger.warning(f"模板配置{key}的值不是字符串类型: {type(value)}")
|
||||
self.templates[template_type] = []
|
||||
except Exception as e:
|
||||
logger.error(f"加载模板配置失败: {e}")
|
||||
|
||||
def save_templates(self):
|
||||
"""保存模板到配置文件"""
|
||||
try:
|
||||
import json
|
||||
# 确保Templates节存在
|
||||
if 'Templates' not in CONFIG:
|
||||
CONFIG.add_section('Templates')
|
||||
|
||||
for template_type, templates in self.templates.items():
|
||||
CONFIG['Templates'][f'templates_{template_type}'] = json.dumps(templates, ensure_ascii=False)
|
||||
|
||||
save_config(CONFIG)
|
||||
except Exception as e:
|
||||
logger.error(f"保存模板配置失败: {e}")
|
||||
messagebox.showerror("保存失败", f"保存模板配置时出错:{e}")
|
||||
|
||||
def get_current_template(self):
|
||||
"""获取当前选中的模板配置"""
|
||||
selection = self.template_listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
current_type = self.coze_generation_type_var.get()
|
||||
if current_type in self.templates and index < len(self.templates[current_type]):
|
||||
return self.templates[current_type][index]
|
||||
|
||||
# 如果没有选中模板,返回当前界面的配置
|
||||
return {
|
||||
'name': self.template_name_var.get() or '默认模板',
|
||||
'type': self.coze_generation_type_var.get(),
|
||||
'workflow_id': self.coze_workflow_id_var.get(),
|
||||
'access_token': self.coze_access_token_var.get(),
|
||||
'is_async': self.coze_is_async_var.get(),
|
||||
'input_data_template': self.coze_input_data_template_var.get()
|
||||
}
|
||||
|
||||
def browse_directory(self, var):
|
||||
directory = filedialog.askdirectory()
|
||||
if directory:
|
||||
@ -490,6 +1026,9 @@ class ArticleReplaceApp(tk.Tk):
|
||||
CONFIG['Coze']['is_async'] = self.coze_is_async_var.get()
|
||||
CONFIG['Coze']['input_data_template'] = self.coze_input_data_template_var.get() # 保存 Coze input data 模板
|
||||
|
||||
# 保存模板配置
|
||||
self.save_templates()
|
||||
|
||||
# 更新Baidu配置
|
||||
CONFIG['Baidu']['api_key'] = self.baidu_api_key_var.get()
|
||||
CONFIG['Baidu']['secret_key'] = self.baidu_secret_key_var.get()
|
||||
@ -560,8 +1099,14 @@ class ArticleReplaceApp(tk.Tk):
|
||||
# 获取AI服务提供商选择
|
||||
ai_service = self.ai_service_var.get()
|
||||
|
||||
# 获取生成类型
|
||||
generation_type = self.generation_type_var.get()
|
||||
|
||||
# 获取当前选中的模板配置
|
||||
current_template = self.get_current_template()
|
||||
|
||||
# 在新线程中运行处理任务
|
||||
self.thread = threading.Thread(target=self.run_processing, args=(excel_path, num_threads, ai_service))
|
||||
self.thread = threading.Thread(target=self.run_processing, args=(excel_path, num_threads, ai_service, generation_type, current_template))
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
@ -572,7 +1117,7 @@ class ArticleReplaceApp(tk.Tk):
|
||||
self.start_button.config(state=tk.NORMAL)
|
||||
self.running = False
|
||||
|
||||
def run_processing(self, excel_path, num_threads, ai_service):
|
||||
def run_processing(self, excel_path, num_threads, ai_service, generation_type=None, current_template=None):
|
||||
"""在后台线程中运行处理任务"""
|
||||
try:
|
||||
# 更新全局变量
|
||||
@ -582,9 +1127,32 @@ class ArticleReplaceApp(tk.Tk):
|
||||
# 记录开始时间
|
||||
start_time = time.time()
|
||||
|
||||
# 如果有模板配置,临时更新CONFIG
|
||||
original_config = None
|
||||
if current_template and ai_service == 'coze':
|
||||
original_config = {
|
||||
'workflow_id': CONFIG['Coze']['workflow_id'],
|
||||
'access_token': CONFIG['Coze']['access_token'],
|
||||
'is_async': CONFIG['Coze']['is_async'],
|
||||
'input_data_template': CONFIG['Coze'].get('input_data_template', '')
|
||||
}
|
||||
|
||||
CONFIG['Coze']['workflow_id'] = current_template.get('workflow_id', '')
|
||||
CONFIG['Coze']['access_token'] = current_template.get('access_token', '')
|
||||
CONFIG['Coze']['is_async'] = current_template.get('is_async', 'true')
|
||||
CONFIG['Coze']['input_data_template'] = current_template.get('input_data_template', '')
|
||||
|
||||
logger.info(f"应用模板配置: {current_template.get('name')}")
|
||||
logger.info(f"Workflow ID: {CONFIG['Coze']['workflow_id']}")
|
||||
logger.info(f"Access Token: {'*' * len(CONFIG['Coze']['access_token'])}")
|
||||
logger.info(f"Is Async: {CONFIG['Coze']['is_async']}")
|
||||
logger.info(f"Input Template: {CONFIG['Coze']['input_data_template']}")
|
||||
|
||||
# 读取链接并处理
|
||||
logger.info(f"开始处理链接,使用 {num_threads} 个线程")
|
||||
results = link_to_text(num_threads=num_threads, ai_service=ai_service)
|
||||
logger.info(f"开始处理链接,使用 {num_threads} 个线程,生成类型: {generation_type}")
|
||||
if current_template:
|
||||
logger.info(f"使用模板: {current_template.get('name', '未命名')}")
|
||||
results = link_to_text(num_threads=num_threads, ai_service=ai_service, current_template=current_template)
|
||||
|
||||
# 计算处理结果
|
||||
total_links = len(results)
|
||||
@ -604,8 +1172,15 @@ class ArticleReplaceApp(tk.Tk):
|
||||
f"共处理 {total_links} 个链接\n成功: {success_links} 个\n失败: {total_links - success_links} 个\n总耗时: {elapsed_time:.2f} 秒"))
|
||||
except Exception as e:
|
||||
logger.error(f"处理任务出错: {e}")
|
||||
self.after(0, lambda: messagebox.showerror("处理失败", f"处理任务出错:{e}"))
|
||||
self.after(0, lambda e=e: messagebox.showerror("处理错误", f"处理任务出错: {e}"))
|
||||
finally:
|
||||
# 恢复原始配置(如果有的话)
|
||||
if original_config is not None:
|
||||
CONFIG['Coze']['workflow_id'] = original_config['workflow_id']
|
||||
CONFIG['Coze']['access_token'] = original_config['access_token']
|
||||
CONFIG['Coze']['is_async'] = original_config['is_async']
|
||||
CONFIG['Coze']['input_data_template'] = original_config['input_data_template']
|
||||
|
||||
# 恢复开始按钮状态
|
||||
self.after(0, lambda: self.start_button.config(state=tk.NORMAL))
|
||||
self.running = False
|
||||
|
||||
@ -12,12 +12,13 @@ from config import *
|
||||
|
||||
|
||||
# ==============================主程序===========================
|
||||
def process_link(link_info, ai_service):
|
||||
def process_link(link_info, ai_service, current_template=None):
|
||||
link, article_type = link_info # 解包链接和类型信息
|
||||
"""
|
||||
处理单个链接
|
||||
:param link: 要处理的链接
|
||||
:param ai_service: AI服务提供商,可选值:dify, coze
|
||||
:param current_template: 当前选择的模板配置
|
||||
"""
|
||||
try:
|
||||
if link.startswith("https://www.toutiao.com"):
|
||||
@ -81,30 +82,52 @@ def process_link(link_info, ai_service):
|
||||
# }
|
||||
message_content = call_dify_workflow(input_data)
|
||||
elif ai_service == "coze":
|
||||
# logger.info("coze正在处理")
|
||||
# weijin = ""
|
||||
# if check_keywords:
|
||||
# weijin = "违禁"
|
||||
# # 从配置加载 Coze input_data 模板
|
||||
# input_data_template_str = CONFIG['Coze'].get('input_data_template',
|
||||
# '{{"article": "{article_text}", "link":"{link}", "weijin":"{weijin}"}}')
|
||||
# try:
|
||||
# # 解析模板字符串为字典
|
||||
# input_data_template = json.loads(input_data_template_str)
|
||||
# # 使用实际变量格式化模板
|
||||
# input_data = {k: v.format(article_text=article_text, link=link, weijin=weijin) for k, v in
|
||||
# input_data_template.items()}
|
||||
# except (json.JSONDecodeError, KeyError, AttributeError) as e:
|
||||
# logger.error(f"处理 Coze input_data 模板时出错: {e}. 使用默认模板.")
|
||||
# input_data = {
|
||||
# "article": article_text,
|
||||
# "link": link,
|
||||
# "weijin": weijin
|
||||
# }
|
||||
logger.info("coze正在处理")
|
||||
|
||||
# 如果有模板配置,临时更新CONFIG
|
||||
original_config = None
|
||||
if current_template:
|
||||
original_config = {
|
||||
'workflow_id': CONFIG['Coze']['workflow_id'],
|
||||
'access_token': CONFIG['Coze']['access_token'],
|
||||
'is_async': CONFIG['Coze']['is_async'],
|
||||
'input_data_template': CONFIG['Coze'].get('input_data_template', '')
|
||||
}
|
||||
|
||||
CONFIG['Coze']['workflow_id'] = current_template.get('workflow_id', '')
|
||||
CONFIG['Coze']['access_token'] = current_template.get('access_token', '')
|
||||
CONFIG['Coze']['is_async'] = current_template.get('is_async', 'true')
|
||||
CONFIG['Coze']['input_data_template'] = current_template.get('input_data_template', '')
|
||||
|
||||
logger.info(f"应用模板配置: {current_template.get('name')}")
|
||||
logger.info(f"Workflow ID: {CONFIG['Coze']['workflow_id']}")
|
||||
logger.info(f"Access Token: {'*' * len(CONFIG['Coze']['access_token'])}")
|
||||
logger.info(f"Is Async: {CONFIG['Coze']['is_async']}")
|
||||
logger.info(f"Input Template: {CONFIG['Coze']['input_data_template']}")
|
||||
|
||||
try:
|
||||
# 从配置加载 Coze input_data 模板
|
||||
input_data_template_str = CONFIG['Coze'].get('input_data_template',
|
||||
'{"article": "{article_text}", "link":"{link}", "weijin":"{weijin}"}')
|
||||
# 解析模板字符串为字典
|
||||
input_data_template = json.loads(input_data_template_str)
|
||||
# 使用实际变量格式化模板
|
||||
input_data = input_data_template
|
||||
except (json.JSONDecodeError, KeyError, AttributeError) as e:
|
||||
logger.error(f"处理 Coze input_data 模板时出错: {e}. 使用默认模板.")
|
||||
input_data = {
|
||||
"article": article_text
|
||||
}
|
||||
|
||||
try:
|
||||
message_content = call_coze_article_workflow(input_data)
|
||||
finally:
|
||||
# 恢复原始配置(如果有的话)
|
||||
if original_config is not None:
|
||||
CONFIG['Coze']['workflow_id'] = original_config['workflow_id']
|
||||
CONFIG['Coze']['access_token'] = original_config['access_token']
|
||||
CONFIG['Coze']['is_async'] = original_config['is_async']
|
||||
CONFIG['Coze']['input_data_template'] = original_config['input_data_template']
|
||||
|
||||
# 获取当前时间并格式化
|
||||
current_time = datetime.now().strftime("%H:%M:%S")
|
||||
@ -151,7 +174,7 @@ def process_link(link_info, ai_service):
|
||||
|
||||
if img_urls:
|
||||
# 在类型目录下创建图片目录
|
||||
type_picture_dir = os.path.join(PICTURE_BASE_PATH, article_type)
|
||||
type_picture_dir = os.path.join(IMGS_BASE_PATH, article_type)
|
||||
safe_open_directory(type_picture_dir)
|
||||
download_and_process_images(img_urls, file_name, type_picture_dir)
|
||||
|
||||
@ -160,7 +183,7 @@ def process_link(link_info, ai_service):
|
||||
raise
|
||||
|
||||
|
||||
def link_to_text(prompt1=None, prompt2=None, num_threads=None, ai_service="dify"):
|
||||
def link_to_text(num_threads=None, ai_service="dify", current_template=None):
|
||||
use_link_path = 'use_link_path.txt'
|
||||
|
||||
# 读取链接
|
||||
@ -174,13 +197,14 @@ def link_to_text(prompt1=None, prompt2=None, num_threads=None, ai_service="dify"
|
||||
database = CONFIG['Database']['database']
|
||||
|
||||
for link_info in links:
|
||||
link = link_info[0] # 获取链接
|
||||
link = link_info[0].strip() # 获取链接并去除空白字符
|
||||
article_type = link_info[1].strip() # 获取类型并去除空白字符
|
||||
logging.info(f"总共{len(links)}个链接")
|
||||
# if check_link_exists(host, user, password, database, link):
|
||||
# logger.info(f"链接已存在: {link}")
|
||||
# continue
|
||||
# else:
|
||||
filtered_links.append(link)
|
||||
filtered_links.append((link, article_type)) # 保存链接和类型的元组
|
||||
# logger.info(f"链接不存在: {link}")
|
||||
# print("链接不存在,存储到过滤器中:", link)
|
||||
|
||||
@ -189,7 +213,7 @@ def link_to_text(prompt1=None, prompt2=None, num_threads=None, ai_service="dify"
|
||||
return []
|
||||
|
||||
# 使用多线程处理链接
|
||||
results = process_links_with_threads(filtered_links, num_threads, ai_service)
|
||||
results = process_links_with_threads(filtered_links, num_threads, ai_service, current_template)
|
||||
|
||||
# 记录已处理的链接
|
||||
with open(use_link_path, 'a+', encoding='utf-8') as f:
|
||||
@ -206,7 +230,7 @@ result_queue = queue.Queue()
|
||||
|
||||
|
||||
# 工作线程函数
|
||||
def worker(ai_service):
|
||||
def worker(ai_service, current_template=None):
|
||||
while True:
|
||||
try:
|
||||
# 从队列中获取任务
|
||||
@ -217,7 +241,7 @@ def worker(ai_service):
|
||||
# 处理链接
|
||||
try:
|
||||
logger.info(f"开始处理链接:{link}")
|
||||
process_link(link, ai_service)
|
||||
process_link(link, ai_service, current_template)
|
||||
result_queue.put((link, True, None)) # 成功
|
||||
except Exception as e:
|
||||
result_queue.put((link, False, str(e))) # 失败
|
||||
@ -230,7 +254,7 @@ def worker(ai_service):
|
||||
|
||||
|
||||
# 多线程处理链接
|
||||
def process_links_with_threads(links, num_threads=None, ai_service="dify"):
|
||||
def process_links_with_threads(links, num_threads=None, ai_service="dify", current_template=None):
|
||||
if num_threads is None:
|
||||
num_threads = min(MAX_THREADS, len(links))
|
||||
else:
|
||||
@ -245,9 +269,9 @@ def process_links_with_threads(links, num_threads=None, ai_service="dify"):
|
||||
# 创建工作线程
|
||||
threads = []
|
||||
|
||||
# 将AI服务选择传递给worker函数
|
||||
# 将AI服务选择和模板配置传递给worker函数
|
||||
for _ in range(num_threads):
|
||||
t = threading.Thread(target=worker, args=(ai_service,))
|
||||
t = threading.Thread(target=worker, args=(ai_service, current_template))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
threads.append(t)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user