当前位置: 首页 > news >正文

Python自动化办公(系统维护及开发任务状态自动推送)

Python自动化办公,

1.需求分析

  • 系统维护及开发人员的工作一般都会比较繁杂,领导们喜欢实时掌控项目的进度,但是领导们很多时候是不会自己主动去查看及分析项目进度数据的,干活的牛马们也没空整天日报,周报,月报,季报,年报…
  • 活又有了,又该想想怎么干,需求的核心是实现自动整理数据,数据图表化后自动推送,本公司工程软件部的所有任务分配都是在工程管理系统上排定,任务的详细进度及达成数据需要自行导出分析,这个部分很不符合我们的自动化宗旨,我们就从这部分需求下手,任务执行及达成状况自动推送到相关人员,领导也可实时掌控工作任务状况.

2.实现逻辑

需求有了,我们看看具体的实施逻辑

  • 首先,所有的项目开发及维护分配任务是已经有了的(会要求所有需求都登记在内部开发的工程管理系统需求处理模块),我们只需要获取所有工作任务并按要求分析整理好并图表化,此部分数据我们直接去工程管理系统数据库查表获取(推荐还是通过接口获取)
  • 其次,我们解析并整理任务数据,此部分数据图表展示按自身实际需求去处理
  • 再次,我们以企业微信消息推送方式推送数据信息
  • 最后,我们制订任务计划,让所有的信息按要求每天推送

效果演示

  • 自动企微推送(没有可以邮件推送)
    在这里插入图片描述
  • 推送的详细数据报告及图表(用html网页编写,数据按自己需求即可,此处仅做案例展示)
    在这里插入图片描述

