Skip to content

Commit b70a793

Browse files
committed
AutoClock模块分离(UI与runner模块分离)
Signed-off-by: wuqiongjin <suchinfinity@qq.com>
1 parent d868050 commit b70a793

14 files changed

Lines changed: 439 additions & 148 deletions

Dockerfile.build

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
1515

1616
# 安装系统依赖
1717
RUN apt-get update && apt-get install -y \
18+
file \
1819
curl \
1920
wget \
2021
git \
@@ -59,4 +60,8 @@ RUN python3 -m pip install --upgrade pip && \
5960
python3 -m pip install pyinstaller
6061

6162
# 构建脚本,并修复生成文件的权限
62-
CMD bash linux_build.sh && chmod -R 777 /build/dist
63+
ENV HOST_UID=1000
64+
ENV HOST_GID=1000
65+
66+
# 构建脚本,并修复生成文件的权限/归属
67+
CMD bash linux_build.sh && chown -R ${HOST_UID}:${HOST_GID} /build/dist || true && chmod -R 775 /build/dist

docker_build.sh

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,34 @@ fi
2626
# 在容器中打包
2727
echo ""
2828
echo "步骤2: 在Docker容器中打包应用..."
29-
docker run --rm -v "$(pwd)/dist:/build/dist" auto-clock-builder
29+
HOST_UID=$(id -u)
30+
HOST_GID=$(id -g)
31+
docker run --rm \
32+
-e HOST_UID=${HOST_UID} \
33+
-e HOST_GID=${HOST_GID} \
34+
-v "$(pwd)/dist:/build/dist" \
35+
auto-clock-builder
3036

3137
if [ $? -ne 0 ]; then
3238
echo "打包失败"
3339
exit 1
3440
fi
3541

36-
# 检查结果
37-
if [ -f "dist/auto_clock" ]; then
42+
# 检查结果 (onedir)
43+
if [ -f "dist/auto_clock/auto_clock" ]; then
3844
echo ""
3945
echo "================================"
4046
echo "打包成功!"
4147
echo "================================"
4248
echo ""
43-
echo "可执行文件: dist/auto_clock"
49+
echo "可执行文件: dist/auto_clock/auto_clock"
50+
echo "Runner: dist/auto_clock/auto-clock-runner"
4451
echo ""
4552
echo "检查GLIBC依赖:"
46-
ldd dist/auto_clock | grep GLIBC || echo " (无GLIBC依赖显示)"
53+
ldd dist/auto_clock/auto_clock | grep GLIBC || echo " (无GLIBC依赖显示)"
4754
echo ""
4855
echo "此版本应该可以在 Ubuntu 20.04+ 系统上运行"
4956
else
50-
echo "打包失败,未找到可执行文件"
57+
echo "打包失败,未找到可执行文件 dist/auto_clock/auto_clock"
5158
exit 1
5259
fi

entry.py

Lines changed: 11 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44
import random
55
import argparse
6+
import subprocess
67
from datetime import datetime, date
78

89
from PyQt5.QtWidgets import QApplication
@@ -11,9 +12,7 @@
1112
from src.utils.log import Log
1213
from src.utils.utils import Utils
1314
from src.ui.ui import ConfigWindow
14-
from src.core.clock_manager import run_clock
1515
from src.utils.const import Key, AppPath
16-
from src.extend.email_server import send_email_by_result
1716
from ui.init_ui import init_ui
1817
import chinese_calendar as calendar
1918

@@ -114,108 +113,16 @@ def run_windows_sleep(delay=30):
114113
Log.error("使用 --help 参数查看所有可用选项")
115114
sys.exit(1)
116115

