使用 Python + wxPython 开发一个本地工作日志管理工具
2026/6/8 7:36:12 网站建设 项目流程

背景

日常办公中,工作日志往往具有明显的重复性:例如每天需要记录“考勤”“订饭”,每周一需要记录“周会”“收周报”等固定事项。但实际记录时,又经常夹杂临时任务、请假、补充说明等内容。

如果完全手写,每天都要重复输入固定内容;如果只用 Excel,又不够便捷,查询、复制、统计都比较麻烦。因此,我使用 Python 和 wxPython 编写了一个桌面端工作日志程序,用来快速记录、查询、复制和导出工作日志。

项目核心文件为work_log_app.py,数据保存在同目录下的work_log_data.json中。
C:\Users\86182\Desktop\工作日志

目标

本程序的目标是做一个轻量、离线、方便使用的工作日志工具,主要功能包括:

  1. 按日期记录工作日志,自动显示星期。
  2. 支持每天固定事项,例如“考勤”“订饭”。
  3. 支持每周固定事项,例如周一“周会”“收周报”。
  4. 支持请假状态,并且请假时仍可填写临时事项。
  5. 支持常用词维护、模糊搜索和快速加入。
  6. 支持按日期查询、按事项关键词查询。
  7. 支持按年度、月度以日历形式统计记录情况。
  8. 支持复制全部日志或复制指定起止日期范围内的日志。
  9. 支持导出 Excel 文件。
  10. 支持 Python 运行和 exe 打包运行时的数据路径兼容。

方法

程序采用 wxPython 构建桌面界面,使用 JSON 保存本地数据,使用 Python 标准库生成 Excel 文件。

整体结构可以分为四层:

  1. 数据层:负责读取和保存work_log_data.json
  2. 工具函数层:负责日期、星期、格式化、排序、查询等通用逻辑。
  3. 导出层:负责将日志内容导出为.xlsx文件。
  4. 界面层:使用wx.Framewx.Notebookwx.Panel等控件构建功能界面。

程序入口如下:

defmain():app=wx.App(False)frame=WorkLogFrame()frame.Show()app.MainLoop()

其中WorkLogFrame是主窗口类,所有界面和事件逻辑都集中在这个类中。

过程

1. 数据文件路径处理

程序首先处理数据文件路径:

APP_DIR=Path(sys.executable).resolve().parentifgetattr(sys,"frozen",False)elsePath(__file__).resolve().parent DATA_FILE=APP_DIR/"work_log_data.json"

这段代码解决了一个很常见的问题:Python 直接运行时,数据文件应放在.py文件同目录;打包成 exe 后,数据文件应放在 exe 同目录。如果继续使用__file__,打包后可能会指向临时解包目录,导致程序读不到原有记录。

2. 数据结构设计

日志数据使用 JSON 保存,结构清晰,便于维护:

{"daily_tasks":["考勤。","订饭。"],"weekly_tasks":{"0":["周会。","收周报。"]},"common_words":["考勤。","订饭。","请假"],"entries":[{"date":"2026-06-03","tasks":["考勤。","订饭。","编写工作日志程序。"]}]}

其中:

  • daily_tasks表示每天默认事项。
  • weekly_tasks表示每周固定事项,0代表周一。
  • common_words表示常用词。
  • entries表示实际日志记录。

读取数据时,程序会自动补齐缺失字段:

data.setdefault("daily_tasks",DEFAULT_DAILY_TASKS[:])data.setdefault("weekly_tasks",dict(DEFAULT_WEEKLY_TASKS))data.setdefault("entries",[])data.setdefault("common_words",unique_items(generated_words))

这样即使后续程序增加了新字段,旧数据文件也可以继续兼容。

3. 日志格式化

日志复制时,需要生成类似下面的文本:

2026-06-03 周三 考勤。 订饭。 编写工作日志程序。

对应函数为:

defformat_day_block(entry):tasks=entry.get("tasks",[])header=f"{entry['date']}{weekday_name(entry['date'])}"ifnottasks:returnheaderreturnf"{header}\n"+"\n\n".join(tasks)

这里通过weekday_name()自动计算星期,通过空行分隔事项,方便直接复制到微信、文档或邮件中。

4. 主界面设计

程序使用wx.Notebook创建四个页签:

self.notebook.AddPage(self.record_panel,"记录")self.notebook.AddPage(self.query_panel,"查询")self.notebook.AddPage(self.stats_panel,"统计")self.notebook.AddPage(self.words_panel,"常用词")

四个页面分别负责:

  • 记录:日常录入、保存、删除、复制、导出。
  • 查询:按日期或事项关键词查询。
  • 统计:按年度、月度生成日历视图。
  • 常用词:编辑每天事项、周一事项和常用词。

5. 记录功能实现

记录页提供日期选择、前一天、后一天、请假、每日事项、每周事项、临时事项等控件。

切换日期时,会自动加载当天记录:

defset_selected_date(self,iso_date):self.selected_date=iso_date dt=datetime.strptime(iso_date,"%Y-%m-%d")wx_dt=wx.DateTime(dt.day,dt.month-1,dt.year)self.date_picker.SetValue(wx_dt)self.query_date_picker.SetValue(wx_dt)self.copy_start_picker.SetValue(wx_dt)self.copy_end_picker.SetValue(wx_dt)self.load_entry_for_date(iso_date)