3.代码实现

  • 一些参数信息我们用标准的JSON
    {
    "图表存储位置": "/Linux存放生成的图表图片目录/end_img",
    "win系统图表存储位置": "S:\\Windows存放生成的图表图片目录\\end_img",
    "html缓存位置": "Linux存放生成的html文件路径/html_cache",
    "win系统html缓存位置": "P:\\Windows存放生成的html文件路径\\工程管理系统缓存"
    }
    
  • 首先获取我们的工程管理数据库需求数据(推荐使用接口获取)
    # 获取全部需求信息数据
    def _get_base_data(self):"""获取全部需求信息数据:return: 基础信息数据字典列表"""_where = ""if self.sys in ["工程软件组CAM系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('Incam', 'Genesis')")elif self.sys in ["工程软件组MI系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('Inplan', '物料')")elif self.sys in ["工程数据组工程管理系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('工程管理系统')")elif self.sys in ["工程数据组LOT卡系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('LOT卡')")elif self.sys in ["工程软件部联络函"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('联络函')")elif self.sys in ["日常维护&其他"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) not in ""('Incam', 'Genesis', 'Inplan', '物料', '工程管理系统', 'LOT卡', '联络函')")_sql = f"""SELECT (SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='Site') AND DicValue=requirement_0_main.Site) AS 基地,(SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND Id=requirement_0_main.RequireSoftware) AS 需求软件,(SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NOT NULL AND Id=requirement_0_main.RequireType) AS 需求类别,(SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='RequireStatus') AND DicValue=requirement_0_main.RequireStatus) AS 需求状态,JobName AS 参考料号,Topic AS 主题,Detail AS 详细描述,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.Register) AS 登记人,RegisterDate AS 登记时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.RequireAudit) AS 需求审核人,RequireAuditTime AS 需求审核时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.DevAuditor) AS 开发审核人,DevAuditorTime AS 开发审核时间,PlannedCompletionTime AS 计划完成时间,ActualCompletionTime AS 实际完成时间,ActualCompletionTime AS 实际完成时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.TestPerson) AS 测试人,TestTime AS 测试时间,(SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='TestResult') AND DicValue=requirement_0_main.TestResult) AS 测试结果,TestRemark AS 测试意见,TestBackTimes AS 退回次数FROM requirement_0_main{_where}"""_data = self.sql.exec_query(_sql)return _data
  • 整理数据生成图表(根据需求产生需要的数据及图表)
      # 统计各基地需求信息def _get_reviewed_info(self, _site):"""统计各基地需求信息:return:"""_dict = {}_num = 0for i in self.data:if _site in ["湖南", "广东", "泰国&台湾", "全部"]:if i["基地"] == _site:_num += 1if i["需求状态"] not in _dict.keys():_dict[i["需求状态"]] = 0_dict[i["需求状态"]] += 1else:_num += 1if i["需求状态"] not in _dict.keys():_dict[i["需求状态"]] = 0_dict[i["需求状态"]] += 1_str = _siteif _site in ["全部"]:_str = "其他"if _site not in ["湖南", "广东", "泰国&台湾", "全部"]:_str = ""# 中文标签plt.rcParams['font.sans-serif'] = ['STKaiti']  # 指定默认字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号'-'显示为方块的问题# 创建图像# 组合标签和数据,并根据数据排序data = sorted(zip(_dict.keys(), _dict.values()), key=lambda x: x[1], reverse=True)if len(data) == 0:returnlabels, sizes = zip(*data)labels = tuple([i.split(",")[0] + ",\n" + i.split(",")[1] if "," in i else i for i in list(labels)])# 获取所有颜色_colors = list(colors.TABLEAU_COLORS.values())plt.figure(figsize=(12, 6))  # 设置图像大小为8x6plt.bar(labels, sizes, width=0.3, color=_colors, edgecolor='black')plt.title(f'{_str}需求汇总({time.strftime("%Y-%m-%d", time.localtime())})', fontsize=16)  # 添加标题plt.xlabel(f'{_str}总需求汇总数量:{_num}', fontsize=14)  # 添加x轴标签plt.ylabel('数量', fontsize=12)  # 添加y轴标签plt.xticks(fontsize=10)  # 设置x轴刻度标签字体大小plt.yticks(fontsize=10)  # 设置y轴刻度标签字体大小# 添加数据标签for i, v in enumerate(sizes):plt.text(i, v + 1, str(v), ha='center', fontsize=10)plt.tight_layout()  # 自动调整布局plt.savefig(f'{self.img_path}/{_str}成本管理中心需求汇总.png')self.img_list.append(f'{self.img_path}/{_str}成本管理中心需求汇总.png')# plt.show()
    
  • 信息推送(邮件推送及企业微信推送)
        # 企微推送
    def _send_wechat_message(self):"""推送信息:return:"""img_data_list = []for i in self.img_list:with open(i, 'rb') as f:img_data_list.append(f'<img src="data:image/png;base64,%s" alt="Embedded Image">' %base64.b64encode(f.read()).decode('utf-8'))_h = "\n".join(img_data_list)html_text = """<html><head><style>.timestamp {font-size: 24px;}.container {margin: 20px;display: flex;flex-wrap: wrap;justify-content: space-between;}.container img {margin: 20px;max-width: 46%%;margin-bottom: 4%%;border-radius: 10px;object-fit: cover;object-position: center;}body {margin: 10px;background-color: #170044;color: #FFF;}</style></head><body><h2 style="text-align: center;font-size: 30px;margin-left: 20px; margin-right: 20px;">所有基地&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;成本管理中心需求汇总(%s)&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;%s</h2><div class="container">%s</div></body></html>""" % (self.sys, time.strftime("%Y-%m-%d", time.localtime()), _h)self.html_file = f"{self.html_path}\\{self.sys}-{time.strftime('%Y-%m-%d', time.localtime())}.html"with open(self.html_file, "w") as f:f.write(html_text)_wc = WeChatMessage()_dict = _wc.get_users_id()_users_id = [list(i.values())[0] for i in _dict["工程软件部"] + _dict["工程数据组"]]# _users_id = [list(i.values())[0] for i in _dict["工程软件部"]]if self.sys == "工程软件组CAM系统":_users_id = [list(i.values())[0] for i in _dict["工程软件组"]if list(i.keys())[0] in ["张三", "田甜", "姚胜兰"]]elif self.sys == "工程软件组MI系统":_users_id = [list(i.values())[0] for i in _dict["工程软件组"]if list(i.keys())[0] in ["罗秀青", "吴贤宗", "朱奇敏", "许定红"]]elif self.sys == "工程数据组工程管理系统":_users_id = [list(i.values())[0] for i in _dict["工程数据组"]]elif self.sys == "工程数据组LOT卡系统":_users_id = [list(i.values())[0] for i in _dict["工程数据组"]]# # 测试用# _users_id = [list(i.values())[0] for i in _dict["工程软件组"]#              if list(i.keys())[0] in ["张三"]]locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')_wc.send_text_card_message(to_users=_users_id,agent_id=1000039,file_url=self.html_file,_title=f'成本管理中心{self.sys}需求汇总-'f'{time.strftime("%Y年%m月%d日", time.localtime())}')# 发送邮件
    def _send_mail(self):"""发送邮件:return:"""img_data_list = []for i in self.img_list:with open(i, 'rb') as f:img_data_list.append(f'<img src="data:image/png;base64,%s" alt="Embedded Image">' %base64.b64encode(f.read()).decode('utf-8'))_h = "\n".join(img_data_list)html_text = """<html><head><style>.timestamp {font-size: 24px;}.container {margin: 20px;display: flex;flex-wrap: wrap;justify-content: space-between;}.container img {margin: 20px;max-width: 46%%;margin-bottom: 4%%;border-radius: 10px;object-fit: cover;object-position: center;}body {margin: 10px;background-color: #170044;color: #FFF;}</style></head><body><h2 style="text-align: center;font-size: 30px;margin-left: 20px; margin-right: 20px;">所有基地&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;成本管理中心需求汇总&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;%s</h2><div class="container">%s</div></body></html>""" % (time.strftime("%Y-%m-%d", time.localtime()), _h)_to_list = ["pe_software@askpcb.com","shenglan.yao@askpcb.com","zhangliang@askpcb.com","xiuqing.luo@askpcb.com"]try:SM = sendMail.MailMain("益阳210服务器(系统需求汇总分析.py)","sysinfo@askpcb.com",_to_list,f"{html_text}",f"成本管理中心需求汇总")SM.SendMail(text_type="html")print('邮件发送成功!')except BaseException as e:print(f'邮件发送失败!错误详情:{e}')
    
  • 完成代码
    #!/usr/bin/env py3kimport re
    import sys
    import os
    import random
    import time
    import locale
    import base64
    import platform
    import matplotlib.pyplot as plt
    from matplotlib import colorsif platform.system() == 'Windows':sys.path.append("S:\\site_data\\scripts\\py3_package")
    else:sys.path.append("/incam/server/site_data/scripts/py3_package")
    from SqlClasses import AskMiMySqlServer
    from GuiClasses import *
    from ApiClasses import *
    import sendMail# 开发日志
    _header = {'脚本名称': '系统需求汇总分析程式','开发人员': 'Twei Tang','开发时间': '2023年11月21日','版本信息': 'A.1.1','联系方式': ('邮箱地址<>','微信号码<358143105>','手机号码<13627441202>'),'开发信息': ('无'),'修改信息': ('历史版本(A.1.0),首次开发测试,暂无版本变更信息','当前版本(A.1.1),添加台湾&泰国需求汇总数据,修改工程管理中心为成本管理中心,2024/5/15,周三,唐伟'),'沟通记录': ('无')
    }class DoMain:def __init__(self):self.app = QApplication(sys.argv)self.gui = MainGui()self.sql = AskMiMySqlServer(_port=3360, db="epms")  # 字典形式返回数据self.sys = "所有系统"if len(sys.argv) > 1:if sys.argv[1] in ["CAM系统"]:self.sys = "工程软件组CAM系统"elif sys.argv[1] in ["MI系统"]:self.sys = "工程软件组MI系统"elif sys.argv[1] in ["管理系统"]:self.sys = "工程数据组工程管理系统"elif sys.argv[1] in ["LOT系统"]:self.sys = "工程数据组LOT卡系统"elif sys.argv[1] in ["联络函"]:self.sys = "工程软件部联络函"else:self.sys = "日常维护&其他"self.data = self._get_base_data()if platform.system() == 'Windows':self.m_json = self.gui.GetConFigMethods("S:\\site_data\\scripts\\py3_package\\config\\公共制作\\系统需求汇总配置文档.json")self.img_path = self.m_json["win系统图表存储位置"]self.html_path = self.m_json["win系统html缓存位置"]else:self.m_json = self.gui.GetConFigMethods(self.gui.config_path + "/公共制作/系统需求汇总配置文档.json")self.img_path = self.m_json["图表存储位置"]self.html_path = self.m_json["html缓存位置"]self.img_list = []# 获取全部需求信息数据def _get_base_data(self):"""获取全部需求信息数据:return: 基础信息数据字典列表"""_where = ""if self.sys in ["工程软件组CAM系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('Incam', 'Genesis')")elif self.sys in ["工程软件组MI系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('Inplan', '物料')")elif self.sys in ["工程数据组工程管理系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('工程管理系统')")elif self.sys in ["工程数据组LOT卡系统"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('LOT卡')")elif self.sys in ["工程软件部联络函"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) in ('联络函')")elif self.sys in ["日常维护&其他"]:_where = ("WHERE (SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND ""Id=requirement_0_main.RequireSoftware) not in ""('Incam', 'Genesis', 'Inplan', '物料', '工程管理系统', 'LOT卡', '联络函')")_sql = f"""SELECT (SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='Site') AND DicValue=requirement_0_main.Site) AS 基地,(SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NULL AND Id=requirement_0_main.RequireSoftware) AS 需求软件,(SELECT TypeValue AS _VALUE FROM requirement_1_type WHERE ParentId IS NOT NULL AND Id=requirement_0_main.RequireType) AS 需求类别,(SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='RequireStatus') AND DicValue=requirement_0_main.RequireStatus) AS 需求状态,JobName AS 参考料号,Topic AS 主题,Detail AS 详细描述,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.Register) AS 登记人,RegisterDate AS 登记时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.RequireAudit) AS 需求审核人,RequireAuditTime AS 需求审核时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.DevAuditor) AS 开发审核人,DevAuditorTime AS 开发审核时间,PlannedCompletionTime AS 计划完成时间,ActualCompletionTime AS 实际完成时间,ActualCompletionTime AS 实际完成时间,(SELECT UserTrueName FROM sys_user WHERE User_Id = requirement_0_main.TestPerson) AS 测试人,TestTime AS 测试时间,(SELECT DicName FROM sys_dictionarylist WHERE Dic_ID=(SELECT Dic_ID FROM sys_dictionary WHERE DicNo='TestResult') AND DicValue=requirement_0_main.TestResult) AS 测试结果,TestRemark AS 测试意见,TestBackTimes AS 退回次数FROM requirement_0_main{_where}"""_data = self.sql.exec_query(_sql)return _data# 统计各基地需求信息def _get_reviewed_info(self, _site):"""统计各基地需求信息:return:"""_dict = {}_num = 0for i in self.data:if _site in ["湖南", "广东", "泰国&台湾", "全部"]:if i["基地"] == _site:_num += 1if i["需求状态"] not in _dict.keys():_dict[i["需求状态"]] = 0_dict[i["需求状态"]] += 1else:_num += 1if i["需求状态"] not in _dict.keys():_dict[i["需求状态"]] = 0_dict[i["需求状态"]] += 1_str = _siteif _site in ["全部"]:_str = "其他"if _site not in ["湖南", "广东", "泰国&台湾", "全部"]:_str = ""# 中文标签plt.rcParams['font.sans-serif'] = ['STKaiti']  # 指定默认字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号'-'显示为方块的问题# 创建图像# 组合标签和数据,并根据数据排序data = sorted(zip(_dict.keys(), _dict.values()), key=lambda x: x[1], reverse=True)if len(data) == 0:returnlabels, sizes = zip(*data)labels = tuple([i.split(",")[0] + ",\n" + i.split(",")[1] if "," in i else i for i in list(labels)])# 获取所有颜色_colors = list(colors.TABLEAU_COLORS.values())plt.figure(figsize=(12, 6))  # 设置图像大小为8x6plt.bar(labels, sizes, width=0.3, color=_colors, edgecolor='black')plt.title(f'{_str}需求汇总({time.strftime("%Y-%m-%d", time.localtime())})', fontsize=16)  # 添加标题plt.xlabel(f'{_str}总需求汇总数量:{_num}', fontsize=14)  # 添加x轴标签plt.ylabel('数量', fontsize=12)  # 添加y轴标签plt.xticks(fontsize=10)  # 设置x轴刻度标签字体大小plt.yticks(fontsize=10)  # 设置y轴刻度标签字体大小# 添加数据标签for i, v in enumerate(sizes):plt.text(i, v + 1, str(v), ha='center', fontsize=10)plt.tight_layout()  # 自动调整布局plt.savefig(f'{self.img_path}/{_str}成本管理中心需求汇总.png')self.img_list.append(f'{self.img_path}/{_str}成本管理中心需求汇总.png')# plt.show()def _send_wechat_message(self):"""推送信息:return:"""img_data_list = []for i in self.img_list:with open(i, 'rb') as f:img_data_list.append(f'<img src="data:image/png;base64,%s" alt="Embedded Image">' %base64.b64encode(f.read()).decode('utf-8'))_h = "\n".join(img_data_list)html_text = """<html><head><style>.timestamp {font-size: 24px;}.container {margin: 20px;display: flex;flex-wrap: wrap;justify-content: space-between;}.container img {margin: 20px;max-width: 46%%;margin-bottom: 4%%;border-radius: 10px;object-fit: cover;object-position: center;}body {margin: 10px;background-color: #170044;color: #FFF;}</style></head><body><h2 style="text-align: center;font-size: 30px;margin-left: 20px; margin-right: 20px;">所有基地&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;成本管理中心需求汇总(%s)&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;%s</h2><div class="container">%s</div></body></html>""" % (self.sys, time.strftime("%Y-%m-%d", time.localtime()), _h)self.html_file = f"{self.html_path}\\{self.sys}-{time.strftime('%Y-%m-%d', time.localtime())}.html"with open(self.html_file, "w") as f:f.write(html_text)_wc = WeChatMessage()_dict = _wc.get_users_id()_users_id = [list(i.values())[0] for i in _dict["工程软件部"] + _dict["工程数据组"]]# _users_id = [list(i.values())[0] for i in _dict["工程软件部"]]if self.sys == "工程软件组CAM系统":_users_id = [list(i.values())[0] for i in _dict["工程软件组"]if list(i.keys())[0] in ["张三", "田四", "姚老五"]]elif self.sys == "工程软件组MI系统":_users_id = [list(i.values())[0] for i in _dict["工程软件组"]if list(i.keys())[0] in ["罗八", "吴九", "朱十一", "许大麻"]]elif self.sys == "工程数据组工程管理系统":_users_id = [list(i.values())[0] for i in _dict["工程数据组"]]elif self.sys == "工程数据组LOT卡系统":_users_id = [list(i.values())[0] for i in _dict["工程数据组"]]# # 测试用# _users_id = [list(i.values())[0] for i in _dict["工程软件组"]#              if list(i.keys())[0] in ["唐伟"]]locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')_wc.send_text_card_message(to_users=_users_id,agent_id=1000039,file_url=self.html_file,_title=f'成本管理中心{self.sys}需求汇总-'f'{time.strftime("%Y年%m月%d日", time.localtime())}')# 发送邮件def _send_mail(self):"""发送邮件:return:"""img_data_list = []for i in self.img_list:with open(i, 'rb') as f:img_data_list.append(f'<img src="data:image/png;base64,%s" alt="Embedded Image">' %base64.b64encode(f.read()).decode('utf-8'))_h = "\n".join(img_data_list)html_text = """<html><head><style>.timestamp {font-size: 24px;}.container {margin: 20px;display: flex;flex-wrap: wrap;justify-content: space-between;}.container img {margin: 20px;max-width: 46%%;margin-bottom: 4%%;border-radius: 10px;object-fit: cover;object-position: center;}body {margin: 10px;background-color: #170044;color: #FFF;}</style></head><body><h2 style="text-align: center;font-size: 30px;margin-left: 20px; margin-right: 20px;">所有基地&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;成本管理中心需求汇总&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;%s</h2><div class="container">%s</div></body></html>""" % (time.strftime("%Y-%m-%d", time.localtime()), _h)_to_list = ["张三@henxing.com","姚老五@henxing.com","赵二@henxing.com","罗八@henxing.com"]try:SM = sendMail.MailMain("XXX服务器(系统需求汇总分析.py)","你的邮箱服务器账号",_to_list,f"{html_text}",f"成本管理中心需求汇总")SM.SendMail(text_type="html")print('邮件发送成功!')except BaseException as e:print(f'邮件发送失败!错误详情:{e}')if __name__ == "__main__":_do = DoMain()_do._get_reviewed_info(_site="湖南")_do._get_reviewed_info(_site="广东")_do._get_reviewed_info(_site="泰国&台湾")_do._get_reviewed_info(_site="全部")_do._get_reviewed_info(_site="所有")# _do._send_mail()_do._send_wechat_message()sys.exit()
    