117-
config_data = Utils.read_dict_from_json(AppPath.DataJson)
118-
send_email_success = False
119-
send_email_failed = False
120-
email = None
121-
if config_data and config_data.get(Key.NotificationEmail):
122-
email = config_data.get(Key.NotificationEmail)
123-
send_email_success = config_data.get(Key.SendEmailWhenSuccess, False)
124-
send_email_failed = config_data.get(Key.SendEmailWhenFailed, False)
125-
126-
ok = False
127-
error = None
128-
task = None
129-
try:
130-
if args.task_id:
131-
task = Utils.find_task(args.task_id)
132-
Log.info(f"Auto Clock Get Task Id: {args.task_id}")
133-
if not task:
134-
raise Exception(f"Task ID: {args.task_id} not found.")
135-
operation = task.get(Key.Operation)
136-
day_time_type = task.get(Key.DayTimeType)
137-
trigger_type = task.get(Key.TriggerType)
138-
139-
# SmartHoliday: only execute on Chinese workdays within the same year
140-
if trigger_type == Key.SmartHoliday:
141-
try:
142-
start_year = int(task.get(Key.Year))
143-
start_month = int(task.get(Key.Month))
144-
start_day = int(task.get(Key.Day))
145-
start_date = date(start_year, start_month, start_day)
146-
except Exception as e:
147-
Log.error(f"SmartHoliday task missing or invalid start date, skip execution. Error: {e}")
148-
sys.exit(1)
149-
150-
today = date.today()
151-
152-
# Only valid in the creation year
153-
if today.year != start_year:
154-
Log.info(f"SmartHoliday task year mismatch (task: {start_year}, today: {today.year}), skip execution.")
155-
sys.exit(0)
156-
157-
# Only valid between start_date and end of year
158-
if today < start_date or today > date(start_year, 12, 31):
159-
Log.info(f"SmartHoliday: today {today} is out of valid range [{start_date}, {start_year}-12-31], skip execution.")
160-
sys.exit(0)
161-
162-
# Only execute on Chinese workdays (including adjusted workdays/holidays)
163-
if not calendar.is_workday(today):
164-
Log.info(f"SmartHoliday: today {today} is not a Chinese workday, skip execution.")
165-
sys.exit(0)
166-
167-
if day_time_type and day_time_type == Key.Random:
168-
time_offset = task.get(Key.TimeOffset, 0)
169-
random_sec = random.randint(0, time_offset)
170-
Log.info(f"将等待 {random_sec} 秒...")
171-
time.sleep(random_sec)
172-
Log.info("等待结束!继续执行任务")
173-
174-
Log.info(f"Task ID: {args.task_id} has found, Task Name: {task.get(Key.TaskName)} Operation: {operation}")
175-
start_time = datetime.now()
176-
177-
if operation == Key.AutoClock:
178-
ok, error = run_clock()
179-
elif operation == Key.ShutDownSystem:
180-
ok, error = run_windows_shutdown(30)
181-
elif operation == Key.SystemSleep:
182-
ok, error = run_windows_sleep(30)
183-
elif operation == Key.DisconnectNetwork:
184-
# 对于断网操作,Windows和Linux都支持延迟参数
185-
ok, error = disconnect_network(30)
186-
elif operation == Key.ConnectNetwork:
187-
# 对于联网操作,通常不需要延迟
188-
ok, error = connect_network()
189-
# 联网后等待10秒,确保网络已经稳定连接
190-
if ok:
191-
Log.info("网络连接成功,等待10秒确保网络稳定...")
192-
time.sleep(10)
193-
Log.info("网络稳定等待完成")
194-
else:
195-
error = f"No operation specified for: {operation}"
196-
197-
end_time = datetime.now()
198-
elapsed_time = end_time - start_time
199-
elapsed_sec = elapsed_time.total_seconds()
200-
task[Key.CostTime] = int(elapsed_sec)
201-
Log.info(f"Finish Task. Start at: {start_time} End at: {end_time} Cost time: {elapsed_sec} sec")
202-
else:
203-
exit()
204-
except Exception as e:
205-
error = str(e)
206-
207-
config_data = Utils.read_dict_from_json(AppPath.DataJson)
208-
if not config_data or not config_data.get(Key.NotificationEmail): exit()
116+
if not args.task_id:
117+
Log.error("任务模式需要提供task_id参数")
118+
sys.exit(1)
209119

210-
email = config_data.get(Key.NotificationEmail)
211-
send_email_success = config_data.get(Key.SendEmailWhenSuccess, False)
212-
send_email_failed = config_data.get(Key.SendEmailWhenFailed, False)
120+
runner_cmd = Utils.get_runner_execute_file()
121+
cmd = f"{runner_cmd} --task_id={args.task_id}"
122+
if args.headless:
123+
cmd += " --headless"
213124

214-
if not error: error = "Unknow Error"
215-
Log.info(f"task: {task}")
216-
Log.info(f"ok: {ok} error: {error}")
217-
Log.info(f"email: {email} send_email_success: {send_email_success} send_email_failed: {send_email_failed}")
218-
219-
send_email_by_result(task=task, email=email, send_email_success=send_email_success,
220-
send_email_failed=send_email_failed, ok=ok, error=error)
125+
Log.info(f"Delegate task to runner: {cmd}")
126+
result = subprocess.run(cmd, shell=True)
127+
sys.exit(result.returncode)
221128
Log.close()

linux_build.sh

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,41 @@ fi
3737
# 开始打包
3838
echo ""
3939
echo "开始打包应用程序..."
40-
pyinstaller pack_linux.spec
40+
pyinstaller --clean --noconfirm pack_linux.spec
4141

4242
# 检查打包是否成功
43-
if [ -f "dist/auto_clock" ]; then
43+
if [ -f "dist/auto_clock/auto_clock" ]; then
4444
echo ""
4545
echo "设置驱动文件执行权限..."
4646
# 查找并设置所有msedgedriver文件的执行权限
4747
find dist -name "msedgedriver" -type f -exec chmod +x {} \;
48+
49+
if [ ! -f "dist/auto_clock/auto-clock-runner" ]; then
50+
echo ""
51+
echo "================================"
52+
echo "打包失败!"
53+
echo "================================"
54+
echo "缺少runner可执行文件: dist/auto_clock/auto-clock-runner"
55+
exit 1
56+
fi
4857