点击“前一天”“后一天”时,本质上是对日期做加减:

defmove_selected_date(self,days):new_date=date.fromisoformat(self.selected_date)+timedelta(days=days)self.set_selected_date(new_date.isoformat())

保存日志时,程序会将勾选事项和临时事项合并:

defcollect_tasks(self):extras=normalize_lines(self.extra_text.GetValue())ifself.leave_check.GetValue():returnunique_items(["请假"]+extras)tasks=[]...tasks.extend(extras)returnunique_items(tasks)

这里有一个细节:请假并不是完全排他的状态。即使勾选“请假”,仍然可以继续填写临时事项,例如“请假”“处理邮件”“参加线上会议”等。

6. 常用词模糊搜索

记录页右侧有常用词列表,支持输入关键词过滤:

defrefresh_common_words_ui(self):all_words=self.data.get("common_words",[])words=all_words keyword=self.quick_word_filter.GetValue().strip()ifkeyword:words=[wordforwordinwordsifkeywordinword]self.quick_words_list.Set(words)

双击常用词后,会加入到临时事项中:

defon_quick_word_double_click(self,event):index=self.quick_words_list.GetSelection()ifindex!=wx.NOT_FOUND:self.add_quick_task(self.quick_words_list.GetString(index))

这种设计适合高频输入场景,减少重复打字。

7. 查询功能实现

查询页支持两种方式。

第一种是按日期查询:

defon_query_day(self,event):iso_date=self.get_picker_iso(self.query_date_picker)entry=entry_by_date(self.data["entries"],iso_date)

第二种是按事项关键词查询:

defon_query_task(self,event):keyword=self.task_query_combo.GetValue().strip()forentryinsorted_entries(self.data["entries"]):hit_tasks=[taskfortaskinentry.get("tasks",[])ifkeywordintask]

这可以快速回答“某件事在哪几天做过”这个问题。

8. 指定日期范围复制

除了复制全部日志,程序还支持复制某个起止日期范围内的内容:

defentries_between(entries,start_iso,end_iso):start=min(start_iso,end_iso)end=max(start_iso,end_iso)returnsorted_entries([entryforentryinentriesifstart<=entry["date"]<=end])

即使用户把结束日期选在开始日期前面,程序也会自动纠正范围。

9. 日历统计功能

统计页使用wx.grid.Grid构建月度日历视图:

self.calendar_grid=wx.grid.Grid(self.stats_panel)self.calendar_grid.CreateGrid(6,7)

程序通过calendar.Calendar().monthdatescalendar()获取月历数据,然后根据日志状态设置单元格颜色:

  • 红色:请假。
  • 绿色:已记录。
  • 白色:当月未记录。
  • 灰色:非当前月份日期。

核心逻辑如下:

if"请假"intasks:value+="\n请假"bg=wx.Colour(255,205,205)else:value+=f"\n{len(tasks)}项"bg=wx.Colour(220,242,220)

双击日历中的某一天,还可以直接跳转到记录页进行查看或修改。

10. Excel 导出

程序没有依赖openpyxl,而是使用标准库zipfile手动生成.xlsx文件。

Excel 本质上是一个 ZIP 包,里面包含若干 XML 文件。程序构造了:

  • [Content_Types].xml
  • _rels/.rels
  • xl/workbook.xml
  • xl/_rels/workbook.xml.rels
  • xl/worksheets/sheet1.xml

最终写入压缩包:

withzipfile.ZipFile(path,"w",zipfile.ZIP_DEFLATED)aszf:forname,contentinfiles.items():zf.writestr(name,content)

这种方式的优点是不需要额外安装第三方 Excel 库,适合轻量级工具。

结果

最终完成的程序具备较完整的工作日志管理能力:

  1. 可以快速记录每天事项。
  2. 可以自动填充每日、每周固定事项。
  3. 可以处理请假和临时事项。
  4. 可以维护常用词,并支持模糊搜索。
  5. 可以查询某一天的日志。
  6. 可以查询某件事在哪些日期做过。
  7. 可以按月用日历方式查看记录情况。
  8. 可以复制全部日志或指定日期范围内的日志。
  9. 可以导出 Excel 文件。
  10. 可以兼容 Python 运行和 exe 打包运行。

程序数据保存在本地 JSON 文件中,不依赖网络,也不依赖数据库,适合个人办公使用。

总结

这个项目虽然规模不大,但涵盖了桌面应用开发中的多个典型问题:界面设计、事件绑定、本地数据持久化、日期处理、文本格式化、查询统计、Excel 导出以及 exe 打包后的路径兼容。

从实现角度看,wxPython 适合开发这类本地办公小工具;JSON 适合保存轻量级结构化数据;标准库生成 Excel 虽然代码量略多,但避免了额外依赖。

后续还可以继续扩展,例如增加多用户配置、日志分类、导入历史 Excel、按关键词统计频次、生成月报周报等功能。对于日常办公自动化来说,这类“小而实用”的工具往往最能节省时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询