4.自动执行

  • Windows自动任务计划
    • 1.打开开始菜单搜索"任务计划程序"单击打开
      在这里插入图片描述
    • 2.打开任务计划配置主界面后单击"创建任务"
      在这里插入图片描述
    • 3.分别按下图配置你的自动任务
      常规
      在这里插入图片描述
      触发器
      在这里插入图片描述
      在弹出的编辑窗口配置触发器,完成后单击确定
      在这里插入图片描述
      操作
      在这里插入图片描述
      在弹出的编辑窗口配置操作,完成后单击确定
      在这里插入图片描述
      条件
      如图设置条件
      在这里插入图片描述
      设置
      如图设置
      在这里插入图片描述

相关文章:

Python自动化办公(系统维护及开发任务状态自动推送)

Python自动化办公, 1.需求分析 系统维护及开发人员的工作一般都会比较繁杂,领导们喜欢实时掌控项目的进度,但是领导们很多时候是不会自己主动去查看及分析项目进度数据的,干活的牛马们也没空整天日报,周报,月报,季报,年报…活又有了,又该想想怎么干,需求的核心是实现自动整理…...

CentOS7 Apache安装踩坑

Gnome桌面右键弹出终端。 [rootlocalhost ~]# yum repolist 已加载插件&#xff1a;fastestmirror, langpacks /var/run/yum.pid 已被锁定&#xff0c;PID 为 2611 的另一个程序正在运行。 Another app is currently holding the yum lock; waiting for it to exit... [root…...

