|
@@ -12,7 +12,7 @@
|
|
|
|
|
|
|
|
注意事项:
|
|
注意事项:
|
|
|
1. 确保Chrome浏览器已安装
|
|
1. 确保Chrome浏览器已安装
|
|
|
-2. 脚本使用Chrome用户配置文件,路径为:C:\Users\zhens\AppData\Local\Google\Chrome\User Data
|
|
|
|
|
|
|
+2. 脚本使用Chrome用户配置文件,路径为:C:/Users/zhens/AppData/Local/Google/Chrome/User Data
|
|
|
3. 运行前请确保没有其他Chrome进程在运行
|
|
3. 运行前请确保没有其他Chrome进程在运行
|
|
|
4. 脚本会自动关闭所有Chrome进程,请确保没有重要工作未保存
|
|
4. 脚本会自动关闭所有Chrome进程,请确保没有重要工作未保存
|
|
|
5. 如果修改了Chrome用户配置路径,需要相应修改代码中的user_data_dir变量
|
|
5. 如果修改了Chrome用户配置路径,需要相应修改代码中的user_data_dir变量
|
|
@@ -25,8 +25,119 @@ import asyncio
|
|
|
import os
|
|
import os
|
|
|
import psutil
|
|
import psutil
|
|
|
import time
|
|
import time
|
|
|
|
|
+import tkinter as tk
|
|
|
|
|
+from tkinter import scrolledtext
|
|
|
from playwright.async_api import async_playwright
|
|
from playwright.async_api import async_playwright
|
|
|
|
|
|
|
|
|
|
+def get_user_input():
|
|
|
|
|
+ """通过GUI窗口获取用户输入的日报内容"""
|
|
|
|
|
+ root = tk.Tk()
|
|
|
|
|
+ root.title("日报填写助手")
|
|
|
|
|
+ root.geometry("900x700")
|
|
|
|
|
+
|
|
|
|
|
+ # 设置窗口样式
|
|
|
|
|
+ root.configure(bg='#f0f0f0')
|
|
|
|
|
+ root.option_add('*Font', '微软雅黑 10')
|
|
|
|
|
+
|
|
|
|
|
+ # 创建主框架
|
|
|
|
|
+ main_frame = tk.Frame(root, bg='#f0f0f0', padx=20, pady=20)
|
|
|
|
|
+ main_frame.pack(fill=tk.BOTH, expand=True)
|
|
|
|
|
+
|
|
|
|
|
+ # 创建标题
|
|
|
|
|
+ title_label = tk.Label(main_frame,
|
|
|
|
|
+ text="日报填写",
|
|
|
|
|
+ font=("微软雅黑", 16, "bold"),
|
|
|
|
|
+ bg='#f0f0f0',
|
|
|
|
|
+ pady=10)
|
|
|
|
|
+ title_label.pack()
|
|
|
|
|
+
|
|
|
|
|
+ # 创建今日工作总结输入区域
|
|
|
|
|
+ summary_frame = tk.LabelFrame(main_frame,
|
|
|
|
|
+ text="今日工作总结",
|
|
|
|
|
+ font=("微软雅黑", 12),
|
|
|
|
|
+ bg='#f0f0f0',
|
|
|
|
|
+ padx=10,
|
|
|
|
|
+ pady=5)
|
|
|
|
|
+ summary_frame.pack(fill=tk.BOTH, expand=True, pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ summary_text = scrolledtext.ScrolledText(summary_frame,
|
|
|
|
|
+ width=80,
|
|
|
|
|
+ height=8,
|
|
|
|
|
+ font=("微软雅黑", 11),
|
|
|
|
|
+ wrap=tk.WORD,
|
|
|
|
|
+ padx=10,
|
|
|
|
|
+ pady=10)
|
|
|
|
|
+ summary_text.pack(fill=tk.BOTH, expand=True)
|
|
|
|
|
+
|
|
|
|
|
+ # 创建明日工作计划输入区域
|
|
|
|
|
+ plan_frame = tk.LabelFrame(main_frame,
|
|
|
|
|
+ text="明日工作计划",
|
|
|
|
|
+ font=("微软雅黑", 12),
|
|
|
|
|
+ bg='#f0f0f0',
|
|
|
|
|
+ padx=10,
|
|
|
|
|
+ pady=5)
|
|
|
|
|
+ plan_frame.pack(fill=tk.BOTH, expand=True, pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ plan_text = scrolledtext.ScrolledText(plan_frame,
|
|
|
|
|
+ width=80,
|
|
|
|
|
+ height=8,
|
|
|
|
|
+ font=("微软雅黑", 11),
|
|
|
|
|
+ wrap=tk.WORD,
|
|
|
|
|
+ padx=10,
|
|
|
|
|
+ pady=10)
|
|
|
|
|
+ plan_text.pack(fill=tk.BOTH, expand=True)
|
|
|
|
|
+
|
|
|
|
|
+ # 创建底部控制区域
|
|
|
|
|
+ bottom_frame = tk.Frame(main_frame, bg='#f0f0f0', pady=10)
|
|
|
|
|
+ bottom_frame.pack(fill=tk.X)
|
|
|
|
|
+
|
|
|
|
|
+ # 创建复选框
|
|
|
|
|
+ keep_original = tk.BooleanVar(value=False)
|
|
|
|
|
+ check_button = tk.Checkbutton(bottom_frame,
|
|
|
|
|
+ text="保留原有内容",
|
|
|
|
|
+ variable=keep_original,
|
|
|
|
|
+ font=("微软雅黑", 11),
|
|
|
|
|
+ bg='#f0f0f0')
|
|
|
|
|
+ check_button.pack(side=tk.LEFT, padx=10)
|
|
|
|
|
+
|
|
|
|
|
+ # 创建提交按钮
|
|
|
|
|
+ result = {"summary": "", "plan": "", "is_submitted": False, "keep_original": False}
|
|
|
|
|
+ def submit():
|
|
|
|
|
+ result["summary"] = summary_text.get("1.0", tk.END).strip()
|
|
|
|
|
+ result["plan"] = plan_text.get("1.0", tk.END).strip()
|
|
|
|
|
+ result["keep_original"] = keep_original.get()
|
|
|
|
|
+ result["is_submitted"] = True
|
|
|
|
|
+ root.quit()
|
|
|
|
|
+ root.destroy()
|
|
|
|
|
+
|
|
|
|
|
+ submit_button = tk.Button(bottom_frame,
|
|
|
|
|
+ text="提交",
|
|
|
|
|
+ command=submit,
|
|
|
|
|
+ font=("微软雅黑", 12, "bold"),
|
|
|
|
|
+ bg='#4CAF50',
|
|
|
|
|
+ fg='white',
|
|
|
|
|
+ width=15,
|
|
|
|
|
+ height=2,
|
|
|
|
|
+ relief=tk.FLAT)
|
|
|
|
|
+ submit_button.pack(side=tk.RIGHT, padx=10)
|
|
|
|
|
+
|
|
|
|
|
+ # 设置窗口居中
|
|
|
|
|
+ root.update_idletasks()
|
|
|
|
|
+ width = root.winfo_width()
|
|
|
|
|
+ height = root.winfo_height()
|
|
|
|
|
+ x = (root.winfo_screenwidth() // 2) - (width // 2)
|
|
|
|
|
+ y = (root.winfo_screenheight() // 2) - (height // 2)
|
|
|
|
|
+ root.geometry(f'{width}x{height}+{x}+{y}')
|
|
|
|
|
+
|
|
|
|
|
+ # 设置窗口图标(如果有的话)
|
|
|
|
|
+ try:
|
|
|
|
|
+ root.iconbitmap('icon.ico') # 如果有图标文件的话
|
|
|
|
|
+ except:
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ root.mainloop()
|
|
|
|
|
+ return result["summary"], result["plan"], result["is_submitted"], result["keep_original"]
|
|
|
|
|
+
|
|
|
# 执行自动化浏览器操作的协程函数
|
|
# 执行自动化浏览器操作的协程函数
|
|
|
|
|
|
|
|
def close_chrome():
|
|
def close_chrome():
|
|
@@ -45,24 +156,21 @@ async def run(playwright):
|
|
|
close_chrome()
|
|
close_chrome()
|
|
|
|
|
|
|
|
# 使用用户实际的Chrome配置,配置查询chrome://version
|
|
# 使用用户实际的Chrome配置,配置查询chrome://version
|
|
|
- user_data_dir = r'C:\Users\zhens\AppData\Local\Google\Chrome\User Data'
|
|
|
|
|
|
|
+ user_data_dir = r'C:/Users/zhens/AppData/Local/Google/Chrome/User Data'
|
|
|
|
|
|
|
|
def text_to_div_html(text):
|
|
def text_to_div_html(text):
|
|
|
"""将多行文本转换为<div>...</div>格式的HTML"""
|
|
"""将多行文本转换为<div>...</div>格式的HTML"""
|
|
|
lines = [line.strip() for line in text.strip().splitlines() if line.strip()]
|
|
lines = [line.strip() for line in text.strip().splitlines() if line.strip()]
|
|
|
return ''.join(f'<div>{line}</div>' for line in lines)
|
|
return ''.join(f'<div>{line}</div>' for line in lines)
|
|
|
|
|
|
|
|
- # 你可以在这里自定义要填写的内容
|
|
|
|
|
- summary_text = """
|
|
|
|
|
- 一、今日完成CRM脚本开发
|
|
|
|
|
- 二、完成小程序测试工作
|
|
|
|
|
- 三、修复了异常处理bug
|
|
|
|
|
- """
|
|
|
|
|
- plan_text = """
|
|
|
|
|
- 一、明天继续完善脚本
|
|
|
|
|
- 二、小程序工人付费工作完善
|
|
|
|
|
- 三、增加更多异常场景测试
|
|
|
|
|
- """
|
|
|
|
|
|
|
+ # 获取用户输入的日报内容
|
|
|
|
|
+ summary_text, plan_text, is_submitted, keep_original = get_user_input()
|
|
|
|
|
+
|
|
|
|
|
+ # 如果用户取消输入,直接退出程序
|
|
|
|
|
+ if not is_submitted:
|
|
|
|
|
+ print("用户取消了日报填写,程序退出")
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
summary_html = text_to_div_html(summary_text)
|
|
summary_html = text_to_div_html(summary_text)
|
|
|
plan_html = text_to_div_html(plan_text)
|
|
plan_html = text_to_div_html(plan_text)
|
|
|
|
|
|
|
@@ -119,17 +227,25 @@ async def run(playwright):
|
|
|
# 今日工作总结输入
|
|
# 今日工作总结输入
|
|
|
# 1. 先点击输入框,确保获得焦点
|
|
# 1. 先点击输入框,确保获得焦点
|
|
|
await page.locator('div.question:has-text("今日工作总结") .maileditor-editorview[contenteditable="true"]').click()
|
|
await page.locator('div.question:has-text("今日工作总结") .maileditor-editorview[contenteditable="true"]').click()
|
|
|
- # 2. 使用键盘输入方式模拟真实输入,这样可以触发输入事件
|
|
|
|
|
|
|
+ # 2. 如果不保留原有内容,则清空输入框
|
|
|
|
|
+ if not keep_original:
|
|
|
|
|
+ await page.keyboard.press('Control+A')
|
|
|
|
|
+ await page.keyboard.press('Delete')
|
|
|
|
|
+ # 3. 使用键盘输入方式模拟真实输入
|
|
|
await page.keyboard.type(summary_text)
|
|
await page.keyboard.type(summary_text)
|
|
|
- # 3. 等待输入完成,确保内容被正确输入
|
|
|
|
|
|
|
+ # 4. 等待输入完成,确保内容被正确输入
|
|
|
await asyncio.sleep(2)
|
|
await asyncio.sleep(2)
|
|
|
|
|
|
|
|
# 明日工作计划输入
|
|
# 明日工作计划输入
|
|
|
# 1. 先点击输入框,确保获得焦点
|
|
# 1. 先点击输入框,确保获得焦点
|
|
|
await page.locator('div.question:has-text("明日工作计划") .maileditor-editorview[contenteditable="true"]').click()
|
|
await page.locator('div.question:has-text("明日工作计划") .maileditor-editorview[contenteditable="true"]').click()
|
|
|
- # 2. 使用键盘输入方式模拟真实输入,如果通过代码编辑,会导致输入栏没有任何信息
|
|
|
|
|
|
|
+ # 2. 如果不保留原有内容,则清空输入框
|
|
|
|
|
+ if not keep_original:
|
|
|
|
|
+ await page.keyboard.press('Control+A')
|
|
|
|
|
+ await page.keyboard.press('Delete')
|
|
|
|
|
+ # 3. 使用键盘输入方式模拟真实输入
|
|
|
await page.keyboard.type(plan_text)
|
|
await page.keyboard.type(plan_text)
|
|
|
- # 3. 等待输入完成
|
|
|
|
|
|
|
+ # 4. 等待输入完成
|
|
|
await asyncio.sleep(2)
|
|
await asyncio.sleep(2)
|
|
|
|
|
|
|
|
# 等待内容保存
|
|
# 等待内容保存
|
|
@@ -138,9 +254,9 @@ async def run(playwright):
|
|
|
|
|
|
|
|
# 点击提交按钮
|
|
# 点击提交按钮
|
|
|
# 1. 等待提交按钮出现
|
|
# 1. 等待提交按钮出现
|
|
|
- await page.wait_for_selector('button.FillFooter_confirm__0ClPl', timeout=60000)
|
|
|
|
|
- # 2. 点击提交按钮,添加延迟模拟真实点击
|
|
|
|
|
- await page.click('button.FillFooter_confirm__0ClPl', delay=100)
|
|
|
|
|
|
|
+ # await page.wait_for_selector('button.FillFooter_confirm__0ClPl', timeout=60000)
|
|
|
|
|
+ # # 2. 点击提交按钮,添加延迟模拟真实点击
|
|
|
|
|
+ # await page.click('button.FillFooter_confirm__0ClPl', delay=100)
|
|
|
|
|
|
|
|
# 等待提交完成
|
|
# 等待提交完成
|
|
|
# 给系统足够的时间来处理提交操作
|
|
# 给系统足够的时间来处理提交操作
|