4958
echo ""
5059
echo "================================"
5160
echo "打包成功!"
5261
echo "================================"
5362
echo ""
54-
echo "可执行文件位置: dist/auto_clock"
63+
echo "可执行文件位置: dist/auto_clock/auto_clock"
64+
echo "Runner位置: dist/auto_clock/auto-clock-runner"
5565
echo ""
5666
echo "使用方法:"
5767
echo " 1. 图形界面模式:"
58-
echo " ./dist/auto_clock"
68+
echo " ./dist/auto_clock/auto_clock"
5969
echo ""
6070
echo " 2. 无头模式执行任务:"
61-
echo " ./dist/auto_clock --headless --task_id=YOUR_TASK_ID"
71+
echo " ./dist/auto_clock/auto_clock --headless --task_id=YOUR_TASK_ID"
6272
echo ""
6373
echo " 3. 任务模式:"
64-
echo " ./dist/auto_clock --task_id=YOUR_TASK_ID"
74+
echo " ./dist/auto_clock/auto_clock --task_id=YOUR_TASK_ID"
6575
echo ""
6676
echo "注意事项:"
6777
echo " - 首次运行需要配置 config.json"

pack.spec

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT
99
project_root = r"."
1010
# 主脚本路径
1111
main_script = os.path.join(project_root, "entry.py")
12+
runner_script = os.path.join(project_root, "src", "runner", "runner_main.py")
1213
ico = os.path.join(project_root, "icon.ico")
1314

1415
# 依赖的额外文件
@@ -24,7 +25,7 @@ if os.path.exists(ico_dir):
2425
if os.path.exists(resource_path):
2526
extra_files.append((str(resource_path), os.path.join(".", "ui", "resource")))
2627

27-
a = Analysis(
28+
a_ui = Analysis(
2829
[str(main_script)],
2930
pathex=[str(project_root)],
3031
binaries=[],
@@ -40,28 +41,86 @@ a = Analysis(
4041
noarchive=False,
4142
)
4243

43-
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
44+
a_runner = Analysis(
45+
[str(runner_script)],
46+
pathex=[str(project_root)],
47+
binaries=[],
48+
datas=[],
49+
hiddenimports=[],
50+
hookspath=[],
51+
hooksconfig={},
52+
runtime_hooks=[],
53+
excludes=[],
54+
win_no_prefer_redirects=False,
55+
win_private_assemblies=False,
56+
cipher=None,
57+
noarchive=False,
58+
)
59+
60+
pyz_ui = PYZ(a_ui.pure, a_ui.zipped_data, cipher=None)
61+
pyz_runner = PYZ(a_runner.pure, a_runner.zipped_data, cipher=None)
4462

45-
exe = EXE(
46-
pyz,
47-
a.scripts,
48-
a.binaries,
49-
a.zipfiles,
50-
a.datas,
63+
exe_ui = EXE(
64+
pyz_ui,
65+
a_ui.scripts,
66+
[],
67+
[],
5168
[],
52-
name="auto_clock", # exe 文件名
69+
[],
70+
name="auto_clock",
5371
debug=False,
5472
bootloader_ignore_signals=False,
5573
strip=False,
5674
upx=False,
5775
upx_exclude=[],
5876
runtime_tmpdir=None,
5977
console=False,
78+
exclude_binaries=True,
79+
disable_windowed_traceback=False,
80+
argv_emulation=False,
81+
target_arch=None,
82+
codesign_identity=None,
83+
entitlements_file=None,
84+
icon=ico,
85+
uac_admin=True
86+
)
87+
88+
exe_runner = EXE(
89+
pyz_runner,
90+
a_runner.scripts,
91+
[],
92+
[],
93+
[],
94+
[],
95+
name="auto-clock-runner",
96+
debug=False,
97+
bootloader_ignore_signals=False,
98+
strip=False,
99+
upx=False,
100+
upx_exclude=[],
101+
runtime_tmpdir=None,
102+
console=True,
103+
exclude_binaries=True,
60104
disable_windowed_traceback=False,
61105
argv_emulation=False,
62106
target_arch=None,
63107
codesign_identity=None,
64108
entitlements_file=None,
65109
icon=ico,
66110
uac_admin=True
111+
)
112+
113+
coll = COLLECT(
114+
exe_ui,
115+
exe_runner,
116+
a_ui.binaries,
117+
a_ui.zipfiles,
118+
a_ui.datas,
119+
a_runner.binaries,
120+
a_runner.zipfiles,
121+
a_runner.datas,
122+
strip=False,
123+
upx=False,
124+
upx_exclude=[],
125+
name="auto_clock"
67126
)

0 commit comments

Comments
 (0)