OpenMMlab导出MaskFormer/Mask2Former模型并用onnxruntime和tensorrt推理

onnxruntime推理 使用mmdeploy导出onnx模型&#xff1a; from mmdeploy.apis import torch2onnx from mmdeploy.backend.sdk.export_info import export2SDK# img ./bus.jpg # work_dir ./work_dir/onnx/maskformer # save_file ./end2end.onnx # deploy_cfg ./configs/m…...

若依微服务中配置 MySQL + DM 多数据源

文章目录 1、导入 MySQL 和达梦&#xff08;DM&#xff09;依赖2、在 application-druid.yml 中配置达梦&#xff08;DM&#xff09;数据源3、在 DruidConfig 类中配置多数据源信息4、在 Service 层或方法级别切换数据源4.1 在 Service 类上切换到从库数据源4.2 在方法级别切换…...

一些前端组件介绍

wangEditor &#xff1a; 一款开源 Web 富文本编辑器&#xff0c;可用于 jQuery Vue React等 https://www.wangeditor.com/ Handsontable&#xff1a;一款前端可编辑电子表格https://blog.csdn.net/carcarrot/article/details/108492356mitt&#xff1a;Mitt 是一个在 Vue.js 应…...

python学opencv|读取图像(九)用numpy创建黑白相间灰度图

