|
|
@@ -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)
|