Merge branch 'master' of https://gitee.com/TeaCodeNice/crawler-plugin
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,12 @@ from config import runing_task, runing_shop
|
||||
from datetime import datetime
|
||||
from amazon.del_brand import AmamzonBase, kill_process
|
||||
|
||||
# 导入 webview 用于前端通知
|
||||
try:
|
||||
import webview
|
||||
except ImportError:
|
||||
webview = None
|
||||
|
||||
class AmzoneApprove(AmamzonBase):
|
||||
|
||||
def SwitchPage(self):
|
||||
@@ -190,8 +196,8 @@ class AmzoneApprove(AmamzonBase):
|
||||
num = 0
|
||||
|
||||
while 1:
|
||||
if num > 3: #测试
|
||||
return
|
||||
# if num > 3: #测试
|
||||
# return
|
||||
# 等待加载完成
|
||||
load_ele = self.tab.eles("xpath://div[contains(@class,'Loader-module__loader')]",timeout=5)
|
||||
if len(load_ele) > 0:
|
||||
@@ -202,14 +208,17 @@ class AmzoneApprove(AmamzonBase):
|
||||
page_pamel = self.tab.eles('xpath://kat-pagination',timeout=5)
|
||||
if len(page_pamel) > 0:
|
||||
current_page = page_pamel[0].sr('xpath:.//ul[@class="pages"]//li[@aria-current="true"]').text
|
||||
print(f"开始处理,当前页码: {current_page}")
|
||||
print(f"【current_page】开始处理,当前页码: {current_page}")
|
||||
|
||||
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=3)
|
||||
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=10)
|
||||
print(f"获取到 {len(sku_ls)}")
|
||||
for sku_ele in sku_ls[0:2]:
|
||||
# for sku_ele in sku_ls[0:2]:
|
||||
for sku_ele in sku_ls:
|
||||
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]')
|
||||
solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]|.//kat-link[@label="修复被禁止显示的商品"]|//kat-link[@label="解决商品移除风险"]')
|
||||
solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]|.//kat-link[@label="修复被禁止显示的商品"]|.//kat-link[@label="解决商品移除风险"]')
|
||||
if len(solve_problem) == 0:
|
||||
print(f"{asin},没有处理入口,不处理")
|
||||
yield (asin,"没有处理入口,不处理")
|
||||
continue
|
||||
asin = sku_ele.ele('xpath:.//div[contains(@class,"JanusSplitBox-module__container")]//div[contains(@class,"JanusSplitBox-module__panel--") and contains(string(.),"ASIN")]/..//div[last()]').text
|
||||
print(f"ASIN {asin} 存在问题,正在点击解决...")
|
||||
@@ -235,9 +244,9 @@ class AmzoneApprove(AmamzonBase):
|
||||
|
||||
# 解决商品信息违规问题 按钮
|
||||
kat_box_ls = action_panel.eles('xpath:.//kat-box[@variant="white"]',timeout=5)
|
||||
if len(kat_box_ls) == 0:
|
||||
print(f"ASIN {asin} 的操作面板中未找到选项,跳过...")
|
||||
continue
|
||||
# if len(kat_box_ls) == 0:
|
||||
# print(f"ASIN {asin} 的操作面板中未找到选项,跳过...")
|
||||
# continue
|
||||
print(f"ASIN {asin}需要处理的有:{len(kat_box_ls)}个问题.")
|
||||
# 解决商品信息违规问题 按钮,有多少个都要处理
|
||||
for i in range(len(kat_box_ls)):
|
||||
@@ -284,7 +293,7 @@ class AmzoneApprove(AmamzonBase):
|
||||
kat_box_ls = action_panel.eles('xpath:.//kat-box[@variant="white"]', timeout=5)
|
||||
|
||||
# 修复商品信息
|
||||
repair_product = action_panel.eles('xpath://kat-button[@class="action-button"]',timeout=5)
|
||||
repair_product = action_panel.eles('xpath:.//kat-button[@class="action-button"]',timeout=5)
|
||||
if len(repair_product) > 0:
|
||||
print(f"ASIN {asin} 存在修复商品信息按钮,正在点击...")
|
||||
self.clear_tab()
|
||||
@@ -316,7 +325,7 @@ class AmzoneApprove(AmamzonBase):
|
||||
break
|
||||
next_page_btn.click()
|
||||
num += 1
|
||||
print(f"正在翻页,已翻 {num} 页...")
|
||||
# print(f"正在翻页,已翻 {num} 页...")
|
||||
|
||||
|
||||
class ApproveTask:
|
||||
@@ -330,6 +339,75 @@ class ApproveTask:
|
||||
"UK": "英国"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def show_notification(message: str, message_type: str = "error"):
|
||||
"""显示 pywebview 顶层通知(5秒后自动消失)
|
||||
|
||||
Args:
|
||||
message: 通知消息
|
||||
message_type: 消息类型 (success/warning/error/info)
|
||||
"""
|
||||
if webview and webview.windows:
|
||||
try:
|
||||
# 转义单引号,防止 JavaScript 语法错误
|
||||
safe_message = message.replace("'", "\\'").replace('"', '\\"').replace('\n', '\\n')
|
||||
|
||||
# 设置通知样式颜色
|
||||
color_map = {
|
||||
'success': '#67C23A',
|
||||
'warning': '#E6A23C',
|
||||
'error': '#F56C6C',
|
||||
'info': '#909399'
|
||||
}
|
||||
bg_color = color_map.get(message_type, '#F56C6C')
|
||||
|
||||
# 构建前端通知的 JavaScript 代码 - 创建原生 HTML 通知
|
||||
js_code = f"""
|
||||
(function() {{
|
||||
// 移除已存在的通知
|
||||
var existingNotif = document.getElementById('pywebview-notification');
|
||||
if (existingNotif) {{
|
||||
existingNotif.remove();
|
||||
}}
|
||||
|
||||
// 创建通知容器
|
||||
var notif = document.createElement('div');
|
||||
notif.id = 'pywebview-notification';
|
||||
notif.style.cssText = 'position: fixed; top: 20px; left: 50%; transform: translateX(-50%); ' +
|
||||
'background: {bg_color}; color: white; padding: 12px 20px; border-radius: 4px; ' +
|
||||
'box-shadow: 0 2px 12px rgba(0,0,0,0.3); z-index: 99999; font-size: 14px; ' +
|
||||
'max-width: 600px; word-wrap: break-word; display: flex; align-items: center; gap: 10px;';
|
||||
|
||||
// 添加消息内容
|
||||
var msgSpan = document.createElement('span');
|
||||
msgSpan.textContent = '{safe_message}';
|
||||
notif.appendChild(msgSpan);
|
||||
|
||||
// 添加关闭按钮
|
||||
var closeBtn = document.createElement('span');
|
||||
closeBtn.innerHTML = '×';
|
||||
closeBtn.style.cssText = 'cursor: pointer; font-size: 18px; font-weight: bold; margin-left: 10px;';
|
||||
closeBtn.onclick = function() {{ notif.remove(); }};
|
||||
notif.appendChild(closeBtn);
|
||||
|
||||
// 添加到页面
|
||||
document.body.appendChild(notif);
|
||||
|
||||
// 5秒后自动消失
|
||||
setTimeout(function() {{
|
||||
if (notif && notif.parentNode) {{
|
||||
notif.style.transition = 'opacity 0.3s';
|
||||
notif.style.opacity = '0';
|
||||
setTimeout(function() {{ notif.remove(); }}, 300);
|
||||
}}
|
||||
}}, 5000);
|
||||
}})();
|
||||
"""
|
||||
# 在第一个窗口中执行 JavaScript
|
||||
webview.windows[0].evaluate_js(js_code)
|
||||
except Exception as e:
|
||||
print(f"显示通知失败: {str(e)}")
|
||||
|
||||
"""
|
||||
处理流程:
|
||||
1、解析任务json,提取对应的companyName 组组装user_info实例化 AmzoneApprove
|
||||
@@ -385,6 +463,8 @@ class ApproveTask:
|
||||
"""
|
||||
from datetime import datetime
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
if level == "ERROR":
|
||||
self.show_notification(message, "error")
|
||||
print(f"[{timestamp}] [ApproveTask] [{level}] {message}")
|
||||
|
||||
def process_task(self, task_data: dict):
|
||||
@@ -439,6 +519,7 @@ class ApproveTask:
|
||||
|
||||
shop_name = shop_item.get("shopName", "未知店铺")
|
||||
self.log(f"[{idx}/{len(items)}] 开始处理店铺: {shop_name}")
|
||||
self.show_notification(f"开始处理店铺: {shop_name}", "info")
|
||||
|
||||
try:
|
||||
self.process_shop(shop_item, country_codes, task_id,risk_listing_filter)
|
||||
@@ -502,11 +583,11 @@ class ApproveTask:
|
||||
self.log(f"尝试打开店铺 {shop_name} (第 {retry + 1}/{max_retries} 次)")
|
||||
|
||||
# 如果不是第一次尝试,先杀进程
|
||||
if retry > 0:
|
||||
self.log("重试前先杀掉浏览器进程...")
|
||||
kill_process("v6")
|
||||
kill_process("v5")
|
||||
time.sleep(2)
|
||||
# if retry > 0:
|
||||
# self.log("重试前先杀掉浏览器进程...")
|
||||
# kill_process("v6")
|
||||
# kill_process("v5")
|
||||
# time.sleep(2)
|
||||
|
||||
# 组装用户信息并创建驱动
|
||||
user_info = {
|
||||
@@ -522,7 +603,8 @@ class ApproveTask:
|
||||
else:
|
||||
self.log(f"打开店铺失败: {browser}", "WARNING")
|
||||
driver = None
|
||||
|
||||
# 判断是否需要登录
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
self.log(f"打开店铺异常: {str(e)}", "ERROR")
|
||||
@@ -535,7 +617,8 @@ class ApproveTask:
|
||||
|
||||
# 检查是否成功打开
|
||||
if not driver or not browser or browser == "店铺不存在":
|
||||
self.log(f"店铺 {shop_name} 打开失败,已重试 {max_retries} 次,跳过该店铺", "ERROR")
|
||||
error_msg = f"店铺 {shop_name} 打开失败,已重试 {max_retries} 次,跳过该店铺"
|
||||
self.log(error_msg, "ERROR")
|
||||
# 从执行列表中移除
|
||||
if shop_name in runing_shop:
|
||||
del runing_shop[shop_name]
|
||||
@@ -589,7 +672,9 @@ class ApproveTask:
|
||||
|
||||
# 转换国家代码为中文名称
|
||||
country_name = self.country_info.get(country_code, country_code)
|
||||
self.log(f"开始处理国家: {country_name} ({country_code})")
|
||||
info_mes = f"开始处理国家: {country_name} ({country_code})"
|
||||
self.log(info_mes)
|
||||
self.show_notification(info_mes, "info")
|
||||
|
||||
# 更新当前处理的国家
|
||||
if task_id in runing_task:
|
||||
@@ -630,7 +715,8 @@ class ApproveTask:
|
||||
|
||||
# 如果切换失败,直接返回
|
||||
if not switch_success:
|
||||
self.log(f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家", "ERROR")
|
||||
error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家"
|
||||
self.log(error_message, "ERROR")
|
||||
if task_id in runing_task:
|
||||
runing_task[task_id]["processed_countries"] += 1
|
||||
return
|
||||
@@ -819,3 +905,5 @@ if __name__ == '__main__':
|
||||
print(f"ASIN {asin} 的处理结果: {status}")
|
||||
print("已完成操作")
|
||||
|
||||
# for i in range(0):
|
||||
# print(i)
|
||||
0
app/amazon/backend_api.py
Normal file
0
app/amazon/backend_api.py
Normal file
@@ -10,6 +10,7 @@ import os
|
||||
from typing import Literal
|
||||
from DrissionPage import Chromium
|
||||
from DrissionPage.common import By
|
||||
from DrissionPage._pages.chromium_tab import ChromiumTab
|
||||
|
||||
|
||||
def kill_process(version: Literal["v5", "v6"]):
|
||||
@@ -33,7 +34,7 @@ class ZiniaoDriver:
|
||||
self.socket_port = socket_port
|
||||
self.client_path = None
|
||||
self.browser = None
|
||||
self.tab = None
|
||||
self.tab: ChromiumTab = None
|
||||
self.store_id = None
|
||||
|
||||
def get_zinaio_exe(self, protocol_name: str = "superbrowser"):
|
||||
@@ -136,11 +137,11 @@ class ZiniaoDriver:
|
||||
print(r)
|
||||
return r.get("browserList")
|
||||
elif str(r.get("statusCode")) == "-10003":
|
||||
print(f"login Err {json.dumps(r, ensure_ascii=False)}")
|
||||
exit()
|
||||
print(f"【get_browser_list】登录失败 {json.dumps(r, ensure_ascii=False)}")
|
||||
# exit()
|
||||
else:
|
||||
print(f"Fail {json.dumps(r, ensure_ascii=False)} ")
|
||||
exit()
|
||||
print(f"【get_browser_list】失败 {json.dumps(r, ensure_ascii=False)} ")
|
||||
# exit()
|
||||
|
||||
def open_store(self, store_info, isWebDriverReadOnlyMode=0, isprivacy=0,
|
||||
isHeadless=0, cookieTypeSave=0, jsInfo=""):
|
||||
@@ -188,11 +189,11 @@ class ZiniaoDriver:
|
||||
if str(r.get("statusCode")) == "0":
|
||||
return r
|
||||
elif str(r.get("statusCode")) == "-10003":
|
||||
print(f"login Err {json.dumps(r, ensure_ascii=False)}")
|
||||
exit()
|
||||
raise RuntimeError(f"【open_store】登录失败 {json.dumps(r, ensure_ascii=False)}")
|
||||
# exit()
|
||||
else:
|
||||
print(f"Fail {json.dumps(r, ensure_ascii=False)} ")
|
||||
exit()
|
||||
raise RuntimeError(f"【open_store】失败 {json.dumps(r, ensure_ascii=False)} ")
|
||||
# exit()
|
||||
|
||||
def get_browser(self, port) -> Chromium:
|
||||
"""
|
||||
@@ -209,6 +210,17 @@ class ZiniaoDriver:
|
||||
|
||||
def start_client(self):
|
||||
"""启动紫鸟客户端"""
|
||||
|
||||
# 检查端口是否已经启动
|
||||
try:
|
||||
url = f'http://127.0.0.1:{self.socket_port}'
|
||||
response = requests.get(url, timeout=2)
|
||||
print(f"端口 {self.socket_port} 已经启动,跳过启动客户端操作")
|
||||
return
|
||||
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
|
||||
# 端口未启动,继续执行启动操作
|
||||
print(f"端口 {self.socket_port} 未启动,开始启动客户端")
|
||||
|
||||
self.client_path = self.get_zinaio_exe("superbrowserv6").strip('"')
|
||||
print(self.client_path)
|
||||
cmd = [self.client_path, '--run_type=web_driver', '--ipc_type=http',
|
||||
@@ -261,7 +273,8 @@ class ZiniaoDriver:
|
||||
print("ip检测页地址为空,请升级紫鸟浏览器到最新版")
|
||||
print(f"=====关闭店铺:{shop_name}=====")
|
||||
self.close_store(self.store_id)
|
||||
exit()
|
||||
# exit()
|
||||
raise RuntimeError("没有IP检测地址,为了店铺安全不打开店铺")
|
||||
ip_usable = self.open_ip_check(self.browser, ip_check_url)
|
||||
if ip_usable:
|
||||
print("ip检测通过,打开店铺平台主页")
|
||||
@@ -298,11 +311,11 @@ class ZiniaoDriver:
|
||||
if str(r.get("statusCode")) == "0":
|
||||
return r
|
||||
elif str(r.get("statusCode")) == "-10003":
|
||||
print(f"login Err {json.dumps(r, ensure_ascii=False)}")
|
||||
exit()
|
||||
raise RuntimeError(f"【close_store】登录失败 {json.dumps(r, ensure_ascii=False)}")
|
||||
# exit()
|
||||
else:
|
||||
print(f"Fail {json.dumps(r, ensure_ascii=False)} ")
|
||||
exit()
|
||||
raise RuntimeError(f"【close_store】失败: {json.dumps(r, ensure_ascii=False)} ")
|
||||
# exit()
|
||||
|
||||
def open_launcher_page(self, launcher_page: str, browser: Chromium = None):
|
||||
"""
|
||||
@@ -436,8 +449,38 @@ class AmamzonBase(ZiniaoDriver):
|
||||
print(f"切换国家时发生异常:{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def need_login(self):
|
||||
"""
|
||||
判断是否需要登录,部分国家可能需要登录后才能切换国家
|
||||
处理流程:
|
||||
|
||||
"""
|
||||
need_login_ele = self.tab.eles('xpath://h1[@class="a-spacing-small"]',timeout=5)
|
||||
if len(need_login_ele) >0:
|
||||
print("检测到需要登录元素")
|
||||
return True
|
||||
return False
|
||||
|
||||
def login(self,password,username=""):
|
||||
try:
|
||||
pwd_input = self.tab.ele('xpath://input[@type="password"]',timeout=10)
|
||||
pwd_input.input(password)
|
||||
submit_btn = self.tab.ele('xpath://input[@id="signInSubmit"]',timeout=10)
|
||||
submit_btn.click()
|
||||
self.tab.wait.doc_loaded()
|
||||
|
||||
opt_code_input = self.tab.ele('xpath://input[@name="otpCode"]',timeout=10)
|
||||
opt_code_input.wait.displayed(timeout=10,raise_err=False)
|
||||
for _ in range(30):
|
||||
if opt_code_input.value is not None and opt_code_input.value.strip() != "":
|
||||
print("检测到验证码输入完成")
|
||||
submit_btn = self.tab.ele('xpath://input[@id="auth-signin-button"]',timeout=10)
|
||||
submit_btn.click()
|
||||
self.tab.wait.doc_loaded()
|
||||
return True
|
||||
except Exception as e:
|
||||
print("登录过程中发生异常:" + traceback.format_exc())
|
||||
return False
|
||||
|
||||
class AmazoneDriver(AmamzonBase):
|
||||
"""亚马逊专用驱动类,继承自ZiniaoDriver"""
|
||||
|
||||
@@ -78,7 +78,7 @@ class TaskMonitor:
|
||||
|
||||
except Exception as e:
|
||||
# 静默处理队列为空的超时,只记录真正的异常
|
||||
if "Empty" not in str(e):
|
||||
if str(e) and "Empty" not in str(e):
|
||||
self.log(f"任务监控异常: {str(e)}", "ERROR")
|
||||
# 队列为空时不需要额外等待,直接继续循环
|
||||
|
||||
@@ -210,11 +210,11 @@ class TaskMonitor:
|
||||
self.log(f"尝试打开店铺 {shop_name} (第 {retry + 1}/{max_retries} 次)")
|
||||
|
||||
# 如果不是第一次尝试,先杀进程
|
||||
if retry > 0:
|
||||
self.log("重试前先杀掉浏览器进程...")
|
||||
kill_process("v6")
|
||||
kill_process("v5")
|
||||
time.sleep(2)
|
||||
# if retry > 0:
|
||||
# self.log("重试前先杀掉浏览器进程...")
|
||||
# kill_process("v6")
|
||||
# kill_process("v5")
|
||||
# time.sleep(2)
|
||||
|
||||
# 创建驱动并打开店铺
|
||||
user_info = {
|
||||
@@ -230,6 +230,27 @@ class TaskMonitor:
|
||||
else:
|
||||
self.log(f"打开店铺失败: {browser}", "WARNING")
|
||||
driver = None
|
||||
|
||||
# 判断是否需要登录
|
||||
# need_login = driver.need_login()
|
||||
# if need_login:
|
||||
# self.log(f"店铺 {shop_name} 需要登录,正在登录...")
|
||||
# password = ""
|
||||
|
||||
# login_success = driver.login(password)
|
||||
# if login_success:
|
||||
# self.log(f"店铺 {shop_name} 登录成功,正在重新打开店铺...")
|
||||
# browser = driver.open_shop(shop_name)
|
||||
# if browser and browser != "店铺不存在":
|
||||
# self.log(f"成功打开店铺 {shop_name} 登录后")
|
||||
# break
|
||||
# else:
|
||||
# self.log(f"登录后打开店铺失败: {browser}", "WARNING")
|
||||
# driver = None
|
||||
# else:
|
||||
# self.log(f"店铺 {shop_name} 登录失败", "WARNING")
|
||||
# driver = None
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"打开店铺异常: {str(e)}", "ERROR")
|
||||
|
||||
@@ -110,7 +110,10 @@ def proxy(path):
|
||||
if key.lower() in ['host', 'content-length', 'connection']:
|
||||
continue
|
||||
headers[key] = value
|
||||
ignore_url = [f"{JAVA_API_BASE}/api/delete-brand/tasks/batch",f"{JAVA_API_BASE}/api/delete-brand/history"]
|
||||
ignore_url = [f"{JAVA_API_BASE}/api/delete-brand/tasks/batch",
|
||||
f"{JAVA_API_BASE}/api/delete-brand/history",
|
||||
f"{JAVA_API_BASE}/api/product-risk-resolve/tasks/batch",
|
||||
]
|
||||
if target_url not in ignore_url:
|
||||
try:
|
||||
print("=============================")
|
||||
|
||||
39
app/main.py
39
app/main.py
@@ -11,7 +11,7 @@ from amazon.main import TaskMonitor
|
||||
os.makedirs(cache_path,exist_ok=True)
|
||||
if not debug:
|
||||
today = datetime.datetime.now().strftime("%Y_%m_%d")
|
||||
sys.stdout = open(os.path.join(cache_path,f'{today}.log'), 'a',buffering=1)
|
||||
sys.stdout = open(os.path.join(cache_path,f'{today}.log'), 'a',buffering=1,encoding='utf-8')
|
||||
sys.stderr = sys.stdout
|
||||
|
||||
import webview
|
||||
@@ -20,6 +20,9 @@ import time
|
||||
import requests
|
||||
import subprocess
|
||||
|
||||
from amazon.del_brand import kill_process
|
||||
|
||||
|
||||
|
||||
with open("version.txt","w",encoding="utf-8") as file:
|
||||
file.write(json.dumps({"version":version}))
|
||||
@@ -54,8 +57,15 @@ class WindowAPI:
|
||||
window.events.restored += lambda _: setattr(self, '_is_maximized', False)
|
||||
|
||||
def close(self):
|
||||
sys.exit(1)
|
||||
self._window.destroy()
|
||||
try:
|
||||
kill_process('v6')
|
||||
except Exception as e:
|
||||
print(f"【退出前】关闭紫鸟浏览器进程异常: {str(e)}")
|
||||
try:
|
||||
self._window.destroy()
|
||||
except:
|
||||
pass
|
||||
os._exit(0) # 强制退出整个进程,包括所有线程
|
||||
|
||||
def minimize(self):
|
||||
self._window.minimize()
|
||||
@@ -358,6 +368,23 @@ def start_task_monitor():
|
||||
print(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 任务监控线程异常退出: {traceback.format_exc()}")
|
||||
|
||||
|
||||
def on_window_closing():
|
||||
"""窗口关闭事件处理器,执行与 close() 方法相同的清理逻辑"""
|
||||
# 先关闭窗口,避免看起来卡着
|
||||
try:
|
||||
if webview.windows:
|
||||
webview.windows[0].destroy()
|
||||
except:
|
||||
pass
|
||||
|
||||
# 然后执行清理逻辑
|
||||
try:
|
||||
kill_process('v6')
|
||||
except Exception as e:
|
||||
print(f"【退出前】关闭紫鸟浏览器进程异常: {str(e)}")
|
||||
os._exit(0) # 强制退出整个进程,包括所有线程
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists(cache_path):
|
||||
os.makedirs(cache_path,exist_ok=True)
|
||||
@@ -384,11 +411,15 @@ def main():
|
||||
frameless=False,
|
||||
easy_drag=True
|
||||
)
|
||||
|
||||
# 为窗口关闭事件添加处理器
|
||||
window.events.closing += on_window_closing
|
||||
|
||||
api = WindowAPI(window)
|
||||
window.expose(api.close, api.minimize, api.maximize, api.toggle_maximize, generate_images, api.save_image, api.save_image_to_folder, api.select_folder, api.select_brand_xlsx_files, api.select_brand_folder,
|
||||
api.save_file_from_url, api.save_template_xlsx,api.save_template_zip,api.upload_file_to_java,api.open_external_url,api.enqueue_json,api.get_detail_del,api.save_file_from_url_new)
|
||||
webview.start(
|
||||
debug=True,
|
||||
debug=False,
|
||||
storage_path=cache_path,
|
||||
private_mode=False
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user