【1】引言 前述学习过程中&#xff0c;掌握了用numpy创建矩阵数据&#xff0c;把所有像素点的BGR取值设置为0&#xff0c;然后创建纯黑灰度图的方法&#xff0c;具体链接为&#xff1a; python学opencv|读取图像&#xff08;八&#xff09;用numpy创建纯黑灰度图-CSDN博客 在…...

AtCoder Beginner Contest 383

C - Humidifier 3 Description 一个 h w h \times w hw 的网格&#xff0c;每个格子可能是墙、空地或者城堡。 一个格子是好的&#xff0c;当且仅当从至少一个城堡出发&#xff0c;走不超过 d d d 步能到达。&#xff08;只能上下左右走&#xff0c;不能穿墙&#xff09;&…...

20. 内置模块

一、random模块 random 模块用来创建随机数的模块。 random.random() # 随机生成一个大于0且小于1之间的小数 random.randint(a, b) # 随机生成一个大于等于a小于等于b的随机整数 random.uniform(a, b) …...

《知识拓展 · 统一建模语言UML》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

计算机网络-Wireshark探索ARP

使用工具 Wiresharkarp: To inspect and clear the cache used by the ARP protocol on your computer.curl(MacOS)ifconfig(MacOS or Linux): to inspect the state of your computer’s network interface.route/netstat: To inspect the routes used by your computer.Brows…...

