luocaiyang 3 týždňov pred
rodič
commit
33e34f1adc

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 20 - 12
.qoder/repowiki/zh/content/API参考文档/系统配置API.md


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 16 - 9
.qoder/repowiki/zh/content/后端架构/启动配置与服务注册.md


+ 331 - 0
.qoder/repowiki/zh/content/后端架构/定时任务系统/数据导入任务/Batch Update Jx Data Job.md

@@ -0,0 +1,331 @@
+# 批量更新Jx数据作业
+
+<cite>
+**本文引用的文件**
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs)
+- [SystemDataController.cs](file://wispro.sp.api/Controllers/SystemDataController.cs)
+- [Program.cs](file://wispro.sp.api/Program.cs)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs)
+- [PerformanceItem.cs](file://wospro.sp.entity/PerformanceItem.cs)
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs)
+- [appsettings.json](file://wispro.sp.api/appsettings.json)
+</cite>
+
+## 目录
+1. [简介](#简介)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构总览](#架构总览)
+5. [详细组件分析](#详细组件分析)
+6. [依赖关系分析](#依赖关系分析)
+7. [性能考量](#性能考量)
+8. [故障排查指南](#故障排查指南)
+9. [结论](#结论)
+10. [附录](#附录)
+
+## 简介
+本文件围绕“批量更新Jx数据作业(BatchUpdateJXDataJob)”进行系统化技术文档梳理,覆盖其职责、执行流程、数据来源、关键算法、错误处理、性能特征与运维建议。该作业负责从IPEasy批量报表与网页抓取两种渠道获取绩效数据,对当月未结算且非特定前缀的绩效事项进行批量匹配与更新,并在字段变更时触发点数重算或仅保存更新。
+
+## 项目结构
+- 作业实现位于 wispro.sp.api/Job/BatchUpdateJXDataJob.cs,实现 Quartz 的 IJob 接口。
+- 通过控制器接口触发执行,控制器位于 wispro.sp.api/Controllers/SystemDataController.cs。
+- 作业调度由 wispro.sp.api/Program.cs 中的 QuartzUtil 配置 Cron 触发器,按配置定时运行。
+- 数据抓取工具位于 wispro.sp.utility/IPEasyUtility.cs,提供报表下载与网页抓取能力。
+- 实体模型位于 wospro.sp.entity/PerformanceItem.cs,描述绩效事项的核心字段。
+- 补充作业 UpdateJXDataFromIPEasyJob.cs 提供单条抓取与批量抓取能力,作为补充手段。
+
+```mermaid
+graph TB
+subgraph "API服务"
+C["SystemDataController<br/>触发作业"]
+P["Program<br/>Quartz调度"]
+Q["QuartzUtil<br/>作业注册/触发器"]
+end
+subgraph "作业"
+J["BatchUpdateJXDataJob<br/>批量更新Jx数据"]
+UJ["UpdateJXDataFromIPEasyJob<br/>单条/批量抓取"]
+end
+subgraph "数据源"
+IP["IPEasyUtility<br/>报表下载/网页抓取"]
+DB["数据库<br/>PerformanceItem等"]
+end
+C --> J
+P --> Q
+Q --> J
+J --> IP
+J --> DB
+UJ --> IP
+UJ --> DB
+```
+
+图表来源
+- [SystemDataController.cs](file://wispro.sp.api/Controllers/SystemDataController.cs#L1-L46)
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs#L1-L112)
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L1-L206)
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs#L1-L120)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+- [PerformanceItem.cs](file://wospro.sp.entity/PerformanceItem.cs#L1-L120)
+
+章节来源
+- [SystemDataController.cs](file://wispro.sp.api/Controllers/SystemDataController.cs#L1-L46)
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs#L1-L112)
+
+## 核心组件
+- BatchUpdateJXDataJob:实现 IJob,负责筛选当月待更新绩效事项、批量下载IPEasy报表、合并索引、逐条匹配与更新、统计与日志输出。
+- IPEasyUtility:封装浏览器自动化下载报表与网页抓取逻辑,支持等待文件下载完成、登录、报表导出、文件解析等。
+- PerformanceItem:绩效事项实体,包含案号、处理事项、阶段、系数、字数、核稿人、外部处理人、申请类型、案件类型、状态等字段。
+- UpdateJXDataFromIPEasyJob:补充的单条/批量抓取作业,可直接调用以更新个别或批量记录。
+- Quartz 调度:Program.cs 中通过 QuartzUtil 注册 Cron 触发器,按配置周期运行 BatchUpdateJXDataJob。
+
+章节来源
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L1-L206)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+- [PerformanceItem.cs](file://wospro.sp.entity/PerformanceItem.cs#L1-L120)
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs#L1-L120)
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+
+## 架构总览
+作业执行链路:
+- 控制器 SystemDataController 提供 UpdateJXData 接口,异步启动 BatchUpdateJXDataJob。
+- Program.cs 使用 QuartzUtil 注册 BatchUpdateJXDataJob,按 appsettings.json 中 UpdateScheduleSetting 配置的 Cron 表达式定时触发。
+- BatchUpdateJXDataJob 从数据库筛选当月待更新记录,调用 IPEasyUtility 下载两个报表,构建“案号+处理事项”字典索引,逐条匹配更新;若匹配失败则单条抓取。
+- 更新完成后,如字段发生变更且非“特殊点数申诉”,则调用控制器刷新点数;否则仅保存更新。
+
+```mermaid
+sequenceDiagram
+participant Client as "客户端/调用方"
+participant Ctrl as "SystemDataController"
+participant Job as "BatchUpdateJXDataJob"
+participant Util as "IPEasyUtility"
+participant DB as "数据库"
+Client->>Ctrl : 调用 UpdateJXData()
+Ctrl->>Job : 异步执行 Execute()
+Job->>DB : 查询当月待更新的绩效事项
+Job->>Util : 下载报表1上月完成案件
+Util-->>Job : 返回DataTable
+Job->>Util : 下载报表2中国一次OA授权表
+Util-->>Job : 返回DataTable
+Job->>Job : 构建“案号|处理事项”字典索引
+loop 逐条处理
+Job->>DB : 匹配DataRow或单条抓取
+Job->>Util : 单条抓取网页抓取
+Util-->>Job : 返回动态对象
+Job->>DB : 更新字段并判断是否保存/重算
+end
+Job-->>Client : 日志与统计输出
+```
+
+图表来源
+- [SystemDataController.cs](file://wispro.sp.api/Controllers/SystemDataController.cs#L1-L46)
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L22-L205)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+
+## 详细组件分析
+
+### BatchUpdateJXDataJob 组件分析
+- 职责与入口
+  - 实现 IJob.Execute,筛选当月未结算且非特定前缀的绩效事项,加载关联实体。
+  - 通过 IPEasyUtility 下载两个报表,合并为统一字典索引。
+  - 逐条匹配更新,匹配失败则单条抓取,带重试与异常处理。
+  - 字段变更时根据申诉状态决定是否重算点数或仅保存。
+- 关键流程
+  - 数据筛选:过滤 AgentFeedbackMemo、CalMonth 状态、CaseNo 前缀。
+  - 报表下载:两个报表分别下载,异常捕获并记录。
+  - 索引构建:以“案号|处理事项”为键,避免重复与冲突。
+  - 匹配更新:优先批量匹配 DataRow,失败则单条抓取,最多重试三次。
+  - 变更处理:字段变化时调用控制器刷新点数或直接保存。
+- 错误处理与日志
+  - 分层 try/catch 记录异常与统计信息,输出到本地文本文件。
+  - 单条抓取失败时最多重试三次,避免偶发网络/页面问题影响整体。
+- 性能与并发
+  - 逐条处理并带短暂休眠,降低对目标系统的压力。
+  - 字典索引 O(1) 查找,整体复杂度受记录数线性影响。
+
+```mermaid
+flowchart TD
+Start(["开始 Execute"]) --> LoadItems["筛选当月待更新记录"]
+LoadItems --> HasItems{"是否有待更新记录?"}
+HasItems --> |否| End(["结束"])
+HasItems --> |是| Download1["下载报表1"]
+Download1 --> Download2["下载报表2"]
+Download2 --> BuildIndex["构建案号|处理事项索引"]
+BuildIndex --> Loop["逐条处理"]
+Loop --> Match{"批量匹配成功?"}
+Match --> |是| UpdateFromRow["从DataRow更新字段"]
+Match --> |否| SingleFetch["单条抓取最多重试3次"]
+UpdateFromRow --> Changed{"字段是否变更?"}
+SingleFetch --> Changed
+Changed --> |是| Refresh["刷新点数或保存"]
+Changed --> |否| Next["继续下一条"]
+Refresh --> Next
+Next --> Loop
+Loop --> Stats["输出统计与日志"]
+Stats --> End
+```
+
+图表来源
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L22-L205)
+
+章节来源
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L1-L206)
+
+### IPEasyUtility 组件分析
+- 报表下载
+  - 支持根据报表名称导出并等待下载完成,自动处理文件大小稳定与扩展名清理。
+  - 登录、切换框架、调用报表导出脚本、等待导出完成并下载。
+- 网页抓取
+  - 提供获取单个案件的处理事项、系数、字数、核稿人、外部处理人、申请类型、案件系数、类型、阶段等信息的动态对象。
+  - 内置等待元素、选择器、表格解析与文件下载流程。
+- 配置与环境
+  - 读取账户、密码、下载目录、Chrome驱动路径、是否无头模式等配置。
+  - 创建 ChromeDriver 并设置下载目录、禁用弹窗、隐式等待等参数。
+
+```mermaid
+classDiagram
+class IPEasyUtility {
++DownloadReport(reportName, isModifyDate) DataTable
++GetPerformanceRecord(caseNo, doItem, caseStage) dynamic
+-CreateChromeDriver(downloadPath) ChromeDriver
+-Login(driver, wait) void
+-WaitForFileDownload(dir, timeout) string
+}
+```
+
+图表来源
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1-L200)
+
+章节来源
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+
+### PerformanceItem 实体分析
+- 关键字段
+  - 案号、处理事项、阶段、系数、字数、核稿人、外部处理人、申请类型、案件类型、状态、基础点数、申诉标记等。
+- 与作业的关系
+  - BatchUpdateJXDataJob 依据这些字段进行匹配、更新与点数重算。
+  - UpdateJXDataFromIPEasyJob 也基于这些字段进行赋值与保存。
+
+```mermaid
+erDiagram
+PERFORMANCE_ITEM {
+int Id PK
+string CaseNo
+string DoItem
+string CaseStage
+string CaseCoefficient
+string DoItemCoefficient
+int? ReviewerId
+int? ExternalHandlerId
+string ApplicationType
+string CaseType
+int? WordCount
+double? BasePoint
+string AgentFeedbackMemo
+}
+```
+
+图表来源
+- [PerformanceItem.cs](file://wospro.sp.entity/PerformanceItem.cs#L1-L120)
+
+章节来源
+- [PerformanceItem.cs](file://wospro.sp.entity/PerformanceItem.cs#L1-L200)
+
+### UpdateJXDataFromIPEasyJob 补充分析
+- 单条抓取与批量抓取
+  - 提供 UpdateFromIPEasy 与 RefreshFromIPEasy_BatchThread,支持按条件筛选并批量更新。
+  - 带重试机制与进度文件,避免重启后从头开始导致耗时过长。
+- 与 BatchUpdateJXDataJob 的关系
+  - 两者互补:前者侧重单条/批量抓取,后者侧重批量报表匹配+单条兜底。
+  - 均在字段变更时触发点数刷新或保存。
+
+章节来源
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs#L265-L414)
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs#L416-L548)
+
+## 依赖关系分析
+- BatchUpdateJXDataJob 依赖
+  - Quartz IJob 接口(由 Program.cs 与 QuartzUtil 注册)
+  - IPEasyUtility(报表下载与网页抓取)
+  - 数据库上下文(EF Core)与实体 PerformanceItem
+  - 控制器 PerformanceItemController(刷新点数)
+- Quartz 调度
+  - Program.cs 通过 QuartzUtil.Add 注册 BatchUpdateJXDataJob,使用 appsettings.json 中 UpdateScheduleSetting 的 Cron 表达式。
+- 配置
+  - IPEasy 登录凭据、下载目录、Chrome 驱动路径、无头模式等。
+  - 邮件、附件存储等其他配置项。
+
+```mermaid
+graph LR
+J["BatchUpdateJXDataJob"] --> Q["QuartzUtil"]
+J --> U["IPEasyUtility"]
+J --> E["EF Core/DbContext"]
+E --> P["PerformanceItem"]
+J --> C["PerformanceItemController"]
+Q --> S["Program"]
+S --> A["appsettings.json"]
+```
+
+图表来源
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L1-L206)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs#L1-L112)
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+- [appsettings.json](file://wispro.sp.api/appsettings.json#L1-L64)
+
+章节来源
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs#L1-L112)
+- [appsettings.json](file://wispro.sp.api/appsettings.json#L1-L64)
+
+## 性能考量
+- 批量匹配效率
+  - 使用字典索引 O(1) 查找,整体复杂度近似 O(N)。
+- 网络与IO
+  - 报表下载与网页抓取均涉及浏览器自动化与文件IO,建议合理设置等待与重试策略。
+- 并发与节流
+  - 逐条处理并带短暂休眠,避免对IPEasy造成过大压力。
+- 点数重算成本
+  - 字段变更触发刷新点数,需注意数据库写入与计算开销。
+
+[本节为通用性能讨论,无需列出具体文件来源]
+
+## 故障排查指南
+- 常见问题
+  - 报表下载失败或无数据:检查 IPEasy 登录凭据、报表名称、下载目录权限与网络连通性。
+  - 网页抓取异常:检查 Chrome 驱动路径、无头模式配置、页面元素定位是否变化。
+  - 字段未更新:确认申诉状态是否为“特殊点数申诉”,该状态下不会重算点数。
+  - 重试仍失败:查看日志文件与异常堆栈,确认是否为偶发性网络波动。
+- 定位方法
+  - 查看本地日志文件(批处理日志与抓取日志),关注统计信息与失败条目。
+  - 在控制器中调用 UpdateJXData 接口进行手动触发,便于快速验证。
+  - 检查 appsettings.json 中 IPEasySetting 与 UpdateScheduleSetting 配置是否正确。
+
+章节来源
+- [BatchUpdateJXDataJob.cs](file://wispro.sp.api/Job/BatchUpdateJXDataJob.cs#L18-L430)
+- [IPEasyUtility.cs](file://wispro.sp.utility/IPEasyUtility.cs#L1093-L1200)
+- [appsettings.json](file://wispro.sp.api/appsettings.json#L1-L64)
+
+## 结论
+BatchUpdateJXDataJob 通过“批量报表匹配+单条网页抓取”的双通道策略,高效地对当月绩效事项进行数据更新,并在字段变更时智能决定是否重算点数。结合 Quartz 的定时调度与完善的日志统计,该作业具备良好的稳定性与可观测性。建议在生产环境中持续监控日志与报表可用性,确保更新质量与系统健康。
+
+[本节为总结性内容,无需列出具体文件来源]
+
+## 附录
+- 触发方式
+  - 控制器接口:SystemDataController.UpdateJXData
+  - 定时调度:Program.cs + QuartzUtil + appsettings.json
+- 关键配置
+  - UpdateScheduleSetting:Cron 表达式,控制作业执行频率
+  - IPEasySetting:下载目录、账户、密码、Chrome 驱动路径、无头模式等
+- 相关作业
+  - UpdateJXDataFromIPEasyJob:单条/批量抓取补充
+  - CalJXJob:每日基础点数计算(与本作业配合)
+
+章节来源
+- [SystemDataController.cs](file://wispro.sp.api/Controllers/SystemDataController.cs#L1-L46)
+- [Program.cs](file://wispro.sp.api/Program.cs#L71-L126)
+- [QuartzUtil.cs](file://wispro.sp.api/Job/QuartzUtil.cs#L1-L112)
+- [appsettings.json](file://wispro.sp.api/appsettings.json#L1-L64)
+- [UpdateJXDataFromIPEasyJob.cs](file://wispro.sp.api/Job/UpdateJXDataFromIPEasyJob.cs#L416-L548)

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 150 - 64
.qoder/repowiki/zh/content/后端架构/定时任务系统/数据导入任务/绩效数据实时更新任务.md


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 1
.qoder/repowiki/zh/meta/repowiki-metadata.json


+ 2 - 2
wispro.sp.api/appsettings.json

@@ -27,11 +27,11 @@
   },
   "IPEasySetting": {
     "DownloadFileSavePath": "c:\\temp",
-    "isHeadless": "false",
+    "isHeadless": "true",
     "Account": "caiyangl",
     "Password": "j)wx*lier*@3",
     "ChormeDriverPath": "e:\\source\\repos\\StaffPerformance\\packages\\ChormeDriver\\142",
-    "ScheduleSetting": "00 33 14 21 * ? *",
+    "ScheduleSetting": "00 40 15 21 * ? *",
     "IPEasyWeb": "http://47.106.94.35/Login.aspx"
   },
   "MailSetting": {