减少30%人工处理时间,AI OCR与表格识别助力医疗化验单快速处理

在医疗行业&#xff0c;化验单作为重要的诊断依据和数据来源&#xff0c;涉及大量的文字和表格信息&#xff0c;传统的手工输入和数据处理方式不仅繁琐&#xff0c;而且容易出错&#xff0c;给医院的运营效率和数据准确性带来较大挑战。随着人工智能技术的快速发展&#xff0c;…...

1.2.3计算机软件

一个完整的计算机系统由硬件和软件组成&#xff0c;用户使用软件&#xff0c;而软件运行在硬件之上&#xff0c;软件进一步的划分为两类&#xff1a;应用软件和系统软件。普通用户通常只会跟应用软件打交道。应用软件是为了解决用户的某种特定的需求而研发出来的。除了每个人都…...

二、uni-forms

避坑指南&#xff1a;uni-forms表单在uni-app中的实践经验-CSDN博客...

Android13开机向导

文章目录 前言需求-场景第三方资料说明需求思路按照平台 思路 从配置上去 feature换个思路&#xff0c;去feature。SimMissingActivity 判断跳过逻辑SetupWizardUtils 判断SIM 、 hasSystemFeature FEATURE_TELEPHONYPackageManager.FEATURE_TELEPHONYApplicationPackageManage…...

软件测试丨Appium 源码分析与定制

在本文中&#xff0c;我们将深入Appium的源码&#xff0c;探索它的底层架构、定制化使用方法和给软件测试带来的优势。我们将详细介绍这些技术如何解决实际问题&#xff0c;并与大家分享一些实用的案例&#xff0c;以帮助读者更好地理解和应用这一技术。 Appium简介 什么是App…...

1.网络知识-IP与子网掩码的关系及计算实例

IP与子网掩码 说实话&#xff0c;之前没有注意过&#xff0c;今天我打开自己的办公地电脑&#xff0c;看到我的网络配置如下&#xff1a; 我看到我的子网掩码是255.255.254.0&#xff0c;我就奇怪了&#xff0c;我经常见到的子网掩码都是255.255.255.0啊&#xff1f;难道公司配…...

Android中Gradle常用配置

前言 本文记录了一些常用的gradle配置&#xff0c;基本上都是平时开发中可能会使用到的&#xff0c;如果有新内容会不定时更新&#xff0c;附官网 1.依赖库版本写法 不推荐写法&#xff1a; dependencies {compile com.example.code.abc:def:2. // 不推荐的写法 }这样写虽然可…...

Linux操作系统3-文件与IO操作2(文件描述符fd与文件重定向)

上篇文章&#xff1a;Linux操作系统3-文件与IO操作1(从C语言IO操作到系统调用)-CSDN博客 本篇代码Gitee仓库&#xff1a;myLerningCode 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 本篇重点&#xff1a;文件描述符fd与文件重定向 目录 一. 文件描述…...

k8s调度策略

调度策略 binpack&#xff08;装箱策略&#xff09; Binpacking策略&#xff08;又称装箱问题&#xff09;是一种优化算法&#xff0c;用于将物品有效地放入容器&#xff08;或“箱子”&#xff09;中&#xff0c;使得所使用的容器数量最少&#xff0c;Kubernetes等集群管理系…...

uniapp中父组件传参到子组件页面渲染不生效问题处理实战记录

上篇文件介绍了,父组件数据更新正常但是页面渲染不生效的问题,详情可以看下:uniapp中父组件数组更新后与页面渲染数组不一致实战记录 本文在此基础上由于新增需求衍生出新的问题.本文只记录一下解决思路. 下面说下新增需求方便理解场景: 商品信息设置中添加抽奖概率设置…...

螺丝螺帽缺陷检测识别数据集,支持yolo,coco,voc三种格式的标记,一共3081张图片

螺丝螺帽缺陷检测识别数据集&#xff0c;支持yolo&#xff0c;coco&#xff0c;voc三种格式的标记&#xff0c;一共3081张图片 3081总图像数 数据集分割 训练组90&#xff05; 2781图片 有效集7% 220图片 测试集3% 80图片 预处理…...

一个简单带颜色的Map

越简单 越实用。越少设计&#xff0c;越易懂。 需求背景&#xff1a; 创建方法&#xff0c;声明一个hashset&#xff0c; 元素为 {“#DE3200”, “#FA8C00”, “#027B00”, “#27B600”, “#5EB600”} 。 对应的key为 key1 、key2、key3、key4、key5。 封装该方法&#xff0c…...

kubeadm安装K8s集群之基础环境配置

系列文章目录 1.kubeadm安装K8s集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx 3.kubeadm安装K8s集群之master节点加入 4.kubeadm安装K8s集群之worker1节点加入 kubeadm安装K8s集群基础环境配置 1.首先确保所有机器可以通信&#xff0c;然后配置主机host…...

前端实现在线预览excel文件

在前端开发中&#xff0c;经常会遇到需要在线预览各种文件的需求。本文将介绍如何使用前端技术实现在线预览 Excel 文件的功能。 一、基于微软office服务的excel预览 获取要预览的 Excel 文件的 URL&#xff08;例如存储在 OneDrive 或 SharePoint 上的文件&#xff09;。 使…...

关于idea-Java-servlet-Tomcat-Web开发中出现404NOT FOUND问题的解决

在做web项目时&#xff0c;第一次使用servlet开发链接前端和后端的操作&#xff0c;果不其然&#xff0c;遇到了诸多问题&#xff0c;而遇到最多的就是运行项目打开页面时出现404NOT FOUND的情况。因为这个问题我也是鼓捣了好久&#xff0c;上网查了许多资料才最终解决&#xf…...

SCRM私域流量管理工具助力企业微信电商转型升级

内容概要 在当今数字化时代&#xff0c;SCRM&#xff08;社交客户关系管理&#xff09;私域流量管理工具正逐渐成为企业转型的重要助力。尤其是在电商领域&#xff0c;企业微信的兴起为许多公司打开了新的销售渠道&#xff0c;通过SCRM系统的高效整合&#xff0c;企业能够更加…...

三相异步电动机为什么能够旋转?

三相异步电动机&#xff0c;作为一种广泛应用于工业、农业及其他领域的电动机&#xff0c;其工作原理的理解对于工程技术人员以及相关从业者来说至关重要。 一、三相异步电动机的基本结构 三相异步电动机主要由定子、转子和机壳组成。定子是电动机的静止部分&#xff0c;包含…...

优化移动端H5:常见问题与解决方案

移动端H5开发中的“坑”与解决方案 本文介绍了开发中遇到的几个关于移动端H5开发中的小问题&#xff0c;以及解决的方法。 一、iOS滑动不流畅问题 在iOS设备上&#xff0c;H5页面的滑动效果有时会出现不流畅的情况&#xff0c;特别是在页面高度超过一屏时。这通常是由于iOS的…...

TM1不藏私系列——#10. TM1快速运算的秘密武器-Feeder

与其他BI产品对比&#xff0c;TM1的快速运算能力一骑绝尘。 但是在多维度的数据组合下&#xff0c;TM1是依据什么进行运算的呢&#xff1f; 今天将和大家一同了解TM1快速运算的秘密武器-Feeder。 上期我们提到通过配置维度中的元素权重&#xff0c;可以在合并层级加总计算。除…...

【Python】【Conda 】Conda vs venv:Python开发者的虚拟环境选择指南

目录 引言一、概述1.1 Conda 虚拟环境1.2 Python venv 虚拟环境 二、安装与设置2.1 安装 Conda 虚拟环境2.2 安装 Python venv 虚拟环境 三、依赖管理3.1 Conda 依赖管理3.2 Python venv 依赖管理 四、适用场景五、性能与资源占用5.1 Conda 性能与资源占用5.2 Python venv 性能…...

网站建站的标准/重庆seo网页优化

1、Base64编码介绍Base64不能称为加解密算法&#xff0c;Base64编码可以把二进制数据转换为可打印的ASCII字符&#xff0c;常用于email消息中的二进制数据编码和HTTP协议中的basic认证。Base64编码之后的ASCII字符串包括64个可打印字符&#xff0c;如下&#xff1a;26个大写字母…...

英文版wordpress安装/seo超级外链工具

欢迎关注头条号&#xff1a;老顾聊技术精品技术文章分享&#xff0c;知识的组装工目录前言先更新数据库&#xff0c;再更新缓存先更新缓存&#xff0c;再更新数据库先删除缓存&#xff0c;再更新数据库先更新数据库&#xff0c;再删除缓存删除缓存失败&#xff0c;导致不一致读…...

有什么网站做交流会/网页搜索引擎大全

转自&#xff1a;http://www.openphp.cn Eclipse 是一款很强大的 IDE&#xff0c;本站曾经也发过两篇关于使用它配置 PHP 调试环境的文章&#xff0c;现在已经出了 3.0.1 版本和中文语言包了&#xff0c;所以本文简单介绍一下它的汉化方法。 下载 Eclipse 3.0.1 和语言包&…...

重庆做网站开发的集中/seo排名培训学校

参考林海峰老师的配置教程 http://blog.51cto.com/9161406/1839667转载于:https://www.cnblogs.com/luhuajun/p/7379938.html...

b2b平台好做吗/seo分析是什么意思

1、生产者消费者问题三种关系&#xff1a;生产者--生产者&#xff08;互斥&#xff09;&#xff1b;消费者-消费者&#xff08;互斥&#xff09;&#xff1b;生产者--消费者&#xff08;互斥同步&#xff09;两个角色&#xff1a;生产者&#xff1b;消费者一种生产场所&#xf…...

沈阳网站制作找网势科技/平台宣传推广方案

共享打印机作为企业日常OA办公必不可少的设备&#xff0c;我们需要用到的功能包括打印、服务、扫描于一体&#xff0c;甚至还包括传真功能&#xff0c;如何发挥共享打印机的功能呢&#xff1f;我们可以选择激光一体机、多功能复印机这样的设备&#xff0c;由于激光一体机成本比…...