Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbe2d110e4 | |||
| 12b9e0e771 | |||
| f58ec994bc | |||
| 7e23d68e9b | |||
| fefcfe4595 | |||
| 10ebe9240b | |||
| 96cdb0f62e | |||
| 76859fd774 | |||
| c06e3e55f9 | |||
| 32d41244e5 | |||
| ba8520a351 | |||
| 26835e265a | |||
| 708402c7fb | |||
| b7bce93995 | |||
| bfccdd3a37 | |||
| 3e2f46d26d | |||
| 83405a9b8e | |||
| 76f7adddd5 | |||
| cd1adc5647 | |||
| fb12e63c4c | |||
| 73d17836d7 |
42
.gitignore
vendored
42
.gitignore
vendored
@ -1,29 +1,27 @@
|
|||||||
# Python缓存文件
|
# Python
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.pyc
|
||||||
*$py.class
|
*.pyo
|
||||||
|
.pytest_cache/
|
||||||
|
.venv/
|
||||||
|
|
||||||
# 虚拟环境
|
# Build & dist
|
||||||
venv/
|
build/
|
||||||
env/
|
dist/
|
||||||
ENV/
|
release/
|
||||||
|
*.spec
|
||||||
|
|
||||||
# 日志文件
|
# Logs & temp
|
||||||
logs/*.log
|
logs/
|
||||||
logs/*.active
|
|
||||||
*.log.*
|
|
||||||
|
|
||||||
# 临时文件和缓存
|
|
||||||
data/temp/
|
data/temp/
|
||||||
data/*.bak
|
|
||||||
*.bak
|
# Runtime outputs
|
||||||
|
data/output/
|
||||||
|
data/result/
|
||||||
|
|
||||||
|
# OS/IDE
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
# 输出文件(可选是否忽略)
|
|
||||||
# data/output/
|
|
||||||
|
|
||||||
# IDE文件
|
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
|
|||||||
43
.trae/documents/优化列映射向导的尺寸、置顶行为与字段标签.md
Normal file
43
.trae/documents/优化列映射向导的尺寸、置顶行为与字段标签.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
## 问题与目标
|
||||||
|
- 弹窗尺寸偏小,不便操作
|
||||||
|
- 弹窗及文件选择后没有在最上层,易被其他窗口遮挡
|
||||||
|
- 字段英文名不直观,需要显示中文对应(银豹模板列)
|
||||||
|
|
||||||
|
## 改进方案
|
||||||
|
### 1. 弹窗尺寸与置顶行为
|
||||||
|
- 将列映射向导窗口尺寸调整为 `780x660`,保持自适应(子控件 `fill=tk.BOTH, expand=True`)
|
||||||
|
- 打开向导时:`dlg.lift()`、`dlg.attributes('-topmost', True)`,`after_idle` 取消置顶但保持焦点;`dlg.transient(root)`、`dlg.grab_set()` 防止被遮挡
|
||||||
|
- 选择文件后的回调中再次 `dlg.lift()` 和短暂置顶,确保返回后窗口在最上层
|
||||||
|
- 同步为模板管理窗口应用同样策略
|
||||||
|
|
||||||
|
### 2. 字段标签中文提示
|
||||||
|
- 列映射向导的标准字段改为按 `ColumnMapper.STANDARD_COLUMNS` 动态生成(若可用),并为每个字段追加中文说明,例如:
|
||||||
|
- `barcode(条码)`
|
||||||
|
- `name(商品名称)`
|
||||||
|
- `specification(规格)`
|
||||||
|
- `quantity(数量)`
|
||||||
|
- `unit(单位)`
|
||||||
|
- `unit_price(采购单价)`
|
||||||
|
- `total_price(金额/小计)`
|
||||||
|
- `category(类别)`
|
||||||
|
- `brand(品牌)`
|
||||||
|
- `supplier(供应商)`
|
||||||
|
- 若 `ColumnMapper` 不可用,则用内置 `friendly_labels` 字典生成上述标签
|
||||||
|
|
||||||
|
### 3. 布局优化与可用性
|
||||||
|
- 保持“文件路径 + 浏览 + 预览前30行 + 加载列”四项同一行,按钮设 `padx=6`,保证易点
|
||||||
|
- 映射区使用 `ttk.Combobox(state='readonly')`,宽度适配,并确保行高足够(留白)
|
||||||
|
- 预览区保留顶部表格(前30行),支持点击行自动填充表头行号;加载列时按指定行读取
|
||||||
|
|
||||||
|
### 4. 代码改动位置
|
||||||
|
- `启动器.py`:
|
||||||
|
- `open_column_mapping_wizard_alt`:调整几何尺寸与置顶;在“浏览”回调与预览/加载流程中补充 `lift/topmost`;扩展标准字段与中文标签
|
||||||
|
- `open_template_manager`:统一尺寸与置顶行为
|
||||||
|
- 仅UI与行为改动,不影响处理逻辑;保存仍写入 `suppliers_config.json` 的 `header_row` 与 `column_mapping`
|
||||||
|
|
||||||
|
### 5. 验证
|
||||||
|
- 打开列映射向导:窗口足够大,居中且在最上层;选择文件后窗口仍在最上层
|
||||||
|
- 字段标签显示为英+中:如 `name(商品名称)`
|
||||||
|
- 预览前30行与加载列同一行;点击预览行自动写入表头行号;保存后提示成功并写入配置
|
||||||
|
|
||||||
|
请确认以上方案,确认后我将立即实施并验证。
|
||||||
41
.trae/documents/供应商管理GUI与可视化配置方案.md
Normal file
41
.trae/documents/供应商管理GUI与可视化配置方案.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
## 目标
|
||||||
|
- 在系统设置中提供“供应商管理”GUI,支持新增/编辑/删除供应商,无需手改代码或JSON。
|
||||||
|
- 一站式配置:基本信息、表头与列映射、规则与词典、模板管理,保存后即时生效。
|
||||||
|
|
||||||
|
## 界面设计
|
||||||
|
- 入口:右侧“系统设置”新增按钮“供应商管理”。
|
||||||
|
- 布局:
|
||||||
|
- 左栏:供应商列表(名称),支持搜索/新建/复制/删除。
|
||||||
|
- 右侧Tab:
|
||||||
|
1) 基本信息:`name`、`description`、`filename_patterns`、`content_indicators`、`header_row`
|
||||||
|
2) 列映射与表头:嵌入现有“列映射向导”核心(预览前30行、表头选行、加载列、智能映射、导入/导出)
|
||||||
|
3) 规则与词典:词典编辑(忽略词、单位同义词、包装倍数、名称正则、默认单位/包装);规则预设与规则预览(原始→规范化)
|
||||||
|
4) 模板管理:`output_templates` 列表、当前选择与批量校验
|
||||||
|
- 操作按钮:保存(写入`suppliers_config.json`)、重载处理器、导入/导出供应商配置(单个或全部)。
|
||||||
|
|
||||||
|
## 数据流与验证
|
||||||
|
- 加载/保存:统一读写`config/suppliers_config.json`;保存后调用`ProcessorService.reload_processors()`。
|
||||||
|
- 校验:复用`ProcessorService._validate_suppliers_config`;保存前进行schema校验,错误弹窗聚合列表。
|
||||||
|
- 预设:提供“基础拆分与推断”规则预设;可导入/导出自定义规则。
|
||||||
|
|
||||||
|
## 增强逻辑(自动化建议)
|
||||||
|
- 新建供应商时,可选择样例Excel:
|
||||||
|
- 自动检测表头与初始列映射;基于列名关键词给出映射建议。
|
||||||
|
- 词典预填:常见单位同义词、默认单位“瓶”、常见包装倍数(件/箱/提/盒)。
|
||||||
|
|
||||||
|
## 实施步骤
|
||||||
|
1) 创建`open_supplier_manager`弹窗(系统设置入口),左列表+右侧Tab结构。
|
||||||
|
2) 基本信息Tab:表单与校验;保存更新到JSON。
|
||||||
|
3) 列映射与表头Tab:复用现有向导组件(预览/加载/智能映射/导入/导出)。
|
||||||
|
4) 规则与词典Tab:编辑词典与规则预览,保存写入`dictionary`与`rules`。
|
||||||
|
5) 模板管理Tab:维护`output_templates`与`current_template_index`,批量校验与报告显示。
|
||||||
|
6) 保存与重载:统一写入后调用处理器重载并日志提示。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
- GUI走查:新增/复制/删除供应商配置;规则预览正确;模板校验能识别缺失列。
|
||||||
|
- 处理生效:保存后立刻按新规则规范化并填充模板输出。
|
||||||
|
|
||||||
|
## 后续扩展
|
||||||
|
- 多供应商批量校验与报告导出;词典共享/继承;规则预设库扩展。
|
||||||
|
|
||||||
|
如果确认,我将开始实现该GUI及其数据流,并将现有向导整合到供应商管理中以形成一站式配置体验。
|
||||||
70
.trae/documents/供应商规则系统全面优化与落地计划.md
Normal file
70
.trae/documents/供应商规则系统全面优化与落地计划.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
## 痛点复盘
|
||||||
|
- 不同供应商存在强差异:列名不统一、单位混杂在数量、规格隐藏在名称、供应商缺失等
|
||||||
|
- 现有向导只解决列映射层面,规则与词典编辑、执行顺序与生效范围不清晰
|
||||||
|
- 缺少可视化“从原始→规范化→模板填充”的贯通验证;流程易跑不通
|
||||||
|
|
||||||
|
## 总体方案
|
||||||
|
- 建立“供应商规则系统”:可配置、可视化、可预览,贯穿 映射→清洗→规则→模板 填充全链路
|
||||||
|
- 提供“规则库 + 词典 + 执行管道”三层抽象,支持每家供应商自定义规则组合与执行顺序
|
||||||
|
- 完善 GUI:供应商管理中的四大Tab一站式配置,规则编辑器内置预设与预览,落地即验证
|
||||||
|
|
||||||
|
## 数据模型
|
||||||
|
- `suppliers_config.json` 每个供应商对象结构:
|
||||||
|
- `name`、`description`
|
||||||
|
- `filename_patterns`、`content_indicators`
|
||||||
|
- `header_row`
|
||||||
|
- `column_mapping`(源列→标准列)
|
||||||
|
- `rules`: 有序规则数组(见下)
|
||||||
|
- `dictionary`: 解析词典(`ignore_words`、`unit_synonyms`、`pack_multipliers`、`name_patterns`、`default_unit`、`default_package_quantity`)
|
||||||
|
- `output_templates`: 模板列表;`current_template_index`: 当前模板索引
|
||||||
|
|
||||||
|
## 规则库(首批)
|
||||||
|
- `split_quantity_unit(source)`: 拆分数量中的单位(箱/件/提/盒/瓶),无单位用默认单位
|
||||||
|
- `extract_spec_from_name(source)`: 从名称抽取规格/包装(容量×数量/简单双乘),应用忽略词与名称正则
|
||||||
|
- `normalize_unit(target,map)`: 单位归一(同义词→统一单位),件/箱/提/盒按包装倍数转换数量为“瓶”
|
||||||
|
- `compute_quantity_from_total()`: 数量缺失时用金额/单价回推数量
|
||||||
|
- `fill_missing(fills)`: 缺失填充,例如单位默认“瓶”
|
||||||
|
- `mark_gift()`: 金额/单价为0或名称含“赠品/O/o/空”标记赠品
|
||||||
|
- 后续扩展:`classify_category(name)`, `extract_brand(name)`, `strip_noise(name)` 等
|
||||||
|
|
||||||
|
## 执行管道
|
||||||
|
- 处理器执行顺序:映射→清洗→规则(有序)→模板填充
|
||||||
|
- 每条规则可访问 `dictionary`,执行结果在 DataFrame 上可追踪(供预览)
|
||||||
|
- 提供“预览栈”:展示原始→每步规则输出(多步Diff),定位问题
|
||||||
|
|
||||||
|
## GUI优化
|
||||||
|
- 供应商管理:
|
||||||
|
- 左侧供应商列表(搜索/新建/复制/删除/导入/导出)
|
||||||
|
- 右侧四大Tab:
|
||||||
|
- 基本信息:必填校验与保存
|
||||||
|
- 列映射与表头:现有向导增强(滚动条、表头选行、智能映射、导入/导出)
|
||||||
|
- 规则与词典:
|
||||||
|
- 规则编辑器(顺序可调整:上/下移动、插入/删除规则)
|
||||||
|
- 词典编辑(忽略词、单位同义词、包装倍数、名称正则、默认值)
|
||||||
|
- 规则预设(常用组合)与“应用规则预览”(展示原始→规范化两列;可切换查看逐步Diff)
|
||||||
|
- 模板管理:模板列表/当前选择与批量校验,显示缺失/多余列报告
|
||||||
|
- 性能与体验:所有弹窗置顶回焦;滚动与水平滚动;列宽拖拽与一键导出预览为CSV
|
||||||
|
|
||||||
|
## 使用路径(推荐)
|
||||||
|
1. 新建供应商→选样例Excel→自动表头与初始映射建议
|
||||||
|
2. 规则预设:选择“基础拆分与推断”→应用规则预览→查看原始/规范化对比
|
||||||
|
3. 细化词典:补充忽略词、单位同义词、包装倍数、名称正则→再次预览
|
||||||
|
4. 保存并重载→跑一份真实文件→最近文件中打开结果核验→如有差异回到规则编辑器微调
|
||||||
|
|
||||||
|
## 验证与可视化
|
||||||
|
- 单元测试:表头识别/数量拆分/名称规格解析/单位归一/数量回推/赠品标记
|
||||||
|
- 烟雾测试:5–10类典型供货商样本端到端验证(含极端情况:无单位、名称含噪声、数量混合单位)
|
||||||
|
- 日志:每步规则执行计数与示例行输出(前/后5行),便于定位问题
|
||||||
|
|
||||||
|
## 交付物
|
||||||
|
- 规则引擎模块与规范接口;处理器接入
|
||||||
|
- 供应商管理GUI(规则编辑器、词典编辑器、预设与预览)
|
||||||
|
- 扩展配置示例与测试数据;打包脚本校验资源
|
||||||
|
|
||||||
|
## 里程碑
|
||||||
|
- Day 1:规则库与引擎扩展、处理器接入、预览栈接口
|
||||||
|
- Day 2:GUI规则编辑器(顺序调整/增删)、词典编辑器、规则预设与预览
|
||||||
|
- Day 3:模板批量校验、单元与烟雾测试、日志强化
|
||||||
|
- Day 4:回归修正与打包交付
|
||||||
|
|
||||||
|
确认后我将开始实现上述内容,确保不同供应商可独立配置精细规则并“所见即所得”验证,流程稳定可跑通。
|
||||||
52
.trae/documents/供应商词典与规则编辑器扩展方案.md
Normal file
52
.trae/documents/供应商词典与规则编辑器扩展方案.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
## 目标
|
||||||
|
- 为具体供应商定制更细的解析规则(词典、包装倍数、忽略词、同义单位),并在列映射向导提供可视化编辑入口与预览。
|
||||||
|
|
||||||
|
## 配置扩展
|
||||||
|
- 扩展 `suppliers_config.json` 每个供应商对象新增:
|
||||||
|
- `dictionary`: 解析词典
|
||||||
|
- `ignore_words`: ["白膜","彩膜","赠品"](在名称解析时剔除)
|
||||||
|
- `unit_synonyms`: {"箱":"件","提":"件","盒":"件","瓶":"瓶"}
|
||||||
|
- `pack_multipliers`: {"件": 24, "箱": 24, "提": 12, "盒": 10}(缺规格时用于单位归一)
|
||||||
|
- `name_patterns`: [正则表达式](从名称抽取规格/容量×数量,如 `([\d\.]+)(ml|l|升|毫升)[*×xX](\d+)`)
|
||||||
|
- `default_unit`: "瓶"
|
||||||
|
- `default_package_quantity`: 1
|
||||||
|
- `rules`: 规则数组(与现有一致),规则在执行时可访问 `dictionary`
|
||||||
|
- `output_templates`: 模板列表;`current_template_index`: 当前选择索引
|
||||||
|
|
||||||
|
## 规则引擎增强
|
||||||
|
- 在 `app/core/handlers/rule_engine.py`:
|
||||||
|
- `apply_rules(df, rules, dictionary=None)` 接口增加 `dictionary` 参数
|
||||||
|
- `extract_spec_from_name`:先剔除 `ignore_words`,匹配 `name_patterns`,无匹配时按 `pack_multipliers` 推断包装数量
|
||||||
|
- `normalize_unit`:使用 `unit_synonyms` 统一单位;如单位为“件/箱/提/盒”且有 `package_quantity` 或 `pack_multipliers`,数量×包装并单位归一为“瓶”
|
||||||
|
- `split_quantity_unit`:解析数量中的单位,同义词归一;无单位时用 `default_unit`
|
||||||
|
- 其余规则(回推数量、填充、赠品标记)保持不变
|
||||||
|
|
||||||
|
## 供应商处理器接入
|
||||||
|
- `GenericSupplierProcessor`:
|
||||||
|
- 从 `supplier_config['dictionary']` 取词典并传入 `apply_rules`,保证每家供应商按自身词典执行
|
||||||
|
- 若未配置词典,使用默认空词典
|
||||||
|
|
||||||
|
## 向导UI扩展(右侧系统设置→列映射向导)
|
||||||
|
- 增加“供应商规则”区域:
|
||||||
|
- 可编辑列表:
|
||||||
|
- 忽略词(多行输入或表格)
|
||||||
|
- 单位同义词(键值对表格:原单位→统一单位)
|
||||||
|
- 包装倍数(单位→包装数量)
|
||||||
|
- 名称正则(多行,每行一个表达式)
|
||||||
|
- 默认单位、默认包装数量(输入框)
|
||||||
|
- 操作:新增/删除、导入(JSON)/导出(JSON)、保存
|
||||||
|
- 规则预览:
|
||||||
|
- 选择预设(基础拆分与推断或自定义),点击“应用规则预览”,显示“原始/规范化”两列树表对比
|
||||||
|
- 保存行为:将 `dictionary` 与 `rules` 写入对应供应商的 `suppliers_config.json` 并重载处理器
|
||||||
|
|
||||||
|
## 验证与测试
|
||||||
|
- 单元测试:
|
||||||
|
- 名称解析(容量×数量、简单乘法、忽略词影响、同义词归一)
|
||||||
|
- 数量拆分与单位归一(“4瓶/1箱/3件/2提/2盒”)
|
||||||
|
- 包装倍数应用与数量回推
|
||||||
|
- 烟雾测试:构建 5–10 类供货商样本,验证端到端转换与模板填充可用
|
||||||
|
|
||||||
|
## 交付
|
||||||
|
- 完成词典与规则编辑入口、配置扩展与引擎接入,提交验证报告与示例配置;保留导入/导出便于你迭代调整。
|
||||||
|
|
||||||
|
确认后我将按此方案实现:扩展配置→增强规则引擎→处理器接入→向导UI与预览→测试。
|
||||||
30
.trae/documents/修复“验证匹配”面板未加载问题.md
Normal file
30
.trae/documents/修复“验证匹配”面板未加载问题.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
## 原因
|
||||||
|
|
||||||
|
* 按钮调用了 `safe_open_validation_panel`,其内部检查 `open_validation_panel` 是否存在;当前代码中未定义该函数,导致始终提示“程序未加载,请重启”。
|
||||||
|
|
||||||
|
## 修复方案
|
||||||
|
|
||||||
|
* 在 `启动器.py` 中新增顶层函数 `open_validation_panel(log_widget)`,与其它 `open_*` 工具函数并列,确保加载顺序稳定。
|
||||||
|
|
||||||
|
* 保留按钮绑定到 `safe_open_validation_panel`,其将直接调用新定义的 `open_validation_panel`。
|
||||||
|
|
||||||
|
## 实施
|
||||||
|
|
||||||
|
* 添加 `open_validation_panel`:
|
||||||
|
|
||||||
|
* 入口参数:`log_widget`
|
||||||
|
|
||||||
|
* 实现与之前描述一致:供应商选择、原始文件/期望结果选择、运行验证生成差异、生成建议并“应用建议”写回配置。
|
||||||
|
|
||||||
|
* 放置位置:`show_supported_processors` 与 `safe_open_validation_panel` 相邻区域,确保可见与可用。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
|
||||||
|
* 启动程序→系统设置→点击“验证匹配”,应正常打开面板无提示。
|
||||||
|
|
||||||
|
* 选择“农夫山泉”与提供的文件后运行验证,查看差异与建议。
|
||||||
|
|
||||||
|
## 预期
|
||||||
|
|
||||||
|
* 面板不再提示重启;功能可用。
|
||||||
|
|
||||||
57
.trae/documents/基于样例结果的验证闭环与规则简化优化.md
Normal file
57
.trae/documents/基于样例结果的验证闭环与规则简化优化.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
## 目标
|
||||||
|
- 用你提供的原始文件与期望结果跑通“验证闭环”,自动对比差异并生成修正建议。
|
||||||
|
- 将“规则设置”改造成通俗易懂的“向导 + 快速模板 + 自动识别”,让普通用户也能完成操作。
|
||||||
|
|
||||||
|
## 验证闭环(立即可用)
|
||||||
|
- 新增“验证匹配”面板:
|
||||||
|
- 选择原始Excel:`data/output/微信图片_20251115212128_148_108.xlsx`
|
||||||
|
- 选择期望结果:`data/result/采购单_微信图片_20251115212128_148_108.xls`
|
||||||
|
- 一键运行当前供应商流程 → 自动生成临时结果 → 与期望结果进行单元格级对比
|
||||||
|
- 输出差异报告:
|
||||||
|
- 列差异(列缺失/多余/名称不一致)
|
||||||
|
- 行差异(按条码或名称对齐,数量/单位/单价/金额差异)
|
||||||
|
- 规则差异归因(例如:数量未拆分、单位未归一)
|
||||||
|
- 按“应用建议”自动调整当前供应商的规则/词典(可撤销)
|
||||||
|
|
||||||
|
## 简化操作设计
|
||||||
|
- 两种模式:
|
||||||
|
- 简单模式(默认):
|
||||||
|
- 步骤:选择文件 → 选择供应商 → 选择快速模板 → 预览 → 生成
|
||||||
|
- 字段中文说明(name(商品名称)、quantity(数量)等)与自动建议
|
||||||
|
- 高级模式:
|
||||||
|
- 可编辑规则顺序与参数、词典、正则;具备步骤预览与Diff
|
||||||
|
- 快速模板:
|
||||||
|
- “无数量/单位列”模板:自动配置拆分数量单位→名称提取规格→单位归一→缺省填充→标记赠品
|
||||||
|
- “纯金额/单价反推数量”模板:直接回推数量
|
||||||
|
- “条码驱动匹配”模板:条码为主键对齐
|
||||||
|
|
||||||
|
## 自动识别与建议
|
||||||
|
- 列名识别:从表头关键词自动映射常用字段
|
||||||
|
- 单位与数量:从“订单数量”拆分,单位同义词与包装倍数自动套用
|
||||||
|
- 名称提取规格:词典与正则库(容量×数量、双乘、“550水24白膜”)自动解析;失败行计数提示
|
||||||
|
- 自动修正建议:
|
||||||
|
- 若数量为空:建议添加“split_quantity_unit(source=订单数量)”
|
||||||
|
- 若单位为“箱/件/提/盒”:建议添加“normalize_unit + pack_multipliers”
|
||||||
|
- 若金额与单价存在且数量为空:建议添加“compute_quantity_from_total”
|
||||||
|
|
||||||
|
## 差异对比与一键修复
|
||||||
|
- 差异可视化:原始→规范化→模板填充三栏对比;支持仅显示变化列、导出CSV
|
||||||
|
- 一键修复:将建议以“卡片”列表展示,点击应用后立即刷新预览;支持撤销上一步
|
||||||
|
|
||||||
|
## 交互流程
|
||||||
|
1) 进入“验证匹配” → 选择原始与期望 → 运行 → 查看差异
|
||||||
|
2) 点击“应用建议”直观修复规则/词典 → 差异减少直至匹配
|
||||||
|
3) 切回“简单模式”一键生成采购单
|
||||||
|
|
||||||
|
## 技术实现要点
|
||||||
|
- 供应商配置:继续使用 `suppliers_config.json`,但在GUI中隐藏JSON细节,改为中文表单与下拉
|
||||||
|
- 规则执行:保留引擎,新增“建议生成器”根据差异报告生成规则/词典变更
|
||||||
|
- 对比对齐:优先按条码对齐;无条码时按名称近似匹配(去噪后模糊比对)
|
||||||
|
|
||||||
|
## 里程碑
|
||||||
|
- Day 1:验证面板与差异对比;建议生成器(数量/单位/规格/金额)
|
||||||
|
- Day 2:简单/高级模式切换;快速模板与自动识别
|
||||||
|
- Day 3:一键修复与撤销;导出差异报告
|
||||||
|
- Day 4:回归测试与打包;提供“农夫山泉”预设并用你的样例验证匹配
|
||||||
|
|
||||||
|
确认后我将实现“验证匹配”面板并接入建议修复,先用你提供的农夫山泉样例跑通闭环,再推广到其它供应商。
|
||||||
54
.trae/documents/继续执行周计划(任务7–10).md
Normal file
54
.trae/documents/继续执行周计划(任务7–10).md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
## 目标
|
||||||
|
- 按照优化实施计划,从第3周任务7/8开始全面落地,并同时推进第4周任务9/10,确保可视化、配置驱动和交付质量提升。
|
||||||
|
|
||||||
|
## 任务7:列映射向导完善
|
||||||
|
- 字段扩展与中文提示:标准字段统一以英+中展示,支持更多列(条码、名称、规格、数量、单位、单价、金额/小计、分类、品牌、供应商)。
|
||||||
|
- 自动建议增强:结合样本数据统计(字符串比例、特殊关键词、数值特征)给出更可靠的映射建议。
|
||||||
|
- 表头定位增强:支持预览选择,并保存 `header_row`;向导内清晰提示当前使用的表头行。
|
||||||
|
- 配置管理:支持导入/导出映射方案(JSON),可一键应用到多供应商。
|
||||||
|
- 热重载与快捷入口:保存后自动重载供应商处理器;在系统设置区和快捷键中提供入口。
|
||||||
|
|
||||||
|
## 任务8:模板管理与校验完善
|
||||||
|
- 模板组管理:支持为每个供应商选择/保存多个模板(默认、备用),UI下拉选择当前模板。
|
||||||
|
- 差异检测:读取模板首行表头与系统标准列比较,列表显示缺失/多余字段与修复建议。
|
||||||
|
- 批量校验:可一次性校验选定供应商的所有模板组并生成报告。
|
||||||
|
- 示例生成:按标准列生成示例模板,便于对齐格式。
|
||||||
|
|
||||||
|
## 任务9:单元测试与烟雾测试
|
||||||
|
- 单元测试(pytest):
|
||||||
|
- `_find_header_row` 不同格式表头识别(第一行/中间行/合并行/空白行混杂)。
|
||||||
|
- `GenericSupplierProcessor` 列映射、清洗规则(remove_rows/fill_na/convert_type)与公式计算。
|
||||||
|
- 模板填充的关键路径(必要列检测、数量/赠送量/单价写入)。
|
||||||
|
- 烟雾测试:准备小样本(图片→OCR→Excel→采购单),验证端到端可用,记录日志与输出。
|
||||||
|
|
||||||
|
## 任务10:打包与版本信息
|
||||||
|
- 版本信息:主窗口标题与“关于”对话框显示版本号、构建时间、更新日志入口。
|
||||||
|
- 打包校验:构建后检查模板与配置文件存在性;打包时拷贝资源并生成校验报告。
|
||||||
|
- 更新脚本:完善 `build_exe.py` 支持版本号注入与资源校验失败时中止。
|
||||||
|
|
||||||
|
## 实现要点
|
||||||
|
- GUI:系统设置页整合入口;对话框使用 780×660/540 尺寸,`topmost`/`lift`/`focus_force` 保证焦点。
|
||||||
|
- 配置:`suppliers_config.json` 增加 `header_row`、`column_mapping`、`output_templates`(数组)与当前选择索引。
|
||||||
|
- 处理器:优先使用保存的表头行;模板管理选择的模板在处理时应用。
|
||||||
|
- 日志与提示:保存/校验/重载操作统一写入日志面板并气泡提示。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
- 交互走查:向导流程顺畅、字段标签明确、置顶行为正常。
|
||||||
|
- 单元测试通过率达标(≥90%覆盖关键模块);烟雾测试输出正确文件且无异常。
|
||||||
|
- 打包后 EXE 启动显示版本信息;资源齐备,最近文件可双击打开。
|
||||||
|
|
||||||
|
## 变更范围
|
||||||
|
- `启动器.py`(设置页UI、向导与模板管理弹窗)
|
||||||
|
- `app/core/processors/supplier_processors/generic_supplier_processor.py`(读取与映射逻辑)
|
||||||
|
- `app/core/excel/processor.py`(表头行识别与模板填充校验)
|
||||||
|
- `config/suppliers_config.json`(结构扩展)
|
||||||
|
- `tests/`(新增pytest用例与烟雾测试脚本)
|
||||||
|
- `build_exe.py`(版本注入与校验)
|
||||||
|
|
||||||
|
## 时间安排
|
||||||
|
- Day 1:任务7 UI/配置完成,处理器联动与验证
|
||||||
|
- Day 2:任务8 模板管理增强与批量校验
|
||||||
|
- Day 3:任务9 单元测试与烟雾测试
|
||||||
|
- Day 4:任务10 打包与版本信息,回归测试与文档补充
|
||||||
|
|
||||||
|
确认后我将按以上计划开始实施并逐项提交验证结果。
|
||||||
52
.trae/documents/继续改进并显性呈现改动.md
Normal file
52
.trae/documents/继续改进并显性呈现改动.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
## 概览
|
||||||
|
- 目标:让改动更可见并提升识别/处理准确性与可操作性
|
||||||
|
- 范围:GUI入口与提示、表头识别与手动指定、供应商配置联动、交互一致性
|
||||||
|
|
||||||
|
## 可见入口改造
|
||||||
|
- 在“Excel处理→特殊处理”区新增两个明显按钮:
|
||||||
|
- “列映射向导”:加载 Excel 源列 → 映射到标准列 → 保存至 `config/suppliers_config.json`
|
||||||
|
- “模板管理”:选择模板、校验表头列是否包含必需项 → 保存路径至供应商配置
|
||||||
|
- 在“快捷操作”区补充一个“显示处理器类型”入口,便于确认支持的文件类型
|
||||||
|
- 在保存成功后增加气泡提示与日志条目(log 面板出现“列映射已保存”“模板路径已保存”)
|
||||||
|
|
||||||
|
## 手动表头行支持
|
||||||
|
- 在“列映射向导”弹窗增加“表头行号(从1开始)”输入框:
|
||||||
|
- 加载列时按照指定行重读 Excel 并展示源列
|
||||||
|
- 保存时将 `header_row`(零基索引)写入 `suppliers_config.json`
|
||||||
|
- 通用供应商处理器读取时优先使用 `supplier_config['header_row']`;未设置时执行自动表头检测(关键词+非空比例+字符串比例)
|
||||||
|
|
||||||
|
## 自动表头检测增强
|
||||||
|
- Excel 单文件处理与通用供应商处理器:
|
||||||
|
- 扫描范围扩大到前 30 行
|
||||||
|
- 扩充关键词:加入金额类(“金额/小计/总计/合计/合计金额”)
|
||||||
|
- 综合评分:关键词命中+非空比例+字符串比例,阈值达到即判为表头;否则选第一个有效行
|
||||||
|
|
||||||
|
## 交互与一致性
|
||||||
|
- “单个识别”按钮直接弹出图片选择(只允许 `jpg/jpeg/png/bmp`),取消即终止
|
||||||
|
- “单个处理”按钮弹出 Excel 选择(只允许 `xlsx/xls`),取消即终止,不再默认处理最新 Excel
|
||||||
|
- 处理完成后不再自动打开 `result/output` 目录,改为通过“最近文件”双击打开
|
||||||
|
- 最近文件仅记录图片/Excel,自动过滤无效并按修改时间降序展示,空历史时从 `data/output`、`data/result` 回填合规文件
|
||||||
|
|
||||||
|
## 供应商配置联动
|
||||||
|
- `suppliers_config.json`:
|
||||||
|
- `column_mapping`:保存源列→标准列映射
|
||||||
|
- `header_row`:保存手动指定的表头行(零基)
|
||||||
|
- `output_template`:保存模板路径(相对路径)
|
||||||
|
- 处理器加载时校验并日志提示不合法项,保留已通过的配置
|
||||||
|
|
||||||
|
## 验证与可视化
|
||||||
|
- 操作日志:保存映射/模板时写入成功日志
|
||||||
|
- 处理器信息:通过“显示处理器类型”对话框列出支持的扩展名和描述
|
||||||
|
- 手动表头验证:在向导中“加载列”后,源列下拉应出现正确列名;处理后“最近文件”出现输出采购单
|
||||||
|
|
||||||
|
## 预计改动位置
|
||||||
|
- GUI按钮与向导弹窗:`启动器.py`(特殊处理区与工具函数)
|
||||||
|
- 自动表头检测与手动表头使用:
|
||||||
|
- Excel处理:`app/core/excel/processor.py` 的 `_find_header_row`、`process_specific_file`
|
||||||
|
- 通用供应商处理:`app/core/processors/supplier_processors/generic_supplier_processor.py` 的 `_read_supplier_data`、`_find_header_row`
|
||||||
|
- 供应商配置:`config/suppliers_config.json`
|
||||||
|
|
||||||
|
## 交付
|
||||||
|
- 提交代码改动后,更新打包 EXE,便携包包含上述 UI 与功能;提供操作说明与可见验证点。
|
||||||
|
|
||||||
|
请确认以上计划,确认后我将按此逐项实现并验证。
|
||||||
50
.trae/documents/解决“只有订单数量列”场景的可操作方案.md
Normal file
50
.trae/documents/解决“只有订单数量列”场景的可操作方案.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
## 你现在就能这样做
|
||||||
|
- 目标:在没有“规格/数量/单位”列、只有“订单数量”列(如“4瓶/1箱/5箱/3件”)时,拆分出数量与单位,并按名称提取规格,最终规范化为银豹模板字段。
|
||||||
|
|
||||||
|
### A. 最小映射(只为模板填充)
|
||||||
|
- 在“供应商管理 → 列映射与表头”页,只需映射这些常用列:
|
||||||
|
- name ← 商品名称
|
||||||
|
- barcode ← 条码(如有)
|
||||||
|
- unit_price ← 单价(如有)
|
||||||
|
- total_price ← 金额/小计(如有)
|
||||||
|
- 不需要映射“数量/单位/规格”,后续用规则直接从原始列生成。
|
||||||
|
|
||||||
|
### B. 规则与词典设置(关键)
|
||||||
|
- 在“供应商管理 → 规则与词典”页:
|
||||||
|
1) 规则列表按顺序添加:
|
||||||
|
- split_quantity_unit,参数:source=订单数量
|
||||||
|
- extract_spec_from_name,参数:source=商品名称
|
||||||
|
- normalize_unit,参数:target=unit,map={"箱":"件","提":"件","盒":"件"}
|
||||||
|
- fill_missing,参数:fills={"unit":"瓶"}
|
||||||
|
- mark_gift(可选)
|
||||||
|
- compute_quantity_from_total(可选,当只有金额/单价时)
|
||||||
|
2) 词典设置:
|
||||||
|
- unit_synonyms:{"箱":"件","提":"件","盒":"件","瓶":"瓶"}
|
||||||
|
- pack_multipliers:{"件":24,"箱":24,"提":12,"盒":10}(根据你的供应商习惯调整)
|
||||||
|
- default_unit:瓶
|
||||||
|
- default_package_quantity:1
|
||||||
|
- ignore_words:如(白膜、彩膜、赠品)
|
||||||
|
- name_patterns(每行一个正则):
|
||||||
|
- (\d+(?:\.\d+)?)(ml|l|升|毫升)[*×xX](\d+)
|
||||||
|
- (\d+)[*×xX](\d+)瓶
|
||||||
|
- 需要时加入供应商特有格式,如“550水24白膜”可匹配“(\d{2,3}).*?(\d{1,3})”并将第二组当作包装数
|
||||||
|
|
||||||
|
### C. 预览与验证
|
||||||
|
- 在“规则与词典”页选择Excel,点击“生成步骤预览”:
|
||||||
|
- 看“原始 → 规范化”两侧表,对比是否出现 quantity(数值)、unit(单位)、specification、package_quantity
|
||||||
|
- 在“预览步骤”中逐步查看每一条规则的结果;必要时导出CSV核对
|
||||||
|
- 保存后会自动重载处理器;用真实文件跑一次,结果会出现在“最近文件”,双击打开核验。
|
||||||
|
|
||||||
|
### D. 解释关键点
|
||||||
|
- 映射是为了模板填充字段的命名统一;对于“订单数量”这种来源列,规则会直接读取 source=订单数量,不要求你把它映射成标准列。
|
||||||
|
- 规则执行后,会产生标准字段:quantity、unit、specification、package_quantity,可被模板填充。
|
||||||
|
- normalize_unit会用词典的pack_multipliers或name解析出的package_quantity,自动把“件/箱/提/盒”的数量换算成“瓶”,并将unit统一为“瓶”。
|
||||||
|
|
||||||
|
## 我将继续优化的点(让流程更清晰)
|
||||||
|
1) 规则表单中的“来源列”改为可选下拉(直接从Excel列名取值),无需手填。
|
||||||
|
2) 步骤预览支持“仅显示变化的列(Diff模式)”与“错误计数”(未匹配的行统计)。
|
||||||
|
3) 提供“无数量/单位列”的快速模版:自动添加上述规则与词典默认值,一键套用。
|
||||||
|
4) 规则帮助提示:每条规则说明输入/输出字段与常见示例。
|
||||||
|
5) 供应商级的“测试运行”:选文件→一键规范化→预览→导出结果,独立于正式处理。
|
||||||
|
|
||||||
|
如果你同意,我将按上述方案完善GUI交互(来源列下拉、快速模板、Diff预览、错误计数与一键测试),并把默认规则与词典预设直接提供出来,确保“只有订单数量列”的场景开箱可用。
|
||||||
42
.trae/documents/通用采购单规范化与规则引擎优化方案.md
Normal file
42
.trae/documents/通用采购单规范化与规则引擎优化方案.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
## 目标
|
||||||
|
- 通过规则引擎把不同供货商的OCR表格规范为统一字段,并自动拆分“数量+单位”、从名称推断规格、标记赠品,最终稳定填充银豹模板。
|
||||||
|
|
||||||
|
## 配置与规则
|
||||||
|
- 扩展 `suppliers_config.json`:
|
||||||
|
- `rules`: 规则数组(顺序执行)
|
||||||
|
- `output_templates`: 模板列表;`current_template_index`: 当前模板索引
|
||||||
|
- 规则类型:
|
||||||
|
- `split_quantity_unit`(拆分“4瓶/1箱/3件/2提/2盒”)
|
||||||
|
- `extract_spec_from_name`(解析“1.8L×8瓶”“550水24白膜”等)
|
||||||
|
- `normalize_unit`(单位归一“箱/件/提/盒/瓶”→统一“瓶”,按包装转换数量)
|
||||||
|
- `compute_quantity_from_total`(数量缺失时用金额/单价反推)
|
||||||
|
- `infer_supplier`(文件名/内容推断供应商)
|
||||||
|
- `fill_missing`(填默认值)
|
||||||
|
- `mark_gift`(金额/单价=0或“赠品/O/o/空”)
|
||||||
|
|
||||||
|
## 实现
|
||||||
|
- 新建 `app/core/handlers/rule_engine.py`:输入DataFrame与规则列表,返回规范化DataFrame
|
||||||
|
- 在 `GenericSupplierProcessor` 中:列映射→清洗→规则引擎→输出
|
||||||
|
- 列映射向导增强:
|
||||||
|
- 增加“规则预设”选择与“应用规则预览”按钮,显示原始/规范化后的对比
|
||||||
|
- 支持导入/导出(映射+规则)JSON
|
||||||
|
- 模板管理增强:模板组选择、批量校验、示例模板生成
|
||||||
|
|
||||||
|
## 解析与正则
|
||||||
|
- 名称解析:
|
||||||
|
- 容量×数量:`(\d+(?:\.\d+)?)(ml|l|升|毫升)[*×xX](\d+)`
|
||||||
|
- 简单数量×数量:`(\d+)[*×xX](\d+)`
|
||||||
|
- 词典忽略词:如“白膜”等
|
||||||
|
- 数量拆分:`(?P<num>\d+(?:\.\d+)?)(?P<unit>箱|件|提|盒|瓶)`
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
- 单元测试覆盖规则与表头识别;烟雾测试涵盖“无单位/规格/数量混杂”的样本
|
||||||
|
- GUI预览确认规则效果;保存后热重载处理器
|
||||||
|
|
||||||
|
## 里程碑
|
||||||
|
- Day 1:规则引擎与处理器接入
|
||||||
|
- Day 2:向导规则预览与导入/导出;模板组管理
|
||||||
|
- Day 3:测试与样本库
|
||||||
|
- Day 4:打包与交付验证
|
||||||
|
|
||||||
|
请确认,我将立即开始实现并逐步提交验证结果。
|
||||||
57
CHANGELOG.md
57
CHANGELOG.md
@ -1,30 +1,39 @@
|
|||||||
# 更新日志
|
# Changelog
|
||||||
|
|
||||||
## v1.1.0 (2025-05-30)
|
## [v2.2.0] - 2026-03-31
|
||||||
|
### Added
|
||||||
|
- **UI Simplification**: Removed dedicated buttons for Rongcheng and Tobacco; all Excel orders now use the intelligent auto-routing.
|
||||||
|
- **Enhanced Yang Biyue Support**: Fixed column mapping for Yang Biyue orders, ensuring standard fields (Barcode, Quantity, Price) are correctly extracted.
|
||||||
|
- **Headless API Auto-Detect**: `headless_api.py` now automatically distinguishes between Image (OCR) and Excel (Direct) inputs based on file extension.
|
||||||
|
|
||||||
### 新特性
|
### Fixed
|
||||||
- 添加对特殊条码6958620703716的处理,支持同时设置规格和条码映射
|
- **Yang Biyue Preprocessing**: Resolved issue where data was empty due to incorrect column renaming.
|
||||||
- 增强不规范规格格式的解析能力(如"IL*12"、"6oo*12"等)
|
- **Interference Filtering**: Added logic to exclude distractor columns like "Settlement Unit" or "Base Quantity" during preprocessing.
|
||||||
- 支持带重量单位的规格解析(如"5kg*6")
|
|
||||||
- 添加数量为空时通过金额和单价自动计算数量的功能
|
|
||||||
|
|
||||||
### 修复
|
### Removed
|
||||||
- 修复条码映射功能在特殊处理后不生效的问题
|
- **Redundant Files**: Cleaned up `run.py`, `clean.py`, and unused CLI modules.
|
||||||
- 修复OrderService中缺少merge_all_purchase_orders方法导致合并采购单报错的问题
|
- **Legacy UI Elements**: Removed tobacco-specific keyboard shortcuts and help entries.
|
||||||
- 修复了条码映射对话框无法同时添加特殊处理和映射的问题
|
|
||||||
|
|
||||||
### 改进
|
## [v2.1.0] - 2026-03-30
|
||||||
- 改进了BarcodeMapper类,使其支持同时进行特殊处理和条码映射
|
### Added
|
||||||
- 改进了规格解析逻辑,增加了对各种单位和格式的支持
|
- **Intelligent Recognition**: Automated fingerprinting for Rongcheng Yigou, Tobacco, and Yang Biyue orders.
|
||||||
- 添加条码映射对话框中可视化标记映射关系
|
- **Auto-Routing**: `OrderService.process_excel` now automatically handles preprocessing without explicit flags.
|
||||||
- 更新了条码映射配置文件,增加了更多特殊条码处理
|
- **Headless API Enhancements**: `headless_api.py` updated to support the new intelligent recognition mode.
|
||||||
- 改进商品验证器,在数量为空但单价和金额存在时,自动计算数量
|
- **Comprehensive Documentation**: Added `OPENCLAW_GUIDE.md` and `FINAL_UPDATE_REPORT.md`.
|
||||||
|
|
||||||
## v1.0.0 (2025-05-01)
|
### Fixed
|
||||||
|
- **Rongcheng Yigou**: Fixed barcode splitting issue where quantities were incorrectly distributed (30 to 5).
|
||||||
|
- **Tobacco Orders**: Corrected unit price calculation (divided by 10) and quantity calculation (multiplied by 10).
|
||||||
|
- **Identification Failure**: Fixed issue where `header=0` caused identification keywords at the very first row to be missed.
|
||||||
|
|
||||||
### 初始版本
|
## [v2.0.0] - 2026-03-25
|
||||||
- 基础OCR识别功能
|
### Added
|
||||||
- Excel处理功能
|
- **Headless API**: First release of `headless_api.py` for OpenClaw integration.
|
||||||
- 采购单合并功能
|
- **Price Validation**: Integration with PosPal item data for unit price auditing.
|
||||||
- 烟草订单处理功能
|
- **Asynchronous Logging**: GUI now uses a queue for log output to prevent UI freezing.
|
||||||
- 图形用户界面
|
|
||||||
|
## [v1.1.0] - 2026-03-10
|
||||||
|
### Added
|
||||||
|
- **Rongcheng Yigou Support**: Initial support for Rongcheng Excel templates.
|
||||||
|
- **Tobacco Support**: Initial support for Tobacco Excel templates.
|
||||||
|
- **Excel Processor**: Refactored core processing logic into `ExcelProcessor`.
|
||||||
|
|||||||
30
FINAL_UPDATE_REPORT.md
Normal file
30
FINAL_UPDATE_REPORT.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# OCR 订单处理系统 - v2.2 更新报告
|
||||||
|
|
||||||
|
## 1. 业务逻辑与 UI 变更 (v2.2 Updates)
|
||||||
|
|
||||||
|
### 1.1 UI 极简优化
|
||||||
|
- **移除专用按钮**:从主界面彻底移除了“蓉城易购”和“烟草处理”两个特定按钮。
|
||||||
|
- **统一入口**:所有供应商 Excel 订单现在均通过“处理 Excel 文件”或直接拖拽至主界面进行处理。系统会自动识别并路由。
|
||||||
|
- **快捷键更新**:移除了 `Ctrl+T` (烟草处理) 快捷键,简化了键盘操作逻辑。
|
||||||
|
|
||||||
|
### 1.2 杨碧月预处理修复
|
||||||
|
- **列名校准**:修正了预处理输出列名,确保与银豹处理器期望的中文列名(商品条码、数量、单价等)完全一致。
|
||||||
|
- **干扰过滤**:在提取列时,自动排除了 `结算单位`、`基本单位数量` 等名称相似的非业务列,提高了匹配精度。
|
||||||
|
|
||||||
|
### 1.3 Headless API 智能增强
|
||||||
|
- **后缀感知**:`headless_api.py` 能够根据文件后缀自动区分图片与 Excel,不再需要显式指定 `--excel` 或 `--tobacco`。
|
||||||
|
- **零配置接入**:OpenClaw 仅需运行 `python headless_api.py [文件路径]` 即可完成全流程。
|
||||||
|
|
||||||
|
## 2. 供应商清洗规则 (保持最新)
|
||||||
|
| 供应商 | 条码列 | 数量逻辑 | 单价逻辑 | 金额逻辑 |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **蓉城易购** | E列 (Index 4) | N列 (Index 13),不换算 | Q列 (Index 16) | S列 (Index 18) |
|
||||||
|
| **烟草公司** | B列 (Index 1) | G列 (Index 6) **x 10** | E列 (Index 4) **/ 10** | H列 (Index 7) |
|
||||||
|
|
||||||
|
## 3. 代码与环境清理
|
||||||
|
- **移除无用文件**:清理了 `run.py` (冗余)、`clean.py` (旧脚本) 以及 `doc/` (旧文档)。
|
||||||
|
- **模块重构**:删除了 `app/cli/` 模块,所有命令行逻辑已合并至根目录的 `headless_api.py`。
|
||||||
|
|
||||||
|
---
|
||||||
|
*报告生成日期:2026-03-31*
|
||||||
|
*负责人:Trae Code Assistant*
|
||||||
@ -1,82 +0,0 @@
|
|||||||
|
|
||||||
# -*- mode: python ; coding: utf-8 -*-
|
|
||||||
|
|
||||||
block_cipher = None
|
|
||||||
|
|
||||||
# 需要包含的数据文件
|
|
||||||
added_files = [
|
|
||||||
('config.ini', '.'),
|
|
||||||
('config/barcode_mappings.json', 'config/'),
|
|
||||||
('config/config.ini', 'config/'),
|
|
||||||
('templates/银豹-采购单模板.xls', 'templates/'),
|
|
||||||
('app', 'app'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# 需要隐式导入的模块
|
|
||||||
hidden_imports = [
|
|
||||||
'tkinter',
|
|
||||||
'tkinter.ttk',
|
|
||||||
'tkinter.filedialog',
|
|
||||||
'tkinter.messagebox',
|
|
||||||
'tkinter.scrolledtext',
|
|
||||||
'pandas',
|
|
||||||
'numpy',
|
|
||||||
'openpyxl',
|
|
||||||
'xlrd',
|
|
||||||
'xlwt',
|
|
||||||
'xlutils',
|
|
||||||
'requests',
|
|
||||||
'configparser',
|
|
||||||
'threading',
|
|
||||||
'datetime',
|
|
||||||
'json',
|
|
||||||
're',
|
|
||||||
'subprocess',
|
|
||||||
'shutil',
|
|
||||||
'app.config.settings',
|
|
||||||
'app.services.ocr_service',
|
|
||||||
'app.services.order_service',
|
|
||||||
'app.services.tobacco_service',
|
|
||||||
'app.core.utils.dialog_utils',
|
|
||||||
'app.core.excel.converter',
|
|
||||||
]
|
|
||||||
|
|
||||||
a = Analysis(
|
|
||||||
['启动器.py'],
|
|
||||||
pathex=[],
|
|
||||||
binaries=[],
|
|
||||||
datas=added_files,
|
|
||||||
hiddenimports=hidden_imports,
|
|
||||||
hookspath=[],
|
|
||||||
hooksconfig={},
|
|
||||||
runtime_hooks=[],
|
|
||||||
excludes=[],
|
|
||||||
win_no_prefer_redirects=False,
|
|
||||||
win_private_assemblies=False,
|
|
||||||
cipher=block_cipher,
|
|
||||||
noarchive=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|
||||||
|
|
||||||
exe = EXE(
|
|
||||||
pyz,
|
|
||||||
a.scripts,
|
|
||||||
a.binaries,
|
|
||||||
a.zipfiles,
|
|
||||||
a.datas,
|
|
||||||
[],
|
|
||||||
name='OCR订单处理系统',
|
|
||||||
debug=False,
|
|
||||||
bootloader_ignore_signals=False,
|
|
||||||
strip=False,
|
|
||||||
upx=True,
|
|
||||||
upx_exclude=[],
|
|
||||||
runtime_tmpdir=None,
|
|
||||||
console=False,
|
|
||||||
disable_windowed_traceback=False,
|
|
||||||
argv_emulation=False,
|
|
||||||
target_arch=None,
|
|
||||||
codesign_identity=None,
|
|
||||||
entitlements_file=None,
|
|
||||||
)
|
|
||||||
53
OPENCLAW_GUIDE.md
Normal file
53
OPENCLAW_GUIDE.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# OCR 订单处理系统 - OpenClaw 对接指南 (v2.2)
|
||||||
|
|
||||||
|
## 1. 核心接口说明 (headless_api.py)
|
||||||
|
|
||||||
|
`headless_api.py` 是系统的统一命令行入口。它支持**智能文件类型与供应商识别**,OpenClaw 通常**无需携带任何功能参数**。
|
||||||
|
|
||||||
|
### 1.1 全自动智能模式 (推荐方式)
|
||||||
|
无论是收到**图片**还是 **Excel**,都可以直接调用。系统会自动判断文件类型:如果是 Excel 则自动识别供应商指纹(蓉城、烟草、杨碧月等)并处理;如果是图片则先 OCR 后再智能处理。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 自动处理 data/input 中最新的文件 (图片或 Excel)
|
||||||
|
python headless_api.py
|
||||||
|
|
||||||
|
# 处理指定的任意文件 (图片或 Excel)
|
||||||
|
python headless_api.py "data/input/my_file.jpg"
|
||||||
|
python headless_api.py "data/input/my_file.xlsx"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 显式特殊指令 (备用)
|
||||||
|
仅在自动识别失效或需要特殊操作时使用。
|
||||||
|
```bash
|
||||||
|
# 强制指定为 Excel 处理模式
|
||||||
|
python headless_api.py --excel
|
||||||
|
|
||||||
|
# --- 条码映射与特殊处理指令 ---
|
||||||
|
|
||||||
|
# 1. 简单的条码映射 (旧条码 -> 新条码)
|
||||||
|
python headless_api.py --update-mapping --barcode "123" --target "456"
|
||||||
|
|
||||||
|
# 2. 特殊倍数处理 (例如某条码识别为1件,实际需换算为30瓶)
|
||||||
|
python headless_api.py --update-mapping --barcode "690123" --multiplier 30 --unit "瓶"
|
||||||
|
|
||||||
|
# 3. 固定单价与规格
|
||||||
|
python headless_api.py --update-mapping --barcode "690123" --price 3.5 --spec "1*30"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 字段与逻辑变更
|
||||||
|
|
||||||
|
### 2.1 蓉城易购 (Rongcheng)
|
||||||
|
- **条码映射**:E列 (Index 4)。
|
||||||
|
- **数量逻辑**:N列 (Index 13)。直接提取,不进行单位换算。
|
||||||
|
- **条码分裂**:支持 `/` `,` `,` `、` 分隔符自动均分。
|
||||||
|
|
||||||
|
### 2.2 烟草公司 (Tobacco)
|
||||||
|
- **条码映射**:B列 (Index 1)。
|
||||||
|
- **数量逻辑**:G列 (订单量) **x 10**。
|
||||||
|
- **单价逻辑**:E列 (批发价) **/ 10**。
|
||||||
|
|
||||||
|
### 2.3 杨碧月 (Yang Biyue)
|
||||||
|
- **自动对齐**:自动识别经手人并对齐“商品条码”、“数量”、“单价”等标准列。
|
||||||
|
|
||||||
|
---
|
||||||
|
*版本:2.2 | 更新日期:2026-03-31*
|
||||||
85
README.md
85
README.md
@ -1,43 +1,66 @@
|
|||||||
# 益选-OCR订单处理系统
|
# 益选 OCR 订单处理系统
|
||||||
|
|
||||||
一个集OCR识别、Excel处理和订单合并功能于一体的采购单处理系统。
|
## 概览
|
||||||
|
- 面向零售与分销场景的采购单处理工具,支持图片 OCR → Excel 规范化 → 模板填充 → 合并导出全流程
|
||||||
|
- 通过供应商管理与规则引擎,适配不同供应商的格式差异(数量含单位、名称包含规格、缺失列补齐)
|
||||||
|
- 提供验证匹配面板与单价校验机制,确保输出与既定模板一致且价格合理
|
||||||
|
|
||||||
## 主要功能
|
## 核心功能
|
||||||
|
- **全自动智能识别**:系统现在能自动识别 Excel 内容特征(如:蓉城易购 RCDH、烟草公司专卖证号、杨碧月经手人),并自动路由至专用预处理流程,无需手动干预。
|
||||||
|
- **图片/Excel处理**:支持拖拽或选择文件,一键生成标准银豹采购单。
|
||||||
|
- **极简 UI 体验**:移除了冗余的供应商特定按钮,所有 Excel 统一走智能路由处理。
|
||||||
|
- **无界面自动化接口 (headless_api.py)**:专为 OpenClaw 等平台设计,支持全自动文件类型与供应商识别。
|
||||||
|
- **单价预警机制**:自动比对 `templates/商品资料.xlsx`,若价差超过 1.0 元则触发警告。
|
||||||
|
|
||||||
- **OCR识别**:识别图片中的商品信息,包括条码、名称、数量、单价等
|
## 供应商专用逻辑 (v2.2)
|
||||||
- **Excel处理**:将OCR识别结果处理成规范的Excel采购单
|
### 蓉城易购 (Rongcheng)
|
||||||
- **采购单合并**:合并多个采购单,汇总相同商品
|
- **精准映射**:商品条码(E列)、数量(N列)、单价(Q列)、金额(S列)。
|
||||||
- **条码映射**:支持将特定条码映射为其他条码,适应不同系统要求
|
- **条码分裂**:支持多条码行(如 `条码1/条码2`)自动均分数量。
|
||||||
- **规格处理**:智能解析商品规格,实现单位自动转换
|
- **逻辑简化**:直接提取原始数量,不进行多余的单位或包装换算。
|
||||||
- **烟草订单处理**:专门处理烟草公司订单
|
|
||||||
|
|
||||||
## 技术特点
|
### 烟草公司 (Tobacco)
|
||||||
|
- **换算逻辑**:条码(B列)、数量(G列 x 10)、单价(E列 / 10)、总额(H列)。
|
||||||
|
- **智能跳行**:自动识别并跳过合计行及非数据行。
|
||||||
|
|
||||||
- 基于Python开发,使用Tkinter构建图形界面
|
### 杨碧月订单
|
||||||
- 采用模块化设计,易于扩展和维护
|
- **自动对齐**:识别到经手人“杨碧月”后,自动将非标 Excel 转换为标准列格式,支持单位换算(件 -> 瓶)。
|
||||||
- 自动处理各种不规范数据格式
|
|
||||||
- 配置文件支持,可自定义各种处理参数
|
|
||||||
- 日志记录,便于问题排查
|
|
||||||
|
|
||||||
## 使用方法
|
## 关键适配(蓉城易购)
|
||||||
|
- 新模板(如“订单1765440157955.xlsx”):
|
||||||
|
- 使用第三行作为表头(`header=2`)
|
||||||
|
- 关键词选列并重命名到期望字段:商品条码(小条码)、订购数量(小单位)、单价(小单位)、优惠后金额(小单位)、单位
|
||||||
|
- 单位优先匹配“单位(订购单位)”列,清洗为去空白并将“件”替换为“份”
|
||||||
|
- 多条码行(逗号/顿号/斜杠/空格分隔)拆分为多行,数量均分并重算金额,单位保持订购单位
|
||||||
|
- 新模板映射:将“优惠后金额(小单位)”作为单价,“出库小计(元)”作为金额来源
|
||||||
|
|
||||||
1. 运行`启动器.py`打开主界面
|
## 使用说明
|
||||||
2. 根据需要选择相应功能按钮
|
1. 运行程序(EXE或源码运行)
|
||||||
3. 按照提示操作,完成数据处理
|
2. 在主界面:
|
||||||
|
- 拖拽或选择图片/Excel进行处理
|
||||||
|
- 系统设置 → 供应商管理:配置供应商、列映射与规则;使用规则预览查看规范化效果
|
||||||
|
- 系统设置 → 验证匹配:选择原始与期望文件,差异对比;应用建议后重载配置
|
||||||
|
3. 处理成功后,采购单保存到 `data/output` 或 `data/result`,最近文件列表可双击打开查看
|
||||||
|
|
||||||
## 系统要求
|
## 构建与打包
|
||||||
|
- 依赖:Python 3.9+,虚拟环境建议
|
||||||
|
- 安装打包工具:`pip install pyinstaller`
|
||||||
|
- 运行打包脚本:`python build_exe.py`
|
||||||
|
- 生成 EXE:`dist/OCR订单处理系统.exe`
|
||||||
|
- 生成便携包:`release/OCR订单处理系统.exe`(包含 `templates/银豹-采购单模板.xls` 与 `templates/商品资料.xlsx`)
|
||||||
|
|
||||||
- Python 3.8+
|
## Git 提交建议
|
||||||
- 所需第三方库:详见`requirements.txt`
|
- 建议忽略构建目录与运行输出(见 `.gitignore`)
|
||||||
|
- 保留模板与配置:`templates/银豹-采购单模板.xls`、`templates/商品资料.xlsx`、`config/config.ini`、`config/barcode_mappings.json`
|
||||||
|
|
||||||
## 最近更新
|
## 常见问题
|
||||||
|
- 表头识别失败:在供应商管理的“列映射与表头”页预览表头行并选择正确行号
|
||||||
|
- 数量含单位:启用 `split_quantity_unit` 与 `normalize_unit` 规则并配置单位同义词与包装倍数
|
||||||
|
- 名称中规格:配置 `ignore_words` 与 `name_patterns`,使用步骤预览确认解析效果
|
||||||
|
- 单价校验未提示:确认 `templates/商品资料.xlsx` 存在且列名包含“进货价”与条码列(`商品条码/条码/barcode`)
|
||||||
|
|
||||||
请查看[更新日志](CHANGELOG.md)了解最新版本变更。
|
## 变更记录(近期)
|
||||||
|
- 新增验证匹配面板与建议修复
|
||||||
|
- 规则预设与步骤预览(原始→逐步→规范化)
|
||||||
|
- 单价校验机制(价差>1元提示)
|
||||||
|
- 蓉城易购新模板适配(第三行表头、单位(订购单位)、多条码拆分、金额映射)
|
||||||
|
|
||||||
## 贡献者
|
|
||||||
|
|
||||||
- 欢欢欢
|
|
||||||
|
|
||||||
## 版权
|
|
||||||
|
|
||||||
© 2025 益选-OCR订单处理系统
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
"""
|
|
||||||
OCR订单处理系统 - 命令行接口
|
|
||||||
-------------------------
|
|
||||||
提供命令行工具,便于用户使用系统功能。
|
|
||||||
"""
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
"""
|
|
||||||
Excel处理命令行工具
|
|
||||||
---------------
|
|
||||||
提供Excel处理相关的命令行接口。
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from ..config.settings import ConfigManager
|
|
||||||
from ..core.utils.log_utils import get_logger, close_logger
|
|
||||||
from ..services.order_service import OrderService
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
def create_parser() -> argparse.ArgumentParser:
|
|
||||||
"""
|
|
||||||
创建命令行参数解析器
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
参数解析器
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser(description='Excel处理工具')
|
|
||||||
|
|
||||||
# 通用选项
|
|
||||||
parser.add_argument('--config', type=str, help='配置文件路径')
|
|
||||||
|
|
||||||
# 子命令
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='子命令')
|
|
||||||
|
|
||||||
# 处理Excel命令
|
|
||||||
process_parser = subparsers.add_parser('process', help='处理Excel文件')
|
|
||||||
process_parser.add_argument('--input', type=str, help='输入Excel文件路径,如果不指定则处理最新的文件')
|
|
||||||
|
|
||||||
# 查看命令
|
|
||||||
list_parser = subparsers.add_parser('list', help='获取最新的Excel文件')
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def process_excel(order_service: OrderService, input_file: Optional[str] = None) -> bool:
|
|
||||||
"""
|
|
||||||
处理Excel文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
order_service: 订单服务
|
|
||||||
input_file: 输入文件路径,如果为None则处理最新的文件
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
处理是否成功
|
|
||||||
"""
|
|
||||||
if input_file:
|
|
||||||
if not os.path.exists(input_file):
|
|
||||||
logger.error(f"输入文件不存在: {input_file}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
result = order_service.process_excel(input_file)
|
|
||||||
else:
|
|
||||||
latest_file = order_service.get_latest_excel()
|
|
||||||
if not latest_file:
|
|
||||||
logger.warning("未找到可处理的Excel文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.info(f"处理最新的Excel文件: {latest_file}")
|
|
||||||
result = order_service.process_excel(latest_file)
|
|
||||||
|
|
||||||
if result:
|
|
||||||
logger.info(f"处理成功,输出文件: {result}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error("处理失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def list_latest_excel(order_service: OrderService) -> bool:
|
|
||||||
"""
|
|
||||||
获取最新的Excel文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
order_service: 订单服务
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
是否找到Excel文件
|
|
||||||
"""
|
|
||||||
latest_file = order_service.get_latest_excel()
|
|
||||||
|
|
||||||
if latest_file:
|
|
||||||
logger.info(f"最新的Excel文件: {latest_file}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.info("未找到Excel文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def main(args: Optional[List[str]] = None) -> int:
|
|
||||||
"""
|
|
||||||
Excel处理命令行主函数
|
|
||||||
|
|
||||||
Args:
|
|
||||||
args: 命令行参数,如果为None则使用sys.argv
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
退出状态码
|
|
||||||
"""
|
|
||||||
parser = create_parser()
|
|
||||||
parsed_args = parser.parse_args(args)
|
|
||||||
|
|
||||||
if parsed_args.command is None:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 创建配置管理器
|
|
||||||
config = ConfigManager(parsed_args.config) if parsed_args.config else ConfigManager()
|
|
||||||
|
|
||||||
# 创建订单服务
|
|
||||||
order_service = OrderService(config)
|
|
||||||
|
|
||||||
# 根据命令执行不同功能
|
|
||||||
if parsed_args.command == 'process':
|
|
||||||
success = process_excel(order_service, parsed_args.input)
|
|
||||||
elif parsed_args.command == 'list':
|
|
||||||
success = list_latest_excel(order_service)
|
|
||||||
else:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0 if success else 1
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"执行过程中发生错误: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# 关闭日志
|
|
||||||
close_logger(__name__)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
||||||
@ -1,147 +0,0 @@
|
|||||||
"""
|
|
||||||
订单合并命令行工具
|
|
||||||
--------------
|
|
||||||
提供订单合并相关的命令行接口。
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from ..config.settings import ConfigManager
|
|
||||||
from ..core.utils.log_utils import get_logger, close_logger
|
|
||||||
from ..services.order_service import OrderService
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
def create_parser() -> argparse.ArgumentParser:
|
|
||||||
"""
|
|
||||||
创建命令行参数解析器
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
参数解析器
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser(description='订单合并工具')
|
|
||||||
|
|
||||||
# 通用选项
|
|
||||||
parser.add_argument('--config', type=str, help='配置文件路径')
|
|
||||||
|
|
||||||
# 子命令
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='子命令')
|
|
||||||
|
|
||||||
# 合并命令
|
|
||||||
merge_parser = subparsers.add_parser('merge', help='合并采购单')
|
|
||||||
merge_parser.add_argument('--input', type=str, help='输入采购单文件路径列表,以逗号分隔,如果不指定则合并所有采购单')
|
|
||||||
|
|
||||||
# 列出采购单命令
|
|
||||||
list_parser = subparsers.add_parser('list', help='列出采购单文件')
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def merge_orders(order_service: OrderService, input_files: Optional[str] = None) -> bool:
|
|
||||||
"""
|
|
||||||
合并采购单
|
|
||||||
|
|
||||||
Args:
|
|
||||||
order_service: 订单服务
|
|
||||||
input_files: 输入文件路径列表,以逗号分隔,如果为None则合并所有采购单
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
合并是否成功
|
|
||||||
"""
|
|
||||||
if input_files:
|
|
||||||
# 分割输入文件列表
|
|
||||||
file_paths = [path.strip() for path in input_files.split(',')]
|
|
||||||
|
|
||||||
# 检查文件是否存在
|
|
||||||
for path in file_paths:
|
|
||||||
if not os.path.exists(path):
|
|
||||||
logger.error(f"输入文件不存在: {path}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
result = order_service.merge_orders(file_paths)
|
|
||||||
else:
|
|
||||||
# 获取所有采购单文件
|
|
||||||
file_paths = order_service.get_purchase_orders()
|
|
||||||
if not file_paths:
|
|
||||||
logger.warning("未找到采购单文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.info(f"合并 {len(file_paths)} 个采购单文件")
|
|
||||||
result = order_service.merge_orders()
|
|
||||||
|
|
||||||
if result:
|
|
||||||
logger.info(f"合并成功,输出文件: {result}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error("合并失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def list_purchase_orders(order_service: OrderService) -> bool:
|
|
||||||
"""
|
|
||||||
列出采购单文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
order_service: 订单服务
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
是否有采购单文件
|
|
||||||
"""
|
|
||||||
files = order_service.get_purchase_orders()
|
|
||||||
|
|
||||||
if not files:
|
|
||||||
logger.info("未找到采购单文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.info(f"采购单文件 ({len(files)}):")
|
|
||||||
for file in files:
|
|
||||||
logger.info(f" {file}")
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main(args: Optional[List[str]] = None) -> int:
|
|
||||||
"""
|
|
||||||
订单合并命令行主函数
|
|
||||||
|
|
||||||
Args:
|
|
||||||
args: 命令行参数,如果为None则使用sys.argv
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
退出状态码
|
|
||||||
"""
|
|
||||||
parser = create_parser()
|
|
||||||
parsed_args = parser.parse_args(args)
|
|
||||||
|
|
||||||
if parsed_args.command is None:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 创建配置管理器
|
|
||||||
config = ConfigManager(parsed_args.config) if parsed_args.config else ConfigManager()
|
|
||||||
|
|
||||||
# 创建订单服务
|
|
||||||
order_service = OrderService(config)
|
|
||||||
|
|
||||||
# 根据命令执行不同功能
|
|
||||||
if parsed_args.command == 'merge':
|
|
||||||
success = merge_orders(order_service, parsed_args.input)
|
|
||||||
elif parsed_args.command == 'list':
|
|
||||||
success = list_purchase_orders(order_service)
|
|
||||||
else:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0 if success else 1
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"执行过程中发生错误: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# 关闭日志
|
|
||||||
close_logger(__name__)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
||||||
@ -1,164 +0,0 @@
|
|||||||
"""
|
|
||||||
OCR命令行工具
|
|
||||||
----------
|
|
||||||
提供OCR识别相关的命令行接口。
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from ..config.settings import ConfigManager
|
|
||||||
from ..core.utils.log_utils import get_logger, close_logger
|
|
||||||
from ..services.ocr_service import OCRService
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
def create_parser() -> argparse.ArgumentParser:
|
|
||||||
"""
|
|
||||||
创建命令行参数解析器
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
参数解析器
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser(description='OCR识别工具')
|
|
||||||
|
|
||||||
# 通用选项
|
|
||||||
parser.add_argument('--config', type=str, help='配置文件路径')
|
|
||||||
|
|
||||||
# 子命令
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='子命令')
|
|
||||||
|
|
||||||
# 单文件处理命令
|
|
||||||
process_parser = subparsers.add_parser('process', help='处理单个文件')
|
|
||||||
process_parser.add_argument('--input', type=str, required=True, help='输入图片文件路径')
|
|
||||||
|
|
||||||
# 批量处理命令
|
|
||||||
batch_parser = subparsers.add_parser('batch', help='批量处理文件')
|
|
||||||
batch_parser.add_argument('--batch-size', type=int, help='批处理大小')
|
|
||||||
batch_parser.add_argument('--max-workers', type=int, help='最大线程数')
|
|
||||||
|
|
||||||
# 查看未处理文件命令
|
|
||||||
list_parser = subparsers.add_parser('list', help='列出未处理的文件')
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def process_file(ocr_service: OCRService, input_file: str) -> bool:
|
|
||||||
"""
|
|
||||||
处理单个文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ocr_service: OCR服务
|
|
||||||
input_file: 输入文件路径
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
处理是否成功
|
|
||||||
"""
|
|
||||||
if not os.path.exists(input_file):
|
|
||||||
logger.error(f"输入文件不存在: {input_file}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not ocr_service.validate_image(input_file):
|
|
||||||
logger.error(f"输入文件无效: {input_file}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
result = ocr_service.process_image(input_file)
|
|
||||||
|
|
||||||
if result:
|
|
||||||
logger.info(f"处理成功,输出文件: {result}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error("处理失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def process_batch(ocr_service: OCRService, batch_size: Optional[int] = None, max_workers: Optional[int] = None) -> bool:
|
|
||||||
"""
|
|
||||||
批量处理文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ocr_service: OCR服务
|
|
||||||
batch_size: 批处理大小
|
|
||||||
max_workers: 最大线程数
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
处理是否成功
|
|
||||||
"""
|
|
||||||
total, success = ocr_service.process_images_batch(batch_size, max_workers)
|
|
||||||
|
|
||||||
if total == 0:
|
|
||||||
logger.warning("没有找到需要处理的文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.info(f"批量处理完成,总计: {total},成功: {success}")
|
|
||||||
return success > 0
|
|
||||||
|
|
||||||
def list_unprocessed(ocr_service: OCRService) -> bool:
|
|
||||||
"""
|
|
||||||
列出未处理的文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ocr_service: OCR服务
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
是否有未处理的文件
|
|
||||||
"""
|
|
||||||
files = ocr_service.get_unprocessed_images()
|
|
||||||
|
|
||||||
if not files:
|
|
||||||
logger.info("没有未处理的文件")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.info(f"未处理的文件 ({len(files)}):")
|
|
||||||
for file in files:
|
|
||||||
logger.info(f" {file}")
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main(args: Optional[List[str]] = None) -> int:
|
|
||||||
"""
|
|
||||||
OCR命令行主函数
|
|
||||||
|
|
||||||
Args:
|
|
||||||
args: 命令行参数,如果为None则使用sys.argv
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
退出状态码
|
|
||||||
"""
|
|
||||||
parser = create_parser()
|
|
||||||
parsed_args = parser.parse_args(args)
|
|
||||||
|
|
||||||
if parsed_args.command is None:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 创建配置管理器
|
|
||||||
config = ConfigManager(parsed_args.config) if parsed_args.config else ConfigManager()
|
|
||||||
|
|
||||||
# 创建OCR服务
|
|
||||||
ocr_service = OCRService(config)
|
|
||||||
|
|
||||||
# 根据命令执行不同功能
|
|
||||||
if parsed_args.command == 'process':
|
|
||||||
success = process_file(ocr_service, parsed_args.input)
|
|
||||||
elif parsed_args.command == 'batch':
|
|
||||||
success = process_batch(ocr_service, parsed_args.batch_size, parsed_args.max_workers)
|
|
||||||
elif parsed_args.command == 'list':
|
|
||||||
success = list_unprocessed(ocr_service)
|
|
||||||
else:
|
|
||||||
parser.print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0 if success else 1
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"执行过程中发生错误: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# 关闭日志
|
|
||||||
close_logger(__name__)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
||||||
@ -117,25 +117,29 @@ class ConfigManager:
|
|||||||
获取路径配置并确保它是一个有效的绝对路径
|
获取路径配置并确保它是一个有效的绝对路径
|
||||||
如果create为True,则自动创建该目录
|
如果create为True,则自动创建该目录
|
||||||
"""
|
"""
|
||||||
path = self.get(section, option, fallback)
|
from pathlib import Path
|
||||||
|
path_str = self.get(section, option, fallback)
|
||||||
|
path = Path(path_str)
|
||||||
|
|
||||||
if not os.path.isabs(path):
|
if not path.is_absolute():
|
||||||
# 相对路径,转为绝对路径
|
# 相对路径,转为绝对路径(相对于项目根目录)
|
||||||
path = os.path.abspath(path)
|
path = Path(os.getcwd()) / path
|
||||||
|
|
||||||
if create and not os.path.exists(path):
|
if create:
|
||||||
try:
|
try:
|
||||||
# 如果是文件路径,创建其父目录
|
# 智能判断是文件还是目录
|
||||||
if '.' in os.path.basename(path):
|
# 如果有后缀名则认为是文件,创建其父目录
|
||||||
directory = os.path.dirname(path)
|
if path.suffix:
|
||||||
if directory and not os.path.exists(directory):
|
directory = path.parent
|
||||||
os.makedirs(directory, exist_ok=True)
|
if not directory.exists():
|
||||||
logger.info(f"已创建目录: {directory}")
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
logger.info(f"已创建父目录: {directory}")
|
||||||
else:
|
else:
|
||||||
# 否则认为是目录路径
|
# 否则认为是目录路径
|
||||||
os.makedirs(path, exist_ok=True)
|
if not path.exists():
|
||||||
logger.info(f"已创建目录: {path}")
|
path.mkdir(parents=True, exist_ok=True)
|
||||||
|
logger.info(f"已创建目录: {path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"创建目录失败: {path}, 错误: {e}")
|
logger.error(f"创建目录失败: {path}, 错误: {e}")
|
||||||
|
|
||||||
return path
|
return str(path.absolute())
|
||||||
@ -285,6 +285,16 @@ class UnitConverter:
|
|||||||
|
|
||||||
logger.debug(f"解析规格: {spec}")
|
logger.debug(f"解析规格: {spec}")
|
||||||
|
|
||||||
|
# 新增:处理“1件=12桶/袋/盒...”等等式规格,统一为1*12
|
||||||
|
eq_match = re.match(r'(\d+(?:\.\d+)?)\s*(?:件|箱|提|盒)\s*[==]\s*(\d+)\s*(?:瓶|桶|盒|支|个|袋|罐|包|卷)', spec)
|
||||||
|
if eq_match:
|
||||||
|
try:
|
||||||
|
level2 = int(eq_match.group(2))
|
||||||
|
logger.info(f"解析等式规格: {spec} -> 1*{level2}")
|
||||||
|
return 1, level2, None
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
# 处理三级包装,如1*5*12
|
# 处理三级包装,如1*5*12
|
||||||
three_level_match = re.match(r'(\d+)[*](\d+)[*](\d+)', spec)
|
three_level_match = re.match(r'(\d+)[*](\d+)[*](\d+)', spec)
|
||||||
if three_level_match:
|
if three_level_match:
|
||||||
@ -522,4 +532,4 @@ class UnitConverter:
|
|||||||
更新是否成功
|
更新是否成功
|
||||||
"""
|
"""
|
||||||
self.special_barcodes = new_mappings
|
self.special_barcodes = new_mappings
|
||||||
return self.save_barcode_mappings(new_mappings)
|
return self.save_barcode_mappings(new_mappings)
|
||||||
|
|||||||
@ -63,8 +63,9 @@ class JianUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = product.get('unit', '')
|
unit = str(product.get('unit', '')).strip()
|
||||||
return unit == '件'
|
# 匹配"件"、"件、"、"件装"等
|
||||||
|
return unit == '件' or unit.startswith('件')
|
||||||
|
|
||||||
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
@ -117,8 +118,9 @@ class BoxUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = product.get('unit', '')
|
unit = str(product.get('unit', '')).strip()
|
||||||
return unit == '箱'
|
# 匹配"箱"、"箱、"、"箱装"等
|
||||||
|
return unit == '箱' or unit.startswith('箱')
|
||||||
|
|
||||||
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
@ -171,8 +173,8 @@ class TiHeUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = product.get('unit', '')
|
unit = str(product.get('unit', '')).strip()
|
||||||
return unit in ['提', '盒']
|
return unit in ['提', '盒'] or unit.startswith('提') or unit.startswith('盒')
|
||||||
|
|
||||||
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import numpy as np
|
|||||||
import xlrd
|
import xlrd
|
||||||
import xlwt
|
import xlwt
|
||||||
from xlutils.copy import copy as xlcopy
|
from xlutils.copy import copy as xlcopy
|
||||||
from typing import Dict, List, Optional, Tuple, Union, Any
|
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ...config.settings import ConfigManager
|
from ...config.settings import ConfigManager
|
||||||
@ -414,7 +414,7 @@ class PurchaseOrderMerger:
|
|||||||
logger.error(f"创建合并采购单时出错: {e}")
|
logger.error(f"创建合并采购单时出错: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process(self, file_paths: Optional[List[str]] = None) -> Optional[str]:
|
def process(self, file_paths: Optional[List[str]] = None, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理采购单合并
|
处理采购单合并
|
||||||
|
|
||||||
@ -427,6 +427,11 @@ class PurchaseOrderMerger:
|
|||||||
# 如果未指定文件路径,则获取所有采购单文件
|
# 如果未指定文件路径,则获取所有采购单文件
|
||||||
if file_paths is None:
|
if file_paths is None:
|
||||||
file_paths = self.get_purchase_orders()
|
file_paths = self.get_purchase_orders()
|
||||||
|
try:
|
||||||
|
if progress_cb:
|
||||||
|
progress_cb(97)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 检查是否有文件需要合并
|
# 检查是否有文件需要合并
|
||||||
if not file_paths:
|
if not file_paths:
|
||||||
@ -438,16 +443,26 @@ class PurchaseOrderMerger:
|
|||||||
if merged_df is None:
|
if merged_df is None:
|
||||||
logger.error("合并采购单失败")
|
logger.error("合并采购单失败")
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
|
if progress_cb:
|
||||||
|
progress_cb(98)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 创建合并的采购单文件
|
# 创建合并的采购单文件
|
||||||
output_file = self.create_merged_purchase_order(merged_df)
|
output_file = self.create_merged_purchase_order(merged_df)
|
||||||
if output_file is None:
|
if output_file is None:
|
||||||
logger.error("创建合并采购单文件失败")
|
logger.error("创建合并采购单文件失败")
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
|
if progress_cb:
|
||||||
|
progress_cb(100)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 记录已合并文件
|
# 记录已合并文件
|
||||||
for file_path in file_paths:
|
for file_path in file_paths:
|
||||||
self.merged_files[file_path] = output_file
|
self.merged_files[file_path] = output_file
|
||||||
self._save_merged_files()
|
self._save_merged_files()
|
||||||
|
|
||||||
return output_file
|
return output_file
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import numpy as np
|
|||||||
import xlrd
|
import xlrd
|
||||||
import xlwt
|
import xlwt
|
||||||
from xlutils.copy import copy as xlcopy
|
from xlutils.copy import copy as xlcopy
|
||||||
from typing import Dict, List, Optional, Tuple, Union, Any
|
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ...config.settings import ConfigManager
|
from ...config.settings import ConfigManager
|
||||||
@ -253,6 +253,20 @@ class ExcelProcessor:
|
|||||||
# 跳过空条码行
|
# 跳过空条码行
|
||||||
if not product['barcode']:
|
if not product['barcode']:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# 检查备注列,过滤换货、退货、作废等非采购行
|
||||||
|
skip_row = False
|
||||||
|
for col in df.columns:
|
||||||
|
col_str = str(col)
|
||||||
|
if any(k in col_str for k in ['备注', '说明', '类型', '备注1']):
|
||||||
|
val = str(row[col]).strip()
|
||||||
|
# 过滤常见的非采购关键字
|
||||||
|
if any(k in val for k in ['换货', '退货', '作废', '减钱', '冲减', '赠品单', '补货']):
|
||||||
|
logger.info(f"过滤非采购行: {product['barcode']} - {product.get('name', '')}, 原因: {col_str}包含 '{val}'")
|
||||||
|
skip_row = True
|
||||||
|
break
|
||||||
|
if skip_row:
|
||||||
|
continue
|
||||||
|
|
||||||
# 提取商品名称
|
# 提取商品名称
|
||||||
if '商品名称' in df.columns and not pd.isna(row['商品名称']):
|
if '商品名称' in df.columns and not pd.isna(row['商品名称']):
|
||||||
@ -281,6 +295,36 @@ class ExcelProcessor:
|
|||||||
product['amount'] = row['小计']
|
product['amount'] = row['小计']
|
||||||
elif column_mapping.get('amount') and not pd.isna(row[column_mapping['amount']]):
|
elif column_mapping.get('amount') and not pd.isna(row[column_mapping['amount']]):
|
||||||
product['amount'] = row[column_mapping['amount']]
|
product['amount'] = row[column_mapping['amount']]
|
||||||
|
# 根据金额判断赠品:金额为0、为空、或为o/O
|
||||||
|
amt = product.get('amount', None)
|
||||||
|
try:
|
||||||
|
is_amt_gift = False
|
||||||
|
if amt is None:
|
||||||
|
is_amt_gift = True
|
||||||
|
elif isinstance(amt, str):
|
||||||
|
s = amt.strip()
|
||||||
|
if s == '' or s.lower() == 'o' or s == '0' or s == '○':
|
||||||
|
is_amt_gift = True
|
||||||
|
else:
|
||||||
|
amt_clean = re.sub(r'[^\d\.,]', '', s)
|
||||||
|
if ',' in amt_clean and '.' not in amt_clean:
|
||||||
|
amt_clean = amt_clean.replace(',', '.')
|
||||||
|
elif ',' in amt_clean and '.' in amt_clean:
|
||||||
|
amt_clean = amt_clean.replace(',', '')
|
||||||
|
if amt_clean:
|
||||||
|
try:
|
||||||
|
is_amt_gift = float(amt_clean) == 0.0
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
is_amt_gift = float(amt) == 0.0
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
pass
|
||||||
|
if is_amt_gift:
|
||||||
|
product['is_gift'] = True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 提取数量
|
# 提取数量
|
||||||
if '数量' in df.columns and not pd.isna(row['数量']):
|
if '数量' in df.columns and not pd.isna(row['数量']):
|
||||||
@ -472,7 +516,7 @@ class ExcelProcessor:
|
|||||||
logger.warning(f"通过金额和单价计算数量失败: {e}")
|
logger.warning(f"通过金额和单价计算数量失败: {e}")
|
||||||
|
|
||||||
# 判断是否为赠品(价格为0)
|
# 判断是否为赠品(价格为0)
|
||||||
is_gift = price == 0
|
is_gift = bool(product.get('is_gift', False)) or (price == 0)
|
||||||
|
|
||||||
logger.info(f"处理商品: 条码={barcode}, 数量={quantity}, 单价={price}, 是否赠品={is_gift}")
|
logger.info(f"处理商品: 条码={barcode}, 数量={quantity}, 单价={price}, 是否赠品={is_gift}")
|
||||||
|
|
||||||
@ -575,17 +619,16 @@ class ExcelProcessor:
|
|||||||
Returns:
|
Returns:
|
||||||
表头行索引,如果未找到则返回None
|
表头行索引,如果未找到则返回None
|
||||||
"""
|
"""
|
||||||
# 定义可能的表头关键词
|
|
||||||
header_keywords = [
|
header_keywords = [
|
||||||
'条码', '条形码', '商品条码', '商品名称', '名称', '数量', '单位', '单价',
|
'条码', '条形码', '商品条码', '商品名称', '名称', '数量', '单位', '单价',
|
||||||
'规格', '商品编码', '采购数量', '采购单位', '商品', '品名'
|
'规格', '商品编码', '采购数量', '采购单位', '商品', '品名',
|
||||||
|
'金额', '小计', '总计', '合计', '合计金额'
|
||||||
]
|
]
|
||||||
|
|
||||||
# 存储每行的匹配分数
|
# 存储每行的匹配分数
|
||||||
row_scores = []
|
row_scores = []
|
||||||
|
|
||||||
# 遍历前10行(通常表头不会太靠后)
|
max_rows_to_check = min(30, len(df))
|
||||||
max_rows_to_check = min(10, len(df))
|
|
||||||
for row in range(max_rows_to_check):
|
for row in range(max_rows_to_check):
|
||||||
row_data = df.iloc[row]
|
row_data = df.iloc[row]
|
||||||
score = 0
|
score = 0
|
||||||
@ -631,7 +674,7 @@ class ExcelProcessor:
|
|||||||
logger.warning("无法识别表头行")
|
logger.warning("无法识别表头行")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_specific_file(self, file_path: str) -> Optional[str]:
|
def process_specific_file(self, file_path: str, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理指定的Excel文件
|
处理指定的Excel文件
|
||||||
|
|
||||||
@ -649,6 +692,11 @@ class ExcelProcessor:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 读取Excel文件时不立即指定表头
|
# 读取Excel文件时不立即指定表头
|
||||||
|
if progress_cb:
|
||||||
|
try:
|
||||||
|
progress_cb(92)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
df = pd.read_excel(file_path, header=None)
|
df = pd.read_excel(file_path, header=None)
|
||||||
logger.info(f"成功读取Excel文件: {file_path}, 共 {len(df)} 行")
|
logger.info(f"成功读取Excel文件: {file_path}, 共 {len(df)} 行")
|
||||||
|
|
||||||
@ -660,11 +708,25 @@ class ExcelProcessor:
|
|||||||
|
|
||||||
logger.info(f"识别到表头在第 {header_row+1} 行")
|
logger.info(f"识别到表头在第 {header_row+1} 行")
|
||||||
|
|
||||||
# 重新读取Excel,正确指定表头行
|
# 重新设置表头,避免二次读取
|
||||||
df = pd.read_excel(file_path, header=header_row)
|
if progress_cb:
|
||||||
logger.info(f"使用表头行重新读取数据,共 {len(df)} 行有效数据")
|
try:
|
||||||
|
progress_cb(94)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 使用识别到的表头行设置列名,并过滤掉表头之前的行
|
||||||
|
df.columns = df.iloc[header_row]
|
||||||
|
df = df.iloc[header_row + 1:].reset_index(drop=True)
|
||||||
|
|
||||||
|
logger.info(f"重新整理数据结构,共 {len(df)} 行有效数据")
|
||||||
|
|
||||||
# 提取商品信息
|
# 提取商品信息
|
||||||
|
if progress_cb:
|
||||||
|
try:
|
||||||
|
progress_cb(96)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
products = self.extract_product_info(df)
|
products = self.extract_product_info(df)
|
||||||
|
|
||||||
if not products:
|
if not products:
|
||||||
@ -685,6 +747,11 @@ class ExcelProcessor:
|
|||||||
|
|
||||||
# 不再自动打开输出目录
|
# 不再自动打开输出目录
|
||||||
logger.info(f"采购单已保存到: {output_file}")
|
logger.info(f"采购单已保存到: {output_file}")
|
||||||
|
if progress_cb:
|
||||||
|
try:
|
||||||
|
progress_cb(100)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
return output_file
|
return output_file
|
||||||
|
|
||||||
@ -694,7 +761,7 @@ class ExcelProcessor:
|
|||||||
logger.error(f"处理Excel文件时出错: {file_path}, 错误: {e}")
|
logger.error(f"处理Excel文件时出错: {file_path}, 错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_latest_file(self) -> Optional[str]:
|
def process_latest_file(self, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理最新的Excel文件
|
处理最新的Excel文件
|
||||||
|
|
||||||
@ -708,7 +775,7 @@ class ExcelProcessor:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# 处理文件
|
# 处理文件
|
||||||
return self.process_specific_file(latest_file)
|
return self.process_specific_file(latest_file, progress_cb=progress_cb)
|
||||||
|
|
||||||
def _detect_column_mapping(self, df: pd.DataFrame) -> Dict[str, str]:
|
def _detect_column_mapping(self, df: pd.DataFrame) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
@ -889,6 +956,11 @@ class ExcelProcessor:
|
|||||||
|
|
||||||
logger.debug(f"清理后的规格字符串: {spec_str}")
|
logger.debug(f"清理后的规格字符串: {spec_str}")
|
||||||
|
|
||||||
|
# 新增:匹配“1件=12桶/袋/盒…”等等式规格,取右侧数量作为包装数量
|
||||||
|
eq_match = re.search(r'(\d+(?:\.\d+)?)\s*(?:件|箱|提|盒)\s*[==]\s*(\d+)\s*(?:瓶|桶|盒|支|个|袋|罐|包|卷)', spec_str)
|
||||||
|
if eq_match:
|
||||||
|
return int(eq_match.group(2))
|
||||||
|
|
||||||
# 匹配带单位的格式,如"5kg*6"、"450g*15"、"450ml*15"
|
# 匹配带单位的格式,如"5kg*6"、"450g*15"、"450ml*15"
|
||||||
weight_pattern = r'(\d+(?:\.\d+)?)\s*(?:kg|KG|千克|公斤)[*×](\d+)'
|
weight_pattern = r'(\d+(?:\.\d+)?)\s*(?:kg|KG|千克|公斤)[*×](\d+)'
|
||||||
match = re.search(weight_pattern, spec_str)
|
match = re.search(weight_pattern, spec_str)
|
||||||
@ -946,4 +1018,4 @@ class ExcelProcessor:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"解析规格'{spec_str}'时出错: {e}")
|
logger.warning(f"解析规格'{spec_str}'时出错: {e}")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -1,355 +0,0 @@
|
|||||||
"""
|
|
||||||
单位转换器测试模块
|
|
||||||
---------------
|
|
||||||
测试单位转换和条码映射逻辑
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
from typing import Dict, Any
|
|
||||||
|
|
||||||
# 添加项目根目录到Python路径
|
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..')))
|
|
||||||
|
|
||||||
from app.core.excel.converter import UnitConverter
|
|
||||||
from app.core.excel.validators import ProductValidator
|
|
||||||
|
|
||||||
|
|
||||||
class TestUnitConverter(unittest.TestCase):
|
|
||||||
"""
|
|
||||||
测试单位转换器功能
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
"""
|
|
||||||
测试前的准备工作
|
|
||||||
"""
|
|
||||||
self.converter = UnitConverter()
|
|
||||||
|
|
||||||
def test_jian_unit_conversion(self):
|
|
||||||
"""
|
|
||||||
测试"件"单位的转换
|
|
||||||
"""
|
|
||||||
# 准备测试数据
|
|
||||||
product = {
|
|
||||||
'barcode': '6954767400129',
|
|
||||||
'name': '美汁源果粒橙1.8L*8瓶',
|
|
||||||
'specification': '1.8L*8',
|
|
||||||
'quantity': 1.0,
|
|
||||||
'unit': '件',
|
|
||||||
'price': 65.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果
|
|
||||||
self.assertEqual(result['quantity'], 8.0)
|
|
||||||
self.assertEqual(result['price'], 8.125)
|
|
||||||
self.assertEqual(result['unit'], '瓶')
|
|
||||||
|
|
||||||
def test_box_unit_conversion(self):
|
|
||||||
"""
|
|
||||||
测试"箱"单位的转换
|
|
||||||
"""
|
|
||||||
# 准备测试数据
|
|
||||||
product = {
|
|
||||||
'barcode': '6925303721244',
|
|
||||||
'name': '统一鲜橙多2L*6瓶',
|
|
||||||
'specification': '2L*6',
|
|
||||||
'quantity': 1.0,
|
|
||||||
'unit': '箱',
|
|
||||||
'price': 43.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果
|
|
||||||
self.assertEqual(result['quantity'], 6.0)
|
|
||||||
self.assertEqual(result['price'], 7.1666666666666667)
|
|
||||||
self.assertEqual(result['unit'], '瓶')
|
|
||||||
|
|
||||||
def test_tihe_unit_conversion_level3(self):
|
|
||||||
"""
|
|
||||||
测试"提"单位的转换(三级规格)
|
|
||||||
"""
|
|
||||||
# 准备测试数据(三级规格:1*6*4,表示1排6提,每提4瓶)
|
|
||||||
product = {
|
|
||||||
'barcode': '6921168509347',
|
|
||||||
'name': '农夫山泉550ml*24瓶',
|
|
||||||
'specification': '1*6*4',
|
|
||||||
'quantity': 2.0,
|
|
||||||
'unit': '提',
|
|
||||||
'price': 16.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果:三级规格,提单位特殊处理,数量*最后一级
|
|
||||||
self.assertEqual(result['quantity'], 8.0) # 2提 * 4瓶/提
|
|
||||||
self.assertEqual(result['price'], 4.0) # 16元/提 ÷ 4瓶/提
|
|
||||||
self.assertEqual(result['unit'], '瓶')
|
|
||||||
|
|
||||||
def test_tihe_unit_conversion_level2(self):
|
|
||||||
"""
|
|
||||||
测试"提"单位的转换(二级规格)
|
|
||||||
"""
|
|
||||||
# 准备测试数据(二级规格:1*4,表示每件4提)
|
|
||||||
product = {
|
|
||||||
'barcode': '6921168509347',
|
|
||||||
'name': '农夫山泉550ml*4瓶',
|
|
||||||
'specification': '1*4',
|
|
||||||
'quantity': 5.0,
|
|
||||||
'unit': '提',
|
|
||||||
'price': 10.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果:二级规格,提单位保持不变
|
|
||||||
self.assertEqual(result['quantity'], 5.0)
|
|
||||||
self.assertEqual(result['price'], 10.0)
|
|
||||||
self.assertEqual(result['unit'], '提')
|
|
||||||
|
|
||||||
def test_barcode_mapping(self):
|
|
||||||
"""
|
|
||||||
测试条码映射
|
|
||||||
"""
|
|
||||||
# 准备测试数据(使用需要被映射的条码)
|
|
||||||
product = {
|
|
||||||
'barcode': '6920584471055', # 这个条码应映射到6920584471017
|
|
||||||
'name': '测试映射条码商品',
|
|
||||||
'specification': '1*12',
|
|
||||||
'quantity': 1.0,
|
|
||||||
'unit': '件',
|
|
||||||
'price': 60.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果:条码应该被映射
|
|
||||||
self.assertEqual(result['barcode'], '6920584471017')
|
|
||||||
self.assertEqual(result['quantity'], 12.0) # 同时处理件单位转换
|
|
||||||
self.assertEqual(result['price'], 5.0) # 60元/件 ÷ 12瓶/件
|
|
||||||
self.assertEqual(result['unit'], '瓶')
|
|
||||||
|
|
||||||
def test_special_barcode_multiplier(self):
|
|
||||||
"""
|
|
||||||
测试特殊条码的倍数处理
|
|
||||||
"""
|
|
||||||
# 准备测试数据(使用特殊条码)
|
|
||||||
product = {
|
|
||||||
'barcode': '6925019900087', # 特殊条码:数量*10,单位转瓶
|
|
||||||
'name': '特殊条码商品',
|
|
||||||
'specification': '1*10',
|
|
||||||
'quantity': 2.0,
|
|
||||||
'unit': '箱',
|
|
||||||
'price': 100.0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行转换
|
|
||||||
result = self.converter.process_unit_conversion(product)
|
|
||||||
|
|
||||||
# 验证结果:特殊条码乘数应该生效
|
|
||||||
self.assertEqual(result['quantity'], 20.0) # 2箱 * 10倍数
|
|
||||||
self.assertEqual(result['price'], 5.0) # 100元/箱 ÷ 10倍数/箱
|
|
||||||
self.assertEqual(result['unit'], '瓶')
|
|
||||||
|
|
||||||
|
|
||||||
class TestProductValidator(unittest.TestCase):
|
|
||||||
"""
|
|
||||||
测试商品数据验证器功能
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
"""
|
|
||||||
测试前的准备工作
|
|
||||||
"""
|
|
||||||
self.validator = ProductValidator()
|
|
||||||
|
|
||||||
def test_validate_barcode(self):
|
|
||||||
"""
|
|
||||||
测试条码验证
|
|
||||||
"""
|
|
||||||
# 测试有效条码
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode('6925303721244')
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(barcode, '6925303721244')
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试包含非数字字符的条码
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode('6925303-721244')
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(barcode, '6925303721244')
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试5开头的条码修正
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode('5925303721244')
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(barcode, '6925303721244')
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试过短的条码
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode('12345')
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(barcode, '12345')
|
|
||||||
self.assertIn("条码长度异常", error)
|
|
||||||
|
|
||||||
# 测试仓库标识
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode('仓库')
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(barcode, '仓库')
|
|
||||||
self.assertEqual(error, "条码为仓库标识")
|
|
||||||
|
|
||||||
# 测试空值
|
|
||||||
is_valid, barcode, error = self.validator.validate_barcode(None)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(barcode, "")
|
|
||||||
self.assertEqual(error, "条码为空")
|
|
||||||
|
|
||||||
def test_validate_quantity(self):
|
|
||||||
"""
|
|
||||||
测试数量验证
|
|
||||||
"""
|
|
||||||
# 测试有效数量
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity(10)
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(quantity, 10.0)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试字符串数量
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity("25.5")
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(quantity, 25.5)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试带单位的数量
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity("30瓶")
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(quantity, 30.0)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试零数量
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity(0)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(quantity, 0.0)
|
|
||||||
self.assertIn("数量必须大于0", error)
|
|
||||||
|
|
||||||
# 测试负数量
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity(-5)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(quantity, 0.0)
|
|
||||||
self.assertIn("数量必须大于0", error)
|
|
||||||
|
|
||||||
# 测试非数字
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity("abc")
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(quantity, 0.0)
|
|
||||||
self.assertIn("数量不包含数字", error)
|
|
||||||
|
|
||||||
# 测试空值
|
|
||||||
is_valid, quantity, error = self.validator.validate_quantity(None)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(quantity, 0.0)
|
|
||||||
self.assertEqual(error, "数量为空")
|
|
||||||
|
|
||||||
def test_validate_price(self):
|
|
||||||
"""
|
|
||||||
测试单价验证
|
|
||||||
"""
|
|
||||||
# 测试有效单价
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price(12.5)
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(price, 12.5)
|
|
||||||
self.assertFalse(is_gift)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试字符串单价
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price("8.0")
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(price, 8.0)
|
|
||||||
self.assertFalse(is_gift)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试零单价(赠品)
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price(0)
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(price, 0.0)
|
|
||||||
self.assertTrue(is_gift)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试"赠品"标记
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price("赠品")
|
|
||||||
self.assertTrue(is_valid)
|
|
||||||
self.assertEqual(price, 0.0)
|
|
||||||
self.assertTrue(is_gift)
|
|
||||||
self.assertIsNone(error)
|
|
||||||
|
|
||||||
# 测试负单价
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price(-5)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(price, 0.0)
|
|
||||||
self.assertTrue(is_gift)
|
|
||||||
self.assertIn("单价不能为负数", error)
|
|
||||||
|
|
||||||
# 测试空值
|
|
||||||
is_valid, price, is_gift, error = self.validator.validate_price(None)
|
|
||||||
self.assertFalse(is_valid)
|
|
||||||
self.assertEqual(price, 0.0)
|
|
||||||
self.assertTrue(is_gift)
|
|
||||||
self.assertEqual(error, "单价为空,视为赠品")
|
|
||||||
|
|
||||||
def test_validate_product(self):
|
|
||||||
"""
|
|
||||||
测试商品数据验证
|
|
||||||
"""
|
|
||||||
# 准备测试数据(有效商品)
|
|
||||||
product = {
|
|
||||||
'barcode': '6954767400129',
|
|
||||||
'name': '测试商品',
|
|
||||||
'specification': '1*12',
|
|
||||||
'quantity': 3.0,
|
|
||||||
'price': 36.0,
|
|
||||||
'unit': '件',
|
|
||||||
'is_gift': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证有效商品
|
|
||||||
result = self.validator.validate_product(product)
|
|
||||||
self.assertEqual(result['barcode'], '6954767400129')
|
|
||||||
self.assertEqual(result['quantity'], 3.0)
|
|
||||||
self.assertEqual(result['price'], 36.0)
|
|
||||||
self.assertFalse(result['is_gift'])
|
|
||||||
|
|
||||||
# 验证赠品商品
|
|
||||||
gift_product = product.copy()
|
|
||||||
gift_product['price'] = 0
|
|
||||||
result = self.validator.validate_product(gift_product)
|
|
||||||
self.assertEqual(result['price'], 0.0)
|
|
||||||
self.assertTrue(result['is_gift'])
|
|
||||||
|
|
||||||
# 验证需要修复的商品
|
|
||||||
invalid_product = {
|
|
||||||
'barcode': '5954767-400129', # 需要修复前缀和移除非数字
|
|
||||||
'name': '测试商品',
|
|
||||||
'specification': '1*12',
|
|
||||||
'quantity': '2件', # 需要提取数字
|
|
||||||
'price': '赠品', # 赠品标记
|
|
||||||
'unit': '件',
|
|
||||||
'is_gift': False
|
|
||||||
}
|
|
||||||
|
|
||||||
result = self.validator.validate_product(invalid_product)
|
|
||||||
self.assertEqual(result['barcode'], '6954767400129') # 5->6,移除 '-'
|
|
||||||
self.assertEqual(result['quantity'], 2.0) # 提取数字
|
|
||||||
self.assertEqual(result['price'], 0.0) # 赠品价格为0
|
|
||||||
self.assertTrue(result['is_gift']) # 标记为赠品
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@ -225,6 +225,36 @@ class ProductValidator:
|
|||||||
validated_product['is_gift'] = True
|
validated_product['is_gift'] = True
|
||||||
if error_msg:
|
if error_msg:
|
||||||
logger.info(error_msg)
|
logger.info(error_msg)
|
||||||
|
|
||||||
|
amount = product.get('amount', None)
|
||||||
|
try:
|
||||||
|
is_amount_gift = False
|
||||||
|
if amount is None:
|
||||||
|
is_amount_gift = True
|
||||||
|
elif isinstance(amount, str):
|
||||||
|
s = amount.strip()
|
||||||
|
if s == '' or s.lower() == 'o' or s == '0':
|
||||||
|
is_amount_gift = True
|
||||||
|
else:
|
||||||
|
amt_clean = re.sub(r'[^\d\.,]', '', s)
|
||||||
|
if ',' in amt_clean and '.' not in amt_clean:
|
||||||
|
amt_clean = amt_clean.replace(',', '.')
|
||||||
|
elif ',' in amt_clean and '.' in amt_clean:
|
||||||
|
amt_clean = amt_clean.replace(',', '')
|
||||||
|
if amt_clean:
|
||||||
|
try:
|
||||||
|
is_amount_gift = float(amt_clean) == 0.0
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
is_amount_gift = float(amount) == 0.0
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
pass
|
||||||
|
if is_amount_gift:
|
||||||
|
validated_product['is_gift'] = True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 验证数量
|
# 验证数量
|
||||||
quantity = product.get('quantity', None)
|
quantity = product.get('quantity', None)
|
||||||
@ -268,4 +298,4 @@ class ProductValidator:
|
|||||||
logger.warning(f"数量验证失败: {error_msg}")
|
logger.warning(f"数量验证失败: {error_msg}")
|
||||||
validated_product['quantity'] = 0.0
|
validated_product['quantity'] = 0.0
|
||||||
|
|
||||||
return validated_product
|
return validated_product
|
||||||
9
app/core/handlers/__init__.py
Normal file
9
app/core/handlers/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
"""
|
||||||
|
数据处理handlers模块初始化文件
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .data_cleaner import DataCleaner
|
||||||
|
from .column_mapper import ColumnMapper
|
||||||
|
from .calculator import DataCalculator
|
||||||
|
|
||||||
|
__all__ = ['DataCleaner', 'ColumnMapper', 'DataCalculator']
|
||||||
378
app/core/handlers/calculator.py
Normal file
378
app/core/handlers/calculator.py
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
"""
|
||||||
|
数据计算处理器
|
||||||
|
|
||||||
|
提供各种数据计算功能,如数量计算、价格计算、汇总统计等
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from typing import Dict, Any, Optional, List, Union
|
||||||
|
from ...core.utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DataCalculator:
|
||||||
|
"""数据计算处理器
|
||||||
|
|
||||||
|
提供标准化的数据计算功能,支持各种业务计算规则
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
||||||
|
"""初始化数据计算器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 计算配置
|
||||||
|
"""
|
||||||
|
self.config = config or {}
|
||||||
|
self.calculation_rules = []
|
||||||
|
|
||||||
|
def add_rule(self, rule_type: str, **kwargs):
|
||||||
|
"""添加计算规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
rule_type: 规则类型
|
||||||
|
**kwargs: 规则参数
|
||||||
|
"""
|
||||||
|
rule = {'type': rule_type, **kwargs}
|
||||||
|
self.calculation_rules.append(rule)
|
||||||
|
logger.debug(f"添加计算规则: {rule_type}")
|
||||||
|
|
||||||
|
def calculate(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
"""执行数据计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 输入数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
计算后的数据
|
||||||
|
"""
|
||||||
|
logger.info(f"开始数据计算,原始数据形状: {df.shape}")
|
||||||
|
|
||||||
|
result_df = df.copy()
|
||||||
|
|
||||||
|
for i, rule in enumerate(self.calculation_rules):
|
||||||
|
try:
|
||||||
|
logger.debug(f"执行计算规则 {i+1}/{len(self.calculation_rules)}: {rule['type']}")
|
||||||
|
result_df = self._apply_rule(result_df, rule)
|
||||||
|
logger.debug(f"规则执行完成,数据形状: {result_df.shape}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"计算规则执行失败: {rule}, 错误: {e}")
|
||||||
|
# 继续执行下一个规则,而不是中断整个流程
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.info(f"数据计算完成,最终数据形状: {result_df.shape}")
|
||||||
|
return result_df
|
||||||
|
|
||||||
|
def _apply_rule(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""应用单个计算规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
rule_type = rule.get('type')
|
||||||
|
|
||||||
|
if rule_type == 'multiply':
|
||||||
|
return self._multiply(df, rule)
|
||||||
|
elif rule_type == 'divide':
|
||||||
|
return self._divide(df, rule)
|
||||||
|
elif rule_type == 'add':
|
||||||
|
return self._add(df, rule)
|
||||||
|
elif rule_type == 'subtract':
|
||||||
|
return self._subtract(df, rule)
|
||||||
|
elif rule_type == 'formula':
|
||||||
|
return self._formula(df, rule)
|
||||||
|
elif rule_type == 'round':
|
||||||
|
return self._round(df, rule)
|
||||||
|
elif rule_type == 'sum':
|
||||||
|
return self._sum(df, rule)
|
||||||
|
elif rule_type == 'aggregate':
|
||||||
|
return self._aggregate(df, rule)
|
||||||
|
else:
|
||||||
|
logger.warning(f"未知的计算规则类型: {rule_type}")
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _multiply(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""乘法计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
source_column = rule.get('source_column')
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
factor = rule.get('factor', 1)
|
||||||
|
|
||||||
|
if source_column and target_column:
|
||||||
|
if source_column in df.columns:
|
||||||
|
df[target_column] = df[source_column] * factor
|
||||||
|
logger.debug(f"乘法计算: {source_column} * {factor} -> {target_column}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"源列不存在: {source_column}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _divide(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""除法计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
source_column = rule.get('source_column')
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
divisor = rule.get('divisor', 1)
|
||||||
|
|
||||||
|
if source_column and target_column and divisor != 0:
|
||||||
|
if source_column in df.columns:
|
||||||
|
df[target_column] = df[source_column] / divisor
|
||||||
|
logger.debug(f"除法计算: {source_column} / {divisor} -> {target_column}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"源列不存在: {source_column}")
|
||||||
|
elif divisor == 0:
|
||||||
|
logger.error("除数不能为0")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _add(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""加法计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns', [])
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
constant = rule.get('constant', 0)
|
||||||
|
|
||||||
|
if target_column:
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
if columns:
|
||||||
|
# 列相加
|
||||||
|
valid_columns = [col for col in columns if col in df.columns]
|
||||||
|
if valid_columns:
|
||||||
|
df[target_column] = df[valid_columns].sum(axis=1) + constant
|
||||||
|
logger.debug(f"加法计算: {valid_columns} + {constant} -> {target_column}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"没有有效的列用于加法计算: {columns}")
|
||||||
|
else:
|
||||||
|
# 只加常数
|
||||||
|
if target_column in df.columns:
|
||||||
|
df[target_column] = df[target_column] + constant
|
||||||
|
logger.debug(f"加法计算: {target_column} + {constant}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"目标列不存在: {target_column}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _subtract(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""减法计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
minuend = rule.get('minuend') # 被减数列
|
||||||
|
subtrahend = rule.get('subtrahend') # 减数列
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
constant = rule.get('constant', 0)
|
||||||
|
|
||||||
|
if target_column and minuend and minuend in df.columns:
|
||||||
|
if subtrahend and subtrahend in df.columns:
|
||||||
|
df[target_column] = df[minuend] - df[subtrahend] - constant
|
||||||
|
logger.debug(f"减法计算: {minuend} - {subtrahend} - {constant} -> {target_column}")
|
||||||
|
else:
|
||||||
|
df[target_column] = df[minuend] - constant
|
||||||
|
logger.debug(f"减法计算: {minuend} - {constant} -> {target_column}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"减法计算参数不完整或列不存在")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _formula(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""公式计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
formula = rule.get('formula')
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
|
||||||
|
if formula and target_column:
|
||||||
|
try:
|
||||||
|
df[target_column] = df.eval(formula)
|
||||||
|
logger.debug(f"公式计算: {formula} -> {target_column}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"公式计算失败: {formula}, 错误: {e}")
|
||||||
|
else:
|
||||||
|
logger.warning("公式计算缺少公式或目标列")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _round(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""四舍五入
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns', [])
|
||||||
|
decimals = rule.get('decimals', 0)
|
||||||
|
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
target_columns = columns or df.select_dtypes(include=[np.number]).columns
|
||||||
|
|
||||||
|
for col in target_columns:
|
||||||
|
if col in df.columns and pd.api.types.is_numeric_dtype(df[col]):
|
||||||
|
df[col] = df[col].round(decimals)
|
||||||
|
logger.debug(f"四舍五入: {col} 保留 {decimals} 位小数")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _sum(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""求和计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns', [])
|
||||||
|
target_column = rule.get('target_column')
|
||||||
|
group_by = rule.get('group_by')
|
||||||
|
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
if group_by and group_by in df.columns:
|
||||||
|
# 分组求和
|
||||||
|
if columns:
|
||||||
|
for col in columns:
|
||||||
|
if col in df.columns:
|
||||||
|
sum_result = df.groupby(group_by)[col].sum()
|
||||||
|
logger.debug(f"分组求和: {col} 按 {group_by} 分组")
|
||||||
|
else:
|
||||||
|
# 所有数值列分组求和
|
||||||
|
numeric_columns = df.select_dtypes(include=[np.number]).columns
|
||||||
|
sum_result = df.groupby(group_by)[numeric_columns].sum()
|
||||||
|
logger.debug(f"分组求和: 所有数值列 按 {group_by} 分组")
|
||||||
|
else:
|
||||||
|
# 总体求和
|
||||||
|
if columns:
|
||||||
|
valid_columns = [col for col in columns if col in df.columns]
|
||||||
|
if valid_columns and target_column:
|
||||||
|
df[target_column] = df[valid_columns].sum(axis=1)
|
||||||
|
logger.debug(f"求和计算: {valid_columns} -> {target_column}")
|
||||||
|
else:
|
||||||
|
# 所有数值列求和
|
||||||
|
numeric_columns = df.select_dtypes(include=[np.number]).columns
|
||||||
|
if target_column and len(numeric_columns) > 0:
|
||||||
|
df[target_column] = df[numeric_columns].sum(axis=1)
|
||||||
|
logger.debug(f"求和计算: {list(numeric_columns)} -> {target_column}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _aggregate(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""聚合计算
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
group_by = rule.get('group_by')
|
||||||
|
aggregations = rule.get('aggregations', {})
|
||||||
|
|
||||||
|
if group_by and group_by in df.columns:
|
||||||
|
# 构建聚合函数字典
|
||||||
|
agg_dict = {}
|
||||||
|
for column, func in aggregations.items():
|
||||||
|
if column in df.columns:
|
||||||
|
if isinstance(func, str):
|
||||||
|
agg_dict[column] = func
|
||||||
|
elif isinstance(func, list):
|
||||||
|
agg_dict[column] = func
|
||||||
|
|
||||||
|
if agg_dict:
|
||||||
|
result = df.groupby(group_by).agg(agg_dict)
|
||||||
|
logger.debug(f"聚合计算: 按 {group_by} 分组, 聚合: {agg_dict}")
|
||||||
|
return result.reset_index()
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
# 便捷方法
|
||||||
|
def multiply(self, source_column: str, target_column: str, factor: float):
|
||||||
|
"""乘法计算"""
|
||||||
|
self.add_rule('multiply', source_column=source_column,
|
||||||
|
target_column=target_column, factor=factor)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def divide(self, source_column: str, target_column: str, divisor: float):
|
||||||
|
"""除法计算"""
|
||||||
|
self.add_rule('divide', source_column=source_column,
|
||||||
|
target_column=target_column, divisor=divisor)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add(self, columns: Union[str, List[str]], target_column: str, constant: float = 0):
|
||||||
|
"""加法计算"""
|
||||||
|
self.add_rule('add', columns=columns, target_column=target_column, constant=constant)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def subtract(self, minuend: str, target_column: str,
|
||||||
|
subtrahend: Optional[str] = None, constant: float = 0):
|
||||||
|
"""减法计算"""
|
||||||
|
self.add_rule('subtract', minuend=minuend, target_column=target_column,
|
||||||
|
subtrahend=subtrahend, constant=constant)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def formula(self, formula: str, target_column: str):
|
||||||
|
"""公式计算"""
|
||||||
|
self.add_rule('formula', formula=formula, target_column=target_column)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def round_columns(self, columns: Optional[Union[str, List[str]]] = None, decimals: int = 0):
|
||||||
|
"""四舍五入"""
|
||||||
|
self.add_rule('round', columns=columns, decimals=decimals)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def sum_columns(self, columns: Optional[Union[str, List[str]]] = None,
|
||||||
|
target_column: Optional[str] = None, group_by: Optional[str] = None):
|
||||||
|
"""求和计算"""
|
||||||
|
self.add_rule('sum', columns=columns, target_column=target_column, group_by=group_by)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def aggregate(self, group_by: str, aggregations: Dict[str, Union[str, List[str]]]):
|
||||||
|
"""聚合计算"""
|
||||||
|
self.add_rule('aggregate', group_by=group_by, aggregations=aggregations)
|
||||||
|
return self
|
||||||
276
app/core/handlers/column_mapper.py
Normal file
276
app/core/handlers/column_mapper.py
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
"""
|
||||||
|
列映射处理器
|
||||||
|
|
||||||
|
提供列名映射和转换功能,支持不同供应商的列名标准化
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Dict, Any, Optional, List, Union
|
||||||
|
from ...core.utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ColumnMapper:
|
||||||
|
"""列映射处理器
|
||||||
|
|
||||||
|
提供列名标准化功能,将不同供应商的列名映射到标准列名
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 标准列名定义
|
||||||
|
STANDARD_COLUMNS = {
|
||||||
|
'barcode': ['条码', '条形码', '商品条码', '产品条码', '条码(必填)', 'barcode', 'code'],
|
||||||
|
'name': ['商品名称', '产品名称', '名称', '商品', '产品', 'name', 'product_name'],
|
||||||
|
'specification': ['规格', '规格型号', '型号', 'specification', 'spec', 'model'],
|
||||||
|
'quantity': ['数量', '采购量', '订货数量', '订单量', '需求量', 'quantity', 'qty', '采购量(必填)'],
|
||||||
|
'unit': ['单位', '计量单位', 'unit', 'units'],
|
||||||
|
'unit_price': ['单价', '价格', '采购单价', '进货价', 'unit_price', 'price', '采购单价(必填)'],
|
||||||
|
'total_price': ['总价', '金额', '小计', 'total_price', 'total', 'amount'],
|
||||||
|
'category': ['类别', '分类', '商品类别', 'category', 'type'],
|
||||||
|
'brand': ['品牌', '商标', 'brand'],
|
||||||
|
'supplier': ['供应商', '供货商', 'supplier', 'vendor']
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, mapping_config: Optional[Dict[str, Any]] = None):
|
||||||
|
"""初始化列映射器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mapping_config: 映射配置
|
||||||
|
"""
|
||||||
|
self.mapping_config = mapping_config or {}
|
||||||
|
self.custom_mappings = {}
|
||||||
|
self._build_reverse_mapping()
|
||||||
|
|
||||||
|
def _build_reverse_mapping(self):
|
||||||
|
"""构建反向映射表"""
|
||||||
|
self.reverse_mapping = {}
|
||||||
|
|
||||||
|
# 添加标准列的反向映射
|
||||||
|
for standard_name, variations in self.STANDARD_COLUMNS.items():
|
||||||
|
for variation in variations:
|
||||||
|
self.reverse_mapping[variation.lower()] = standard_name
|
||||||
|
|
||||||
|
# 添加自定义映射
|
||||||
|
for standard_name, custom_names in self.mapping_config.items():
|
||||||
|
if isinstance(custom_names, str):
|
||||||
|
custom_names = [custom_names]
|
||||||
|
|
||||||
|
for custom_name in custom_names:
|
||||||
|
self.reverse_mapping[custom_name.lower()] = standard_name
|
||||||
|
self.custom_mappings[custom_name.lower()] = standard_name
|
||||||
|
|
||||||
|
def map_columns(self, df: pd.DataFrame, target_columns: Optional[List[str]] = None) -> pd.DataFrame:
|
||||||
|
"""映射列名
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 输入数据
|
||||||
|
target_columns: 目标列名列表,如果为None则使用所有标准列
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
列名映射后的数据
|
||||||
|
"""
|
||||||
|
if target_columns is None:
|
||||||
|
target_columns = list(self.STANDARD_COLUMNS.keys())
|
||||||
|
|
||||||
|
logger.info(f"开始列名映射,目标列: {target_columns}")
|
||||||
|
logger.info(f"原始列名: {list(df.columns)}")
|
||||||
|
|
||||||
|
# 创建列名映射
|
||||||
|
column_mapping = {}
|
||||||
|
used_columns = set()
|
||||||
|
|
||||||
|
for target_col in target_columns:
|
||||||
|
# 查找匹配的原始列名
|
||||||
|
matched_column = self._find_matching_column(df.columns, target_col)
|
||||||
|
if matched_column:
|
||||||
|
column_mapping[matched_column] = target_col
|
||||||
|
used_columns.add(matched_column)
|
||||||
|
logger.debug(f"列名映射: {matched_column} -> {target_col}")
|
||||||
|
|
||||||
|
# 重命名列
|
||||||
|
if column_mapping:
|
||||||
|
df_mapped = df.rename(columns=column_mapping)
|
||||||
|
|
||||||
|
# 添加缺失的目标列
|
||||||
|
for target_col in target_columns:
|
||||||
|
if target_col not in df_mapped.columns:
|
||||||
|
df_mapped[target_col] = self._get_default_value(target_col)
|
||||||
|
logger.debug(f"添加缺失列: {target_col}")
|
||||||
|
|
||||||
|
# 只保留目标列
|
||||||
|
existing_target_columns = [col for col in target_columns if col in df_mapped.columns]
|
||||||
|
df_result = df_mapped[existing_target_columns]
|
||||||
|
|
||||||
|
logger.info(f"列名映射完成,结果列名: {list(df_result.columns)}")
|
||||||
|
return df_result
|
||||||
|
else:
|
||||||
|
logger.warning("没有找到可映射的列名")
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _find_matching_column(self, columns: List[str], target_column: str) -> Optional[str]:
|
||||||
|
"""查找匹配的列名
|
||||||
|
|
||||||
|
Args:
|
||||||
|
columns: 原始列名列表
|
||||||
|
target_column: 目标标准列名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
匹配的原始列名或None
|
||||||
|
"""
|
||||||
|
# 获取目标列的所有可能变体
|
||||||
|
possible_names = []
|
||||||
|
|
||||||
|
# 标准列名变体
|
||||||
|
if target_column in self.STANDARD_COLUMNS:
|
||||||
|
possible_names.extend(self.STANDARD_COLUMNS[target_column])
|
||||||
|
|
||||||
|
# 自定义映射
|
||||||
|
for standard_name, custom_names in self.mapping_config.items():
|
||||||
|
if standard_name == target_column:
|
||||||
|
if isinstance(custom_names, str):
|
||||||
|
possible_names.append(custom_names)
|
||||||
|
else:
|
||||||
|
possible_names.extend(custom_names)
|
||||||
|
|
||||||
|
# 查找匹配
|
||||||
|
for possible_name in possible_names:
|
||||||
|
# 精确匹配(忽略大小写)
|
||||||
|
for column in columns:
|
||||||
|
if column.lower() == possible_name.lower():
|
||||||
|
return column
|
||||||
|
|
||||||
|
# 模糊匹配
|
||||||
|
for column in columns:
|
||||||
|
if possible_name.lower() in column.lower() or column.lower() in possible_name.lower():
|
||||||
|
return column
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_default_value(self, column_name: str) -> Any:
|
||||||
|
"""获取列的默认值
|
||||||
|
|
||||||
|
Args:
|
||||||
|
column_name: 列名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
默认值
|
||||||
|
"""
|
||||||
|
# 根据列名类型返回合适的默认值
|
||||||
|
if column_name in ['quantity', 'unit_price', 'total_price']:
|
||||||
|
return 0
|
||||||
|
elif column_name in ['barcode', 'name', 'specification', 'unit', 'category', 'brand', 'supplier']:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_custom_mapping(self, standard_name: str, custom_names: Union[str, List[str]]):
|
||||||
|
"""添加自定义列名映射
|
||||||
|
|
||||||
|
Args:
|
||||||
|
standard_name: 标准列名
|
||||||
|
custom_names: 自定义列名或列名列表
|
||||||
|
"""
|
||||||
|
if isinstance(custom_names, str):
|
||||||
|
custom_names = [custom_names]
|
||||||
|
|
||||||
|
# 更新配置
|
||||||
|
self.mapping_config[standard_name] = custom_names
|
||||||
|
|
||||||
|
# 更新反向映射
|
||||||
|
for custom_name in custom_names:
|
||||||
|
self.reverse_mapping[custom_name.lower()] = standard_name
|
||||||
|
self.custom_mappings[custom_name.lower()] = standard_name
|
||||||
|
|
||||||
|
logger.info(f"添加自定义映射: {standard_name} <- {custom_names}")
|
||||||
|
|
||||||
|
def detect_column_types(self, df: pd.DataFrame) -> Dict[str, str]:
|
||||||
|
"""检测列的数据类型
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
列类型字典
|
||||||
|
"""
|
||||||
|
column_types = {}
|
||||||
|
|
||||||
|
for column in df.columns:
|
||||||
|
if pd.api.types.is_numeric_dtype(df[column]):
|
||||||
|
column_types[column] = 'numeric'
|
||||||
|
elif pd.api.types.is_datetime64_any_dtype(df[column]):
|
||||||
|
column_types[column] = 'datetime'
|
||||||
|
elif pd.api.types.is_bool_dtype(df[column]):
|
||||||
|
column_types[column] = 'boolean'
|
||||||
|
else:
|
||||||
|
column_types[column] = 'text'
|
||||||
|
|
||||||
|
return column_types
|
||||||
|
|
||||||
|
def suggest_column_mapping(self, df: pd.DataFrame) -> Dict[str, List[str]]:
|
||||||
|
"""建议列名映射
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
建议的映射关系
|
||||||
|
"""
|
||||||
|
suggestions = {}
|
||||||
|
|
||||||
|
for column in df.columns:
|
||||||
|
column_lower = column.lower()
|
||||||
|
suggestions[column] = []
|
||||||
|
|
||||||
|
# 检查标准列名
|
||||||
|
for standard_name, variations in self.STANDARD_COLUMNS.items():
|
||||||
|
for variation in variations:
|
||||||
|
if column_lower in variation.lower() or variation.lower() in column_lower:
|
||||||
|
suggestions[column].append(standard_name)
|
||||||
|
|
||||||
|
# 检查自定义映射
|
||||||
|
for custom_name, standard_name in self.custom_mappings.items():
|
||||||
|
if column_lower in custom_name or custom_name in column_lower:
|
||||||
|
suggestions[column].append(standard_name)
|
||||||
|
|
||||||
|
# 去重
|
||||||
|
suggestions[column] = list(set(suggestions[column]))
|
||||||
|
|
||||||
|
# 只返回有建议的列
|
||||||
|
return {k: v for k, v in suggestions.items() if v}
|
||||||
|
|
||||||
|
def validate_mapping(self, df: pd.DataFrame, required_columns: List[str]) -> Dict[str, Any]:
|
||||||
|
"""验证列映射结果
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 映射后的数据
|
||||||
|
required_columns: 必需的列名列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
验证结果
|
||||||
|
"""
|
||||||
|
result = {
|
||||||
|
'valid': True,
|
||||||
|
'missing_columns': [],
|
||||||
|
'empty_columns': [],
|
||||||
|
'warnings': []
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查缺失列
|
||||||
|
for col in required_columns:
|
||||||
|
if col not in df.columns:
|
||||||
|
result['missing_columns'].append(col)
|
||||||
|
result['valid'] = False
|
||||||
|
|
||||||
|
# 检查空列
|
||||||
|
for col in df.columns:
|
||||||
|
if df[col].isnull().all():
|
||||||
|
result['empty_columns'].append(col)
|
||||||
|
result['warnings'].append(f"列 '{col}' 全部为空值")
|
||||||
|
|
||||||
|
# 检查数值列
|
||||||
|
numeric_columns = ['quantity', 'unit_price', 'total_price']
|
||||||
|
for col in numeric_columns:
|
||||||
|
if col in df.columns and not pd.api.types.is_numeric_dtype(df[col]):
|
||||||
|
result['warnings'].append(f"列 '{col}' 不是数值类型")
|
||||||
|
|
||||||
|
return result
|
||||||
401
app/core/handlers/data_cleaner.py
Normal file
401
app/core/handlers/data_cleaner.py
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
"""
|
||||||
|
数据清洗处理器
|
||||||
|
|
||||||
|
提供各种数据清洗功能,如空值处理、重复项处理、数据类型转换等
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Dict, Any, Optional, List, Union
|
||||||
|
from ...core.utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DataCleaner:
|
||||||
|
"""数据清洗处理器
|
||||||
|
|
||||||
|
提供标准化的数据清洗功能,支持链式调用和规则配置
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
||||||
|
"""初始化数据清洗器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 清洗配置
|
||||||
|
"""
|
||||||
|
self.config = config or {}
|
||||||
|
self.cleaning_rules = []
|
||||||
|
|
||||||
|
def add_rule(self, rule_type: str, **kwargs):
|
||||||
|
"""添加清洗规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
rule_type: 规则类型
|
||||||
|
**kwargs: 规则参数
|
||||||
|
"""
|
||||||
|
rule = {'type': rule_type, **kwargs}
|
||||||
|
self.cleaning_rules.append(rule)
|
||||||
|
logger.debug(f"添加清洗规则: {rule_type}")
|
||||||
|
|
||||||
|
def clean(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
"""执行数据清洗
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 输入数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
清洗后的数据
|
||||||
|
"""
|
||||||
|
logger.info(f"开始数据清洗,原始数据形状: {df.shape}")
|
||||||
|
|
||||||
|
result_df = df.copy()
|
||||||
|
|
||||||
|
for i, rule in enumerate(self.cleaning_rules):
|
||||||
|
try:
|
||||||
|
logger.debug(f"执行清洗规则 {i+1}/{len(self.cleaning_rules)}: {rule['type']}")
|
||||||
|
result_df = self._apply_rule(result_df, rule)
|
||||||
|
logger.debug(f"规则执行完成,数据形状: {result_df.shape}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"清洗规则执行失败: {rule}, 错误: {e}")
|
||||||
|
# 继续执行下一个规则,而不是中断整个流程
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.info(f"数据清洗完成,最终数据形状: {result_df.shape}")
|
||||||
|
return result_df
|
||||||
|
|
||||||
|
def _apply_rule(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""应用单个清洗规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
rule_type = rule.get('type')
|
||||||
|
|
||||||
|
if rule_type == 'remove_duplicates':
|
||||||
|
return self._remove_duplicates(df, rule)
|
||||||
|
elif rule_type == 'fill_na':
|
||||||
|
return self._fill_na(df, rule)
|
||||||
|
elif rule_type == 'remove_rows':
|
||||||
|
return self._remove_rows(df, rule)
|
||||||
|
elif rule_type == 'convert_type':
|
||||||
|
return self._convert_type(df, rule)
|
||||||
|
elif rule_type == 'strip_whitespace':
|
||||||
|
return self._strip_whitespace(df, rule)
|
||||||
|
elif rule_type == 'normalize_text':
|
||||||
|
return self._normalize_text(df, rule)
|
||||||
|
elif rule_type == 'validate_data':
|
||||||
|
return self._validate_data(df, rule)
|
||||||
|
else:
|
||||||
|
logger.warning(f"未知的清洗规则类型: {rule_type}")
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _remove_duplicates(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""移除重复项
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
subset = rule.get('subset') # 用于判断重复的列
|
||||||
|
keep = rule.get('keep', 'first') # 保留哪个重复项
|
||||||
|
|
||||||
|
before_count = len(df)
|
||||||
|
df_cleaned = df.drop_duplicates(subset=subset, keep=keep)
|
||||||
|
after_count = len(df_cleaned)
|
||||||
|
|
||||||
|
logger.info(f"移除重复项: {before_count - after_count} 行被移除")
|
||||||
|
return df_cleaned
|
||||||
|
|
||||||
|
def _fill_na(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""填充空值
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns') # 要处理的列
|
||||||
|
value = rule.get('value', 0) # 填充值
|
||||||
|
method = rule.get('method') # 填充方法('ffill', 'bfill', 'mean', 'median')
|
||||||
|
|
||||||
|
if columns:
|
||||||
|
# 处理指定列
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
for col in columns:
|
||||||
|
if col in df.columns:
|
||||||
|
if method == 'ffill':
|
||||||
|
df[col] = df[col].fillna(method='ffill')
|
||||||
|
elif method == 'bfill':
|
||||||
|
df[col] = df[col].fillna(method='bfill')
|
||||||
|
elif method == 'mean':
|
||||||
|
df[col] = df[col].fillna(df[col].mean())
|
||||||
|
elif method == 'median':
|
||||||
|
df[col] = df[col].fillna(df[col].median())
|
||||||
|
else:
|
||||||
|
df[col] = df[col].fillna(value)
|
||||||
|
|
||||||
|
logger.debug(f"填充列 {col} 的空值: {method or value}")
|
||||||
|
else:
|
||||||
|
# 处理所有列
|
||||||
|
if method == 'ffill':
|
||||||
|
df = df.fillna(method='ffill')
|
||||||
|
elif method == 'bfill':
|
||||||
|
df = df.fillna(method='bfill')
|
||||||
|
else:
|
||||||
|
df = df.fillna(value)
|
||||||
|
|
||||||
|
logger.debug(f"填充所有列的空值: {method or value}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _remove_rows(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""移除行
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
condition = rule.get('condition') # 条件表达式
|
||||||
|
columns = rule.get('columns') # 要检查的列
|
||||||
|
values = rule.get('values') # 要移除的值
|
||||||
|
|
||||||
|
if condition:
|
||||||
|
# 使用条件表达式
|
||||||
|
try:
|
||||||
|
before_count = len(df)
|
||||||
|
df_filtered = df.query(condition)
|
||||||
|
after_count = len(df_filtered)
|
||||||
|
logger.info(f"条件过滤: {condition}, 移除了 {before_count - after_count} 行")
|
||||||
|
return df_filtered
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"条件表达式执行失败: {condition}, 错误: {e}")
|
||||||
|
return df
|
||||||
|
|
||||||
|
if columns and values:
|
||||||
|
# 基于列值过滤
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
if not isinstance(values, list):
|
||||||
|
values = [values]
|
||||||
|
|
||||||
|
df_filtered = df.copy()
|
||||||
|
for col in columns:
|
||||||
|
if col in df_filtered.columns:
|
||||||
|
mask = ~df_filtered[col].isin(values)
|
||||||
|
df_filtered = df_filtered[mask]
|
||||||
|
logger.debug(f"列 {col} 过滤值 {values}")
|
||||||
|
|
||||||
|
return df_filtered
|
||||||
|
|
||||||
|
logger.warning("移除行规则缺少条件或列配置")
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _convert_type(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""类型转换
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns')
|
||||||
|
target_type = rule.get('target_type', 'float')
|
||||||
|
errors = rule.get('errors', 'coerce') # 错误处理方式
|
||||||
|
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
for col in columns:
|
||||||
|
if col in df.columns:
|
||||||
|
try:
|
||||||
|
if target_type == 'int':
|
||||||
|
df[col] = pd.to_numeric(df[col], errors=errors).astype('Int64')
|
||||||
|
elif target_type == 'float':
|
||||||
|
df[col] = pd.to_numeric(df[col], errors=errors)
|
||||||
|
elif target_type == 'datetime':
|
||||||
|
df[col] = pd.to_datetime(df[col], errors=errors)
|
||||||
|
elif target_type == 'string':
|
||||||
|
df[col] = df[col].astype(str)
|
||||||
|
else:
|
||||||
|
df[col] = df[col].astype(target_type)
|
||||||
|
|
||||||
|
logger.debug(f"列 {col} 类型转换: {target_type}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"列 {col} 类型转换失败: {e}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _strip_whitespace(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""去除空白字符
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns')
|
||||||
|
|
||||||
|
if columns:
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
for col in columns:
|
||||||
|
if col in df.columns and df[col].dtype == 'object':
|
||||||
|
df[col] = df[col].str.strip()
|
||||||
|
logger.debug(f"列 {col} 去除空白字符")
|
||||||
|
else:
|
||||||
|
# 处理所有文本列
|
||||||
|
text_columns = df.select_dtypes(include=['object']).columns
|
||||||
|
for col in text_columns:
|
||||||
|
df[col] = df[col].str.strip()
|
||||||
|
|
||||||
|
logger.debug(f"所有文本列去除空白字符: {list(text_columns)}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _normalize_text(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""文本标准化
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns')
|
||||||
|
lowercase = rule.get('lowercase', False)
|
||||||
|
uppercase = rule.get('uppercase', False)
|
||||||
|
replace_map = rule.get('replace_map', {}) # 替换映射
|
||||||
|
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
target_columns = columns or df.select_dtypes(include=['object']).columns
|
||||||
|
|
||||||
|
for col in target_columns:
|
||||||
|
if col in df.columns and df[col].dtype == 'object':
|
||||||
|
if lowercase:
|
||||||
|
df[col] = df[col].str.lower()
|
||||||
|
elif uppercase:
|
||||||
|
df[col] = df[col].str.upper()
|
||||||
|
|
||||||
|
# 应用替换映射
|
||||||
|
for old, new in replace_map.items():
|
||||||
|
df[col] = df[col].str.replace(old, new)
|
||||||
|
|
||||||
|
logger.debug(f"列 {col} 文本标准化完成")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _validate_data(self, df: pd.DataFrame, rule: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
"""数据验证
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 数据
|
||||||
|
rule: 规则配置
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的数据
|
||||||
|
"""
|
||||||
|
columns = rule.get('columns')
|
||||||
|
min_value = rule.get('min_value')
|
||||||
|
max_value = rule.get('max_value')
|
||||||
|
required = rule.get('required', False)
|
||||||
|
|
||||||
|
if isinstance(columns, str):
|
||||||
|
columns = [columns]
|
||||||
|
|
||||||
|
validation_results = []
|
||||||
|
|
||||||
|
for col in columns:
|
||||||
|
if col in df.columns:
|
||||||
|
# 检查必需值
|
||||||
|
if required:
|
||||||
|
null_count = df[col].isnull().sum()
|
||||||
|
if null_count > 0:
|
||||||
|
validation_results.append(f"{col}: {null_count} 个空值")
|
||||||
|
|
||||||
|
# 检查数值范围
|
||||||
|
if min_value is not None or max_value is not None:
|
||||||
|
if pd.api.types.is_numeric_dtype(df[col]):
|
||||||
|
invalid_mask = pd.Series(False, index=df.index)
|
||||||
|
if min_value is not None:
|
||||||
|
invalid_mask |= df[col] < min_value
|
||||||
|
if max_value is not None:
|
||||||
|
invalid_mask |= df[col] > max_value
|
||||||
|
|
||||||
|
invalid_count = invalid_mask.sum()
|
||||||
|
if invalid_count > 0:
|
||||||
|
validation_results.append(f"{col}: {invalid_count} 个值超出范围")
|
||||||
|
|
||||||
|
if validation_results:
|
||||||
|
logger.warning(f"数据验证发现问题: {', '.join(validation_results)}")
|
||||||
|
else:
|
||||||
|
logger.debug("数据验证通过")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
# 便捷方法
|
||||||
|
def remove_duplicates(self, subset: Optional[List[str]] = None, keep: str = 'first'):
|
||||||
|
"""移除重复项"""
|
||||||
|
self.add_rule('remove_duplicates', subset=subset, keep=keep)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def fill_na(self, columns: Optional[Union[str, List[str]]] = None,
|
||||||
|
value: Any = 0, method: Optional[str] = None):
|
||||||
|
"""填充空值"""
|
||||||
|
self.add_rule('fill_na', columns=columns, value=value, method=method)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def remove_rows(self, condition: Optional[str] = None,
|
||||||
|
columns: Optional[Union[str, List[str]]] = None,
|
||||||
|
values: Optional[Any] = None):
|
||||||
|
"""移除行"""
|
||||||
|
self.add_rule('remove_rows', condition=condition, columns=columns, values=values)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def convert_type(self, columns: Union[str, List[str]], target_type: str, errors: str = 'coerce'):
|
||||||
|
"""类型转换"""
|
||||||
|
self.add_rule('convert_type', columns=columns, target_type=target_type, errors=errors)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def strip_whitespace(self, columns: Optional[Union[str, List[str]]] = None):
|
||||||
|
"""去除空白字符"""
|
||||||
|
self.add_rule('strip_whitespace', columns=columns)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def normalize_text(self, columns: Optional[Union[str, List[str]]] = None,
|
||||||
|
lowercase: bool = False, uppercase: bool = False,
|
||||||
|
replace_map: Optional[Dict[str, str]] = None):
|
||||||
|
"""文本标准化"""
|
||||||
|
self.add_rule('normalize_text', columns=columns, lowercase=lowercase,
|
||||||
|
uppercase=uppercase, replace_map=replace_map or {})
|
||||||
|
return self
|
||||||
|
|
||||||
|
def validate_data(self, columns: Union[str, List[str]],
|
||||||
|
min_value: Optional[float] = None,
|
||||||
|
max_value: Optional[float] = None,
|
||||||
|
required: bool = False):
|
||||||
|
"""数据验证"""
|
||||||
|
self.add_rule('validate_data', columns=columns, min_value=min_value,
|
||||||
|
max_value=max_value, required=required)
|
||||||
|
return self
|
||||||
150
app/core/handlers/rule_engine.py
Normal file
150
app/core/handlers/rule_engine.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import re
|
||||||
|
import pandas as pd
|
||||||
|
from typing import List, Dict, Any, Optional
|
||||||
|
|
||||||
|
def _split_quantity_unit(df: pd.DataFrame, source: str, dictionary: Optional[Dict[str, Any]] = None) -> pd.DataFrame:
|
||||||
|
if source in df.columns:
|
||||||
|
vals = df[source].astype(str).fillna("")
|
||||||
|
nums = []
|
||||||
|
units = []
|
||||||
|
default_unit = (dictionary or {}).get("default_unit", "")
|
||||||
|
unit_synonyms = (dictionary or {}).get("unit_synonyms", {})
|
||||||
|
for v in vals:
|
||||||
|
m = re.search(r"(\d+(?:\.\d+)?)(箱|件|提|盒|瓶)", v)
|
||||||
|
if m:
|
||||||
|
nums.append(float(m.group(1)))
|
||||||
|
u = unit_synonyms.get(m.group(2), m.group(2))
|
||||||
|
units.append(u)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
nums.append(float(v))
|
||||||
|
units.append(unit_synonyms.get(default_unit, default_unit))
|
||||||
|
except:
|
||||||
|
nums.append(0.0)
|
||||||
|
units.append(unit_synonyms.get(default_unit, default_unit))
|
||||||
|
df["quantity"] = nums
|
||||||
|
df["unit"] = units
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _extract_spec_from_name(df: pd.DataFrame, source: str, dictionary: Optional[Dict[str, Any]] = None) -> pd.DataFrame:
|
||||||
|
if source in df.columns:
|
||||||
|
names = df[source].astype(str).fillna("")
|
||||||
|
specs = []
|
||||||
|
packs = []
|
||||||
|
ignore_words = (dictionary or {}).get("ignore_words", [])
|
||||||
|
name_patterns = (dictionary or {}).get("name_patterns", [])
|
||||||
|
for s in names:
|
||||||
|
if ignore_words:
|
||||||
|
for w in ignore_words:
|
||||||
|
s = s.replace(w, "")
|
||||||
|
matched = False
|
||||||
|
for pat in name_patterns:
|
||||||
|
try:
|
||||||
|
m = re.search(pat, s)
|
||||||
|
if m and len(m.groups()) >= 2:
|
||||||
|
try:
|
||||||
|
qty = int(m.group(len(m.groups())))
|
||||||
|
except:
|
||||||
|
qty = None
|
||||||
|
specs.append(s)
|
||||||
|
packs.append(qty)
|
||||||
|
matched = True
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if matched:
|
||||||
|
continue
|
||||||
|
m = re.search(r"(\d+(?:\.\d+)?)(ml|l|升|毫升)[*×xX](\d+)", s, re.IGNORECASE)
|
||||||
|
if m:
|
||||||
|
specs.append(f"{m.group(1)}{m.group(2)}*{m.group(3)}")
|
||||||
|
packs.append(int(m.group(3)))
|
||||||
|
continue
|
||||||
|
m2 = re.search(r"(\d+)[*×xX](\d+)", s)
|
||||||
|
if m2:
|
||||||
|
specs.append(f"1*{m2.group(2)}")
|
||||||
|
packs.append(int(m2.group(2)))
|
||||||
|
continue
|
||||||
|
m3 = re.search(r"(\d{2,3})\D*(\d{1,3})\D*", s)
|
||||||
|
if m3:
|
||||||
|
specs.append(f"1*{m3.group(2)}")
|
||||||
|
packs.append(int(m3.group(2)))
|
||||||
|
continue
|
||||||
|
specs.append("")
|
||||||
|
packs.append(None)
|
||||||
|
df["specification"] = df.get("specification", pd.Series(specs))
|
||||||
|
df["package_quantity"] = packs
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _normalize_unit(df: pd.DataFrame, target: str, unit_map: Dict[str, str], dictionary: Optional[Dict[str, Any]] = None) -> pd.DataFrame:
|
||||||
|
if target in df.columns:
|
||||||
|
df[target] = df[target].astype(str)
|
||||||
|
df[target] = df[target].apply(lambda u: unit_map.get(u, u))
|
||||||
|
pack_multipliers = (dictionary or {}).get("pack_multipliers", {})
|
||||||
|
default_pq = (dictionary or {}).get("default_package_quantity", 1)
|
||||||
|
try:
|
||||||
|
if "quantity" in df.columns:
|
||||||
|
def convert_qty(row):
|
||||||
|
u = row.get(target)
|
||||||
|
q = row.get("quantity")
|
||||||
|
pq = row.get("package_quantity")
|
||||||
|
if u in ("件", "箱", "提", "盒"):
|
||||||
|
mult = pq or pack_multipliers.get(u, default_pq)
|
||||||
|
if pd.notna(q) and pd.notna(mult) and float(mult) > 0:
|
||||||
|
return float(q) * float(mult)
|
||||||
|
return q
|
||||||
|
df["quantity"] = df.apply(convert_qty, axis=1)
|
||||||
|
df[target] = df[target].apply(lambda u: "瓶" if u in ("件","箱","提","盒") else u)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _compute_quantity_from_total(df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
if "quantity" in df.columns and "unit_price" in df.columns:
|
||||||
|
qty = df["quantity"].fillna(0)
|
||||||
|
up = pd.to_numeric(df.get("unit_price", 0), errors="coerce").fillna(0)
|
||||||
|
tp = pd.to_numeric(df.get("total_price", 0), errors="coerce").fillna(0)
|
||||||
|
need = (qty <= 0) & (up > 0) & (tp > 0)
|
||||||
|
df.loc[need, "quantity"] = (tp[need] / up[need]).round(6)
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _fill_missing(df: pd.DataFrame, fills: Dict[str, Any]) -> pd.DataFrame:
|
||||||
|
for k, v in fills.items():
|
||||||
|
if k in df.columns:
|
||||||
|
df[k] = df[k].fillna(v)
|
||||||
|
else:
|
||||||
|
df[k] = v
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _mark_gift(df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
df["is_gift"] = False
|
||||||
|
tp = df.get("total_price")
|
||||||
|
up = df.get("unit_price")
|
||||||
|
flags = pd.Series([False]*len(df))
|
||||||
|
if tp is not None:
|
||||||
|
tpn = pd.to_numeric(tp, errors="coerce").fillna(0)
|
||||||
|
flags = flags | (tpn == 0)
|
||||||
|
if up is not None:
|
||||||
|
upn = pd.to_numeric(up, errors="coerce").fillna(0)
|
||||||
|
flags = flags | (upn == 0)
|
||||||
|
if "name" in df.columns:
|
||||||
|
flags = flags | df["name"].astype(str).str.contains(r"赠品|^o$|^O$", regex=True)
|
||||||
|
df.loc[flags, "is_gift"] = True
|
||||||
|
return df
|
||||||
|
|
||||||
|
def apply_rules(df: pd.DataFrame, rules: List[Dict[str, Any]], dictionary: Optional[Dict[str, Any]] = None) -> pd.DataFrame:
|
||||||
|
out = df.copy()
|
||||||
|
for r in rules or []:
|
||||||
|
t = r.get("type")
|
||||||
|
if t == "split_quantity_unit":
|
||||||
|
out = _split_quantity_unit(out, r.get("source", "quantity"), dictionary)
|
||||||
|
elif t == "extract_spec_from_name":
|
||||||
|
out = _extract_spec_from_name(out, r.get("source", "name"), dictionary)
|
||||||
|
elif t == "normalize_unit":
|
||||||
|
out = _normalize_unit(out, r.get("target", "unit"), r.get("map", {}), dictionary)
|
||||||
|
elif t == "compute_quantity_from_total":
|
||||||
|
out = _compute_quantity_from_total(out)
|
||||||
|
elif t == "fill_missing":
|
||||||
|
out = _fill_missing(out, r.get("fills", {}))
|
||||||
|
elif t == "mark_gift":
|
||||||
|
out = _mark_gift(out)
|
||||||
|
return out
|
||||||
@ -11,7 +11,7 @@ import json
|
|||||||
import base64
|
import base64
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from typing import Dict, List, Optional, Tuple, Union, Any
|
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||||
|
|
||||||
from ...config.settings import ConfigManager
|
from ...config.settings import ConfigManager
|
||||||
from ..utils.log_utils import get_logger
|
from ..utils.log_utils import get_logger
|
||||||
@ -332,7 +332,7 @@ class OCRProcessor:
|
|||||||
logger.error(f"处理图片时出错: {image_path}, 错误: {e}")
|
logger.error(f"处理图片时出错: {image_path}, 错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_images_batch(self, batch_size: int = None, max_workers: int = None) -> Tuple[int, int]:
|
def process_images_batch(self, batch_size: int = None, max_workers: int = None, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
批量处理图片
|
批量处理图片
|
||||||
|
|
||||||
@ -369,6 +369,13 @@ class OCRProcessor:
|
|||||||
for i in range(0, total, batch_size):
|
for i in range(0, total, batch_size):
|
||||||
batch = unprocessed_images[i:i+batch_size]
|
batch = unprocessed_images[i:i+batch_size]
|
||||||
logger.info(f"处理批次 {i//batch_size+1}/{(total+batch_size-1)//batch_size}: {len(batch)} 个文件")
|
logger.info(f"处理批次 {i//batch_size+1}/{(total+batch_size-1)//batch_size}: {len(batch)} 个文件")
|
||||||
|
try:
|
||||||
|
if progress_cb:
|
||||||
|
# 以批次为单位估算进度(0-90%),保留10%给后续阶段
|
||||||
|
percent = int(10 + (i / max(total, 1)) * 80)
|
||||||
|
progress_cb(min(percent, 90))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 使用多线程处理批次
|
# 使用多线程处理批次
|
||||||
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||||
@ -378,4 +385,9 @@ class OCRProcessor:
|
|||||||
success_count += sum(1 for result in results if result is not None)
|
success_count += sum(1 for result in results if result is not None)
|
||||||
|
|
||||||
logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success_count}")
|
logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success_count}")
|
||||||
|
try:
|
||||||
|
if progress_cb:
|
||||||
|
progress_cb(90)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
return total, success_count
|
return total, success_count
|
||||||
|
|||||||
9
app/core/processors/__init__.py
Normal file
9
app/core/processors/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
"""
|
||||||
|
处理器模块初始化文件
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .base import BaseProcessor
|
||||||
|
from .ocr_processor import OCRProcessor
|
||||||
|
from .tobacco_processor import TobaccoProcessor
|
||||||
|
|
||||||
|
__all__ = ['BaseProcessor', 'OCRProcessor', 'TobaccoProcessor']
|
||||||
139
app/core/processors/base.py
Normal file
139
app/core/processors/base.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
"""
|
||||||
|
基础处理器接口模块
|
||||||
|
|
||||||
|
定义所有处理器的基类,提供统一的处理接口
|
||||||
|
"""
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Dict, Any, Optional, List
|
||||||
|
from pathlib import Path
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseProcessor(ABC):
|
||||||
|
"""基础处理器接口 - 所有处理器的基类
|
||||||
|
|
||||||
|
采用策略模式设计,每个处理器负责特定类型的文件处理
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any]):
|
||||||
|
"""初始化处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 处理器配置字典
|
||||||
|
"""
|
||||||
|
self.config = config
|
||||||
|
self.name = self.__class__.__name__
|
||||||
|
self.description = ""
|
||||||
|
self._setup_logging()
|
||||||
|
|
||||||
|
def _setup_logging(self):
|
||||||
|
"""设置处理器日志"""
|
||||||
|
self.logger = logging.getLogger(f"{__name__}.{self.name}")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def can_process(self, file_path: Path) -> bool:
|
||||||
|
"""判断是否能处理该文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否能处理该文件
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def process(self, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""处理文件,返回输出文件路径
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入文件路径
|
||||||
|
output_dir: 输出目录路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径,处理失败返回None
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_required_columns(self) -> List[str]:
|
||||||
|
"""返回需要的列名列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
列名列表
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def validate_input(self, file_path: Path) -> bool:
|
||||||
|
"""验证输入文件有效性
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
文件是否有效
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not file_path.exists():
|
||||||
|
self.logger.warning(f"文件不存在: {file_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not file_path.is_file():
|
||||||
|
self.logger.warning(f"不是文件: {file_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
supported_extensions = self.get_supported_extensions()
|
||||||
|
if supported_extensions and file_path.suffix.lower() not in supported_extensions:
|
||||||
|
self.logger.warning(f"不支持的文件类型: {file_path.suffix}, 支持的类型: {supported_extensions}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"验证文件时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_supported_extensions(self) -> List[str]:
|
||||||
|
"""获取支持的文件扩展名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
支持的扩展名列表,空列表表示支持所有类型
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_output_filename(self, input_file: Path, suffix: str = "_processed") -> str:
|
||||||
|
"""生成输出文件名
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入文件路径
|
||||||
|
suffix: 文件名后缀
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件名
|
||||||
|
"""
|
||||||
|
return f"{input_file.stem}{suffix}{input_file.suffix}"
|
||||||
|
|
||||||
|
def log_processing_start(self, input_file: Path):
|
||||||
|
"""记录处理开始日志"""
|
||||||
|
self.logger.info(f"开始处理文件: {input_file}")
|
||||||
|
self.logger.info(f"处理器: {self.name} - {self.description}")
|
||||||
|
|
||||||
|
def log_processing_end(self, input_file: Path, output_file: Optional[Path] = None, success: bool = True):
|
||||||
|
"""记录处理结束日志"""
|
||||||
|
if success:
|
||||||
|
self.logger.info(f"处理完成: {input_file}")
|
||||||
|
if output_file:
|
||||||
|
self.logger.info(f"输出文件: {output_file}")
|
||||||
|
else:
|
||||||
|
self.logger.error(f"处理失败: {input_file}")
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""字符串表示"""
|
||||||
|
return f"{self.name}({self.description})"
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
"""详细字符串表示"""
|
||||||
|
return f"{self.__class__.__module__}.{self.__class__.__name__}(name='{self.name}', description='{self.description}')"
|
||||||
192
app/core/processors/ocr_processor.py
Normal file
192
app/core/processors/ocr_processor.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
"""
|
||||||
|
OCR处理器
|
||||||
|
|
||||||
|
处理图片文件的OCR识别完整流程:图片识别 → Excel处理 → 标准采购单生成
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional, Dict, Any, List
|
||||||
|
|
||||||
|
from .base import BaseProcessor
|
||||||
|
from ...services.ocr_service import OCRService
|
||||||
|
from ...services.order_service import OrderService
|
||||||
|
from ...core.utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class OCRProcessor(BaseProcessor):
|
||||||
|
"""OCR处理器
|
||||||
|
|
||||||
|
处理图片文件的完整OCR识别流程:
|
||||||
|
1. OCR识别图片中的表格信息
|
||||||
|
2. 处理识别结果生成Excel文件
|
||||||
|
3. 转换为标准采购单格式
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any]):
|
||||||
|
"""初始化OCR处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 配置信息
|
||||||
|
"""
|
||||||
|
super().__init__(config)
|
||||||
|
self.description = "OCR识别完整流程(图片→识别→Excel→采购单)"
|
||||||
|
|
||||||
|
# 初始化服务
|
||||||
|
self.ocr_service = OCRService(config)
|
||||||
|
self.order_service = OrderService(config)
|
||||||
|
|
||||||
|
def can_process(self, file_path: Path) -> bool:
|
||||||
|
"""判断是否为支持的图片文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否能处理该文件
|
||||||
|
"""
|
||||||
|
if not self.validate_input(file_path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 支持的图片格式
|
||||||
|
supported_extensions = ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
|
||||||
|
if file_path.suffix.lower() in supported_extensions:
|
||||||
|
self.logger.info(f"识别为图片文件: {file_path.name}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def process(self, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""处理图片文件的完整OCR流程
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入图片文件路径
|
||||||
|
output_dir: 输出目录路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径,处理失败返回None
|
||||||
|
"""
|
||||||
|
self.log_processing_start(input_file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.logger.info("开始OCR识别流程...")
|
||||||
|
|
||||||
|
# 步骤1: OCR识别
|
||||||
|
self.logger.info("步骤1/3: OCR识别图片...")
|
||||||
|
ocr_result = self._perform_ocr(input_file, output_dir)
|
||||||
|
if not ocr_result:
|
||||||
|
self.logger.error("OCR识别失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 步骤2: Excel处理
|
||||||
|
self.logger.info("步骤2/3: 处理Excel文件...")
|
||||||
|
excel_result = self._process_excel(ocr_result, output_dir)
|
||||||
|
if not excel_result:
|
||||||
|
self.logger.error("Excel处理失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 步骤3: 生成标准采购单
|
||||||
|
self.logger.info("步骤3/3: 生成标准采购单...")
|
||||||
|
final_result = self._generate_purchase_order(excel_result, output_dir)
|
||||||
|
|
||||||
|
if final_result:
|
||||||
|
self.logger.info(f"OCR处理流程完成,输出文件: {final_result}")
|
||||||
|
self.log_processing_end(input_file, final_result, success=True)
|
||||||
|
return final_result
|
||||||
|
else:
|
||||||
|
self.logger.error("生成采购单失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"OCR处理流程出错: {e}", exc_info=True)
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_required_columns(self) -> List[str]:
|
||||||
|
"""返回需要的列名列表"""
|
||||||
|
# OCR处理不直接依赖列名,由后续处理步骤决定
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_supported_extensions(self) -> List[str]:
|
||||||
|
"""支持的文件扩展名"""
|
||||||
|
return ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
|
||||||
|
def _perform_ocr(self, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""执行OCR识别
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入图片文件
|
||||||
|
output_dir: 输出目录
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
OCR生成的Excel文件路径,失败返回None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.logger.info(f"开始OCR识别: {input_file}")
|
||||||
|
|
||||||
|
# 使用OCR服务处理图片
|
||||||
|
result_path = self.ocr_service.process_image(str(input_file))
|
||||||
|
|
||||||
|
if result_path:
|
||||||
|
# 确保结果文件在输出目录中
|
||||||
|
result_path = Path(result_path)
|
||||||
|
if result_path.exists():
|
||||||
|
self.logger.info(f"OCR识别成功,输出文件: {result_path}")
|
||||||
|
return result_path
|
||||||
|
else:
|
||||||
|
self.logger.error(f"OCR结果文件不存在: {result_path}")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
self.logger.error("OCR服务返回None")
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"OCR识别失败: {e}", exc_info=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _process_excel(self, excel_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""处理Excel文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
excel_file: Excel文件路径
|
||||||
|
output_dir: 输出目录
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的Excel文件路径,失败返回None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.logger.info(f"开始处理Excel文件: {excel_file}")
|
||||||
|
|
||||||
|
# 使用订单服务处理Excel文件(生成采购单)
|
||||||
|
result_path = self.order_service.process_excel(str(excel_file))
|
||||||
|
|
||||||
|
if result_path:
|
||||||
|
result_path = Path(result_path)
|
||||||
|
if result_path.exists():
|
||||||
|
self.logger.info(f"Excel处理成功,输出文件: {result_path}")
|
||||||
|
return result_path
|
||||||
|
else:
|
||||||
|
self.logger.error(f"Excel处理结果文件不存在: {result_path}")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
self.logger.error("Excel处理服务返回None")
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Excel处理失败: {e}", exc_info=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _generate_purchase_order(self, processed_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""采购单生成由OrderService完成,此处直接返回处理结果"""
|
||||||
|
try:
|
||||||
|
if processed_file and processed_file.exists():
|
||||||
|
return processed_file
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
7
app/core/processors/supplier_processors/__init__.py
Normal file
7
app/core/processors/supplier_processors/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
供应商处理器模块初始化文件
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .generic_supplier_processor import GenericSupplierProcessor
|
||||||
|
|
||||||
|
__all__ = ['GenericSupplierProcessor']
|
||||||
@ -0,0 +1,483 @@
|
|||||||
|
"""
|
||||||
|
通用供应商处理器
|
||||||
|
|
||||||
|
可配置化的供应商处理器,支持通过配置文件定义处理规则
|
||||||
|
"""
|
||||||
|
|
||||||
|
import fnmatch
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Optional, Dict, Any, List
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from ..base import BaseProcessor
|
||||||
|
from ...utils.log_utils import get_logger
|
||||||
|
from ...handlers.rule_engine import apply_rules
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class GenericSupplierProcessor(BaseProcessor):
|
||||||
|
"""通用供应商处理器
|
||||||
|
|
||||||
|
基于配置文件处理不同供应商的Excel文件,支持:
|
||||||
|
- 文件名模式匹配
|
||||||
|
- 内容特征识别
|
||||||
|
- 列映射配置
|
||||||
|
- 数据清洗规则
|
||||||
|
- 计算处理规则
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any], supplier_config: Dict[str, Any]):
|
||||||
|
"""初始化通用供应商处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 系统配置
|
||||||
|
supplier_config: 供应商特定配置
|
||||||
|
"""
|
||||||
|
super().__init__(config)
|
||||||
|
self.supplier_config = supplier_config
|
||||||
|
|
||||||
|
# 从配置中提取基本信息
|
||||||
|
self.name = supplier_config.get('name', 'GenericSupplier')
|
||||||
|
self.description = supplier_config.get('description', '通用供应商处理器')
|
||||||
|
|
||||||
|
# 处理规则配置
|
||||||
|
self.filename_patterns = supplier_config.get('filename_patterns', [])
|
||||||
|
self.content_indicators = supplier_config.get('content_indicators', [])
|
||||||
|
self.column_mapping = supplier_config.get('column_mapping', {})
|
||||||
|
self.cleaning_rules = supplier_config.get('cleaning_rules', [])
|
||||||
|
self.calculations = supplier_config.get('calculations', [])
|
||||||
|
|
||||||
|
# 输出配置
|
||||||
|
self.output_template = supplier_config.get('output_template', 'templates/银豹-采购单模板.xls')
|
||||||
|
self.output_suffix = supplier_config.get('output_suffix', '_银豹采购单')
|
||||||
|
|
||||||
|
def can_process(self, file_path: Path) -> bool:
|
||||||
|
"""判断是否能处理该文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否能处理
|
||||||
|
"""
|
||||||
|
if not self.validate_input(file_path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查文件名模式
|
||||||
|
if self.filename_patterns:
|
||||||
|
filename_match = self._check_filename_patterns(file_path)
|
||||||
|
if filename_match:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 检查文件内容特征
|
||||||
|
if self.content_indicators:
|
||||||
|
content_match = self._check_content_indicators(file_path)
|
||||||
|
if content_match:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 如果都没有配置,则无法判断
|
||||||
|
if not self.filename_patterns and not self.content_indicators:
|
||||||
|
self.logger.warning(f"处理器 {self.name} 没有配置识别规则")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def process(self, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""处理文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入文件路径
|
||||||
|
output_dir: 输出目录路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径,处理失败返回None
|
||||||
|
"""
|
||||||
|
self.log_processing_start(input_file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 步骤1: 读取数据
|
||||||
|
self.logger.info("步骤1/4: 读取数据...")
|
||||||
|
df = self._read_supplier_data(input_file)
|
||||||
|
if df is None or df.empty:
|
||||||
|
self.logger.error("读取数据失败或数据为空")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 步骤2: 应用列映射
|
||||||
|
self.logger.info("步骤2/4: 应用列映射...")
|
||||||
|
mapped_df = self._apply_column_mapping(df)
|
||||||
|
if mapped_df is None:
|
||||||
|
self.logger.error("列映射失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 步骤3: 数据清洗
|
||||||
|
self.logger.info("步骤3/4: 数据清洗...")
|
||||||
|
cleaned_df = self._apply_data_cleaning(mapped_df)
|
||||||
|
if cleaned_df is None:
|
||||||
|
self.logger.error("数据清洗失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
rules = self.supplier_config.get('rules', [])
|
||||||
|
dictionary = self.supplier_config.get('dictionary')
|
||||||
|
standardized_df = apply_rules(cleaned_df, rules, dictionary)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"规则执行失败: {e}")
|
||||||
|
standardized_df = cleaned_df
|
||||||
|
|
||||||
|
# 步骤4: 计算处理
|
||||||
|
self.logger.info("步骤4/4: 计算处理...")
|
||||||
|
calculated_df = self._apply_calculations(standardized_df)
|
||||||
|
if calculated_df is None:
|
||||||
|
self.logger.error("计算处理失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 生成输出文件
|
||||||
|
output_file = self._generate_output(calculated_df, input_file, output_dir)
|
||||||
|
|
||||||
|
if output_file and output_file.exists():
|
||||||
|
self.logger.info(f"处理完成,输出文件: {output_file}")
|
||||||
|
self.log_processing_end(input_file, output_file, success=True)
|
||||||
|
return output_file
|
||||||
|
else:
|
||||||
|
self.logger.error("输出文件生成失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"处理文件时出错: {e}", exc_info=True)
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_required_columns(self) -> List[str]:
|
||||||
|
"""返回需要的列名列表"""
|
||||||
|
# 从列映射配置中提取目标列名
|
||||||
|
return list(self.column_mapping.values()) if self.column_mapping else []
|
||||||
|
|
||||||
|
def _check_filename_patterns(self, file_path: Path) -> bool:
|
||||||
|
"""检查文件名模式
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否匹配
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
filename = file_path.name
|
||||||
|
for pattern in self.filename_patterns:
|
||||||
|
if fnmatch.fnmatch(filename.lower(), pattern.lower()):
|
||||||
|
self.logger.info(f"文件名匹配成功: {filename} -> {pattern}")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"检查文件名模式时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _check_content_indicators(self, file_path: Path) -> bool:
|
||||||
|
"""检查文件内容特征
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否匹配
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
df = self._read_excel_safely(file_path, nrows=5)
|
||||||
|
|
||||||
|
# 检查列名中是否包含指定关键词
|
||||||
|
columns_str = str(list(df.columns)).lower()
|
||||||
|
|
||||||
|
for indicator in self.content_indicators:
|
||||||
|
if indicator.lower() in columns_str:
|
||||||
|
self.logger.info(f"内容特征匹配成功: {indicator}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"检查内容特征时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _read_supplier_data(self, file_path: Path) -> Optional[pd.DataFrame]:
|
||||||
|
"""读取供应商数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
数据DataFrame或None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
specified = self.supplier_config.get('header_row')
|
||||||
|
if specified is not None:
|
||||||
|
try:
|
||||||
|
df = self._read_excel_safely(file_path, header=int(specified))
|
||||||
|
except Exception:
|
||||||
|
df = self._read_excel_safely(file_path)
|
||||||
|
else:
|
||||||
|
df0 = self._read_excel_safely(file_path, header=None)
|
||||||
|
if df0 is None:
|
||||||
|
return None
|
||||||
|
header_row = self._find_header_row(df0)
|
||||||
|
if header_row is not None:
|
||||||
|
df = self._read_excel_safely(file_path, header=header_row)
|
||||||
|
else:
|
||||||
|
df = self._read_excel_safely(file_path)
|
||||||
|
if df is None or df.empty:
|
||||||
|
self.logger.warning("数据文件为空")
|
||||||
|
return None
|
||||||
|
self.logger.info(f"成功读取数据,形状: {df.shape}")
|
||||||
|
return df
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"读取数据失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _read_excel_safely(self, file_path: Path, **kwargs) -> pd.DataFrame:
|
||||||
|
"""根据扩展名选择合适的读取引擎并带有回退"""
|
||||||
|
suffix = file_path.suffix.lower()
|
||||||
|
try:
|
||||||
|
if suffix == '.xlsx':
|
||||||
|
return pd.read_excel(file_path, engine='openpyxl', **kwargs)
|
||||||
|
elif suffix == '.xls':
|
||||||
|
try:
|
||||||
|
return pd.read_excel(file_path, engine='xlrd', **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"读取xls失败,可能缺少xlrd: {e}")
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
return pd.read_excel(file_path, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"读取Excel失败: {file_path} - {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _find_header_row(self, df: pd.DataFrame) -> Optional[int]:
|
||||||
|
try:
|
||||||
|
header_keywords = [
|
||||||
|
'条码','条形码','商品编码','商品名称','名称','数量','单位','单价','规格',
|
||||||
|
'金额','小计','总计','合计','合计金额'
|
||||||
|
]
|
||||||
|
scores = []
|
||||||
|
rows_to_check = min(30, len(df))
|
||||||
|
for r in range(rows_to_check):
|
||||||
|
row = df.iloc[r]
|
||||||
|
score = 0
|
||||||
|
for cell in row:
|
||||||
|
if isinstance(cell, str):
|
||||||
|
s = cell.strip().lower()
|
||||||
|
for kw in header_keywords:
|
||||||
|
if kw.lower() in s:
|
||||||
|
score += 5
|
||||||
|
non_empty = row.count()
|
||||||
|
if non_empty / max(1, len(row)) > 0.5:
|
||||||
|
score += 2
|
||||||
|
str_count = sum(1 for c in row if isinstance(c, str))
|
||||||
|
if str_count / max(1, len(row)) > 0.5:
|
||||||
|
score += 3
|
||||||
|
scores.append((r, score))
|
||||||
|
scores.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
if scores and scores[0][1] >= 5:
|
||||||
|
return scores[0][0]
|
||||||
|
for r in range(len(df)):
|
||||||
|
if df.iloc[r].notna().sum() > 3:
|
||||||
|
return r
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _apply_column_mapping(self, df: pd.DataFrame) -> Optional[pd.DataFrame]:
|
||||||
|
"""应用列映射
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 原始数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
映射后的数据或None
|
||||||
|
"""
|
||||||
|
if not self.column_mapping:
|
||||||
|
self.logger.info("没有列映射配置")
|
||||||
|
return df
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 应用列重命名
|
||||||
|
df_renamed = df.rename(columns=self.column_mapping)
|
||||||
|
|
||||||
|
# 检查必需的列是否存在
|
||||||
|
required_columns = self.get_required_columns()
|
||||||
|
missing_columns = [col for col in required_columns if col not in df_renamed.columns]
|
||||||
|
|
||||||
|
if missing_columns:
|
||||||
|
self.logger.warning(f"缺少必需的列: {missing_columns}")
|
||||||
|
# 创建缺失的列并填充默认值
|
||||||
|
for col in missing_columns:
|
||||||
|
df_renamed[col] = 0 if '量' in col or '价' in col else ''
|
||||||
|
self.logger.info(f"创建缺失列: {col},默认值: {df_renamed[col].iloc[0] if len(df_renamed) > 0 else 'N/A'}")
|
||||||
|
|
||||||
|
self.logger.info(f"列映射完成,列名: {list(df_renamed.columns)}")
|
||||||
|
return df_renamed
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"列映射失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _apply_data_cleaning(self, df: pd.DataFrame) -> Optional[pd.DataFrame]:
|
||||||
|
"""应用数据清洗规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 映射后的数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
清洗后的数据或None
|
||||||
|
"""
|
||||||
|
if not self.cleaning_rules:
|
||||||
|
self.logger.info("没有数据清洗规则")
|
||||||
|
return df
|
||||||
|
|
||||||
|
try:
|
||||||
|
df_cleaned = df.copy()
|
||||||
|
|
||||||
|
for rule in self.cleaning_rules:
|
||||||
|
rule_type = rule.get('type')
|
||||||
|
|
||||||
|
if rule_type == 'remove_rows':
|
||||||
|
# 删除行
|
||||||
|
condition = rule.get('condition')
|
||||||
|
if condition:
|
||||||
|
before_count = len(df_cleaned)
|
||||||
|
df_cleaned = df_cleaned.query(condition)
|
||||||
|
after_count = len(df_cleaned)
|
||||||
|
self.logger.info(f"删除行规则: {condition}, 删除数量: {before_count - after_count}")
|
||||||
|
|
||||||
|
elif rule_type == 'fill_na':
|
||||||
|
# 填充空值,兼容单列和多列
|
||||||
|
columns = rule.get('columns') or [rule.get('column')] if rule.get('column') else []
|
||||||
|
value = rule.get('value', 0)
|
||||||
|
for col in columns:
|
||||||
|
if col and col in df_cleaned.columns:
|
||||||
|
na_count = df_cleaned[col].isna().sum()
|
||||||
|
df_cleaned[col] = df_cleaned[col].fillna(value)
|
||||||
|
self.logger.info(f"填充空值: {col} -> {value}, 填充数量: {na_count}")
|
||||||
|
|
||||||
|
elif rule_type == 'convert_type':
|
||||||
|
# 类型转换,兼容单列和多列
|
||||||
|
target_type = rule.get('target_type', 'float')
|
||||||
|
columns = rule.get('columns') or [rule.get('column')] if rule.get('column') else []
|
||||||
|
for col in columns:
|
||||||
|
if col and col in df_cleaned.columns:
|
||||||
|
try:
|
||||||
|
if target_type == 'float':
|
||||||
|
df_cleaned[col] = pd.to_numeric(df_cleaned[col], errors='coerce')
|
||||||
|
elif target_type == 'int':
|
||||||
|
df_cleaned[col] = pd.to_numeric(df_cleaned[col], errors='coerce').astype('Int64')
|
||||||
|
self.logger.info(f"类型转换: {col} -> {target_type}")
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"类型转换失败: {col} -> {target_type}: {e}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"未知的清洗规则类型: {rule_type}")
|
||||||
|
|
||||||
|
self.logger.info(f"数据清洗完成,数据形状: {df_cleaned.shape}")
|
||||||
|
return df_cleaned
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"数据清洗失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _apply_calculations(self, df: pd.DataFrame) -> Optional[pd.DataFrame]:
|
||||||
|
"""应用计算处理
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 清洗后的数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
计算后的数据或None
|
||||||
|
"""
|
||||||
|
if not self.calculations:
|
||||||
|
self.logger.info("没有计算规则")
|
||||||
|
return df
|
||||||
|
|
||||||
|
try:
|
||||||
|
df_calculated = df.copy()
|
||||||
|
|
||||||
|
for calculation in self.calculations:
|
||||||
|
calc_type = calculation.get('type')
|
||||||
|
|
||||||
|
if calc_type == 'multiply':
|
||||||
|
# 乘法计算
|
||||||
|
source_column = calculation.get('source_column')
|
||||||
|
target_column = calculation.get('target_column')
|
||||||
|
factor = calculation.get('factor', 1)
|
||||||
|
|
||||||
|
if source_column and target_column:
|
||||||
|
if source_column in df_calculated.columns:
|
||||||
|
df_calculated[target_column] = df_calculated[source_column] * factor
|
||||||
|
self.logger.info(f"乘法计算: {source_column} * {factor} -> {target_column}")
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"源列不存在: {source_column}")
|
||||||
|
|
||||||
|
elif calc_type == 'divide':
|
||||||
|
# 除法计算
|
||||||
|
source_column = calculation.get('source_column')
|
||||||
|
target_column = calculation.get('target_column')
|
||||||
|
divisor = calculation.get('divisor', 1)
|
||||||
|
|
||||||
|
if source_column and target_column and divisor != 0:
|
||||||
|
if source_column in df_calculated.columns:
|
||||||
|
df_calculated[target_column] = df_calculated[source_column] / divisor
|
||||||
|
self.logger.info(f"除法计算: {source_column} / {divisor} -> {target_column}")
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"源列不存在: {source_column}")
|
||||||
|
|
||||||
|
elif calc_type == 'formula':
|
||||||
|
# 公式计算
|
||||||
|
formula = calculation.get('formula')
|
||||||
|
target_column = calculation.get('target_column')
|
||||||
|
|
||||||
|
if formula and target_column:
|
||||||
|
try:
|
||||||
|
df_calculated[target_column] = df_calculated.eval(formula)
|
||||||
|
self.logger.info(f"公式计算: {formula} -> {target_column}")
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"公式计算失败: {formula}: {e}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"未知的计算类型: {calc_type}")
|
||||||
|
|
||||||
|
self.logger.info(f"计算处理完成,数据形状: {df_calculated.shape}")
|
||||||
|
return df_calculated
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"计算处理失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _generate_output(self, df: pd.DataFrame, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""生成输出文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: 最终数据
|
||||||
|
input_file: 输入文件路径
|
||||||
|
output_dir: 输出目录
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径或None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 生成输出文件名
|
||||||
|
timestamp = pd.Timestamp.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
output_filename = f"{input_file.stem}{self.output_suffix}_{timestamp}.xls"
|
||||||
|
output_file = output_dir / output_filename
|
||||||
|
|
||||||
|
# 这里应该使用实际的模板生成逻辑
|
||||||
|
# 暂时直接保存为Excel文件
|
||||||
|
df.to_excel(output_file, index=False)
|
||||||
|
|
||||||
|
self.logger.info(f"输出文件生成成功: {output_file}")
|
||||||
|
return output_file
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"生成输出文件失败: {e}")
|
||||||
|
return None
|
||||||
362
app/core/processors/tobacco_processor.py
Normal file
362
app/core/processors/tobacco_processor.py
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
"""
|
||||||
|
烟草订单处理器
|
||||||
|
|
||||||
|
处理烟草公司特定格式的订单明细文件,生成银豹采购单
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import pandas as pd
|
||||||
|
import xlrd
|
||||||
|
import xlwt
|
||||||
|
from xlutils.copy import copy
|
||||||
|
from openpyxl import load_workbook
|
||||||
|
from typing import Optional, Dict, Any, List, Tuple
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .base import BaseProcessor
|
||||||
|
from ...core.utils.log_utils import get_logger
|
||||||
|
from ...core.utils.dialog_utils import show_custom_dialog
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TobaccoProcessor(BaseProcessor):
|
||||||
|
"""烟草订单处理器
|
||||||
|
|
||||||
|
处理烟草公司订单明细文件,提取商品信息并生成标准银豹采购单格式
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any]):
|
||||||
|
"""初始化烟草订单处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 配置信息
|
||||||
|
"""
|
||||||
|
super().__init__(config)
|
||||||
|
self.description = "处理烟草公司订单明细文件"
|
||||||
|
self.template_file = config.get('Paths', 'template_file', fallback='templates/银豹-采购单模板.xls')
|
||||||
|
|
||||||
|
# 输出目录配置
|
||||||
|
self.result_dir = Path("data/result")
|
||||||
|
self.result_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# 默认输出文件名
|
||||||
|
self.default_output_name = "银豹采购单_烟草公司.xls"
|
||||||
|
|
||||||
|
def can_process(self, file_path: Path) -> bool:
|
||||||
|
"""判断是否为烟草订单文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否能处理该文件
|
||||||
|
"""
|
||||||
|
if not self.validate_input(file_path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查文件名特征
|
||||||
|
filename = file_path.name
|
||||||
|
tobacco_keywords = ['烟草', '卷烟', '订单明细', 'tobacco', '烟']
|
||||||
|
|
||||||
|
# 检查文件内容特征
|
||||||
|
try:
|
||||||
|
df = self._read_excel_safely(file_path, nrows=5)
|
||||||
|
required_columns = ['商品', '盒码', '订单量']
|
||||||
|
|
||||||
|
# 检查文件名或内容特征
|
||||||
|
filename_match = any(keyword in filename for keyword in tobacco_keywords)
|
||||||
|
content_match = all(col in df.columns for col in required_columns)
|
||||||
|
|
||||||
|
if filename_match or content_match:
|
||||||
|
self.logger.info(f"识别为烟草订单文件: {filename}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"检查文件内容时出错: {e}")
|
||||||
|
# 如果无法读取内容,仅基于文件名判断
|
||||||
|
return any(keyword in filename for keyword in tobacco_keywords)
|
||||||
|
|
||||||
|
def process(self, input_file: Path, output_dir: Path) -> Optional[Path]:
|
||||||
|
"""处理烟草订单
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入文件路径
|
||||||
|
output_dir: 输出目录路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径,处理失败返回None
|
||||||
|
"""
|
||||||
|
self.log_processing_start(input_file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 读取订单信息(时间和总金额)
|
||||||
|
order_info = self._read_order_info(input_file)
|
||||||
|
if not order_info:
|
||||||
|
self.logger.error(f"读取订单信息失败: {input_file}")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
order_time, total_amount = order_info
|
||||||
|
self.logger.info(f"订单信息 - 时间: {order_time}, 总金额: {total_amount}")
|
||||||
|
|
||||||
|
# 读取订单数据
|
||||||
|
order_data = self._read_order_data(input_file)
|
||||||
|
if order_data is None or order_data.empty:
|
||||||
|
self.logger.error(f"读取订单数据失败或数据为空: {input_file}")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.logger.info(f"成功读取订单数据,共{len(order_data)}条记录")
|
||||||
|
|
||||||
|
# 生成输出文件路径
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
output_filename = f"银豹采购单_烟草公司_{timestamp}.xls"
|
||||||
|
output_file = output_dir / output_filename
|
||||||
|
|
||||||
|
# 确保输出目录存在
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 生成银豹采购单
|
||||||
|
result = self._generate_pospal_order(order_data, order_time, output_file)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
self.logger.info(f"采购单生成成功: {output_file}")
|
||||||
|
self.log_processing_end(input_file, output_file, success=True)
|
||||||
|
|
||||||
|
# 显示处理结果
|
||||||
|
self._show_processing_result(output_file, order_time, len(order_data), total_amount)
|
||||||
|
|
||||||
|
return output_file
|
||||||
|
else:
|
||||||
|
self.logger.error("生成银豹采购单失败")
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"处理烟草订单时发生错误: {e}", exc_info=True)
|
||||||
|
self.log_processing_end(input_file, success=False)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_required_columns(self) -> List[str]:
|
||||||
|
"""返回需要的列名列表"""
|
||||||
|
return ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
||||||
|
|
||||||
|
def get_supported_extensions(self) -> List[str]:
|
||||||
|
"""支持的文件扩展名"""
|
||||||
|
return ['.xlsx', '.xls']
|
||||||
|
|
||||||
|
def _read_order_info(self, file_path: Path) -> Optional[Tuple[str, float]]:
|
||||||
|
"""读取订单信息(时间和总金额)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
包含订单时间和总金额的元组或None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
wb_info = load_workbook(file_path, data_only=True)
|
||||||
|
ws_info = wb_info.active
|
||||||
|
|
||||||
|
# 从指定单元格读取订单信息
|
||||||
|
order_time = ws_info["H1"].value or "(空)"
|
||||||
|
total_amount = ws_info["H3"].value or 0.0
|
||||||
|
|
||||||
|
self.logger.info(f"成功读取订单信息: 时间={order_time}, 总金额={total_amount}")
|
||||||
|
return (order_time, total_amount)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"读取订单信息出错: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _read_order_data(self, file_path: Path) -> Optional[pd.DataFrame]:
|
||||||
|
"""读取订单数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
订单数据DataFrame或None
|
||||||
|
"""
|
||||||
|
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
||||||
|
|
||||||
|
try:
|
||||||
|
df_old = self._read_excel_safely(file_path, header=None, skiprows=3, names=columns)
|
||||||
|
|
||||||
|
# 过滤订单量不为0的数据,并计算采购量和单价
|
||||||
|
df_filtered = df_old[df_old['订单量'] != 0].copy()
|
||||||
|
|
||||||
|
if df_filtered.empty:
|
||||||
|
self.logger.warning("没有订单量不为0的记录")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 计算采购量和单价
|
||||||
|
df_filtered['采购量'] = df_filtered['订单量'] * 10 # 烟草订单通常需要乘以10
|
||||||
|
df_filtered['采购单价'] = df_filtered['金额'] / df_filtered['采购量']
|
||||||
|
df_filtered = df_filtered.reset_index(drop=True)
|
||||||
|
|
||||||
|
self.logger.info(f"成功处理订单数据,有效记录数: {len(df_filtered)}")
|
||||||
|
return df_filtered
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"读取订单数据失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _read_excel_safely(self, file_path: Path, **kwargs) -> pd.DataFrame:
|
||||||
|
suffix = file_path.suffix.lower()
|
||||||
|
if suffix == '.xlsx':
|
||||||
|
return pd.read_excel(file_path, engine='openpyxl', **kwargs)
|
||||||
|
elif suffix == '.xls':
|
||||||
|
try:
|
||||||
|
return pd.read_excel(file_path, engine='xlrd', **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"读取xls失败,可能缺少xlrd: {e}")
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
return pd.read_excel(file_path, **kwargs)
|
||||||
|
|
||||||
|
def _generate_pospal_order(self, order_data: pd.DataFrame, order_time: str, output_file: Path) -> bool:
|
||||||
|
"""生成银豹采购单
|
||||||
|
|
||||||
|
Args:
|
||||||
|
order_data: 订单数据
|
||||||
|
order_time: 订单时间
|
||||||
|
output_file: 输出文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否生成成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 检查模板文件是否存在
|
||||||
|
template_path = Path(self.template_file)
|
||||||
|
if not template_path.exists():
|
||||||
|
self.logger.error(f"采购单模板文件不存在: {template_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.logger.info(f"使用模板文件: {template_path}")
|
||||||
|
|
||||||
|
# 打开模板,准备写入
|
||||||
|
template_rd = xlrd.open_workbook(str(template_path), formatting_info=True)
|
||||||
|
template_wb = copy(template_rd)
|
||||||
|
template_ws = template_wb.get_sheet(0)
|
||||||
|
|
||||||
|
# 获取模板中的表头列索引
|
||||||
|
header_row = template_rd.sheet_by_index(0).row_values(0)
|
||||||
|
|
||||||
|
# 查找需要的列索引
|
||||||
|
try:
|
||||||
|
barcode_col = header_row.index("条码(必填)")
|
||||||
|
amount_col = header_row.index("采购量(必填)")
|
||||||
|
gift_col = header_row.index("赠送量")
|
||||||
|
price_col = header_row.index("采购单价(必填)")
|
||||||
|
except ValueError as e:
|
||||||
|
self.logger.error(f"模板列查找失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.logger.info(f"模板列索引 - 条码:{barcode_col}, 采购量:{amount_col}, 赠送量:{gift_col}, 单价:{price_col}")
|
||||||
|
|
||||||
|
# 写入数据到模板
|
||||||
|
for i, row in order_data.iterrows():
|
||||||
|
template_ws.write(i + 1, barcode_col, row['盒码']) # 商品条码
|
||||||
|
template_ws.write(i + 1, amount_col, int(row['采购量'])) # 采购量
|
||||||
|
template_ws.write(i + 1, gift_col, "") # 赠送量为空
|
||||||
|
template_ws.write(i + 1, price_col, round(row['采购单价'], 2)) # 采购单价保留两位小数
|
||||||
|
|
||||||
|
# 确保输出目录存在
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 保存输出文件
|
||||||
|
template_wb.save(str(output_file))
|
||||||
|
|
||||||
|
self.logger.info(f"采购单生成成功: {output_file}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"生成银豹采购单失败: {e}", exc_info=True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _show_processing_result(self, output_file: Path, order_time: str, total_count: int, total_amount: float):
|
||||||
|
"""显示处理结果
|
||||||
|
|
||||||
|
Args:
|
||||||
|
output_file: 输出文件路径
|
||||||
|
order_time: 订单时间
|
||||||
|
total_count: 处理条目数
|
||||||
|
total_amount: 总金额
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 创建附加信息
|
||||||
|
additional_info = {
|
||||||
|
"订单来源": "烟草公司",
|
||||||
|
"处理时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
# 格式化金额显示
|
||||||
|
try:
|
||||||
|
if isinstance(total_amount, str):
|
||||||
|
total_amount = float(total_amount.replace(',', ''))
|
||||||
|
amount_display = f"¥{total_amount:.2f}"
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
amount_display = f"¥{total_amount}"
|
||||||
|
|
||||||
|
# 显示自定义对话框
|
||||||
|
show_custom_dialog(
|
||||||
|
title="烟草订单处理结果",
|
||||||
|
message="烟草订单处理完成",
|
||||||
|
result_file=str(output_file),
|
||||||
|
time_info=order_time,
|
||||||
|
count_info=f"{total_count}个商品",
|
||||||
|
amount_info=amount_display,
|
||||||
|
additional_info=additional_info
|
||||||
|
)
|
||||||
|
|
||||||
|
self.logger.info(f"显示处理结果 - 文件:{output_file}, 时间:{order_time}, 数量:{total_count}, 金额:{total_amount}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"显示处理结果时出错: {e}")
|
||||||
|
|
||||||
|
def get_latest_tobacco_order(self) -> Optional[Path]:
|
||||||
|
"""获取最新的烟草订单明细文件(兼容旧接口)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
文件路径或None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 获取今日开始时间戳
|
||||||
|
today = datetime.date.today()
|
||||||
|
today_start = datetime.datetime.combine(today, datetime.time.min).timestamp()
|
||||||
|
|
||||||
|
# 查找订单明细文件
|
||||||
|
result_dir = Path("data/output")
|
||||||
|
if not result_dir.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 查找符合条件的文件
|
||||||
|
candidates = []
|
||||||
|
for file_path in result_dir.glob("订单明细*.xlsx"):
|
||||||
|
if file_path.stat().st_ctime >= today_start:
|
||||||
|
candidates.append(file_path)
|
||||||
|
|
||||||
|
if not candidates:
|
||||||
|
self.logger.warning("未找到今天创建的烟草订单明细文件")
|
||||||
|
# 返回最新的文件
|
||||||
|
all_files = list(result_dir.glob("订单明细*.xlsx"))
|
||||||
|
if all_files:
|
||||||
|
all_files.sort(key=lambda x: x.stat().st_ctime, reverse=True)
|
||||||
|
return all_files[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 返回最新的文件
|
||||||
|
candidates.sort(key=lambda x: x.stat().st_ctime, reverse=True)
|
||||||
|
latest_file = candidates[0]
|
||||||
|
|
||||||
|
self.logger.info(f"找到最新烟草订单明细文件: {latest_file}")
|
||||||
|
return latest_file
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"获取最新烟草订单文件时出错: {e}")
|
||||||
|
return None
|
||||||
@ -219,6 +219,34 @@ def save_json(data: Any, file_path: str, ensure_ascii: bool = False, indent: int
|
|||||||
logger.error(f"保存JSON文件失败: {file_path}, 错误: {e}")
|
logger.error(f"保存JSON文件失败: {file_path}, 错误: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def smart_read_excel(file_path: Union[str, Path], **kwargs) -> Any:
|
||||||
|
"""
|
||||||
|
智能读取 Excel 文件,自动选择引擎并处理常见错误
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: Excel 文件路径
|
||||||
|
**kwargs: 传递给 pd.read_excel 的额外参数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
pandas.DataFrame 对象
|
||||||
|
"""
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
path_str = str(file_path)
|
||||||
|
ext = os.path.splitext(path_str)[1].lower()
|
||||||
|
|
||||||
|
# 自动选择引擎
|
||||||
|
if ext == '.xlsx':
|
||||||
|
kwargs.setdefault('engine', 'openpyxl')
|
||||||
|
elif ext == '.xls':
|
||||||
|
kwargs.setdefault('engine', 'xlrd')
|
||||||
|
|
||||||
|
try:
|
||||||
|
return pd.read_excel(path_str, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"读取 Excel 文件失败: {path_str}, 错误: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
def get_file_size(file_path: str) -> int:
|
def get_file_size(file_path: str) -> int:
|
||||||
"""
|
"""
|
||||||
获取文件大小(字节)
|
获取文件大小(字节)
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Dict
|
from typing import Optional, Dict
|
||||||
@ -58,7 +59,8 @@ def setup_logger(name: str,
|
|||||||
|
|
||||||
# 创建文件处理器
|
# 创建文件处理器
|
||||||
try:
|
try:
|
||||||
file_handler = logging.FileHandler(log_file, encoding='utf-8')
|
# 使用滚动日志,限制单个日志大小与备份数量
|
||||||
|
file_handler = RotatingFileHandler(log_file, maxBytes=5 * 1024 * 1024, backupCount=3, encoding='utf-8')
|
||||||
file_handler.setFormatter(formatter)
|
file_handler.setFormatter(formatter)
|
||||||
file_handler.setLevel(level)
|
file_handler.setLevel(level)
|
||||||
logger.addHandler(file_handler)
|
logger.addHandler(file_handler)
|
||||||
@ -175,4 +177,4 @@ def cleanup_active_marker(name: str) -> None:
|
|||||||
if os.path.exists(active_marker):
|
if os.path.exists(active_marker):
|
||||||
os.remove(active_marker)
|
os.remove(active_marker)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"无法清理日志活跃标记: {e}")
|
print(f"无法清理日志活跃标记: {e}")
|
||||||
|
|||||||
@ -4,7 +4,7 @@ OCR服务模块
|
|||||||
提供OCR识别服务,协调OCR流程。
|
提供OCR识别服务,协调OCR流程。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Dict, List, Optional, Tuple, Union, Any
|
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ..config.settings import ConfigManager
|
from ..config.settings import ConfigManager
|
||||||
@ -88,7 +88,7 @@ class OCRService:
|
|||||||
logger.error(f"处理图片时发生错误: {e}", exc_info=True)
|
logger.error(f"处理图片时发生错误: {e}", exc_info=True)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_images_batch(self, batch_size: int = None, max_workers: int = None) -> Tuple[int, int]:
|
def process_images_batch(self, batch_size: int = None, max_workers: int = None, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
批量处理图片
|
批量处理图片
|
||||||
|
|
||||||
@ -100,10 +100,10 @@ class OCRService:
|
|||||||
(总处理数, 成功处理数)元组
|
(总处理数, 成功处理数)元组
|
||||||
"""
|
"""
|
||||||
logger.info(f"OCRService开始批量处理图片, batch_size={batch_size}, max_workers={max_workers}")
|
logger.info(f"OCRService开始批量处理图片, batch_size={batch_size}, max_workers={max_workers}")
|
||||||
return self.ocr_processor.process_images_batch(batch_size, max_workers)
|
return self.ocr_processor.process_images_batch(batch_size, max_workers, progress_cb)
|
||||||
|
|
||||||
# 添加batch_process作为process_images_batch的别名,确保兼容性
|
# 添加batch_process作为process_images_batch的别名,确保兼容性
|
||||||
def batch_process(self, batch_size: int = None, max_workers: int = None) -> Tuple[int, int]:
|
def batch_process(self, batch_size: int = None, max_workers: int = None, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
批量处理图片(别名方法,与process_images_batch功能相同)
|
批量处理图片(别名方法,与process_images_batch功能相同)
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ class OCRService:
|
|||||||
(总处理数, 成功处理数)元组
|
(总处理数, 成功处理数)元组
|
||||||
"""
|
"""
|
||||||
logger.info(f"OCRService.batch_process被调用,转发到process_images_batch")
|
logger.info(f"OCRService.batch_process被调用,转发到process_images_batch")
|
||||||
return self.process_images_batch(batch_size, max_workers)
|
return self.process_images_batch(batch_size, max_workers, progress_cb)
|
||||||
|
|
||||||
def validate_image(self, image_path: str) -> bool:
|
def validate_image(self, image_path: str) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -190,4 +190,4 @@ class OCRService:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"生成Excel文件时发生错误: {e}", exc_info=True)
|
logger.error(f"生成Excel文件时发生错误: {e}", exc_info=True)
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
提供订单处理服务,协调Excel处理和订单合并流程。
|
提供订单处理服务,协调Excel处理和订单合并流程。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Dict, List, Optional, Tuple, Union, Any
|
import os
|
||||||
|
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||||
|
|
||||||
from ..config.settings import ConfigManager
|
from ..config.settings import ConfigManager
|
||||||
from ..core.utils.log_utils import get_logger
|
from ..core.utils.log_utils import get_logger
|
||||||
@ -43,9 +44,9 @@ class OrderService:
|
|||||||
"""
|
"""
|
||||||
return self.excel_processor.get_latest_excel()
|
return self.excel_processor.get_latest_excel()
|
||||||
|
|
||||||
def process_excel(self, file_path: Optional[str] = None) -> Optional[str]:
|
def process_excel(self, file_path: Optional[str] = None, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理Excel文件,生成采购单
|
处理Excel订单文件,生成标准采购单
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Excel文件路径,如果为None则处理最新的文件
|
file_path: Excel文件路径,如果为None则处理最新的文件
|
||||||
@ -53,12 +54,84 @@ class OrderService:
|
|||||||
Returns:
|
Returns:
|
||||||
输出采购单文件路径,如果处理失败则返回None
|
输出采购单文件路径,如果处理失败则返回None
|
||||||
"""
|
"""
|
||||||
if file_path:
|
if not file_path:
|
||||||
logger.info(f"OrderService开始处理指定Excel文件: {file_path}")
|
file_path = self.excel_processor.get_latest_excel()
|
||||||
return self.excel_processor.process_specific_file(file_path)
|
if not file_path:
|
||||||
else:
|
logger.warning("未找到可处理的Excel文件")
|
||||||
|
return None
|
||||||
logger.info("OrderService开始处理最新Excel文件")
|
logger.info("OrderService开始处理最新Excel文件")
|
||||||
return self.excel_processor.process_latest_file()
|
else:
|
||||||
|
logger.info(f"OrderService开始处理指定Excel文件: {file_path}")
|
||||||
|
|
||||||
|
# 检查是否需要特殊的供应商预处理(如杨碧月)
|
||||||
|
try:
|
||||||
|
from .special_suppliers_service import SpecialSuppliersService
|
||||||
|
special_service = SpecialSuppliersService(self.config)
|
||||||
|
|
||||||
|
# 尝试识别并预处理(注意:这里不再传入 progress_cb 避免无限递归或重复进度条,
|
||||||
|
# 或者我们在 special_service 内部逻辑中处理完后直接返回结果)
|
||||||
|
# 为了避免循环调用,我们在 SpecialSuppliersService 内部不再调用 process_excel,
|
||||||
|
# 而是让 process_excel 识别后自己决定是否处理预处理后的文件。
|
||||||
|
|
||||||
|
# 我们新增一个 check_and_preprocess 方法
|
||||||
|
preprocessed_path = self._check_special_preprocess(file_path)
|
||||||
|
if preprocessed_path:
|
||||||
|
logger.info(f"检测到特殊供应商,已生成预处理文件: {preprocessed_path}")
|
||||||
|
file_path = preprocessed_path
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"检查特殊预处理时出错: {e}")
|
||||||
|
|
||||||
|
return self.excel_processor.process_specific_file(file_path, progress_cb=progress_cb)
|
||||||
|
|
||||||
|
def _check_special_preprocess(self, file_path: str) -> Optional[str]:
|
||||||
|
"""检查并执行特殊的预处理(支持杨碧月、烟草公司、蓉城易购)"""
|
||||||
|
try:
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
|
import pandas as pd
|
||||||
|
import re
|
||||||
|
|
||||||
|
# 仅读取前 50 行进行智能识别 (header=None 确保能读到第一行内容)
|
||||||
|
df_head = smart_read_excel(file_path, nrows=50, header=None)
|
||||||
|
df_str = df_head.astype(str)
|
||||||
|
|
||||||
|
# 1. 识别:烟草公司 (Tobacco)
|
||||||
|
# 特征:内容中包含“专卖证号”或特定证号“510109104938”
|
||||||
|
is_tobacco = df_str.apply(lambda x: x.str.contains('专卖证号|510109104938')).any().any()
|
||||||
|
if is_tobacco:
|
||||||
|
logger.info("识别到烟草公司订单,执行专用预处理...")
|
||||||
|
from .tobacco_service import TobaccoService
|
||||||
|
tobacco_svc = TobaccoService(self.config)
|
||||||
|
return tobacco_svc.preprocess_tobacco_order(file_path)
|
||||||
|
|
||||||
|
# 2. 识别:蓉城易购 (Rongcheng Yigou)
|
||||||
|
# 特征:内容中包含单号标识“RCDH”
|
||||||
|
is_rongcheng = df_str.apply(lambda x: x.str.contains('RCDH')).any().any()
|
||||||
|
if is_rongcheng:
|
||||||
|
logger.info("识别到蓉城易购订单,执行专用预处理...")
|
||||||
|
from .special_suppliers_service import SpecialSuppliersService
|
||||||
|
special_svc = SpecialSuppliersService(self.config)
|
||||||
|
return special_svc.preprocess_rongcheng_yigou(file_path)
|
||||||
|
|
||||||
|
# 3. 识别:杨碧月 (Yang Biyue)
|
||||||
|
# 特征:经手人列包含“杨碧月”
|
||||||
|
handler_col = None
|
||||||
|
for col in df_head.columns:
|
||||||
|
# 在前50行中搜索“经手人”关键字
|
||||||
|
if df_head[col].astype(str).str.contains('经手人').any():
|
||||||
|
handler_col = col
|
||||||
|
break
|
||||||
|
|
||||||
|
if handler_col is not None:
|
||||||
|
# 检查该列是否有“杨碧月”
|
||||||
|
if df_head[handler_col].astype(str).str.contains('杨碧月').any():
|
||||||
|
logger.info("识别到杨碧月订单,执行专用预处理...")
|
||||||
|
from .special_suppliers_service import SpecialSuppliersService
|
||||||
|
special_svc = SpecialSuppliersService(self.config)
|
||||||
|
return special_svc.process_yang_biyue_only(file_path)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"智能预处理识别失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def get_purchase_orders(self) -> List[str]:
|
def get_purchase_orders(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
@ -69,7 +142,7 @@ class OrderService:
|
|||||||
"""
|
"""
|
||||||
return self.order_merger.get_purchase_orders()
|
return self.order_merger.get_purchase_orders()
|
||||||
|
|
||||||
def merge_purchase_orders(self, file_paths: List[str]) -> Optional[str]:
|
def merge_purchase_orders(self, file_paths: List[str], progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并指定的采购单文件
|
合并指定的采购单文件
|
||||||
|
|
||||||
@ -80,9 +153,9 @@ class OrderService:
|
|||||||
合并后的采购单文件路径,如果合并失败则返回None
|
合并后的采购单文件路径,如果合并失败则返回None
|
||||||
"""
|
"""
|
||||||
logger.info(f"OrderService开始合并指定采购单: {file_paths}")
|
logger.info(f"OrderService开始合并指定采购单: {file_paths}")
|
||||||
return self.merge_orders(file_paths)
|
return self.merge_orders(file_paths, progress_cb)
|
||||||
|
|
||||||
def merge_all_purchase_orders(self) -> Optional[str]:
|
def merge_all_purchase_orders(self, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并所有可用的采购单文件
|
合并所有可用的采购单文件
|
||||||
|
|
||||||
@ -90,9 +163,9 @@ class OrderService:
|
|||||||
合并后的采购单文件路径,如果合并失败则返回None
|
合并后的采购单文件路径,如果合并失败则返回None
|
||||||
"""
|
"""
|
||||||
logger.info("OrderService开始合并所有采购单")
|
logger.info("OrderService开始合并所有采购单")
|
||||||
return self.merge_orders(None)
|
return self.merge_orders(None, progress_cb)
|
||||||
|
|
||||||
def merge_orders(self, file_paths: Optional[List[str]] = None) -> Optional[str]:
|
def merge_orders(self, file_paths: Optional[List[str]] = None, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并采购单
|
合并采购单
|
||||||
|
|
||||||
@ -107,4 +180,72 @@ class OrderService:
|
|||||||
else:
|
else:
|
||||||
logger.info("OrderService开始合并所有采购单")
|
logger.info("OrderService开始合并所有采购单")
|
||||||
|
|
||||||
return self.order_merger.process(file_paths)
|
return self.order_merger.process(file_paths, progress_cb)
|
||||||
|
|
||||||
|
def validate_unit_price(self, result_path: str) -> List[str]:
|
||||||
|
"""
|
||||||
|
校验采购单单价与商品资料进货价的差异
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result_path: 待校验的采购单路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
差异信息列表,无差异返回空列表
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
|
|
||||||
|
item_path = os.path.join('templates', '商品资料.xlsx')
|
||||||
|
if not os.path.exists(item_path):
|
||||||
|
logger.warning(f"未找到商品资料文件: {item_path}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
df_item = smart_read_excel(item_path)
|
||||||
|
df_res = smart_read_excel(result_path)
|
||||||
|
|
||||||
|
def _find_col(df, candidates, contains=None):
|
||||||
|
cols = list(df.columns)
|
||||||
|
for c in candidates:
|
||||||
|
if c in cols:
|
||||||
|
return c
|
||||||
|
if contains:
|
||||||
|
for c in cols:
|
||||||
|
if contains in str(c):
|
||||||
|
return c
|
||||||
|
return None
|
||||||
|
|
||||||
|
item_barcode_col = _find_col(df_item, ['商品条码','商品条码(小条码)','条码','barcode'], contains='条码')
|
||||||
|
item_price_col = _find_col(df_item, ['进货价','进货价(必填)'], contains='进货价')
|
||||||
|
res_barcode_col = _find_col(df_res, ['条码','barcode'], contains='条码')
|
||||||
|
res_price_col = _find_col(df_res, ['采购单价','unit_price','单价'], contains='单价')
|
||||||
|
|
||||||
|
if not all([item_barcode_col, item_price_col, res_barcode_col, res_price_col]):
|
||||||
|
logger.warning("未能在文件和商品资料中找到完整的校验列(条码、单价)")
|
||||||
|
return []
|
||||||
|
|
||||||
|
item_map = df_item[[item_barcode_col, item_price_col]].dropna()
|
||||||
|
item_map[item_price_col] = pd.to_numeric(item_map[item_price_col], errors='coerce')
|
||||||
|
item_map = item_map.dropna()
|
||||||
|
imap = dict(zip(item_map[item_barcode_col].astype(str).str.strip(), item_map[item_price_col]))
|
||||||
|
|
||||||
|
df_res['_bc_'] = df_res[res_barcode_col].astype(str).str.strip()
|
||||||
|
df_res['_res_price_'] = pd.to_numeric(df_res[res_price_col], errors='coerce')
|
||||||
|
df_res['_item_price_'] = df_res['_bc_'].map(imap)
|
||||||
|
|
||||||
|
df_check = df_res.dropna(subset=['_res_price_','_item_price_'])
|
||||||
|
df_check['_diff_'] = (df_check['_res_price_'] - df_check['_item_price_']).abs()
|
||||||
|
bad = df_check[df_check['_diff_'] > 1.0]
|
||||||
|
|
||||||
|
results = []
|
||||||
|
if not bad.empty:
|
||||||
|
for i in range(len(bad)):
|
||||||
|
r = bad.iloc[i]
|
||||||
|
results.append(f"条码 {r['_bc_']}: 采购单价={r['_res_price_']} vs 进货价={r['_item_price_']} 差异={r['_diff_']:.2f}")
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"单价校验过程中发生错误: {e}")
|
||||||
|
return []
|
||||||
|
|||||||
297
app/services/processor_service.py
Normal file
297
app/services/processor_service.py
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
"""
|
||||||
|
处理器调度服务
|
||||||
|
|
||||||
|
负责管理和调度各种文件处理器,实现智能文件类型检测和处理器选择
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Any, Optional, List
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from ..core.processors.base import BaseProcessor
|
||||||
|
from ..core.processors.tobacco_processor import TobaccoProcessor
|
||||||
|
from ..core.processors.ocr_processor import OCRProcessor
|
||||||
|
from ..core.utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessorService:
|
||||||
|
"""处理器调度服务
|
||||||
|
|
||||||
|
负责管理所有处理器实例,提供统一的文件处理接口
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any]):
|
||||||
|
"""初始化处理器服务
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: 系统配置字典
|
||||||
|
"""
|
||||||
|
self.config = config
|
||||||
|
self.processors: List[BaseProcessor] = []
|
||||||
|
self._load_processors()
|
||||||
|
logger.info(f"处理器服务初始化完成,加载了{len(self.processors)}个处理器")
|
||||||
|
|
||||||
|
def _load_processors(self):
|
||||||
|
"""加载所有处理器"""
|
||||||
|
try:
|
||||||
|
self.processors = [
|
||||||
|
TobaccoProcessor(self.config),
|
||||||
|
OCRProcessor(self.config),
|
||||||
|
]
|
||||||
|
|
||||||
|
supplier_configs = []
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
# 优先从`config/suppliers_config.json`加载
|
||||||
|
config_path = Path("config/suppliers_config.json")
|
||||||
|
if not config_path.exists():
|
||||||
|
# 兼容其它路径
|
||||||
|
config_path = Path("./suppliers_config.json")
|
||||||
|
if config_path.exists():
|
||||||
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
ok, errs, supplier_configs = self._validate_suppliers_config(data)
|
||||||
|
if not ok:
|
||||||
|
logger.error("供应商配置校验失败:\n" + "\n".join([f"- {e}" for e in errs]))
|
||||||
|
else:
|
||||||
|
logger.info(f"从 {config_path} 加载供应商配置,共 {len(supplier_configs)} 项")
|
||||||
|
else:
|
||||||
|
logger.info("未找到供应商配置文件,跳过供应商处理器加载")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"读取供应商配置失败: {e}")
|
||||||
|
|
||||||
|
for supplier_config in supplier_configs:
|
||||||
|
try:
|
||||||
|
from ..core.processors.supplier_processors.generic_supplier_processor import GenericSupplierProcessor
|
||||||
|
processor = GenericSupplierProcessor(self.config, supplier_config)
|
||||||
|
self.processors.append(processor)
|
||||||
|
logger.info(f"加载供应商处理器: {processor.name}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"加载供应商处理器失败: {e}")
|
||||||
|
|
||||||
|
logger.info(f"成功加载{len(self.processors)}个处理器")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"加载处理器时出错: {e}", exc_info=True)
|
||||||
|
self.processors = [
|
||||||
|
TobaccoProcessor(self.config),
|
||||||
|
OCRProcessor(self.config),
|
||||||
|
]
|
||||||
|
|
||||||
|
def _validate_suppliers_config(self, data):
|
||||||
|
try:
|
||||||
|
suppliers = data.get('suppliers')
|
||||||
|
errors = []
|
||||||
|
valid = []
|
||||||
|
if not isinstance(suppliers, list) or not suppliers:
|
||||||
|
errors.append('suppliers必须是非空数组')
|
||||||
|
return False, errors, []
|
||||||
|
for idx, s in enumerate(suppliers):
|
||||||
|
e = self._validate_single_supplier(s, idx)
|
||||||
|
if e:
|
||||||
|
errors.extend(e)
|
||||||
|
else:
|
||||||
|
valid.append(s)
|
||||||
|
return len(errors) == 0, errors, valid
|
||||||
|
except Exception as e:
|
||||||
|
return False, [f'配置解析异常: {e}'], []
|
||||||
|
|
||||||
|
def _validate_single_supplier(self, s, idx):
|
||||||
|
errs = []
|
||||||
|
prefix = f'suppliers[{idx}]'
|
||||||
|
name = s.get('name')
|
||||||
|
if not name or not isinstance(name, str):
|
||||||
|
errs.append(f'{prefix}.name 必须为字符串')
|
||||||
|
fp = s.get('filename_patterns', [])
|
||||||
|
ci = s.get('content_indicators', [])
|
||||||
|
if not fp and not ci:
|
||||||
|
errs.append(f'{prefix} 必须至少提供 filename_patterns 或 content_indicators 之一')
|
||||||
|
cm = s.get('column_mapping', {})
|
||||||
|
if cm and not isinstance(cm, dict):
|
||||||
|
errs.append(f'{prefix}.column_mapping 必须为对象')
|
||||||
|
cr = s.get('cleaning_rules', [])
|
||||||
|
if cr and not isinstance(cr, list):
|
||||||
|
errs.append(f'{prefix}.cleaning_rules 必须为数组')
|
||||||
|
else:
|
||||||
|
for i, rule in enumerate(cr):
|
||||||
|
rtype = rule.get('type')
|
||||||
|
if rtype not in ('remove_rows','fill_na','convert_type'):
|
||||||
|
errs.append(f'{prefix}.cleaning_rules[{i}].type 非法: {rtype}')
|
||||||
|
if rtype == 'remove_rows' and not rule.get('condition'):
|
||||||
|
errs.append(f'{prefix}.cleaning_rules[{i}].condition 必填')
|
||||||
|
if rtype in ('fill_na','convert_type'):
|
||||||
|
if not rule.get('columns') and not rule.get('column'):
|
||||||
|
errs.append(f'{prefix}.cleaning_rules[{i}] 需提供 columns 或 column')
|
||||||
|
calc = s.get('calculations', [])
|
||||||
|
if calc and not isinstance(calc, list):
|
||||||
|
errs.append(f'{prefix}.calculations 必须为数组')
|
||||||
|
else:
|
||||||
|
for i, c in enumerate(calc):
|
||||||
|
ctype = c.get('type')
|
||||||
|
if ctype not in ('multiply','divide','formula'):
|
||||||
|
errs.append(f'{prefix}.calculations[{i}].type 非法: {ctype}')
|
||||||
|
if ctype in ('multiply','divide'):
|
||||||
|
if not c.get('source_column') or not c.get('target_column'):
|
||||||
|
errs.append(f'{prefix}.calculations[{i}] 需提供 source_column 与 target_column')
|
||||||
|
if ctype == 'formula' and (not c.get('formula') or not c.get('target_column')):
|
||||||
|
errs.append(f'{prefix}.calculations[{i}] 需提供 formula 与 target_column')
|
||||||
|
return errs
|
||||||
|
|
||||||
|
def process_file(self, input_file: Path, output_dir: Path,
|
||||||
|
preferred_processor: Optional[str] = None) -> Optional[Path]:
|
||||||
|
"""处理文件 - 自动选择合适的处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_file: 输入文件路径
|
||||||
|
output_dir: 输出目录路径
|
||||||
|
preferred_processor: 优先使用的处理器名称(可选)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径,处理失败返回None
|
||||||
|
"""
|
||||||
|
if not input_file.exists():
|
||||||
|
logger.error(f"输入文件不存在: {input_file}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not output_dir.exists():
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 如果指定了优先处理器,先尝试使用它
|
||||||
|
if preferred_processor:
|
||||||
|
processor = self._get_processor_by_name(preferred_processor)
|
||||||
|
if processor and processor.can_process(input_file):
|
||||||
|
logger.info(f"使用指定的处理器: {processor.name}")
|
||||||
|
return processor.process(input_file, output_dir)
|
||||||
|
else:
|
||||||
|
logger.warning(f"指定的处理器不可用或无法处理该文件: {preferred_processor}")
|
||||||
|
|
||||||
|
# 自动选择合适的处理器
|
||||||
|
suitable_processors = [p for p in self.processors if p.can_process(input_file)]
|
||||||
|
|
||||||
|
if not suitable_processors:
|
||||||
|
logger.warning(f"未找到适合处理文件的处理器: {input_file}")
|
||||||
|
logger.info(f"支持的文件类型: {self.get_supported_types()}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 使用第一个合适的处理器
|
||||||
|
processor = suitable_processors[0]
|
||||||
|
logger.info(f"使用处理器 {processor.name} 处理文件: {input_file}")
|
||||||
|
|
||||||
|
return processor.process(input_file, output_dir)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理文件时出错: {e}", exc_info=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_processor_by_name(self, name: str) -> Optional[BaseProcessor]:
|
||||||
|
"""根据名称获取处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: 处理器名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理器实例或None
|
||||||
|
"""
|
||||||
|
for processor in self.processors:
|
||||||
|
if processor.name == name or processor.__class__.__name__ == name:
|
||||||
|
return processor
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_supported_types(self) -> List[Dict[str, Any]]:
|
||||||
|
"""获取支持的文件类型信息
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理器类型信息列表
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'name': processor.name,
|
||||||
|
'description': processor.description,
|
||||||
|
'extensions': processor.get_supported_extensions(),
|
||||||
|
'class_name': processor.__class__.__name__
|
||||||
|
}
|
||||||
|
for processor in self.processors
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_processor_info(self) -> List[Dict[str, Any]]:
|
||||||
|
"""获取处理器详细信息
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理器详细信息列表
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'name': processor.name,
|
||||||
|
'description': processor.description,
|
||||||
|
'extensions': processor.get_supported_extensions(),
|
||||||
|
'required_columns': processor.get_required_columns(),
|
||||||
|
'class_name': processor.__class__.__name__,
|
||||||
|
'module': processor.__class__.__module__
|
||||||
|
}
|
||||||
|
for processor in self.processors
|
||||||
|
]
|
||||||
|
|
||||||
|
def can_process_file(self, file_path: Path) -> bool:
|
||||||
|
"""检查是否有处理器能处理该文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否有处理器能处理
|
||||||
|
"""
|
||||||
|
if not file_path.exists():
|
||||||
|
return False
|
||||||
|
|
||||||
|
return any(processor.can_process(file_path) for processor in self.processors)
|
||||||
|
|
||||||
|
def get_suitable_processors(self, file_path: Path) -> List[BaseProcessor]:
|
||||||
|
"""获取能处理该文件的所有处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
合适的处理器列表
|
||||||
|
"""
|
||||||
|
if not file_path.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [p for p in self.processors if p.can_process(file_path)]
|
||||||
|
|
||||||
|
def reload_processors(self):
|
||||||
|
"""重新加载处理器"""
|
||||||
|
logger.info("重新加载处理器...")
|
||||||
|
self.processors.clear()
|
||||||
|
self._load_processors()
|
||||||
|
logger.info(f"重新加载完成,共{len(self.processors)}个处理器")
|
||||||
|
|
||||||
|
def add_processor(self, processor: BaseProcessor):
|
||||||
|
"""添加处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
processor: 处理器实例
|
||||||
|
"""
|
||||||
|
self.processors.append(processor)
|
||||||
|
logger.info(f"添加处理器: {processor.name}")
|
||||||
|
|
||||||
|
def remove_processor(self, processor_name: str) -> bool:
|
||||||
|
"""移除处理器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
processor_name: 处理器名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否成功移除
|
||||||
|
"""
|
||||||
|
for i, processor in enumerate(self.processors):
|
||||||
|
if processor.name == processor_name or processor.__class__.__name__ == processor_name:
|
||||||
|
del self.processors[i]
|
||||||
|
logger.info(f"移除处理器: {processor_name}")
|
||||||
|
return True
|
||||||
|
logger.warning(f"未找到要移除的处理器: {processor_name}")
|
||||||
|
return False
|
||||||
223
app/services/special_suppliers_service.py
Normal file
223
app/services/special_suppliers_service.py
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import pandas as pd
|
||||||
|
import logging
|
||||||
|
from typing import Optional, Callable
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class SpecialSuppliersService:
|
||||||
|
"""
|
||||||
|
处理特殊供应商逻辑的服务类,如蓉城易购等
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, config_manager=None):
|
||||||
|
self.config_manager = config_manager
|
||||||
|
|
||||||
|
def process_yang_biyue_only(self, src_path: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
仅执行杨碧月订单的预处理,返回预处理后的文件路径
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
|
# 读取原始数据
|
||||||
|
df = smart_read_excel(src_path)
|
||||||
|
|
||||||
|
# 检查是否包含“杨碧月”
|
||||||
|
handler_col = None
|
||||||
|
for col in df.columns:
|
||||||
|
if '经手人' in str(col):
|
||||||
|
handler_col = col
|
||||||
|
break
|
||||||
|
|
||||||
|
if handler_col is None or not df[handler_col].astype(str).str.contains('杨碧月').any():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 识别到杨碧月订单,执行专用清洗
|
||||||
|
logger.info("识别到杨碧月订单,正在执行专用清洗...")
|
||||||
|
|
||||||
|
# 定义列映射关系 (映射到 ExcelProcessor 期望的中文列名)
|
||||||
|
# 使用精确匹配优先,防止“结算单位”匹配到“单位”
|
||||||
|
column_map = {
|
||||||
|
'商品条码': '商品条码',
|
||||||
|
'商品名称': '商品名称',
|
||||||
|
'商品规格': '规格',
|
||||||
|
'单位': '单位',
|
||||||
|
'数量': '数量',
|
||||||
|
'含税单价': '单价',
|
||||||
|
'含税金额': '金额'
|
||||||
|
}
|
||||||
|
|
||||||
|
found_cols = {}
|
||||||
|
# 1. 第一遍:尝试精确匹配
|
||||||
|
for target_zh, std_name in column_map.items():
|
||||||
|
for col in df.columns:
|
||||||
|
if str(col).strip() == target_zh:
|
||||||
|
found_cols[col] = std_name
|
||||||
|
break
|
||||||
|
|
||||||
|
# 2. 第二遍:对未匹配成功的列尝试模糊匹配(但要排除特定干扰词)
|
||||||
|
for target_zh, std_name in column_map.items():
|
||||||
|
if std_name in found_cols.values():
|
||||||
|
continue
|
||||||
|
for col in df.columns:
|
||||||
|
col_str = str(col)
|
||||||
|
if target_zh in col_str:
|
||||||
|
# 排除干扰列
|
||||||
|
if target_zh == '单位' and '结算单位' in col_str:
|
||||||
|
continue
|
||||||
|
if target_zh == '数量' and '基本单位数量' in col_str:
|
||||||
|
continue
|
||||||
|
found_cols[col] = std_name
|
||||||
|
break
|
||||||
|
|
||||||
|
if len(found_cols) < 4:
|
||||||
|
logger.error(f"杨碧月订单列匹配不足: 找到 {list(found_cols.values())}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
df_clean = df[list(found_cols.keys())].copy()
|
||||||
|
df_clean = df_clean.rename(columns=found_cols)
|
||||||
|
|
||||||
|
# 过滤掉空的条码行
|
||||||
|
df_clean = df_clean.dropna(subset=['商品条码'])
|
||||||
|
|
||||||
|
# 保存预处理文件
|
||||||
|
out_dir = os.path.dirname(src_path)
|
||||||
|
base = os.path.basename(src_path)
|
||||||
|
final_path = os.path.join(out_dir, f"预处理之后_{base}")
|
||||||
|
df_clean.to_excel(final_path, index=False)
|
||||||
|
|
||||||
|
return final_path
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"预处理杨碧月订单出错: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_yang_biyue(self, src_path: str, progress_cb: Optional[Callable[[int, str], None]] = None) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
处理杨碧月经手的订单(预处理+处理)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if progress_cb: progress_cb(10, "正在进行杨碧月订单预处理...")
|
||||||
|
preprocessed_path = self.process_yang_biyue_only(src_path)
|
||||||
|
|
||||||
|
if not preprocessed_path:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if progress_cb: progress_cb(60, "预处理文件已保存,开始标准转换流程...")
|
||||||
|
|
||||||
|
# 延迟导入以避免循环依赖
|
||||||
|
from app.services.order_service import OrderService
|
||||||
|
order_service = OrderService(self.config_manager)
|
||||||
|
result = order_service.process_excel(preprocessed_path, progress_cb=lambda p: progress_cb(60 + int(p*0.4), "生成采购单中...") if progress_cb else None)
|
||||||
|
return result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理杨碧月订单出错: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def preprocess_rongcheng_yigou(self, src_path: str, progress_cb: Optional[Callable[[int, str], None]] = None) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
蓉城易购订单预处理:按用户提供的 E, N, Q, S 列索引进行强制清洗
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if progress_cb: progress_cb(10, "正在处理蓉城易购预处理...")
|
||||||
|
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
|
# 蓉城易购格式:Row 0是单号,Row 1是联系人,Row 2是表头,Row 3开始是数据
|
||||||
|
df_raw = smart_read_excel(src_path, header=None)
|
||||||
|
|
||||||
|
# 检查数据行数
|
||||||
|
if len(df_raw) <= 3:
|
||||||
|
logger.error("蓉城易购文件数据行数不足")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 提取数据部分 (Row 3开始)
|
||||||
|
df_data = df_raw.iloc[3:].reset_index(drop=True)
|
||||||
|
|
||||||
|
# 用户指定列映射:
|
||||||
|
# E列 (Index 4) -> 商品条码
|
||||||
|
# N列 (Index 13) -> 数量
|
||||||
|
# Q列 (Index 16) -> 单价
|
||||||
|
# S列 (Index 18) -> 金额
|
||||||
|
# C列 (Index 2) -> 商品名称 (通用需求)
|
||||||
|
|
||||||
|
idx_map = {
|
||||||
|
2: '商品名称',
|
||||||
|
4: '商品条码',
|
||||||
|
13: '数量',
|
||||||
|
16: '单价',
|
||||||
|
18: '金额'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 确保列索引不越界
|
||||||
|
available_indices = [i for i in idx_map.keys() if i < df_data.shape[1]]
|
||||||
|
df2 = df_data.iloc[:, available_indices].copy()
|
||||||
|
df2.columns = [idx_map[i] for i in available_indices]
|
||||||
|
|
||||||
|
# 强制转换类型
|
||||||
|
for c in ['数量', '单价', '金额']:
|
||||||
|
if c in df2.columns:
|
||||||
|
df2[c] = pd.to_numeric(df2[c], errors='coerce').fillna(0)
|
||||||
|
|
||||||
|
# 过滤掉空的条码行
|
||||||
|
df2 = df2.dropna(subset=['商品条码'])
|
||||||
|
df2['商品条码'] = df2['商品条码'].astype(str).str.strip()
|
||||||
|
df2 = df2[df2['商品条码'] != '']
|
||||||
|
|
||||||
|
# 核心逻辑:分裂多条码行并均分数量
|
||||||
|
if '商品条码' in df2.columns and '数量' in df2.columns:
|
||||||
|
rows = []
|
||||||
|
for _, row in df2.iterrows():
|
||||||
|
bc_val = str(row.get('商品条码', '')).strip()
|
||||||
|
# 识别分隔符:/ , , 、
|
||||||
|
if any(sep in bc_val for sep in ['/', ',', ',', '、']):
|
||||||
|
parts = re.split(r'[/,,、]+', bc_val)
|
||||||
|
parts = [p.strip() for p in parts if p.strip()]
|
||||||
|
|
||||||
|
if len(parts) >= 2:
|
||||||
|
q_total = float(row.get('数量', 0) or 0)
|
||||||
|
if q_total > 0:
|
||||||
|
n = len(parts)
|
||||||
|
base_qty = int(q_total // n)
|
||||||
|
remainder = int(q_total % n)
|
||||||
|
|
||||||
|
for i, p_bc in enumerate(parts):
|
||||||
|
new_row = row.copy()
|
||||||
|
new_row['商品条码'] = p_bc
|
||||||
|
current_qty = base_qty + (1 if i < remainder else 0)
|
||||||
|
new_row['数量'] = current_qty
|
||||||
|
if '单价' in new_row:
|
||||||
|
try:
|
||||||
|
up = float(new_row['单价'] or 0)
|
||||||
|
new_row['金额'] = up * current_qty
|
||||||
|
except: pass
|
||||||
|
rows.append(new_row)
|
||||||
|
continue
|
||||||
|
rows.append(row)
|
||||||
|
df2 = pd.DataFrame(rows)
|
||||||
|
|
||||||
|
# 保存预处理文件
|
||||||
|
out_dir = os.path.dirname(src_path)
|
||||||
|
base = os.path.basename(src_path)
|
||||||
|
final_path = os.path.join(out_dir, f"预处理之后_{base}")
|
||||||
|
df2.to_excel(final_path, index=False)
|
||||||
|
|
||||||
|
if progress_cb: progress_cb(100, "蓉城易购预处理完成")
|
||||||
|
return final_path
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"预处理蓉城易购订单出错: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_rongcheng_yigou(self, src_path: str, progress_cb: Optional[Callable[[int, str], None]] = None) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
兼容性方法:处理蓉城易购订单并执行后续转换
|
||||||
|
"""
|
||||||
|
cleaned_path = self.preprocess_rongcheng_yigou(src_path, progress_cb)
|
||||||
|
if cleaned_path:
|
||||||
|
return self.order_service.process_excel(cleaned_path, progress_cb=lambda p: progress_cb(60 + int(p*0.4), "生成采购单中...") if progress_cb else None)
|
||||||
|
return None
|
||||||
@ -73,6 +73,77 @@ class TobaccoService:
|
|||||||
logger.warning(f"找到的烟草订单明细文件不是今天创建的: {latest_file}")
|
logger.warning(f"找到的烟草订单明细文件不是今天创建的: {latest_file}")
|
||||||
return latest_file # 仍然返回最新文件,但给出警告
|
return latest_file # 仍然返回最新文件,但给出警告
|
||||||
|
|
||||||
|
def preprocess_tobacco_order(self, file_path: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
烟草订单预处理:按用户提供的 B, E, G, H 列索引进行强制清洗
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"执行烟草订单专用预处理: {file_path}")
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
|
|
||||||
|
# 烟草格式:Row 0是专卖证号,Row 1是表头,Row 2是合计,Row 3开始是数据
|
||||||
|
df_raw = smart_read_excel(file_path, header=None)
|
||||||
|
|
||||||
|
if len(df_raw) <= 3:
|
||||||
|
logger.error("烟草订单文件数据行数不足")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 提取数据部分 (Row 3开始)
|
||||||
|
df_data = df_raw.iloc[3:].reset_index(drop=True)
|
||||||
|
|
||||||
|
# 用户指定列映射:
|
||||||
|
# A列 (Index 0) -> 商品名称
|
||||||
|
# B列 (Index 1) -> 商品条码 (盒码)
|
||||||
|
# E列 (Index 4) -> 批发价 (单价)
|
||||||
|
# G列 (Index 6) -> 订单量 (数量)
|
||||||
|
# H列 (Index 7) -> 金额
|
||||||
|
|
||||||
|
idx_map = {
|
||||||
|
0: '商品名称',
|
||||||
|
1: '商品条码',
|
||||||
|
4: '批发价',
|
||||||
|
6: '数量',
|
||||||
|
7: '金额'
|
||||||
|
}
|
||||||
|
|
||||||
|
available_indices = [i for i in idx_map.keys() if i < df_data.shape[1]]
|
||||||
|
df = df_data.iloc[:, available_indices].copy()
|
||||||
|
df.columns = [idx_map[i] for i in available_indices]
|
||||||
|
|
||||||
|
# 1. 过滤订单量不为0的数据
|
||||||
|
df['数量'] = pd.to_numeric(df['数量'], errors='coerce').fillna(0)
|
||||||
|
df = df[df['数量'] != 0].copy()
|
||||||
|
|
||||||
|
if df.empty:
|
||||||
|
logger.warning("烟草订单无有效订单量记录")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 2. 核心清洗逻辑:
|
||||||
|
# 数量 = 订单量 * 10 (G列)
|
||||||
|
# 单价 = 批发价 / 10 (E列)
|
||||||
|
df['单价'] = pd.to_numeric(df['批发价'], errors='coerce').fillna(0) / 10
|
||||||
|
df['数量'] = df['数量'] * 10
|
||||||
|
|
||||||
|
# 3. 校验金额 (H列)
|
||||||
|
df['金额'] = pd.to_numeric(df['金额'], errors='coerce').fillna(0)
|
||||||
|
|
||||||
|
# 4. 只保留需要的列
|
||||||
|
final_cols = ['商品条码', '商品名称', '数量', '单价', '金额']
|
||||||
|
df_final = df[final_cols].copy()
|
||||||
|
|
||||||
|
# 保存预处理文件
|
||||||
|
out_dir = os.path.dirname(file_path)
|
||||||
|
base = os.path.basename(file_path)
|
||||||
|
final_path = os.path.join(out_dir, f"预处理之后_{base}")
|
||||||
|
df_final.to_excel(final_path, index=False)
|
||||||
|
|
||||||
|
logger.info(f"烟草订单预处理完成: {final_path}")
|
||||||
|
return final_path
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"烟草订单预处理失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def process_tobacco_order(self, input_file=None):
|
def process_tobacco_order(self, input_file=None):
|
||||||
"""
|
"""
|
||||||
处理烟草订单
|
处理烟草订单
|
||||||
@ -165,8 +236,9 @@ class TobaccoService:
|
|||||||
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
# 读取Excel文件
|
# 读取Excel文件
|
||||||
df_old = pd.read_excel(file_path, header=None, skiprows=3, names=columns)
|
df_old = smart_read_excel(file_path, header=None, skiprows=3, names=columns)
|
||||||
|
|
||||||
# 过滤订单量不为0的数据,并计算采购量和单价
|
# 过滤订单量不为0的数据,并计算采购量和单价
|
||||||
df_filtered = df_old[df_old['订单量'] != 0].copy()
|
df_filtered = df_old[df_old['订单量'] != 0].copy()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,316 +0,0 @@
|
|||||||
|
|
||||||
This file lists modules PyInstaller was not able to find. This does not
|
|
||||||
necessarily mean this module is required for running your program. Python and
|
|
||||||
Python 3rd-party packages include a lot of conditional or optional modules. For
|
|
||||||
example the module 'ntpath' only exists on Windows, whereas the module
|
|
||||||
'posixpath' only exists on Posix systems.
|
|
||||||
|
|
||||||
Types if import:
|
|
||||||
* top-level: imported at the top-level - look at these first
|
|
||||||
* conditional: imported within an if-statement
|
|
||||||
* delayed: imported within a function
|
|
||||||
* optional: imported within a try-except-statement
|
|
||||||
|
|
||||||
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
|
||||||
tracking down the missing module yourself. Thanks!
|
|
||||||
|
|
||||||
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
|
|
||||||
missing module named 'org.python' - imported by copy (optional), xml.sax (delayed, conditional)
|
|
||||||
missing module named _scproxy - imported by urllib.request (conditional)
|
|
||||||
missing module named termios - imported by getpass (optional), tty (top-level)
|
|
||||||
missing module named pwd - imported by posixpath (delayed, conditional), shutil (optional), tarfile (optional), pathlib (delayed, conditional, optional), subprocess (optional), netrc (delayed, conditional), getpass (delayed), http.server (delayed, optional), webbrowser (delayed)
|
|
||||||
missing module named 'java.lang' - imported by platform (delayed, optional), xml.sax._exceptions (conditional)
|
|
||||||
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
|
||||||
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
|
||||||
missing module named _posixsubprocess - imported by subprocess (optional), multiprocessing.util (delayed)
|
|
||||||
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
|
||||||
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
|
||||||
missing module named org - imported by pickle (optional)
|
|
||||||
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
|
||||||
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
|
||||||
missing module named grp - imported by shutil (optional), tarfile (optional), pathlib (delayed, optional), subprocess (optional)
|
|
||||||
missing module named pep517 - imported by importlib.metadata (delayed)
|
|
||||||
missing module named posix - imported by os (conditional, optional), shutil (conditional), importlib._bootstrap_external (conditional)
|
|
||||||
missing module named resource - imported by posix (top-level)
|
|
||||||
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
|
||||||
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
|
||||||
missing module named pyimod02_importers - imported by C:\Program Files\Python39\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
|
|
||||||
missing module named simplejson - imported by requests.compat (conditional, optional)
|
|
||||||
missing module named dummy_threading - imported by requests.cookies (optional)
|
|
||||||
missing module named typing_extensions - imported by urllib3.util.retry (conditional), urllib3._collections (conditional), urllib3.util.ssltransport (conditional), urllib3.connectionpool (conditional), urllib3.poolmanager (conditional), urllib3.contrib.emscripten.fetch (conditional), charset_normalizer.legacy (conditional), pandas._typing (conditional)
|
|
||||||
missing module named zstandard - imported by urllib3.util.request (optional), urllib3.response (optional)
|
|
||||||
missing module named compression - imported by urllib3.util.request (optional), urllib3.response (optional)
|
|
||||||
missing module named 'h2.events' - imported by urllib3.http2.connection (top-level)
|
|
||||||
missing module named 'h2.connection' - imported by urllib3.http2.connection (top-level)
|
|
||||||
missing module named h2 - imported by urllib3.http2.connection (top-level)
|
|
||||||
missing module named brotli - imported by urllib3.util.request (optional), urllib3.response (optional)
|
|
||||||
missing module named brotlicffi - imported by urllib3.util.request (optional), urllib3.response (optional)
|
|
||||||
missing module named socks - imported by urllib3.contrib.socks (optional)
|
|
||||||
missing module named 'typing.io' - imported by importlib.resources (top-level)
|
|
||||||
missing module named cryptography - imported by urllib3.contrib.pyopenssl (top-level), requests (conditional, optional)
|
|
||||||
missing module named 'OpenSSL.crypto' - imported by urllib3.contrib.pyopenssl (delayed, conditional)
|
|
||||||
missing module named 'cryptography.x509' - imported by urllib3.contrib.pyopenssl (delayed, optional)
|
|
||||||
missing module named OpenSSL - imported by urllib3.contrib.pyopenssl (top-level)
|
|
||||||
missing module named chardet - imported by requests (optional)
|
|
||||||
missing module named 'pyodide.ffi' - imported by urllib3.contrib.emscripten.fetch (delayed, optional)
|
|
||||||
missing module named pyodide - imported by urllib3.contrib.emscripten.fetch (top-level)
|
|
||||||
missing module named js - imported by urllib3.contrib.emscripten.fetch (top-level)
|
|
||||||
missing module named cStringIO - imported by xlrd.timemachine (conditional)
|
|
||||||
missing module named PIL - imported by openpyxl.drawing.image (optional)
|
|
||||||
missing module named 'defusedxml.ElementTree' - imported by openpyxl.xml.functions (conditional)
|
|
||||||
missing module named 'lxml.etree' - imported by openpyxl.xml.functions (conditional), pandas.io.xml (delayed), pandas.io.formats.xml (delayed), pandas.io.html (delayed)
|
|
||||||
missing module named openpyxl.tests - imported by openpyxl.reader.excel (optional)
|
|
||||||
missing module named defusedxml - imported by openpyxl.xml (delayed, optional)
|
|
||||||
missing module named lxml - imported by openpyxl.xml (delayed, optional), pandas.io.xml (conditional)
|
|
||||||
missing module named _dummy_thread - imported by numpy._core.arrayprint (optional)
|
|
||||||
missing module named numpy._typing._ufunc - imported by numpy._typing (conditional)
|
|
||||||
missing module named 'numpy_distutils.cpuinfo' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
|
|
||||||
missing module named 'numpy_distutils.fcompiler' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
|
|
||||||
missing module named 'numpy_distutils.command' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
|
|
||||||
missing module named numpy_distutils - imported by numpy.f2py.diagnose (delayed, optional)
|
|
||||||
missing module named psutil - imported by numpy.testing._private.utils (delayed, optional)
|
|
||||||
missing module named readline - imported by cmd (delayed, conditional, optional), code (delayed, conditional, optional), pdb (delayed, optional)
|
|
||||||
missing module named win32pdh - imported by numpy.testing._private.utils (delayed, conditional)
|
|
||||||
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
|
||||||
missing module named threadpoolctl - imported by numpy.lib._utils_impl (delayed, optional)
|
|
||||||
missing module named numpy._core.zeros - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.vstack - imported by numpy._core (top-level), numpy.lib._shape_base_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.void - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.vecdot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.ushort - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.unsignedinteger - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ulonglong - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ulong - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uintp - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uintc - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uint64 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uint32 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uint16 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.uint - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ubyte - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.trunc - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.true_divide - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.transpose - imported by numpy._core (top-level), numpy.lib._function_base_impl (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.trace - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.timedelta64 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.tensordot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.tanh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.tan - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.swapaxes - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.sum - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.subtract - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.str_ - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.square - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.sqrt - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
|
||||||
missing module named numpy._core.spacing - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.sort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.sinh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.single - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.signedinteger - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.signbit - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.sign - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.short - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.rint - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.right_shift - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.result_type - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional), numpy.fft._pocketfft (top-level)
|
|
||||||
missing module named numpy._core.remainder - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.reciprocal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
|
||||||
missing module named numpy._core.radians - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.rad2deg - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.prod - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.power - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.positive - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.pi - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.outer - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.ones - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.object_ - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.number - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.not_equal - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.newaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.negative - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ndarray - imported by numpy._core (top-level), numpy.lib._utils_impl (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.multiply - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.moveaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.modf - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.mod - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.minimum - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.maximum - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.max - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.matrix_transpose - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.matmul - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.longdouble - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.long - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logical_xor - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logical_or - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logical_not - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logical_and - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logaddexp2 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.logaddexp - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.log2 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.log1p - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.log - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.linspace - imported by numpy._core (top-level), numpy.lib._index_tricks_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.less_equal - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.less - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.left_shift - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ldexp - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.lcm - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.isscalar - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.isnat - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.isnan - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.isfinite - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.intp - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.integer - imported by numpy._core (conditional), numpy (conditional), numpy.fft._helper (top-level)
|
|
||||||
missing module named numpy._core.intc - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.int8 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.int64 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.int32 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.int16 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.inf - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.inexact - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.iinfo - imported by numpy._core (top-level), numpy.lib._twodim_base_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.hypot - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.hstack - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.heaviside - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.half - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.greater_equal - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.greater - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.gcd - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.frompyfunc - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.frexp - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.fmod - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.fmin - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.fmax - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.floor_divide - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.floor - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.floating - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.float_power - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.float32 - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.float16 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.finfo - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.fabs - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.expm1 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.exp - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.euler_gamma - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.errstate - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.equal - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.empty_like - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
|
||||||
missing module named numpy._core.empty - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy.fft._helper (top-level)
|
|
||||||
missing module named numpy._core.e - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.double - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.dot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.divmod - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.divide - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.diagonal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.degrees - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.deg2rad - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.datetime64 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.csingle - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.cross - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.count_nonzero - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.cosh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.cos - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.copysign - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.conjugate - imported by numpy._core (conditional), numpy (conditional), numpy.fft._pocketfft (top-level)
|
|
||||||
missing module named numpy._core.conj - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.complexfloating - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.complex64 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.clongdouble - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.character - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.ceil - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.cdouble - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.cbrt - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bytes_ - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.byte - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bool_ - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bitwise_xor - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bitwise_or - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bitwise_count - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.bitwise_and - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.atleast_3d - imported by numpy._core (top-level), numpy.lib._shape_base_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.atleast_2d - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.atleast_1d - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.asarray - imported by numpy._core (top-level), numpy.lib._array_utils_impl (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level), numpy.fft._helper (top-level)
|
|
||||||
missing module named numpy._core.asanyarray - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.array_repr - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.array2string - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.array - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.argsort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.arctanh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arctan2 - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arctan - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arcsinh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arcsin - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arccosh - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arccos - imported by numpy._core (conditional), numpy (conditional)
|
|
||||||
missing module named numpy._core.arange - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy.fft._helper (top-level)
|
|
||||||
missing module named numpy._core.amin - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.amax - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named numpy._core.all - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
|
|
||||||
missing module named numpy._core.add - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
|
||||||
missing module named yaml - imported by numpy.__config__ (delayed)
|
|
||||||
missing module named numpy._distributor_init_local - imported by numpy (optional), numpy._distributor_init (optional)
|
|
||||||
missing module named vms_lib - imported by platform (delayed, optional)
|
|
||||||
missing module named java - imported by platform (delayed)
|
|
||||||
missing module named _winreg - imported by platform (delayed, optional)
|
|
||||||
missing module named six.moves.range - imported by six.moves (top-level), dateutil.rrule (top-level)
|
|
||||||
runtime module named six.moves - imported by dateutil.tz.tz (top-level), dateutil.tz._factories (top-level), dateutil.tz.win (top-level), dateutil.rrule (top-level)
|
|
||||||
missing module named dateutil.tz.tzfile - imported by dateutil.tz (top-level), dateutil.zoneinfo (top-level)
|
|
||||||
missing module named StringIO - imported by six (conditional), xlutils.compat (conditional)
|
|
||||||
missing module named numexpr - imported by pandas.core.computation.expressions (conditional), pandas.core.computation.engines (delayed)
|
|
||||||
missing module named numba - imported by pandas.core._numba.executor (delayed, conditional), pandas.core.util.numba_ (delayed, conditional), pandas.core.window.numba_ (delayed, conditional), pandas.core.window.online (delayed, conditional), pandas.core._numba.kernels.mean_ (top-level), pandas.core._numba.kernels.shared (top-level), pandas.core._numba.kernels.sum_ (top-level), pandas.core._numba.kernels.min_max_ (top-level), pandas.core._numba.kernels.var_ (top-level), pandas.core.groupby.numba_ (delayed, conditional), pandas.core._numba.extensions (top-level)
|
|
||||||
missing module named 'numba.extending' - imported by pandas.core._numba.kernels.sum_ (top-level)
|
|
||||||
missing module named 'pyarrow.compute' - imported by pandas.core.arrays._arrow_string_mixins (conditional), pandas.core.arrays.string_arrow (conditional), pandas.core.reshape.merge (delayed, conditional), pandas.core.arrays.arrow.array (conditional), pandas.core.arrays.arrow.accessors (conditional)
|
|
||||||
missing module named 'numba.typed' - imported by pandas.core._numba.extensions (delayed)
|
|
||||||
missing module named 'numba.core' - imported by pandas.core._numba.extensions (top-level)
|
|
||||||
missing module named pyarrow - imported by pandas.core.arrays._arrow_string_mixins (conditional), pandas.core.arrays.masked (delayed), pandas.core.arrays.boolean (delayed, conditional), pandas.core.arrays.numeric (delayed, conditional), pandas.core.arrays.arrow._arrow_utils (top-level), pandas.core.interchange.utils (delayed, conditional), pandas.core.strings.accessor (delayed, conditional), pandas.io._util (conditional), pandas.io.parsers.base_parser (delayed, conditional), pandas.core.arrays.interval (delayed), pandas.core.arrays.arrow.extension_types (top-level), pandas.core.arrays.period (delayed), pandas.core.methods.describe (delayed, conditional), pandas.io.sql (delayed, conditional), pandas.core.arrays.string_arrow (conditional), pandas.core.reshape.merge (delayed, conditional), pandas.core.arrays.arrow.array (conditional), pandas.core.interchange.buffer (conditional), pandas.io.feather_format (delayed), pandas.core.indexes.base (delayed, conditional), pandas.core.dtypes.cast (delayed, conditional), pandas.core.arrays.string_ (delayed, conditional), pandas.core.arrays.arrow.accessors (conditional), pandas.core.dtypes.dtypes (delayed, conditional), pandas.compat.pyarrow (optional), pandas.core.reshape.encoding (delayed, conditional), pandas._testing (conditional)
|
|
||||||
missing module named 'scipy.stats' - imported by pandas.core.nanops (delayed, conditional)
|
|
||||||
missing module named scipy - imported by pandas.core.dtypes.common (delayed, conditional, optional), pandas.core.missing (delayed)
|
|
||||||
missing module named traitlets - imported by pandas.io.formats.printing (delayed, conditional)
|
|
||||||
missing module named 'IPython.core' - imported by pandas.io.formats.printing (delayed, conditional)
|
|
||||||
missing module named IPython - imported by pandas.io.formats.printing (delayed)
|
|
||||||
missing module named xlsxwriter - imported by pandas.io.excel._xlsxwriter (delayed)
|
|
||||||
missing module named 'odf.config' - imported by pandas.io.excel._odswriter (delayed)
|
|
||||||
missing module named 'odf.style' - imported by pandas.io.excel._odswriter (delayed)
|
|
||||||
missing module named 'odf.text' - imported by pandas.io.excel._odfreader (delayed), pandas.io.excel._odswriter (delayed)
|
|
||||||
missing module named 'odf.table' - imported by pandas.io.excel._odfreader (delayed), pandas.io.excel._odswriter (delayed)
|
|
||||||
missing module named 'odf.opendocument' - imported by pandas.io.excel._odfreader (delayed), pandas.io.excel._odswriter (delayed)
|
|
||||||
missing module named pyxlsb - imported by pandas.io.excel._pyxlsb (delayed, conditional)
|
|
||||||
missing module named 'odf.office' - imported by pandas.io.excel._odfreader (delayed)
|
|
||||||
missing module named 'odf.element' - imported by pandas.io.excel._odfreader (delayed)
|
|
||||||
missing module named 'odf.namespaces' - imported by pandas.io.excel._odfreader (delayed)
|
|
||||||
missing module named odf - imported by pandas.io.excel._odfreader (conditional)
|
|
||||||
missing module named python_calamine - imported by pandas.io.excel._calamine (delayed, conditional)
|
|
||||||
missing module named 'matplotlib.pyplot' - imported by pandas.io.formats.style (optional)
|
|
||||||
missing module named matplotlib - imported by pandas.plotting._core (conditional), pandas.io.formats.style (optional)
|
|
||||||
missing module named 'matplotlib.colors' - imported by pandas.plotting._misc (conditional), pandas.io.formats.style (conditional)
|
|
||||||
missing module named markupsafe - imported by pandas.io.formats.style_render (top-level)
|
|
||||||
missing module named botocore - imported by pandas.io.common (delayed, conditional, optional)
|
|
||||||
missing module named sets - imported by pytz.tzinfo (optional)
|
|
||||||
missing module named collections.Mapping - imported by collections (optional), pytz.lazy (optional)
|
|
||||||
missing module named UserDict - imported by pytz.lazy (optional)
|
|
||||||
missing module named 'scipy.sparse' - imported by pandas.core.arrays.sparse.array (conditional), pandas.core.arrays.sparse.scipy_sparse (delayed, conditional), pandas.core.arrays.sparse.accessor (delayed)
|
|
||||||
missing module named pandas.core.internals.Block - imported by pandas.core.internals (conditional), pandas.io.pytables (conditional)
|
|
||||||
missing module named Foundation - imported by pandas.io.clipboard (delayed, conditional, optional)
|
|
||||||
missing module named AppKit - imported by pandas.io.clipboard (delayed, conditional, optional)
|
|
||||||
missing module named PyQt4 - imported by pandas.io.clipboard (delayed, conditional, optional)
|
|
||||||
missing module named qtpy - imported by pandas.io.clipboard (delayed, conditional, optional)
|
|
||||||
missing module named 'sqlalchemy.engine' - imported by pandas.io.sql (delayed)
|
|
||||||
missing module named 'sqlalchemy.types' - imported by pandas.io.sql (delayed, conditional)
|
|
||||||
missing module named 'sqlalchemy.schema' - imported by pandas.io.sql (delayed)
|
|
||||||
missing module named 'sqlalchemy.sql' - imported by pandas.io.sql (conditional)
|
|
||||||
missing module named sqlalchemy - imported by pandas.io.sql (delayed, conditional)
|
|
||||||
missing module named tables - imported by pandas.io.pytables (delayed, conditional)
|
|
||||||
missing module named 'pyarrow.fs' - imported by pandas.io.orc (conditional)
|
|
||||||
missing module named fsspec - imported by pandas.io.orc (conditional)
|
|
||||||
missing module named 'pyarrow.parquet' - imported by pandas.io.parquet (delayed)
|
|
||||||
missing module named google - imported by pandas.io.gbq (conditional)
|
|
||||||
missing module named 'lxml.html' - imported by pandas.io.html (delayed)
|
|
||||||
missing module named bs4 - imported by pandas.io.html (delayed)
|
|
||||||
missing module named pytest - imported by pandas._testing._io (delayed), pandas._testing (delayed)
|
|
||||||
missing module named 'matplotlib.axes' - imported by pandas.plotting._misc (conditional), pandas._testing.asserters (delayed)
|
|
||||||
missing module named 'matplotlib.artist' - imported by pandas._testing.asserters (delayed)
|
|
||||||
missing module named 'matplotlib.table' - imported by pandas.plotting._misc (conditional)
|
|
||||||
missing module named 'matplotlib.figure' - imported by pandas.plotting._misc (conditional)
|
|
||||||
missing module named errorhandler - imported by xlutils.filter (delayed)
|
|
||||||
missing module named guppy - imported by xlutils.filter (optional)
|
|
||||||
File diff suppressed because it is too large
Load Diff
62
build_exe.py
62
build_exe.py
@ -121,6 +121,40 @@ def build_exe():
|
|||||||
"""构建EXE文件"""
|
"""构建EXE文件"""
|
||||||
print("开始构建EXE文件...")
|
print("开始构建EXE文件...")
|
||||||
try:
|
try:
|
||||||
|
# 注入版本信息到根config.ini
|
||||||
|
try:
|
||||||
|
root_cfg = Path('config.ini')
|
||||||
|
from datetime import datetime
|
||||||
|
version_str = datetime.now().strftime('%Y.%m.%d.%H%M')
|
||||||
|
if root_cfg.exists():
|
||||||
|
lines = root_cfg.read_text(encoding='utf-8').splitlines()
|
||||||
|
has_app = any(l.strip().lower() == '[app]' for l in lines)
|
||||||
|
if not has_app:
|
||||||
|
lines.append('[App]')
|
||||||
|
lines.append(f'version = {version_str}')
|
||||||
|
else:
|
||||||
|
# 更新或追加version
|
||||||
|
new_lines = []
|
||||||
|
in_app = False
|
||||||
|
app_written = False
|
||||||
|
for l in lines:
|
||||||
|
if l.strip().lower() == '[app]':
|
||||||
|
in_app = True
|
||||||
|
new_lines.append(l)
|
||||||
|
continue
|
||||||
|
if in_app and l.strip().lower().startswith('version'):
|
||||||
|
new_lines.append(f'version = {version_str}')
|
||||||
|
app_written = True
|
||||||
|
in_app = True
|
||||||
|
continue
|
||||||
|
new_lines.append(l)
|
||||||
|
if not app_written:
|
||||||
|
new_lines.append('version = ' + version_str)
|
||||||
|
lines = new_lines
|
||||||
|
root_cfg.write_text('\n'.join(lines), encoding='utf-8')
|
||||||
|
print(f"已写入版本号: {version_str}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"版本信息注入失败: {e}")
|
||||||
result = subprocess.run([
|
result = subprocess.run([
|
||||||
'pyinstaller',
|
'pyinstaller',
|
||||||
'OCR订单处理系统.spec'
|
'OCR订单处理系统.spec'
|
||||||
@ -150,6 +184,9 @@ def build_exe():
|
|||||||
if root_config_file.exists():
|
if root_config_file.exists():
|
||||||
shutil.copy2(root_config_file, dist_dir)
|
shutil.copy2(root_config_file, dist_dir)
|
||||||
print(f"已复制根配置文件到dist: {root_config_file} -> {dist_dir}")
|
print(f"已复制根配置文件到dist: {root_config_file} -> {dist_dir}")
|
||||||
|
else:
|
||||||
|
print("警告: 根配置文件不存在,将创建缺省版本")
|
||||||
|
(dist_dir / 'config.ini').write_text('[App]\nversion = dev\n', encoding='utf-8')
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"构建失败: {e}")
|
print(f"构建失败: {e}")
|
||||||
@ -164,8 +201,18 @@ def create_portable_package():
|
|||||||
# 创建发布目录
|
# 创建发布目录
|
||||||
release_dir = Path('release')
|
release_dir = Path('release')
|
||||||
if release_dir.exists():
|
if release_dir.exists():
|
||||||
shutil.rmtree(release_dir)
|
try:
|
||||||
release_dir.mkdir()
|
shutil.rmtree(release_dir)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"警告: 无法完全清理发布目录 (可能文件被占用): {e}")
|
||||||
|
# 如果目录还在,尝试清理能清理的部分
|
||||||
|
for item in release_dir.iterdir():
|
||||||
|
try:
|
||||||
|
if item.is_dir(): shutil.rmtree(item)
|
||||||
|
else: item.unlink()
|
||||||
|
except Exception: pass
|
||||||
|
|
||||||
|
release_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
# 复制exe文件
|
# 复制exe文件
|
||||||
exe_file = Path('dist/OCR订单处理系统.exe')
|
exe_file = Path('dist/OCR订单处理系统.exe')
|
||||||
@ -210,6 +257,17 @@ def create_portable_package():
|
|||||||
print(f"已复制模板文件: {template_file} -> {release_dir / 'templates'}")
|
print(f"已复制模板文件: {template_file} -> {release_dir / 'templates'}")
|
||||||
else:
|
else:
|
||||||
print(f"警告: 模板文件不存在: {template_file}")
|
print(f"警告: 模板文件不存在: {template_file}")
|
||||||
|
item_file = Path('templates/商品资料.xlsx')
|
||||||
|
if item_file.exists():
|
||||||
|
try:
|
||||||
|
(Path('dist') / 'templates').mkdir(exist_ok=True)
|
||||||
|
shutil.copy2(item_file, Path('dist') / 'templates')
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
shutil.copy2(item_file, release_dir / 'templates')
|
||||||
|
print(f"已复制商品资料: {item_file} -> {release_dir / 'templates'}")
|
||||||
|
else:
|
||||||
|
print(f"警告: 商品资料文件不存在: {item_file}")
|
||||||
|
|
||||||
# 创建README文件
|
# 创建README文件
|
||||||
readme_content = '''
|
readme_content = '''
|
||||||
|
|||||||
88
clean.py
88
clean.py
@ -1,88 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
清理脚本 - 用于删除无关的文件和日志
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import glob
|
|
||||||
|
|
||||||
def clean_logs():
|
|
||||||
"""清理日志文件"""
|
|
||||||
print("清理日志文件...")
|
|
||||||
|
|
||||||
# 删除.active文件
|
|
||||||
active_files = glob.glob("logs/*.active")
|
|
||||||
for file in active_files:
|
|
||||||
try:
|
|
||||||
os.remove(file)
|
|
||||||
print(f"已删除: {file}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"删除文件时出错 {file}: {e}")
|
|
||||||
|
|
||||||
# 保留最新的日志,删除旧的备份
|
|
||||||
log_files = glob.glob("logs/*.log.*")
|
|
||||||
for file in log_files:
|
|
||||||
try:
|
|
||||||
os.remove(file)
|
|
||||||
print(f"已删除: {file}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"删除文件时出错 {file}: {e}")
|
|
||||||
|
|
||||||
def clean_temp_files():
|
|
||||||
"""清理临时文件"""
|
|
||||||
print("清理临时文件...")
|
|
||||||
|
|
||||||
# 清空临时目录
|
|
||||||
temp_dir = "data/temp"
|
|
||||||
if os.path.exists(temp_dir):
|
|
||||||
for file in os.listdir(temp_dir):
|
|
||||||
file_path = os.path.join(temp_dir, file)
|
|
||||||
try:
|
|
||||||
if os.path.isfile(file_path):
|
|
||||||
os.remove(file_path)
|
|
||||||
print(f"已删除: {file_path}")
|
|
||||||
elif os.path.isdir(file_path):
|
|
||||||
shutil.rmtree(file_path)
|
|
||||||
print(f"已删除目录: {file_path}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"删除文件时出错 {file_path}: {e}")
|
|
||||||
|
|
||||||
# 删除备份文件
|
|
||||||
backup_files = glob.glob("data/*.bak") + glob.glob("config/*.bak")
|
|
||||||
for file in backup_files:
|
|
||||||
try:
|
|
||||||
os.remove(file)
|
|
||||||
print(f"已删除: {file}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"删除文件时出错 {file}: {e}")
|
|
||||||
|
|
||||||
def clean_pycache():
|
|
||||||
"""清理Python缓存文件"""
|
|
||||||
print("清理Python缓存文件...")
|
|
||||||
|
|
||||||
# 查找并删除所有__pycache__目录
|
|
||||||
for root, dirs, files in os.walk("."):
|
|
||||||
for dir in dirs:
|
|
||||||
if dir == "__pycache__":
|
|
||||||
cache_dir = os.path.join(root, dir)
|
|
||||||
try:
|
|
||||||
shutil.rmtree(cache_dir)
|
|
||||||
print(f"已删除目录: {cache_dir}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"删除目录时出错 {cache_dir}: {e}")
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""主函数"""
|
|
||||||
print("开始清理无关文件...")
|
|
||||||
|
|
||||||
clean_logs()
|
|
||||||
clean_temp_files()
|
|
||||||
clean_pycache()
|
|
||||||
|
|
||||||
print("清理完成!")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -10,7 +10,7 @@ api_url = https://aip.baidubce.com/rest/2.0/ocr/v1/table
|
|||||||
input_folder = data/input
|
input_folder = data/input
|
||||||
output_folder = data/output
|
output_folder = data/output
|
||||||
temp_folder = data/temp
|
temp_folder = data/temp
|
||||||
template_folder = templates
|
template_folder = E:\2025Code\python\orc-order-v2\templates
|
||||||
processed_record = data/processed_files.json
|
processed_record = data/processed_files.json
|
||||||
|
|
||||||
[Performance]
|
[Performance]
|
||||||
@ -26,3 +26,6 @@ max_file_size_mb = 4
|
|||||||
[Templates]
|
[Templates]
|
||||||
purchase_order = 银豹-采购单模板.xls
|
purchase_order = 银豹-采购单模板.xls
|
||||||
|
|
||||||
|
[App]
|
||||||
|
version = 2026.03.30.1036
|
||||||
|
|
||||||
|
|||||||
@ -179,6 +179,58 @@
|
|||||||
"map_to": "69021343",
|
"map_to": "69021343",
|
||||||
"description": "条码映射:6923450653012 -> 69021343"
|
"description": "条码映射:6923450653012 -> 69021343"
|
||||||
},
|
},
|
||||||
|
"6923644295844": {
|
||||||
|
"map_to": "6923644285036",
|
||||||
|
"description": "条码映射:6923644295844 -> 6923644285036"
|
||||||
|
},
|
||||||
|
"6907992513157": {
|
||||||
|
"map_to": "6907992513195",
|
||||||
|
"description": "条码映射:6907992513157 -> 6907992513195"
|
||||||
|
},
|
||||||
|
"6902083893842": {
|
||||||
|
"map_to": "6902083907150",
|
||||||
|
"description": "条码映射:6902083893842 -> 6902083907150"
|
||||||
|
},
|
||||||
|
"6902083904685": {
|
||||||
|
"map_to": "6902083905217",
|
||||||
|
"description": "条码映射:6902083904685 -> 6902083905217"
|
||||||
|
},
|
||||||
|
"6917878036849": {
|
||||||
|
"map_to": "6917878036847",
|
||||||
|
"description": "条码映射:6917878036849 -> 6917878036847"
|
||||||
|
},
|
||||||
|
"6903979000078": {
|
||||||
|
"map_to": "6903979000061",
|
||||||
|
"description": "条码映射:6903979000078 -> 6903979000061"
|
||||||
|
},
|
||||||
|
"6937003706353": {
|
||||||
|
"map_to": "6937003706360",
|
||||||
|
"description": "条码映射:6937003706353 -> 6937003706360"
|
||||||
|
},
|
||||||
|
"6923644242961": {
|
||||||
|
"map_to": "6907992100043",
|
||||||
|
"description": "条码映射:6923644242961 -> 6907992100043"
|
||||||
|
},
|
||||||
|
"6923644258382": {
|
||||||
|
"map_to": "6923644252823",
|
||||||
|
"description": "条码映射:6923644258382 -> 6923644252823"
|
||||||
|
},
|
||||||
|
"6923450657430": {
|
||||||
|
"map_to": "69029110",
|
||||||
|
"description": "条码映射:6923450657430 -> 69029110"
|
||||||
|
},
|
||||||
|
"6923450660232": {
|
||||||
|
"map_to": "6923450690123",
|
||||||
|
"description": "条码映射:6923450660232 -> 6923450690123"
|
||||||
|
},
|
||||||
|
"6923450657614": {
|
||||||
|
"map_to": "6923450657607",
|
||||||
|
"description": "条码映射:6923450657614 -> 6923450657607"
|
||||||
|
},
|
||||||
|
"6972556000022": {
|
||||||
|
"map_to": "6977826050028",
|
||||||
|
"description": "条码映射:6972556000022 -> 6977826050028"
|
||||||
|
},
|
||||||
"6925019900087": {
|
"6925019900087": {
|
||||||
"multiplier": 10,
|
"multiplier": 10,
|
||||||
"target_unit": "瓶",
|
"target_unit": "瓶",
|
||||||
@ -201,5 +253,17 @@
|
|||||||
"target_unit": "个",
|
"target_unit": "个",
|
||||||
"specification": "1*14",
|
"specification": "1*14",
|
||||||
"description": "友臣肉松,1盒14个"
|
"description": "友臣肉松,1盒14个"
|
||||||
|
},
|
||||||
|
"6921734933485": {
|
||||||
|
"multiplier": 12,
|
||||||
|
"target_unit": "支",
|
||||||
|
"specification": "1*12",
|
||||||
|
"description": "得力铅笔"
|
||||||
|
},
|
||||||
|
"6901826888244": {
|
||||||
|
"multiplier": 30,
|
||||||
|
"target_unit": "对",
|
||||||
|
"specification": "1*30",
|
||||||
|
"description": "南孚电池"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
237
config/suppliers_config.json
Normal file
237
config/suppliers_config.json
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
{
|
||||||
|
"suppliers": [
|
||||||
|
{
|
||||||
|
"name": "蓉城易购",
|
||||||
|
"description": "蓉城易购供应商订单处理",
|
||||||
|
"filename_patterns": [
|
||||||
|
"*蓉城*",
|
||||||
|
"*rongcheng*",
|
||||||
|
"*易*"
|
||||||
|
],
|
||||||
|
"content_indicators": [
|
||||||
|
"蓉城易购",
|
||||||
|
"商品编码",
|
||||||
|
"订货数量"
|
||||||
|
],
|
||||||
|
"column_mapping": {
|
||||||
|
"商品条码(小条码)": "barcode",
|
||||||
|
"商品名称": "name",
|
||||||
|
"规格": "specification",
|
||||||
|
"订购数量(小单位)": "quantity",
|
||||||
|
"单位": "unit",
|
||||||
|
"单价(小单位)": "unit_price",
|
||||||
|
"优惠后金额(小单位)": "total_price",
|
||||||
|
"备注": "category",
|
||||||
|
"行号": "supplier"
|
||||||
|
},
|
||||||
|
"cleaning_rules": [
|
||||||
|
{
|
||||||
|
"type": "remove_rows",
|
||||||
|
"condition": "订货数量 == 0 or 订货数量.isna()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fill_na",
|
||||||
|
"columns": [
|
||||||
|
"unit_price"
|
||||||
|
],
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"calculations": [
|
||||||
|
{
|
||||||
|
"type": "multiply",
|
||||||
|
"source_column": "quantity",
|
||||||
|
"target_column": "quantity",
|
||||||
|
"factor": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output_suffix": "_蓉城易购_银豹采购单",
|
||||||
|
"header_row": 2,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"type": "split_quantity_unit",
|
||||||
|
"source": "订购数量(小单位)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "extract_spec_from_name",
|
||||||
|
"source": "商品名称"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "normalize_unit",
|
||||||
|
"target": "unit",
|
||||||
|
"map": {
|
||||||
|
"箱": "件",
|
||||||
|
"提": "件",
|
||||||
|
"盒": "件"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "compute_quantity_from_total"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mark_gift"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fill_missing",
|
||||||
|
"fills": {
|
||||||
|
"unit": "瓶"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output_templates": [
|
||||||
|
"templates/银豹-采购单模板.xls"
|
||||||
|
],
|
||||||
|
"current_template_index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "通用食品供应商",
|
||||||
|
"description": "通用食品类供应商订单",
|
||||||
|
"filename_patterns": [
|
||||||
|
"*食品*",
|
||||||
|
"*配送*",
|
||||||
|
"*供货*"
|
||||||
|
],
|
||||||
|
"content_indicators": [
|
||||||
|
"产品条码",
|
||||||
|
"订购量",
|
||||||
|
"进货价"
|
||||||
|
],
|
||||||
|
"column_mapping": {
|
||||||
|
"产品条码": "barcode",
|
||||||
|
"产品名称": "name",
|
||||||
|
"订购量": "quantity",
|
||||||
|
"进货价": "unit_price"
|
||||||
|
},
|
||||||
|
"cleaning_rules": [
|
||||||
|
{
|
||||||
|
"type": "convert_type",
|
||||||
|
"columns": [
|
||||||
|
"unit_price"
|
||||||
|
],
|
||||||
|
"target_type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fill_na",
|
||||||
|
"columns": [
|
||||||
|
"barcode",
|
||||||
|
"name",
|
||||||
|
"quantity"
|
||||||
|
],
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output_suffix": "_食品供应商_银豹采购单",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"type": "split_quantity_unit",
|
||||||
|
"source": "订购量"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "extract_spec_from_name",
|
||||||
|
"source": "产品名称"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "normalize_unit",
|
||||||
|
"target": "unit",
|
||||||
|
"map": {
|
||||||
|
"箱": "件",
|
||||||
|
"提": "件",
|
||||||
|
"盒": "件"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "compute_quantity_from_total"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mark_gift"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fill_missing",
|
||||||
|
"fills": {
|
||||||
|
"unit": "瓶"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output_templates": [
|
||||||
|
"templates/银豹-采购单模板.xls"
|
||||||
|
],
|
||||||
|
"current_template_index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "农夫山泉",
|
||||||
|
"description": "",
|
||||||
|
"filename_patterns": [],
|
||||||
|
"content_indicators": [],
|
||||||
|
"column_mapping": {
|
||||||
|
"条形码": "barcode",
|
||||||
|
"商品名称": "name",
|
||||||
|
"销售价": "unit_price",
|
||||||
|
"订单金额": "total_price",
|
||||||
|
"Unnamed: 0": "supplier",
|
||||||
|
"备注": "brand"
|
||||||
|
},
|
||||||
|
"header_row": 0,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"type": "split_quantity_unit",
|
||||||
|
"source": "订单数量"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "extract_spec_from_name",
|
||||||
|
"source": "name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "normalize_unit",
|
||||||
|
"target": "unit",
|
||||||
|
"map": {
|
||||||
|
"箱": "件",
|
||||||
|
"提": "件",
|
||||||
|
"盒": "件"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "compute_quantity_from_total"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mark_gift"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fill_missing",
|
||||||
|
"fills": {
|
||||||
|
"unit": "瓶"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dictionary": {
|
||||||
|
"ignore_words": [
|
||||||
|
"白膜",
|
||||||
|
"彩膜",
|
||||||
|
"赠品"
|
||||||
|
],
|
||||||
|
"unit_synonyms": {
|
||||||
|
"箱": "件",
|
||||||
|
"提": "件",
|
||||||
|
"盒": "件",
|
||||||
|
"瓶": "瓶"
|
||||||
|
},
|
||||||
|
"pack_multipliers": {
|
||||||
|
"件": 24,
|
||||||
|
"箱": 24,
|
||||||
|
"提": 12,
|
||||||
|
"盒": 10
|
||||||
|
},
|
||||||
|
"name_patterns": [
|
||||||
|
"(\\d+(?:\\.\\d+)?)(ml|mL|ML|l|L|升|毫升)[*×xX](\\d+)",
|
||||||
|
"(\\d+)[*×xX](\\d+)瓶",
|
||||||
|
"(\\d{2,3}).*?(\\d{1,3})"
|
||||||
|
],
|
||||||
|
"default_unit": "瓶",
|
||||||
|
"default_package_quantity": 1
|
||||||
|
},
|
||||||
|
"output_templates": [
|
||||||
|
"templates/银豹-采购单模板.xls"
|
||||||
|
],
|
||||||
|
"current_template_index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
data/input/20260331-112736.jpg
Normal file
BIN
data/input/20260331-112736.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
BIN
data/input/20260331-112747.jpg
Normal file
BIN
data/input/20260331-112747.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 173 KiB |
Binary file not shown.
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"data/output\\7a3a78a02fcf6ccef5daad31bd50bdf2.xlsx": "data/result\\采购单_7a3a78a02fcf6ccef5daad31bd50bdf2.xls"
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1 +1,13 @@
|
|||||||
{"theme": "light"}
|
{
|
||||||
|
"window_size": "900x600",
|
||||||
|
"theme_mode": "light",
|
||||||
|
"recent_files": [
|
||||||
|
"data/result\\采购单_预处理之后_原始数据.xls",
|
||||||
|
"E:/2025Code/python/orc-order-v2/data/output/原始数据.xlsx",
|
||||||
|
"data/result\\采购单_预处理之后_订单1774849009841.xls",
|
||||||
|
"E:/2025Code/python/orc-order-v2/data/output/订单明细20260330133908.xlsx",
|
||||||
|
"data/output\\订单明细20260330133908.xlsx",
|
||||||
|
"E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx",
|
||||||
|
"data/output\\订单1774849009841.xlsx"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
dist/OCR订单处理系统.exe
vendored
BIN
dist/OCR订单处理系统.exe
vendored
Binary file not shown.
28
dist/config.ini
vendored
28
dist/config.ini
vendored
@ -1,28 +0,0 @@
|
|||||||
[API]
|
|
||||||
api_key = O0Fgk3o69RWJ86eAX8BTHRaB
|
|
||||||
secret_key = VyZD5lzcIMgsup1uuD6Cw0pfzS20IGPZ
|
|
||||||
timeout = 30
|
|
||||||
max_retries = 3
|
|
||||||
retry_delay = 2
|
|
||||||
api_url = https://aip.baidubce.com/rest/2.0/ocr/v1/table
|
|
||||||
|
|
||||||
[Paths]
|
|
||||||
input_folder = data/input
|
|
||||||
output_folder = data/output
|
|
||||||
temp_folder = data/temp
|
|
||||||
template_folder = templates
|
|
||||||
processed_record = data/processed_files.json
|
|
||||||
|
|
||||||
[Performance]
|
|
||||||
max_workers = 4
|
|
||||||
batch_size = 5
|
|
||||||
skip_existing = true
|
|
||||||
|
|
||||||
[File]
|
|
||||||
allowed_extensions = .jpg,.jpeg,.png,.bmp
|
|
||||||
excel_extension = .xlsx
|
|
||||||
max_file_size_mb = 4
|
|
||||||
|
|
||||||
[Templates]
|
|
||||||
purchase_order = 银豹-采购单模板.xls
|
|
||||||
|
|
||||||
205
dist/config/barcode_mappings.json
vendored
205
dist/config/barcode_mappings.json
vendored
@ -1,205 +0,0 @@
|
|||||||
{
|
|
||||||
"6920584471055": {
|
|
||||||
"map_to": "6920584471017",
|
|
||||||
"description": "条码映射:6920584471055 -> 6920584471017"
|
|
||||||
},
|
|
||||||
"6925861571159": {
|
|
||||||
"map_to": "69021824",
|
|
||||||
"description": "条码映射:6925861571159 -> 69021824"
|
|
||||||
},
|
|
||||||
"6923644268923": {
|
|
||||||
"map_to": "6923644268480",
|
|
||||||
"description": "条码映射:6923644268923 -> 6923644268480"
|
|
||||||
},
|
|
||||||
"6925861571466": {
|
|
||||||
"map_to": "6925861571459",
|
|
||||||
"description": "条码映射:6925861571466 -> 6925861571459"
|
|
||||||
},
|
|
||||||
"6907992508344": {
|
|
||||||
"map_to": "6907992508191",
|
|
||||||
"description": "条码映射:6907992508344 -> 6907992508191"
|
|
||||||
},
|
|
||||||
"6903979000979": {
|
|
||||||
"map_to": "6903979000962",
|
|
||||||
"description": "条码映射:6903979000979 -> 6903979000962"
|
|
||||||
},
|
|
||||||
"6923644283582": {
|
|
||||||
"map_to": "6923644283575",
|
|
||||||
"description": "条码映射:6923644283582 -> 6923644283575"
|
|
||||||
},
|
|
||||||
"6923644268930": {
|
|
||||||
"map_to": "6923644268497",
|
|
||||||
"description": "条码映射:6923644268930 -> 6923644268497"
|
|
||||||
},
|
|
||||||
"6923644268916": {
|
|
||||||
"map_to": "6923644268503",
|
|
||||||
"description": "条码映射:6923644268916 -> 6923644268503"
|
|
||||||
},
|
|
||||||
"6923644268909": {
|
|
||||||
"map_to": "6923644268510",
|
|
||||||
"description": "条码映射:6923644268909 -> 6923644268510"
|
|
||||||
},
|
|
||||||
"6923644299804": {
|
|
||||||
"map_to": "6923644299774",
|
|
||||||
"description": "条码映射:6923644299804 -> 6923644299774"
|
|
||||||
},
|
|
||||||
"6923644266318": {
|
|
||||||
"map_to": "6923644266066",
|
|
||||||
"description": "条码映射:6923644266318 -> 6923644266066"
|
|
||||||
},
|
|
||||||
"6923644210151": {
|
|
||||||
"map_to": "6923644223458",
|
|
||||||
"description": "条码映射:6923644210151 -> 6923644223458"
|
|
||||||
},
|
|
||||||
"6907992501819": {
|
|
||||||
"map_to": "6907992500133",
|
|
||||||
"description": "条码映射:6907992501819 -> 6907992500133"
|
|
||||||
},
|
|
||||||
"6907992502052": {
|
|
||||||
"map_to": "6907992100272",
|
|
||||||
"description": "条码映射:6907992502052 -> 6907992100272"
|
|
||||||
},
|
|
||||||
"6907992507385": {
|
|
||||||
"map_to": "6907992507095",
|
|
||||||
"description": "条码映射:6907992507385 -> 6907992507095"
|
|
||||||
},
|
|
||||||
"6973726149671": {
|
|
||||||
"map_to": "6973726149657",
|
|
||||||
"description": "条码映射:6973726149671 -> 6973726149657"
|
|
||||||
},
|
|
||||||
"6977426410574": {
|
|
||||||
"map_to": "6977426410567",
|
|
||||||
"description": "条码映射:6977426410574 -> 6977426410567"
|
|
||||||
},
|
|
||||||
"6973726149688": {
|
|
||||||
"map_to": "6973726149664",
|
|
||||||
"description": "条码映射:6973726149688 -> 6973726149664"
|
|
||||||
},
|
|
||||||
"6935205322012": {
|
|
||||||
"map_to": "6935205320018",
|
|
||||||
"description": "条码映射:6935205322012 -> 6935205320018"
|
|
||||||
},
|
|
||||||
"6943497411024": {
|
|
||||||
"map_to": "6943497411017",
|
|
||||||
"description": "条码映射:6943497411024 -> 6943497411017"
|
|
||||||
},
|
|
||||||
"6921734968821": {
|
|
||||||
"map_to": "6921734968814",
|
|
||||||
"description": "条码映射:6921734968821 -> 6921734968814"
|
|
||||||
},
|
|
||||||
"6921734968258": {
|
|
||||||
"map_to": "6921734968241",
|
|
||||||
"description": "条码映射:6921734968258 -> 6921734968241"
|
|
||||||
},
|
|
||||||
"6921734968180": {
|
|
||||||
"map_to": "6921734968173",
|
|
||||||
"description": "条码映射:6921734968180 -> 6921734968173"
|
|
||||||
},
|
|
||||||
"6921734908735": {
|
|
||||||
"map_to": "6935205372772",
|
|
||||||
"description": "条码映射:6921734908735 -> 6935205372772"
|
|
||||||
},
|
|
||||||
"6923644248222": {
|
|
||||||
"map_to": "6923644248208",
|
|
||||||
"description": "条码映射:6923644248222 -> 6923644248208"
|
|
||||||
},
|
|
||||||
"6902083881122": {
|
|
||||||
"map_to": "6902083881085",
|
|
||||||
"description": "条码映射:6902083881122 -> 6902083881085"
|
|
||||||
},
|
|
||||||
"6907992501857": {
|
|
||||||
"map_to": "6907992500010",
|
|
||||||
"description": "条码映射:6907992501857 -> 6907992500010"
|
|
||||||
},
|
|
||||||
"6902083891015": {
|
|
||||||
"map_to": "6902083890636",
|
|
||||||
"description": "条码映射:6902083891015 -> 6902083890636"
|
|
||||||
},
|
|
||||||
"6923450605240": {
|
|
||||||
"map_to": "6923450605226",
|
|
||||||
"description": "条码映射:6923450605240 -> 6923450605226"
|
|
||||||
},
|
|
||||||
"6923450605196": {
|
|
||||||
"map_to": "6923450614624",
|
|
||||||
"description": "条码映射:6923450605196 -> 6923450614624"
|
|
||||||
},
|
|
||||||
"6923450665213": {
|
|
||||||
"map_to": "6923450665206",
|
|
||||||
"description": "条码映射:6923450665213 -> 6923450665206"
|
|
||||||
},
|
|
||||||
"6923450666821": {
|
|
||||||
"map_to": "6923450666838",
|
|
||||||
"description": "条码映射:6923450666821 -> 6923450666838"
|
|
||||||
},
|
|
||||||
"6923450661505": {
|
|
||||||
"map_to": "6923450661499",
|
|
||||||
"description": "条码映射:6923450661505 -> 6923450661499"
|
|
||||||
},
|
|
||||||
"6923450676103": {
|
|
||||||
"map_to": "6923450676097",
|
|
||||||
"description": "条码映射:6923450676103 -> 6923450676097"
|
|
||||||
},
|
|
||||||
"6923450614631": {
|
|
||||||
"map_to": "6923450614624",
|
|
||||||
"description": "条码映射:6923450614631 -> 6923450614624"
|
|
||||||
},
|
|
||||||
"6901424334174": {
|
|
||||||
"map_to": "6973730760015",
|
|
||||||
"description": "条码映射:6901424334174 -> 6973730760015"
|
|
||||||
},
|
|
||||||
"6958620703716": {
|
|
||||||
"map_to": "6958620703907",
|
|
||||||
"description": "条码映射:6958620703716 -> 6958620703907"
|
|
||||||
},
|
|
||||||
"6937003706322": {
|
|
||||||
"map_to": "6937003703833",
|
|
||||||
"description": "条码映射:6937003706322 -> 6937003703833"
|
|
||||||
},
|
|
||||||
"6950783203494": {
|
|
||||||
"map_to": "6950873203494",
|
|
||||||
"description": "条码映射:6950783203494 -> 6950873203494"
|
|
||||||
},
|
|
||||||
"6907992501871": {
|
|
||||||
"map_to": "6907992500010",
|
|
||||||
"description": "条码映射:6907992501871 -> 6907992500010"
|
|
||||||
},
|
|
||||||
"6907992501864": {
|
|
||||||
"map_to": "6907992100012",
|
|
||||||
"description": "条码映射:6907992501864 -> 6907992100012"
|
|
||||||
},
|
|
||||||
"6923644264192": {
|
|
||||||
"map_to": "6923644264116",
|
|
||||||
"description": "条码映射:6923644264192 -> 6923644264116"
|
|
||||||
},
|
|
||||||
"6923450667316": {
|
|
||||||
"map_to": "69042386",
|
|
||||||
"description": "条码映射:6923450667316 -> 69042386"
|
|
||||||
},
|
|
||||||
"6923450653012": {
|
|
||||||
"map_to": "69021343",
|
|
||||||
"description": "条码映射:6923450653012 -> 69021343"
|
|
||||||
},
|
|
||||||
"6925019900087": {
|
|
||||||
"multiplier": 10,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"description": "特殊处理:数量*10,单位转换为瓶"
|
|
||||||
},
|
|
||||||
"6921168593804": {
|
|
||||||
"multiplier": 30,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"description": "NFC产品特殊处理:每箱30瓶"
|
|
||||||
},
|
|
||||||
"6901826888138": {
|
|
||||||
"multiplier": 30,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"fixed_price": 3.7333333333333334,
|
|
||||||
"specification": "1*30",
|
|
||||||
"description": "特殊处理: 规格1*30,数量*30,单价=112/30"
|
|
||||||
},
|
|
||||||
"6958620703907": {
|
|
||||||
"multiplier": 14,
|
|
||||||
"target_unit": "个",
|
|
||||||
"specification": "1*14",
|
|
||||||
"description": "友臣肉松,1盒14个"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
dist/config/config.ini
vendored
28
dist/config/config.ini
vendored
@ -1,28 +0,0 @@
|
|||||||
[API]
|
|
||||||
api_key = O0Fgk3o69RWJ86eAX8BTHRaB
|
|
||||||
secret_key = VyZD5lzcIMgsup1uuD6Cw0pfzS20IGPZ
|
|
||||||
timeout = 30
|
|
||||||
max_retries = 3
|
|
||||||
retry_delay = 2
|
|
||||||
api_url = https://aip.baidubce.com/rest/2.0/ocr/v1/table
|
|
||||||
|
|
||||||
[Paths]
|
|
||||||
input_folder = data/input
|
|
||||||
output_folder = data/output
|
|
||||||
temp_folder = data/temp
|
|
||||||
template_folder = templates
|
|
||||||
processed_record = data/processed_files.json
|
|
||||||
|
|
||||||
[Performance]
|
|
||||||
max_workers = 4
|
|
||||||
batch_size = 5
|
|
||||||
skip_existing = true
|
|
||||||
|
|
||||||
[File]
|
|
||||||
allowed_extensions = .jpg,.jpeg,.png,.bmp
|
|
||||||
excel_extension = .xlsx
|
|
||||||
max_file_size_mb = 4
|
|
||||||
|
|
||||||
[Templates]
|
|
||||||
purchase_order = 银豹-采购单模板.xls
|
|
||||||
|
|
||||||
208
docs/SYSTEM_ARCHITECTURE.md
Normal file
208
docs/SYSTEM_ARCHITECTURE.md
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
# OCR 订单处理系统 - 系统架构文档 (v2.2)
|
||||||
|
|
||||||
|
本文件详述了“OCR 订单处理系统”的技术架构、业务流向、数据模型及部署方案。
|
||||||
|
|
||||||
|
## 1. 系统整体架构图 (System Overall Architecture)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TB
|
||||||
|
subgraph 用户交互层
|
||||||
|
UI[启动器.py / Tkinter GUI]
|
||||||
|
CLI[headless_api.py / CLI]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph 核心业务逻辑层
|
||||||
|
OS[OrderService / 订单调度]
|
||||||
|
OCR[OCRService / 图片识别]
|
||||||
|
SSS[SpecialSuppliersService / 特殊供应商处理]
|
||||||
|
TS[TobaccoService / 烟草处理]
|
||||||
|
EP[ExcelProcessor / 标准化转换]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph 基础设施与存储
|
||||||
|
CONFIG[ConfigManager / JSON 配置]
|
||||||
|
FS[FileSystem / Excel 数据存储]
|
||||||
|
LOG[QueueLogger / 异步日志队列]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph 第三方集成
|
||||||
|
OPENCLAW[OpenClaw 自动化平台]
|
||||||
|
POSPAL[银豹 POS 系统 (导出模板)]
|
||||||
|
end
|
||||||
|
|
||||||
|
UI --> OS
|
||||||
|
CLI --> OS
|
||||||
|
OPENCLAW -- 调用 --> CLI
|
||||||
|
OS --> OCR
|
||||||
|
OS --> SSS
|
||||||
|
OS --> TS
|
||||||
|
OS --> EP
|
||||||
|
EP --> FS
|
||||||
|
EP --> CONFIG
|
||||||
|
SSS --> EP
|
||||||
|
TS --> EP
|
||||||
|
OS -- 验证 --> FS
|
||||||
|
```
|
||||||
|
|
||||||
|
### 图例说明
|
||||||
|
- **用户交互层**:支持桌面 GUI 操作及专为 OpenClaw 设计的无界面 API 接入。
|
||||||
|
- **核心业务层**:各服务高度解耦,通过 `OrderService` 进行智能路由分发。
|
||||||
|
- **存储层**:系统采用“文件即数据库”的设计,利用 Excel 存储模板和商品资料,JSON 存储映射关系。
|
||||||
|
- **第三方集成**:与 OpenClaw 平台通过 CLI 接口对接,最终生成符合银豹 POS 要求的采购单。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 核心业务逻辑流程图 (Core Business Logic)
|
||||||
|
|
||||||
|
以“智能订单识别与预处理”为例:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant User as 用户/OpenClaw
|
||||||
|
participant OS as OrderService
|
||||||
|
participant SSS as SpecialSuppliersService
|
||||||
|
participant TS as TobaccoService
|
||||||
|
participant EP as ExcelProcessor
|
||||||
|
|
||||||
|
User->>OS: 提交 Excel 文件
|
||||||
|
OS->>OS: 扫描前50行内容特征
|
||||||
|
|
||||||
|
alt 包含 "RCDH"
|
||||||
|
OS->>SSS: 路由至蓉城易购预处理
|
||||||
|
SSS->>SSS: 按 E, N, Q, S 列强制清洗
|
||||||
|
SSS-->>OS: 返回清洗后的临时文件
|
||||||
|
else 包含 "专卖证号"
|
||||||
|
OS->>TS: 路由至烟草专用预处理
|
||||||
|
TS->>TS: 数量*10 / 单价/10 / B,E,G,H列映射
|
||||||
|
TS-->>OS: 返回清洗后的临时文件
|
||||||
|
else 包含 "杨碧月"
|
||||||
|
OS->>SSS: 路由至杨碧月列对齐流程
|
||||||
|
SSS-->>OS: 返回标准列临时文件
|
||||||
|
else 通用格式
|
||||||
|
OS->>OS: 直接跳过预处理
|
||||||
|
end
|
||||||
|
|
||||||
|
OS->>EP: 执行标准条码映射与模板填充
|
||||||
|
EP->>EP: 校验单价 (与商品资料比对)
|
||||||
|
EP-->>User: 输出最终银豹采购单 (data/result)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技术注解
|
||||||
|
- **智能指纹识别**:通过 `header=None` 读取前 50 行,避免了因标题行位置不固定导致的识别失败。
|
||||||
|
- **原子化预处理**:每个供应商逻辑独立,预处理结果均为统一格式的中间文件,确立了系统的可扩展性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 技术架构分层图 (Layered Architecture)
|
||||||
|
|
||||||
|
| 分层 | 技术栈 / 组件 | 功能描述 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **表现层 (Presentation)** | Tkinter, headless_api.py | 桌面 GUI 交互与 OpenClaw 命令行接口 |
|
||||||
|
| **业务逻辑层 (Business)** | Python 3.x, Pandas, OCRService | 核心数据清洗、条码分裂、供应商特征识别 |
|
||||||
|
| **数据访问层 (Data)** | Pandas (Excel Engine), Json | 对 Excel 模板、映射表、用户设置的读写 |
|
||||||
|
| **基础设施层 (Infrastructure)** | Queue, Logging, PyInstaller | 异步日志分发、全局错误处理、EXE 打包工具 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 数据架构设计 (Data Architecture)
|
||||||
|
|
||||||
|
系统未采用传统关系型数据库,而是基于 **JSON + Excel** 的混合存储架构。
|
||||||
|
|
||||||
|
### 4.1 表间关系示意 (JSON Mapping)
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
CONFIG_JSON ||--o{ BARCODE_MAPPING_JSON : "存储映射"
|
||||||
|
BARCODE_MAPPING_JSON {
|
||||||
|
string original_barcode "OCR识别出的原始条码"
|
||||||
|
string target_barcode "系统目标条码"
|
||||||
|
}
|
||||||
|
ITEM_DATA_EXCEL ||--o{ PURCHASE_ORDER_EXCEL : "验证单价"
|
||||||
|
ITEM_DATA_EXCEL {
|
||||||
|
string barcode "条码 (主键)"
|
||||||
|
float cost_price "进货价"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 存储方案
|
||||||
|
- **映射关系**:`barcode_mappings.json`。支持运行时动态更新,通过 `headless_api.py --update-mapping` 修改。
|
||||||
|
- **业务数据**:`templates/商品资料.xlsx`。作为单价校验的权威数据源。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 微服务与模块化设计 (Microservices & Modularity)
|
||||||
|
|
||||||
|
虽然系统目前采用单体架构(Monolithic Architecture)以适配桌面部署环境,但在逻辑上采用了**微服务式的模块化设计**:
|
||||||
|
|
||||||
|
- **服务拆分**:每个供应商逻辑(Rongcheng, Tobacco, YangBiyue)都是独立的类,具备高度自治性。
|
||||||
|
- **解耦机制**:通过统一的 `preprocess` 契约(输入:原始文件,输出:清洗后文件)进行交互,未来可轻松迁移至独立服务。
|
||||||
|
- **进程隔离**:GUI 主进程与业务处理线程通过 `queue.Queue` 进行解耦,确保处理逻辑不阻塞用户界面。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 部署架构图 (Deployment)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
subgraph 生产服务器 (Windows)
|
||||||
|
APP[orc-order-v2.exe]
|
||||||
|
DATA[data/ 目录]
|
||||||
|
LOGS[logs/ 目录]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph 自动化平台
|
||||||
|
OC[OpenClaw]
|
||||||
|
end
|
||||||
|
|
||||||
|
OC -- 命令行调用 --> APP
|
||||||
|
APP -- 读写 --> DATA
|
||||||
|
APP -- 记录 --> LOGS
|
||||||
|
```
|
||||||
|
|
||||||
|
### 部署要点
|
||||||
|
- **便携化**:通过 PyInstaller 将 Python 运行环境与依赖打包,实现单文件/单目录部署。
|
||||||
|
- **路径无关性**:系统内部通过 `os.path.abspath` 动态计算路径,支持安装在任意盘符。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 安全架构图 (Security)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[外部输入] --> B{文件类型校验}
|
||||||
|
B -- 非图片/Excel --> C[拒绝处理]
|
||||||
|
B -- 图片/Excel --> D[清洗逻辑]
|
||||||
|
D --> E{单价偏差校验}
|
||||||
|
E -- 差值 > 1.0 --> F[生成警告日志/弹窗]
|
||||||
|
E -- 正常 --> G[生成采购单]
|
||||||
|
G --> H[日志埋点与审计]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安全策略
|
||||||
|
- **数据隔离**:所有处理后的文件存放在 `data/output` 和 `data/result`,不修改原始输入文件。
|
||||||
|
- **权限控制**:系统运行于用户权限下,利用 Windows 文件系统权限保护配置文件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 技术债务与优化建议 (Tech Debt & Optimization)
|
||||||
|
|
||||||
|
### 7.1 当前技术债务
|
||||||
|
1. **并发限制**:目前为单进程串行处理,面对超大规模订单(万行级)可能存在阻塞。
|
||||||
|
2. **持久化局限**:使用 JSON 存储映射关系在条码量达到万级时,查询性能会下降。
|
||||||
|
3. **环境依赖**:OCR 引擎高度依赖 Tesseract/PaddleOCR 等本地二进制库,部署复杂。
|
||||||
|
|
||||||
|
### 7.2 单点故障风险 (SPOF Analysis)
|
||||||
|
1. **本地环境强依赖**:所有 OCR 与 Excel 处理均在单一 Windows 节点,若该节点故障,OpenClaw 对接将完全中断。
|
||||||
|
2. **核心模板丢失**:`templates/` 下的商品资料或采购单模板缺失会导致全流程崩溃。
|
||||||
|
3. **OCR 精度波动**:OCR 结果受图片质量影响,若 OCR 识别条码错误且无映射表,则该行数据将丢失。
|
||||||
|
|
||||||
|
### 7.3 架构优化建议方案
|
||||||
|
- **容灾备份**:建议将 `templates/` 和 `barcode_mappings.json` 定期备份至远程 Git 仓库(如 Gitea)。
|
||||||
|
- **分布式识别**:引入 PaddleOCR 服务端,支持多节点并发 OCR 识别,减少本地算力依赖。
|
||||||
|
- **配置热更新**:支持从远程 URL 加载 `barcode_mappings.json`,实现多机条码库同步。
|
||||||
|
- **数据回退机制**:增加中间文件持久化策略,允许在处理失败时手动干预已清洗的 Excel。
|
||||||
|
|
||||||
|
---
|
||||||
|
*附注:本文档图表均采用 Mermaid 标准编写,可直接在 VS Code (需安装 Mermaid 插件) 或 [Mermaid Live Editor](https://mermaid.live/) 中实时渲染并导出为高清 PNG/SVG 格式。*
|
||||||
|
|
||||||
|
---
|
||||||
|
*文档版本:2.2.0 | 生成日期:2026-03-31*
|
||||||
216
headless_api.py
Normal file
216
headless_api.py
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
OCR订单处理系统 - 无界面自动化接口
|
||||||
|
-----------------------------
|
||||||
|
专为与 openclaw 等自动化平台对接设计。
|
||||||
|
处理流程:输入图片 -> OCR识别 -> 数据清洗 -> 价格校验 -> 输出结果路径。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional, List, Dict
|
||||||
|
|
||||||
|
# 添加当前目录到路径
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
from app.config.settings import ConfigManager
|
||||||
|
from app.services.ocr_service import OCRService
|
||||||
|
from app.services.order_service import OrderService
|
||||||
|
from app.services.tobacco_service import TobaccoService
|
||||||
|
from app.services.special_suppliers_service import SpecialSuppliersService
|
||||||
|
from app.core.utils.log_utils import set_log_level
|
||||||
|
|
||||||
|
# 配置日志输出到 stderr
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
|
stream=sys.stderr
|
||||||
|
)
|
||||||
|
logger = logging.getLogger("HeadlessAPI")
|
||||||
|
|
||||||
|
def get_latest_file(directory: str, extensions: List[str]) -> Optional[str]:
|
||||||
|
"""获取目录中最新的指定后缀文件"""
|
||||||
|
dir_path = Path(directory)
|
||||||
|
if not dir_path.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
files = []
|
||||||
|
for ext in extensions:
|
||||||
|
files.extend(dir_path.glob(f"*{ext}"))
|
||||||
|
files.extend(dir_path.glob(f"*{ext.upper()}"))
|
||||||
|
|
||||||
|
if not files:
|
||||||
|
return None
|
||||||
|
|
||||||
|
latest_file = max(files, key=lambda p: p.stat().st_mtime)
|
||||||
|
return str(latest_file)
|
||||||
|
|
||||||
|
def update_barcode_mapping(barcode: str, target_barcode: str = None, multiplier: float = None, unit: str = None, price: float = None, spec: str = None):
|
||||||
|
"""更新条码映射或特殊处理配置"""
|
||||||
|
try:
|
||||||
|
config_path = os.path.join("config", "barcode_mappings.json")
|
||||||
|
mappings = {}
|
||||||
|
if os.path.exists(config_path):
|
||||||
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
|
mappings = json.load(f)
|
||||||
|
|
||||||
|
# 获取或创建该条码的配置
|
||||||
|
config = mappings.get(barcode, {})
|
||||||
|
|
||||||
|
if target_barcode:
|
||||||
|
config["map_to"] = target_barcode
|
||||||
|
config["description"] = config.get("description", "") + f" 条码映射 -> {target_barcode}"
|
||||||
|
|
||||||
|
if multiplier is not None:
|
||||||
|
config["multiplier"] = multiplier
|
||||||
|
config["description"] = config.get("description", "") + f" 数量倍数*{multiplier}"
|
||||||
|
|
||||||
|
if unit:
|
||||||
|
config["target_unit"] = unit
|
||||||
|
|
||||||
|
if price is not None:
|
||||||
|
config["fixed_price"] = price
|
||||||
|
|
||||||
|
if spec:
|
||||||
|
config["specification"] = spec
|
||||||
|
|
||||||
|
if not config.get("description"):
|
||||||
|
config["description"] = f"特殊条码配置: {barcode}"
|
||||||
|
|
||||||
|
mappings[barcode] = config
|
||||||
|
|
||||||
|
with open(config_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(mappings, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
logger.info(f"成功更新条码配置: {barcode} -> {config}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"更新条码配置失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def run_pipeline(args):
|
||||||
|
"""运行处理流水线"""
|
||||||
|
try:
|
||||||
|
config_manager = ConfigManager()
|
||||||
|
order_service = OrderService(config_manager)
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
final_excel = None
|
||||||
|
|
||||||
|
# 1. 处理条码映射更新
|
||||||
|
if args.update_mapping:
|
||||||
|
if not args.barcode:
|
||||||
|
print("ERROR: --barcode is required for --update-mapping", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 至少需要一个更新项
|
||||||
|
if not any([args.target, args.multiplier, args.unit, args.price, args.spec]):
|
||||||
|
print("ERROR: At least one update option (--target, --multiplier, --unit, --price, --spec) is required", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if update_barcode_mapping(args.barcode, args.target, args.multiplier, args.unit, args.price, args.spec):
|
||||||
|
print(f"SUCCESS: Barcode configuration updated for {args.barcode}")
|
||||||
|
return "MAPPING_UPDATED"
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 2. 烟草公司处理 (显式指定)
|
||||||
|
if args.tobacco:
|
||||||
|
input_path = args.input or get_latest_file("data/output", [".xlsx", ".xls"])
|
||||||
|
if not input_path:
|
||||||
|
print("ERROR: No tobacco order file found.", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
logger.info(f"开始显式处理烟草订单: {input_path}")
|
||||||
|
# 这里的 process_tobacco_order 会调用 preprocess 并生成银豹格式
|
||||||
|
tobacco_service = TobaccoService(config_manager)
|
||||||
|
final_excel = tobacco_service.process_tobacco_order(input_path)
|
||||||
|
|
||||||
|
# 3. 蓉城易购处理 (显式指定)
|
||||||
|
elif args.rongcheng:
|
||||||
|
input_path = args.input or get_latest_file("data/output", [".xlsx", ".xls"])
|
||||||
|
if not input_path:
|
||||||
|
print("ERROR: No Rongcheng Yigou order file found.", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
logger.info(f"开始显式处理蓉城易购订单: {input_path}")
|
||||||
|
special_service = SpecialSuppliersService(config_manager)
|
||||||
|
final_excel = special_service.process_rongcheng_yigou(input_path)
|
||||||
|
|
||||||
|
# 4. 普通 Excel 处理 (支持自动识别烟草/蓉城/杨碧月)
|
||||||
|
elif args.excel:
|
||||||
|
input_path = args.input or get_latest_file("data/input", [".xlsx", ".xls"])
|
||||||
|
if not input_path:
|
||||||
|
print("ERROR: No Excel file found in input.", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
logger.info(f"开始处理 Excel (支持智能识别): {input_path}")
|
||||||
|
# OrderService.process_excel 内部会自动调用 _check_special_preprocess
|
||||||
|
final_excel = order_service.process_excel(input_path)
|
||||||
|
|
||||||
|
# 5. 智能处理 (默认逻辑:自动判断图片还是 Excel)
|
||||||
|
else:
|
||||||
|
input_path = args.input or get_latest_file("data/input", [".jpg", ".jpeg", ".png", ".bmp", ".xlsx", ".xls"])
|
||||||
|
if not input_path:
|
||||||
|
print("ERROR: No input file found in data/input.", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
ext = os.path.splitext(input_path)[1].lower()
|
||||||
|
if ext in [".xlsx", ".xls"]:
|
||||||
|
logger.info(f"智能识别为 Excel 文件,开始处理: {input_path}")
|
||||||
|
final_excel = order_service.process_excel(input_path)
|
||||||
|
else:
|
||||||
|
logger.info(f"智能识别为图片文件,开始 OCR 处理: {input_path}")
|
||||||
|
ocr_service = OCRService(config_manager)
|
||||||
|
excel_intermediate = ocr_service.process_image(input_path)
|
||||||
|
if excel_intermediate:
|
||||||
|
final_excel = order_service.process_excel(excel_intermediate)
|
||||||
|
|
||||||
|
# 6. 后续处理 (校验与输出)
|
||||||
|
if final_excel:
|
||||||
|
# 单价校验
|
||||||
|
discrepancies = order_service.validate_unit_price(final_excel)
|
||||||
|
if discrepancies:
|
||||||
|
print(f"WARNING: Price validation found {len(discrepancies)} issues:", file=sys.stderr)
|
||||||
|
for d in discrepancies:
|
||||||
|
print(f" - {d}", file=sys.stderr)
|
||||||
|
|
||||||
|
duration = time.perf_counter() - start_time
|
||||||
|
logger.info(f"处理完成,耗时: {duration:.2f}s")
|
||||||
|
|
||||||
|
# 输出最终路径
|
||||||
|
abs_path = os.path.abspath(final_excel)
|
||||||
|
print(abs_path)
|
||||||
|
return abs_path
|
||||||
|
else:
|
||||||
|
print("ERROR: Processing failed.", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
print(f"CRITICAL ERROR: {str(e)}", file=sys.stderr)
|
||||||
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="OCR订单处理系统 - 无界面自动化接口")
|
||||||
|
parser.add_argument('input', nargs='?', help='输入文件路径 (图片或Excel)')
|
||||||
|
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument('--excel', action='store_true', help='处理普通 Excel 文件')
|
||||||
|
group.add_argument('--tobacco', action='store_true', help='处理烟草公司订单')
|
||||||
|
group.add_argument('--rongcheng', action='store_true', help='处理蓉城易购订单')
|
||||||
|
group.add_argument('--update-mapping', action='store_true', help='更新条码映射')
|
||||||
|
|
||||||
|
parser.add_argument('--barcode', help='待映射的原始条码 (用于 --update-mapping)')
|
||||||
|
parser.add_argument('--target', help='目标条码 (用于 --update-mapping)')
|
||||||
|
parser.add_argument('--multiplier', type=float, help='数量倍数 (例如箱转瓶填写30)')
|
||||||
|
parser.add_argument('--unit', help='目标单位 (例如"瓶")')
|
||||||
|
parser.add_argument('--price', type=float, help='固定单价')
|
||||||
|
parser.add_argument('--spec', help='固定规格 (例如"1*30")')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
result = run_pipeline(args)
|
||||||
|
sys.exit(0 if result else 1)
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1 +1,2 @@
|
|||||||
2025-08-16 00:52:17,210 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6937003706322 -> 6937003703833
|
2025-08-16 00:52:17,210 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6937003706322 -> 6937003703833
|
||||||
|
2025-11-15 16:34:22,181 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6923450653012 -> 69021343
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,389 @@
|
|||||||
2025-08-16 00:52:16,853 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
2025-08-16 00:52:16,853 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
2025-08-16 00:52:16,861 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
2025-08-16 00:52:16,861 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 20:52:59,975 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,975 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 20:52:59,980 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,980 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 20:52:59,985 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,985 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 20:52:59,999 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,999 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 20:53:00,004 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:53:00,004 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 21:55:05,648 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 21:55:05,656 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 21:55:14,957 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 21:55:14,960 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 21:56:00,538 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 21:56:00,562 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 22:00:56,344 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,344 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 22:00:56,357 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,357 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 22:00:56,364 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,365 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 23:22:38,475 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:22:38,475 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 23:53:32,028 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:53:32,028 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-14 23:56:57,447 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:56:57,447 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 00:18:49,537 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 00:18:49,537 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 00:44:36,719 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 00:44:36,720 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 01:58:02,054 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 01:58:02,054 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 09:48:24,108 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 09:48:24,126 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:06:56,596 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:06:56,620 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:10:31,639 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:10:31,653 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:39:24,612 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:39:24,612 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:39:48,326 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:39:48,337 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:39:52,727 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 10:39:52,728 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 10:49:13,775 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:49:13,775 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:51:44,473 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:51:44,475 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:51:49,960 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:51:49,960 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:54:02,883 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:54:02,886 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:54:06,684 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 10:54:06,705 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 10:58:26,607 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:58:26,621 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 10:58:36,067 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:58:36,082 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 14:17:23,600 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 14:17:23,608 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 14:17:23,670 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 14:17:23,682 - app.core.excel.merger - WARNING - 未在 data/result 目录下找到采购单Excel文件
|
||||||
|
2025-11-15 14:17:23,718 - app.core.excel.merger - WARNING - 没有找到可合并的采购单文件
|
||||||
|
2025-11-15 14:22:16,926 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 14:22:16,935 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:11:57,981 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:11:57,984 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:11:59,649 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:11:59,650 - app.core.excel.merger - INFO - 找到 2 个采购单Excel文件
|
||||||
|
2025-11-15 15:12:52,674 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:12:52,692 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:12:54,195 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:12:54,206 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 15:21:05,667 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:21:05,673 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:22:01,186 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:22:01,202 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:25:41,372 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:25:41,379 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:25:42,598 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:25:42,601 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 15:34:06,486 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:34:06,497 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:34:08,030 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:34:08,041 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 15:37:42,584 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:37:42,592 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:39:11,314 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:39:11,314 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:43:33,538 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:43:33,548 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:43:37,053 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:43:37,054 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 15:54:35,546 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:54:35,559 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 15:54:38,702 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 15:54:38,713 - app.core.excel.merger - INFO - 找到 2 个采购单Excel文件
|
||||||
|
2025-11-15 16:19:42,388 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:19:42,388 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:34:22,131 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:34:22,132 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:46:22,429 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:46:22,440 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:46:28,876 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:46:28,896 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:46:37,767 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:46:37,782 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:46:39,219 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 16:46:39,230 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 16:48:30,476 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:48:30,488 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:48:42,047 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:48:42,063 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:48:43,633 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 16:48:43,644 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 16:52:35,959 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:52:35,969 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:52:37,531 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 16:52:37,541 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 16:57:42,442 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:57:42,451 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:59:07,007 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:59:07,016 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:59:14,595 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:59:14,604 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 16:59:16,171 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 16:59:16,180 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 17:01:30,240 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:01:30,245 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:01:31,385 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 17:01:31,395 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 17:04:33,243 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:04:33,255 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:04:45,041 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:04:45,048 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:04:46,493 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 17:04:46,505 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 17:09:39,846 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:09:39,851 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:12:37,471 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:12:37,476 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:12:39,165 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 17:12:39,173 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-15 17:28:46,834 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:28:46,847 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:28:49,875 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 17:28:49,876 - app.core.excel.merger - INFO - 找到 2 个采购单Excel文件
|
||||||
|
2025-11-15 17:59:22,818 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:59:22,823 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:59:33,491 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:59:33,506 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 17:59:39,835 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:59:39,849 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 18:00:04,153 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 18:00:04,165 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-15 18:00:07,581 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-15 18:00:07,582 - app.core.excel.merger - INFO - 找到 3 个采购单Excel文件
|
||||||
|
2025-11-15 18:01:51,698 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 18:01:51,710 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 10:48:45,534 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 10:48:45,552 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 10:56:22,516 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 10:56:22,516 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 11:23:59,373 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 11:23:59,373 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 11:26:06,795 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 11:26:06,795 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 12:51:06,910 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 12:51:06,910 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 13:03:10,562 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:03:10,563 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 13:03:10,583 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:03:10,584 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 13:18:18,247 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:18:18,248 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 13:18:18,270 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:18:18,271 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 13:51:09,017 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:51:09,018 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 14:25:50,027 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:25:50,031 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 14:25:55,596 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:25:55,612 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 14:25:56,992 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-16 14:25:57,001 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-16 14:39:42,980 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:39:42,980 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 14:39:42,995 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:39:42,996 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 14:59:35,437 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:59:35,437 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:03:21,893 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:03:21,893 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:08:33,545 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:08:33,546 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:11:11,240 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:11:11,254 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:11:12,200 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-16 15:11:12,212 - app.core.excel.merger - INFO - 找到 2 个采购单Excel文件
|
||||||
|
2025-11-16 15:13:47,399 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:13:47,401 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:13:50,815 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-16 15:13:50,816 - app.core.excel.merger - INFO - 找到 3 个采购单Excel文件
|
||||||
|
2025-11-16 15:15:36,200 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:15:36,203 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-16 15:15:39,032 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-16 15:15:39,033 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:36:13,285 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:36:13,295 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:36:14,159 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:36:14,170 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:36:42,097 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:36:42,104 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:36:43,288 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:36:43,297 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:42:25,918 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:42:25,932 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:42:26,808 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:42:26,819 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:44:11,119 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:44:11,128 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:46:17,345 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:46:17,346 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:47:03,916 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:47:03,919 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:50:11,046 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:50:11,047 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-11-20 18:56:30,337 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:56:30,348 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-11-20 18:56:34,058 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-11-20 18:56:34,061 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-12-01 22:21:09,101 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-01 22:21:09,105 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-01 22:21:20,388 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2025-12-01 22:21:20,390 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-12-12 11:00:14,089 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:00:14,095 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:13:15,287 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:13:15,288 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:22:25,990 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:22:25,990 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:32:26,694 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:32:26,694 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:34:40,238 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:34:40,238 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:38:53,256 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:38:53,260 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 11:49:38,203 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 11:49:38,203 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 12:30:07,698 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 12:30:07,700 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2025-12-12 12:32:20,579 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-12 12:32:20,579 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 10:20:20,144 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 10:20:20,145 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 10:21:25,355 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 10:21:25,356 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 10:21:52,469 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 10:21:52,470 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:28:54,451 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:28:54,451 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:29:24,575 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:29:24,576 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:29:24,580 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:29:24,580 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:29:58,483 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:29:58,484 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:29:58,488 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:29:58,488 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:30:29,317 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:30:29,317 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:30:29,321 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:30:29,322 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:31:51,946 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:31:51,947 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:31:51,951 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:31:51,952 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:46:00,210 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:46:00,211 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:46:00,229 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:46:00,230 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:46:02,785 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:46:02,785 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:47:05,233 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:47:05,233 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:47:05,255 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:47:05,256 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:47:06,654 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:47:06,654 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:48:28,519 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:48:28,519 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:48:28,525 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:48:28,525 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:48:30,802 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:48:30,802 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:51:44,156 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:51:44,156 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:51:44,170 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:51:44,171 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 13:51:46,072 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 13:51:46,072 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:00:52,374 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:00:52,374 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:00:52,392 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:00:52,392 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:01:20,295 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:01:20,295 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:01:20,307 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:01:20,308 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:01:24,376 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:01:24,376 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:06:58,242 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:06:58,243 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:07:00,055 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:07:00,055 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:14:46,832 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:14:46,832 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:14:47,891 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:14:47,891 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:23:18,310 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:23:18,310 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:23:20,043 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:23:20,043 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:24:02,882 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:24:02,883 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:24:04,318 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:24:04,318 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:28:39,039 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:28:39,040 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:28:39,737 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:28:39,738 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:41:11,949 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:41:11,949 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:41:33,388 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:41:33,388 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:41:47,796 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:41:47,796 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-30 14:41:49,673 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-30 14:41:49,673 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 08:50:15,740 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 08:50:15,754 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 08:50:17,775 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 08:50:17,775 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 08:52:46,014 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 08:52:46,014 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 08:52:47,191 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 08:52:47,192 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:00:01,693 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:00:01,693 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:03:11,828 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:03:11,829 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:03:13,872 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:03:13,872 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:05:33,093 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:05:33,094 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:05:33,868 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:05:33,868 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:05:36,165 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2026-03-31 09:05:36,165 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2026-03-31 09:07:58,235 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:07:58,235 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:07:58,352 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 09:07:58,353 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 09:08:00,645 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2026-03-31 09:08:00,646 - app.core.excel.merger - INFO - 找到 2 个采购单Excel文件
|
||||||
|
2026-03-31 10:59:54,581 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 10:59:54,581 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 10:59:56,658 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 10:59:56,659 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:01:45,697 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:01:45,697 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:01:47,940 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:01:47,940 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:01:50,780 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2026-03-31 11:01:50,781 - app.core.excel.merger - INFO - 找到 3 个采购单Excel文件
|
||||||
|
2026-03-31 11:27:58,582 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:27:58,583 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:28:01,610 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:28:01,610 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:28:04,092 - app.core.excel.merger - INFO - 搜索目录 data/result 中的采购单Excel文件
|
||||||
|
2026-03-31 11:28:04,093 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2026-03-31 11:28:11,907 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:28:11,908 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
2026-03-31 11:28:13,708 - app.core.excel.merger - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:28:13,708 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成,模板文件: E:\2025Code\python\orc-order-v2\templates\银豹-采购单模板.xls
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
|||||||
|
2025-11-14 21:55:30,948 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-14 23:53:34,369 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 00:20:01,697 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 09:53:49,682 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 10:06:38,107 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 10:39:49,255 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 10:54:03,264 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 14:16:12,391 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 14:41:42,507 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 15:12:40,831 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 15:25:05,333 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 15:33:48,514 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 15:43:34,042 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 16:39:06,073 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 17:28:47,324 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-15 18:00:04,623 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-16 12:50:38,921 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-16 15:11:07,710 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-16 15:13:47,756 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-11-16 15:15:36,568 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-12-01 22:21:09,536 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2026-03-31 11:01:46,107 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2026-03-31 11:27:58,846 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2026-03-31 11:27:58,858 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
@ -0,0 +1,422 @@
|
|||||||
|
2025-11-14 20:52:59,972 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 20:52:59,973 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,973 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 20:52:59,973 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 20:52:59,974 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 20:52:59,976 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 20:52:59,978 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,978 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 20:52:59,978 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 20:52:59,978 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 20:52:59,982 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 20:52:59,982 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,982 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 20:52:59,984 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 20:52:59,984 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 20:52:59,996 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 20:52:59,996 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:52:59,996 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 20:52:59,997 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 20:52:59,997 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 20:53:00,001 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 20:53:00,001 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 20:53:00,001 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 20:53:00,001 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 20:53:00,002 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 21:55:14,932 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 21:55:14,933 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 21:55:14,935 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 21:55:14,936 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 21:55:14,937 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 21:55:15,025 - app.core.ocr.table_ocr - INFO - 找到 0 个图片文件,其中 0 个未处理
|
||||||
|
2025-11-14 21:55:15,031 - app.core.ocr.table_ocr - WARNING - 没有需要处理的图片
|
||||||
|
2025-11-14 21:55:30,512 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 21:55:30,522 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 21:55:30,535 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 21:55:30,547 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 21:55:30,563 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 21:55:30,612 - app.core.ocr.table_ocr - INFO - 开始处理图片: E:/2025Code/python/orc-order-v2/data/input/微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 21:55:32,256 - app.core.ocr.table_ocr - INFO - 图片处理成功: E:/2025Code/python/orc-order-v2/data/input/微信图片_20250909184135_44_108.jpg, 输出文件: data/output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 22:00:56,334 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 22:00:56,335 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,336 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 22:00:56,336 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 22:00:56,338 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 22:00:56,354 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 22:00:56,354 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,354 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 22:00:56,355 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 22:00:56,355 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 22:00:56,361 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 22:00:56,361 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 22:00:56,361 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 22:00:56,361 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 22:00:56,362 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 23:22:38,471 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 23:22:38,471 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:22:38,472 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 23:22:38,472 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 23:22:38,472 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 23:53:32,026 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 23:53:32,026 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:53:32,026 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 23:53:32,026 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 23:53:32,026 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-14 23:53:34,048 - app.core.ocr.table_ocr - INFO - 开始处理图片: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:35,690 - app.core.ocr.table_ocr - INFO - 图片处理成功: data\input\微信图片_20250909184135_44_108.jpg, 输出文件: data/output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:54:00,127 - app.core.ocr.table_ocr - INFO - 开始处理图片: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:01,441 - app.core.ocr.table_ocr - INFO - 图片处理成功: data\input\微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:50,647 - app.core.ocr.table_ocr - INFO - 开始处理图片: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:54:51,981 - app.core.ocr.table_ocr - INFO - 图片处理成功: data\input\微信图片_20251019141843_92_108.jpg, 输出文件: data/output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:56:57,443 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-14 23:56:57,443 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-14 23:56:57,443 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-14 23:56:57,443 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-14 23:56:57,443 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 00:18:49,534 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 00:18:49,534 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 00:18:49,534 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 00:18:49,534 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 00:18:49,535 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 00:20:01,395 - app.core.ocr.table_ocr - INFO - 开始处理图片: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:03,253 - app.core.ocr.table_ocr - INFO - 图片处理成功: data\input\微信图片_20251019141843_92_108.jpg, 输出文件: data/output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:44:36,717 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 00:44:36,717 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 00:44:36,717 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 00:44:36,717 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 00:44:36,718 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 01:58:02,050 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 01:58:02,051 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 01:58:02,051 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 01:58:02,051 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 01:58:02,051 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 09:48:24,086 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 09:48:24,087 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 09:48:24,087 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 09:48:24,087 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 09:48:24,088 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 09:49:24,553 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 09:49:24,553 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 09:49:24,557 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 09:49:24,560 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 09:49:24,563 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 09:53:49,094 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 09:53:49,107 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 09:53:49,118 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 09:53:49,132 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 09:53:49,147 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 09:53:49,215 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 09:53:49,231 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 09:53:49,248 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 09:53:51,046 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 09:53:51,047 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 10:06:37,789 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:06:37,795 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:06:37,803 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:06:37,811 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:06:37,818 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:06:37,843 - app.core.ocr.table_ocr - INFO - 开始处理图片: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 10:06:39,473 - app.core.ocr.table_ocr - INFO - 图片处理成功: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:39:24,607 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:39:24,607 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:39:24,608 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:39:24,608 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:39:24,609 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:39:48,299 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:39:48,301 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:39:48,303 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:39:48,305 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:39:48,308 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:39:48,365 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 10:39:48,368 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 10:39:48,392 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 10:39:50,666 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:39:50,667 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 10:49:13,768 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:49:13,769 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:49:13,769 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:49:13,769 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:49:13,770 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:51:44,469 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:51:44,469 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:51:44,469 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:51:44,470 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:51:44,470 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:51:49,953 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:51:49,954 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:51:49,954 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:51:49,955 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:51:49,955 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:54:02,833 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 10:54:02,834 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 10:54:02,837 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 10:54:02,841 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 10:54:02,846 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 10:54:02,940 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 10:54:02,943 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 10:54:02,973 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 10:54:04,733 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:54:04,738 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 14:16:11,980 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 14:16:11,982 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 14:16:11,985 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 14:16:11,997 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 14:16:11,999 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 14:16:12,028 - app.core.ocr.table_ocr - INFO - 开始处理图片: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251113183218_594_278.jpg
|
||||||
|
2025-11-15 14:16:14,042 - app.core.ocr.table_ocr - INFO - 图片处理成功: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251113183218_594_278.jpg, 输出文件: data/output\微信图片_20251113183218_594_278.xlsx
|
||||||
|
2025-11-15 14:41:42,172 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 14:41:42,173 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 14:41:42,175 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 14:41:42,176 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 14:41:42,179 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 14:41:42,198 - app.core.ocr.table_ocr - INFO - 开始处理图片: F:/下载/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 14:41:44,478 - app.core.ocr.table_ocr - INFO - 图片处理成功: F:/下载/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:11:57,934 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:11:57,937 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:11:57,939 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:11:57,945 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:11:57,946 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:11:58,040 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 15:11:58,053 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 15:11:58,081 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251113183218_594_278.jpg
|
||||||
|
2025-11-15 15:11:58,091 - app.core.ocr.table_ocr - INFO - 已存在对应的Excel文件,跳过处理: 微信图片_20251113183218_594_278.jpg -> 微信图片_20251113183218_594_278.xlsx
|
||||||
|
2025-11-15 15:11:58,132 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 15:12:40,318 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:12:40,333 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:12:40,345 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:12:40,358 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:12:40,370 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:12:40,403 - app.core.ocr.table_ocr - INFO - 开始处理图片: F:/下载/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 15:12:42,172 - app.core.ocr.table_ocr - INFO - 图片处理成功: F:/下载/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:25:05,003 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:25:05,004 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:25:05,006 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:25:05,009 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:25:05,019 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:25:05,052 - app.core.ocr.table_ocr - INFO - 开始处理图片: F:/下载/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 15:25:06,786 - app.core.ocr.table_ocr - INFO - 图片处理成功: F:/下载/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:33:47,219 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:33:47,225 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:33:47,228 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:33:47,229 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:33:47,234 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:33:47,269 - app.core.ocr.table_ocr - INFO - 开始处理图片: F:/下载/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 15:33:50,403 - app.core.ocr.table_ocr - INFO - 图片处理成功: F:/下载/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:39:11,309 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:39:11,310 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:39:11,310 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:39:11,310 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:39:11,311 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:43:33,473 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 15:43:33,474 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 15:43:33,478 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 15:43:33,481 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 15:43:33,485 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 15:43:33,617 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 15:43:33,637 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 15:43:33,670 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251113183218_594_278.jpg
|
||||||
|
2025-11-15 15:43:35,235 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251113183218_594_278.jpg, 输出文件: data/output\微信图片_20251113183218_594_278.xlsx
|
||||||
|
2025-11-15 15:43:35,236 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 16:39:05,575 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 16:39:05,581 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:39:05,587 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 16:39:05,594 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 16:39:05,597 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 16:39:05,641 - app.core.ocr.table_ocr - INFO - 开始处理图片: F:/下载/微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 16:39:07,420 - app.core.ocr.table_ocr - INFO - 图片处理成功: F:/下载/微信图片_20251027125604_98_108.jpg, 输出文件: data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 16:46:22,388 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 16:46:22,388 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 16:46:22,390 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 16:46:22,390 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 16:46:22,392 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 16:46:22,501 - app.core.ocr.table_ocr - INFO - 找到 0 个图片文件,其中 0 个未处理
|
||||||
|
2025-11-15 16:46:22,522 - app.core.ocr.table_ocr - WARNING - 没有需要处理的图片
|
||||||
|
2025-11-15 17:28:46,777 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 17:28:46,778 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:28:46,781 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 17:28:46,784 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 17:28:46,789 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 17:28:46,913 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 17:28:46,930 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 17:28:46,975 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251115145536_614_278.jpg
|
||||||
|
2025-11-15 17:28:48,564 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251115145536_614_278.jpg, 输出文件: data/output\微信图片_20251115145536_614_278.xlsx
|
||||||
|
2025-11-15 17:28:48,566 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 17:29:22,057 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 17:29:22,070 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:29:22,076 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 17:29:22,084 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 17:29:22,098 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 17:29:22,147 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 17:29:22,159 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 17:29:22,180 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251115145536_614_278.jpg
|
||||||
|
2025-11-15 17:29:22,198 - app.core.ocr.table_ocr - INFO - 已存在对应的Excel文件,跳过处理: 微信图片_20251115145536_614_278.jpg -> 微信图片_20251115145536_614_278.xlsx
|
||||||
|
2025-11-15 17:29:22,217 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-15 17:59:39,798 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 17:59:39,799 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 17:59:39,800 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 17:59:39,800 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 17:59:39,801 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 17:59:39,913 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 0 个未处理
|
||||||
|
2025-11-15 17:59:39,930 - app.core.ocr.table_ocr - WARNING - 没有需要处理的图片
|
||||||
|
2025-11-15 18:00:04,112 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-15 18:00:04,114 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-15 18:00:04,116 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-15 18:00:04,117 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-15 18:00:04,119 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-15 18:00:04,224 - app.core.ocr.table_ocr - INFO - 找到 2 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-15 18:00:04,247 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-15 18:00:04,278 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251114131924_600_278.jpg
|
||||||
|
2025-11-15 18:00:05,870 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251114131924_600_278.jpg, 输出文件: data/output\微信图片_20251114131924_600_278.xlsx
|
||||||
|
2025-11-15 18:00:05,872 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-16 11:23:59,369 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 11:23:59,369 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 11:23:59,369 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 11:23:59,369 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 11:23:59,369 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 11:26:06,790 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 11:26:06,791 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 11:26:06,791 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 11:26:06,791 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 11:26:06,792 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 12:50:38,502 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 12:50:38,503 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 12:50:38,504 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 12:50:38,506 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 12:50:38,508 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 12:50:38,541 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-16 12:50:38,550 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-16 12:50:38,560 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251115212128_148_108.jpg
|
||||||
|
2025-11-16 12:50:40,143 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251115212128_148_108.jpg, 输出文件: data/output\微信图片_20251115212128_148_108.xlsx
|
||||||
|
2025-11-16 12:50:40,149 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-16 12:51:06,904 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 12:51:06,906 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 12:51:06,906 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 12:51:06,906 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 12:51:06,907 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 13:03:10,557 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 13:03:10,557 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:03:10,557 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 13:03:10,558 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 13:03:10,558 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 13:03:10,578 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 13:03:10,578 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:03:10,579 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 13:03:10,579 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 13:03:10,580 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 13:18:18,243 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 13:18:18,243 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:18:18,244 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 13:18:18,244 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 13:18:18,244 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 13:18:18,265 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 13:18:18,265 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:18:18,266 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 13:18:18,266 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 13:18:18,267 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 13:51:09,012 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 13:51:09,013 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 13:51:09,013 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 13:51:09,013 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 13:51:09,014 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 14:39:42,975 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 14:39:42,976 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:39:42,976 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 14:39:42,976 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 14:39:42,977 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 14:39:42,990 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 14:39:42,991 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 14:39:42,991 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 14:39:42,991 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 14:39:42,992 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 15:11:05,478 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 15:11:05,485 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:11:05,487 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 15:11:05,489 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 15:11:05,498 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 15:11:05,536 - app.core.ocr.table_ocr - INFO - 找到 2 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-16 15:11:05,549 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-16 15:11:05,571 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151001_152_108.jpg
|
||||||
|
2025-11-16 15:11:08,994 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251116151001_152_108.jpg, 输出文件: data/output\微信图片_20251116151001_152_108.xlsx
|
||||||
|
2025-11-16 15:11:08,995 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-16 15:13:47,370 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 15:13:47,372 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:13:47,375 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 15:13:47,381 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 15:13:47,383 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 15:13:47,457 - app.core.ocr.table_ocr - INFO - 找到 3 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-16 15:13:47,470 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-16 15:13:47,510 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151334_153_108.jpg
|
||||||
|
2025-11-16 15:13:49,392 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251116151334_153_108.jpg, 输出文件: data/output\微信图片_20251116151334_153_108.xlsx
|
||||||
|
2025-11-16 15:13:49,397 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-16 15:15:36,173 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-16 15:15:36,173 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-16 15:15:36,174 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-16 15:15:36,175 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-16 15:15:36,177 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-16 15:15:36,243 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-16 15:15:36,257 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-16 15:15:36,299 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151514_154_108.jpg
|
||||||
|
2025-11-16 15:15:37,808 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251116151514_154_108.jpg, 输出文件: data/output\微信图片_20251116151514_154_108.xlsx
|
||||||
|
2025-11-16 15:15:37,809 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-20 18:44:11,080 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-20 18:44:11,083 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:44:11,087 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-20 18:44:11,089 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-20 18:44:11,094 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-20 18:44:11,194 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-20 18:44:11,216 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-20 18:44:11,261 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151514_154_108.jpg
|
||||||
|
2025-11-20 18:44:11,261 - app.core.ocr.table_ocr - INFO - 已存在对应的Excel文件,跳过处理: 微信图片_20251116151514_154_108.jpg -> 微信图片_20251116151514_154_108.xlsx
|
||||||
|
2025-11-20 18:44:11,295 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-20 18:47:03,864 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-20 18:47:03,867 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:47:03,867 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-20 18:47:03,869 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-20 18:47:03,871 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-20 18:47:03,990 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-20 18:47:04,011 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-20 18:47:04,048 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151514_154_108.jpg
|
||||||
|
2025-11-20 18:47:04,058 - app.core.ocr.table_ocr - INFO - 已存在对应的Excel文件,跳过处理: 微信图片_20251116151514_154_108.jpg -> 微信图片_20251116151514_154_108.xlsx
|
||||||
|
2025-11-20 18:47:04,080 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-11-20 18:56:30,283 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-11-20 18:56:30,284 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-11-20 18:56:30,287 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-11-20 18:56:30,289 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-11-20 18:56:30,291 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-11-20 18:56:30,417 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-11-20 18:56:30,439 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-11-20 18:56:30,483 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251116151514_154_108.jpg
|
||||||
|
2025-11-20 18:56:30,483 - app.core.ocr.table_ocr - INFO - 已存在对应的Excel文件,跳过处理: 微信图片_20251116151514_154_108.jpg -> 微信图片_20251116151514_154_108.xlsx
|
||||||
|
2025-11-20 18:56:30,495 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-12-01 22:21:09,028 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2025-12-01 22:21:09,043 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2025-12-01 22:21:09,046 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2025-12-01 22:21:09,048 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2025-12-01 22:21:09,052 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2025-12-01 22:21:09,173 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-12-01 22:21:09,198 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2025-12-01 22:21:09,246 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20251201221738_176_108.jpg
|
||||||
|
2025-12-01 22:21:10,536 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20251201221738_176_108.jpg, 输出文件: data/output\微信图片_20251201221738_176_108.xlsx
|
||||||
|
2025-12-01 22:21:10,538 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2026-03-31 11:01:45,677 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2026-03-31 11:01:45,691 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:01:45,691 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2026-03-31 11:01:45,692 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2026-03-31 11:01:45,692 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2026-03-31 11:01:45,700 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2026-03-31 11:01:45,701 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 1 个文件
|
||||||
|
2026-03-31 11:01:45,712 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\20260331-110124.jpg
|
||||||
|
2026-03-31 11:01:47,745 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\20260331-110124.jpg, 输出文件: data/output\20260331-110124.xlsx
|
||||||
|
2026-03-31 11:01:47,747 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2026-03-31 11:27:58,576 - app.core.ocr.table_ocr - INFO - 使用输入目录: E:\2025Code\python\orc-order-v2\data\input
|
||||||
|
2026-03-31 11:27:58,576 - app.core.ocr.table_ocr - INFO - 使用输出目录: E:\2025Code\python\orc-order-v2\data\output
|
||||||
|
2026-03-31 11:27:58,577 - app.core.ocr.table_ocr - INFO - 使用临时目录: E:\2025Code\python\orc-order-v2\data\temp
|
||||||
|
2026-03-31 11:27:58,577 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
|
||||||
|
2026-03-31 11:27:58,577 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成:输入目录=data/input, 输出目录=data/output
|
||||||
|
2026-03-31 11:27:58,604 - app.core.ocr.table_ocr - INFO - 找到 2 个图片文件,其中 2 个未处理
|
||||||
|
2026-03-31 11:27:58,605 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 2 个文件
|
||||||
|
2026-03-31 11:27:58,614 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\20260331-112736.jpg
|
||||||
|
2026-03-31 11:27:58,615 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\20260331-112747.jpg
|
||||||
|
2026-03-31 11:28:00,366 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\20260331-112747.jpg, 输出文件: data/output\20260331-112747.xlsx
|
||||||
|
2026-03-31 11:28:00,713 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\20260331-112736.jpg, 输出文件: data/output\20260331-112736.xlsx
|
||||||
|
2026-03-31 11:28:00,715 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 2, 成功: 2
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
2025-11-14 21:55:05,688 - app.core.utils.file_utils - WARNING - 未在目录 data/output 中找到符合条件的文件
|
||||||
|
2025-11-16 10:48:45,595 - app.core.utils.file_utils - WARNING - 未在目录 data/output 中找到符合条件的文件
|
||||||
|
2025-11-16 10:48:45,656 - app.core.utils.file_utils - WARNING - 未在目录 data/output 中找到符合条件的文件
|
||||||
|
2025-11-16 10:56:22,516 - app.core.utils.file_utils - WARNING - 未在目录 data/output 中找到符合条件的文件
|
||||||
@ -0,0 +1,597 @@
|
|||||||
|
2025-11-14 20:52:59,971 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 20:52:59,974 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 20:52:59,976 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 20:52:59,978 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 20:52:59,982 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 20:52:59,984 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 20:52:59,995 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 20:52:59,997 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 20:53:00,000 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 20:53:00,002 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 21:55:14,931 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 21:55:14,939 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 21:55:14,988 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-14 21:55:15,019 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-14 21:55:30,504 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 21:55:30,576 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 21:55:32,258 - app.services.ocr_service - INFO - 处理完成: E:/2025Code/python/orc-order-v2/data/input/微信图片_20250909184135_44_108.jpg -> data/output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 22:00:56,331 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 22:00:56,339 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 22:00:56,354 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 22:00:56,355 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 22:00:56,360 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 22:00:56,362 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 23:22:38,470 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 23:22:38,472 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 23:53:32,025 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 23:53:32,027 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 23:53:35,691 - app.services.ocr_service - INFO - 处理完成: data\input\微信图片_20250909184135_44_108.jpg -> data/output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:37,742 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:39,788 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:41,832 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:43,881 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:45,934 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:48,001 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:53:50,039 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20250909184135_44_108.jpg
|
||||||
|
2025-11-14 23:54:01,442 - app.services.ocr_service - INFO - 处理完成: data\input\微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:03,487 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:05,528 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:07,576 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:09,616 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:13,773 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:15,821 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:17,867 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:19,919 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:21,962 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:24,008 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:26,046 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:28,097 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:30,151 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:32,204 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:34,250 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:36,296 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:38,351 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:40,404 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:42,458 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:44,502 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:46,556 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:48,600 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:51,982 - app.services.ocr_service - INFO - 处理完成: data\input\微信图片_20251019141843_92_108.jpg -> data/output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:54:52,021 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:54,069 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:54:54,107 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:56,148 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:54:56,189 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:54:58,238 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:54:58,275 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:00,326 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:00,364 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:02,419 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:02,462 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:04,521 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:04,558 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:06,605 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:06,642 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:08,703 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:08,740 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:10,786 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:10,827 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:12,879 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:12,916 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:14,960 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:14,996 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:17,036 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:17,073 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:19,125 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:19,162 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:21,204 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:21,242 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:23,294 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:23,335 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:25,382 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:25,421 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:27,467 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:27,505 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:29,547 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:29,582 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:31,622 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:31,669 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:33,737 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:33,774 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:35,817 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:35,853 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:37,920 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:37,961 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:40,013 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:40,051 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:42,108 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:42,146 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:44,193 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:44,229 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:46,275 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:46,315 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:48,365 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:48,404 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:50,443 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:50,482 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:52,535 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:52,573 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:54,614 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:54,653 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:56,710 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:56,748 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:55:58,800 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:55:58,838 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:56:00,891 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:56:00,933 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:56:02,979 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:56:03,018 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:56:05,062 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:56:05,105 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:56:07,162 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:56:07,210 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:56:57,442 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-14 23:56:57,445 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-14 23:56:59,616 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:01,537 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:05,227 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:06,470 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:09,653 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:11,576 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:15,136 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:16,887 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:20,234 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:21,430 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:24,780 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:26,265 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:29,872 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:31,572 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:35,123 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:36,918 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:40,537 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:42,112 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:45,416 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:46,720 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:49,990 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:51,501 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:54,894 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:57:56,395 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:57:59,834 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:01,639 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:05,077 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:06,547 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:09,915 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:11,351 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:14,705 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:16,392 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:19,888 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:21,532 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:24,978 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:26,500 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:29,831 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:31,416 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:34,852 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:36,575 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:39,921 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:41,452 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:44,946 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:46,443 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:50,034 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:51,597 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:58:55,053 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:58:56,555 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:00,070 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:01,844 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:05,320 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:06,825 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:10,473 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:12,139 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:15,603 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:17,192 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:20,612 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:22,114 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:25,589 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:27,211 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:30,767 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:32,326 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:36,011 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:37,686 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:41,201 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:42,778 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:46,304 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:47,761 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:51,191 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:52,841 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-14 23:59:56,216 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-14 23:59:57,611 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:01,219 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:02,758 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:06,052 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:07,434 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:10,840 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:12,561 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:16,097 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:17,522 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:20,868 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:22,464 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:26,088 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:27,515 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:31,017 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:32,515 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:36,053 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:37,624 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:41,060 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:42,493 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:45,839 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:47,275 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:50,609 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:52,109 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:00:55,459 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:00:57,222 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:00,688 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:02,298 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:05,719 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:07,317 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:10,858 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:12,551 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:16,041 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:17,743 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:21,145 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:22,630 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:26,026 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:27,349 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:30,913 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:32,597 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:35,986 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:37,481 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:40,840 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:42,630 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:46,085 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:47,711 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:51,307 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:53,097 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:01:56,452 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:01:57,944 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:01,308 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:02,944 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:06,570 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:08,356 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:12,004 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:13,757 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:17,556 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:19,476 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:22,928 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:24,545 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:27,890 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:29,443 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:32,790 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:34,247 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:37,750 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:39,242 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:42,620 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:44,196 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:47,546 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:49,236 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:52,656 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:54,352 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:02:57,747 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:02:59,241 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:02,582 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:03,966 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:07,396 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:09,150 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:12,454 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:14,078 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:17,563 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:18,931 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:22,254 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:23,958 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:27,433 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:28,875 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:32,492 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:33,730 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:37,280 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:38,745 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:42,378 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:44,064 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:47,518 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:49,323 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:52,839 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:54,315 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:03:57,762 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:03:59,377 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:02,912 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:04,333 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:07,634 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:09,217 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:12,781 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:14,391 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:17,952 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:19,426 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:22,773 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:24,437 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:27,786 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:29,491 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:33,208 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:34,834 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:38,270 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:39,870 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:43,227 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:44,671 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:48,011 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:49,544 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:52,898 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:54,514 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:04:58,133 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:04:59,637 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:03,203 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:04,439 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:07,802 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:09,420 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:13,002 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:14,449 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:17,865 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:19,351 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:22,585 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:24,115 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:27,622 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:29,332 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:32,669 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:34,242 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:37,801 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:39,407 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:42,969 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:44,554 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:48,144 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:49,714 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:53,196 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:54,908 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:05:58,328 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:05:59,736 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:18:49,533 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 00:18:49,535 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 00:18:51,772 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:18:53,982 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:18:57,742 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:18:59,499 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:19:02,811 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:19:04,852 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:19:08,780 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:19:10,559 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:19:14,369 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:19:16,366 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251027125604_98_108.jpg
|
||||||
|
2025-11-15 00:20:03,254 - app.services.ocr_service - INFO - 处理完成: data\input\微信图片_20251019141843_92_108.jpg -> data/output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:06,966 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:10,786 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:14,177 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:17,835 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:21,070 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:24,531 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:28,407 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:31,774 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:35,631 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:39,543 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:20:43,297 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:44:36,716 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 00:44:36,718 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 00:44:39,002 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:44:43,224 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 00:44:47,343 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:02,050 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 01:58:02,051 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 01:58:04,310 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:08,536 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:12,817 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:17,274 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:21,129 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:39,915 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:43,786 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:47,743 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:52,055 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:58:56,257 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:59:38,855 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:59:42,879 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:59:46,931 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:59:51,017 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 01:59:55,157 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:00:39,353 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:00:43,387 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:00:47,550 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:00:52,036 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:00:56,180 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:01:40,371 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:01:44,582 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:01:48,847 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:01:53,093 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:01:57,105 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:02:41,519 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:02:45,567 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:02:49,844 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:02:53,881 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:02:57,870 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:03:42,078 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:03:46,476 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:03:50,820 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:03:54,976 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:03:59,499 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:04:44,020 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:04:48,141 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:04:52,372 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:04:56,700 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:05:00,874 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:05:45,362 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:05:49,450 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:05:53,666 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:05:57,703 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:06:01,736 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:06:46,004 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:06:50,334 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:06:54,620 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:06:59,012 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:07:03,137 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:07:47,221 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:07:51,451 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:07:55,498 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:07:59,518 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:08:03,656 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:08:47,835 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:08:52,031 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:08:56,234 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:09:00,502 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:09:04,593 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:09:48,844 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:09:52,817 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:09:56,979 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:10:01,030 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:10:05,248 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:10:49,756 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:10:53,930 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:10:57,881 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:11:01,994 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:11:05,986 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:11:50,114 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:11:54,250 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:11:58,403 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:12:02,467 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:12:06,514 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:12:50,982 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:12:55,311 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:12:59,508 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:13:03,771 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 02:13:08,205 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: data\input\微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 09:48:24,085 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 09:48:24,088 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 09:49:24,549 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 09:49:24,565 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 09:49:24,572 - app.services.ocr_service - INFO - 文件已处理过,跳过OCR识别: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251019141843_92_108.jpg
|
||||||
|
2025-11-15 09:53:49,066 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 09:53:49,162 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 09:53:49,180 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 09:53:49,195 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 10:06:37,768 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:06:37,827 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:06:39,474 - app.services.ocr_service - INFO - 处理完成: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:39:24,605 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:39:24,609 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:39:48,296 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:39:48,310 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:39:48,360 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 10:39:48,361 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 10:49:13,767 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:49:13,771 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:51:44,468 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:51:44,471 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:51:49,953 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:51:49,956 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:54:02,829 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 10:54:02,847 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 10:54:02,925 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 10:54:02,926 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 14:16:11,975 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 14:16:12,005 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 14:16:14,043 - app.services.ocr_service - INFO - 处理完成: E:/2025Code/python/orc-order-v2/data/input/微信图片_20251113183218_594_278.jpg -> data/output\微信图片_20251113183218_594_278.xlsx
|
||||||
|
2025-11-15 14:41:42,157 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 14:41:42,185 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 14:41:44,498 - app.services.ocr_service - INFO - 处理完成: F:/下载/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:11:57,934 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:11:57,950 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:11:58,027 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 15:11:58,027 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 15:12:40,317 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:12:40,382 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:12:42,173 - app.services.ocr_service - INFO - 处理完成: F:/下载/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:25:04,977 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:25:05,031 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:25:06,788 - app.services.ocr_service - INFO - 处理完成: F:/下载/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:33:47,199 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:33:47,245 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:33:50,404 - app.services.ocr_service - INFO - 处理完成: F:/下载/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:39:11,308 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:39:11,311 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:43:33,472 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 15:43:33,492 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 15:43:33,597 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 15:43:33,597 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 16:39:05,552 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 16:39:05,605 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 16:39:07,421 - app.services.ocr_service - INFO - 处理完成: F:/下载/微信图片_20251027125604_98_108.jpg -> data/output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 16:46:22,384 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 16:46:22,392 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 16:46:22,491 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 16:46:22,491 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 17:28:46,775 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 17:28:46,794 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 17:28:46,901 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 17:28:46,901 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 17:29:22,045 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 17:29:22,113 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 17:29:22,124 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 17:29:22,138 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 17:59:39,797 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 17:59:39,802 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 17:59:39,891 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 17:59:39,892 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-15 18:00:04,109 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-15 18:00:04,120 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-15 18:00:04,212 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-15 18:00:04,213 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-16 11:23:59,366 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 11:23:59,369 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 11:26:06,789 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 11:26:06,792 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 12:50:38,497 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 12:50:38,510 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 12:50:38,512 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-16 12:50:38,524 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-16 12:51:06,904 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 12:51:06,907 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 13:03:10,556 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 13:03:10,559 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 13:03:10,577 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 13:03:10,580 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 13:18:18,242 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 13:18:18,246 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 13:18:18,264 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 13:18:18,267 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 13:51:09,011 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 13:51:09,014 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 14:39:42,974 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 14:39:42,977 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 14:39:42,990 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 14:39:42,993 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 15:11:05,474 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 15:11:05,507 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 15:11:05,514 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-16 15:11:05,525 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-16 15:13:47,369 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 15:13:47,385 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 15:13:47,444 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-16 15:13:47,445 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-16 15:15:36,170 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-16 15:15:36,181 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-16 15:15:36,232 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-16 15:15:36,232 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-20 18:44:11,053 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-20 18:44:11,098 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-20 18:44:11,171 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-20 18:44:11,173 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-20 18:47:03,863 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-20 18:47:03,876 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-20 18:47:03,967 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-20 18:47:03,967 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-11-20 18:56:30,280 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-11-20 18:56:30,296 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-11-20 18:56:30,390 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-11-20 18:56:30,399 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-12-01 22:21:09,016 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-12-01 22:21:09,058 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-12-01 22:21:09,151 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2025-12-01 22:21:09,161 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2026-03-31 11:01:45,665 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2026-03-31 11:01:45,692 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2026-03-31 11:01:45,699 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2026-03-31 11:01:45,700 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2026-03-31 11:27:58,574 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2026-03-31 11:27:58,577 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2026-03-31 11:27:58,603 - app.services.ocr_service - INFO - OCRService.batch_process被调用,转发到process_images_batch
|
||||||
|
2026-03-31 11:27:58,603 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
@ -1,3 +1,878 @@
|
|||||||
2025-08-16 00:52:16,815 - app.services.order_service - INFO - 初始化OrderService
|
2025-08-16 00:52:16,815 - app.services.order_service - INFO - 初始化OrderService
|
||||||
2025-08-16 00:52:16,863 - app.services.order_service - INFO - OrderService初始化完成
|
2025-08-16 00:52:16,863 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
2025-08-16 00:52:16,867 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
2025-08-16 00:52:16,867 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-14 20:52:59,974 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 20:52:59,976 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 20:52:59,979 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 20:52:59,980 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 20:52:59,984 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 20:52:59,985 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 20:52:59,997 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 20:52:59,999 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 20:53:00,002 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 20:53:00,005 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 21:55:05,594 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 21:55:05,663 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 21:55:05,672 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-14 21:55:14,941 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 21:55:14,963 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 21:56:00,461 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 21:56:00,575 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 21:56:00,599 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 22:00:56,339 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 22:00:56,344 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 22:00:56,355 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 22:00:56,357 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 22:00:56,362 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 22:00:56,365 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 23:22:38,472 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 23:22:38,475 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 23:53:32,027 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 23:53:32,028 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 23:53:35,691 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:37,742 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:39,788 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:41,832 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:43,882 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:45,934 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:48,001 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:53:50,039 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20250909184135_44_108.xlsx
|
||||||
|
2025-11-14 23:54:01,442 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:03,487 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:05,529 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:07,577 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:09,616 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:13,773 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:15,821 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:17,867 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:19,919 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:21,962 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:24,008 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:26,047 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:28,098 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:30,151 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:32,204 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:34,250 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:36,296 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:38,351 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:40,404 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:42,458 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:44,502 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:46,556 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:48,600 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:51,983 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:54:52,021 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:54,069 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:54:54,107 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:56,148 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:54:56,189 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:54:58,238 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:54:58,275 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:00,326 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:00,365 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:02,420 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:02,462 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:04,521 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:04,558 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:06,605 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:06,643 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:08,703 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:08,740 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:10,788 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:10,828 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:12,879 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:12,916 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:14,960 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:14,996 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:17,036 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:17,073 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:19,125 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:19,162 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:21,205 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:21,243 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:23,295 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:23,335 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:25,382 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:25,421 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:27,467 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:27,505 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:29,547 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:29,582 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:31,622 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:31,669 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:33,737 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:33,774 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:35,817 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:35,853 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:37,921 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:37,961 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:40,014 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:40,051 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:42,108 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:42,147 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:44,193 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:44,229 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:46,275 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:46,315 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:48,365 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:48,404 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:50,443 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:50,482 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:52,535 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:52,573 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:54,614 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:54,653 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:56,710 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:56,748 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:55:58,800 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:55:58,838 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:56:00,891 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:56:00,935 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:56:02,980 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:56:03,018 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:56:05,062 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:56:05,106 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:56:07,162 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:56:07,210 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:56:57,445 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-14 23:56:57,448 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-14 23:56:59,671 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:01,610 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:05,270 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:06,524 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:09,725 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:11,648 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:15,205 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:16,956 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:20,272 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:21,477 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:24,830 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:26,314 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:29,933 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:31,639 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:35,183 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:36,999 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:40,585 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:42,149 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:45,471 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:46,771 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:50,045 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:51,537 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:54,947 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:57:56,455 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:57:59,886 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:01,675 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:05,116 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:06,597 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:09,988 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:11,402 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:14,762 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:16,456 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:19,926 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:21,593 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:25,017 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:26,549 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:29,869 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:31,480 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:34,917 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:36,626 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:39,970 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:41,505 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:45,014 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:46,495 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:50,070 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:51,660 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:58:55,105 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:58:56,605 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:00,139 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:01,892 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:05,383 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:06,901 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:10,551 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:12,206 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:15,639 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:17,241 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:20,663 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:22,160 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:25,634 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:27,248 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:30,819 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:32,365 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:36,079 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:37,734 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:41,258 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:42,824 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:46,370 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:47,834 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:51,254 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:52,905 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-14 23:59:56,269 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-14 23:59:57,672 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:01,256 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:02,807 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:06,104 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:07,485 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:10,893 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:12,610 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:16,149 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:17,562 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:20,946 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:22,538 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:26,131 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:27,583 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:31,069 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:32,567 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:36,102 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:37,675 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:41,096 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:42,559 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:45,876 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:47,314 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:50,657 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:52,159 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:00:55,531 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:00:57,287 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:00,725 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:02,358 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:05,756 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:07,382 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:10,909 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:12,635 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:16,124 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:17,810 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:21,182 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:22,681 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:26,069 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:27,398 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:30,983 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:32,654 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:36,036 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:37,546 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:40,916 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:42,666 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:46,135 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:47,771 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:51,376 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:53,154 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:01:56,488 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:01:58,006 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:01,361 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:03,000 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:06,651 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:08,438 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:12,057 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:13,824 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:17,635 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:19,526 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:23,005 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:24,594 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:27,928 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:29,505 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:32,852 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:34,299 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:37,813 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:39,281 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:42,672 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:44,232 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:47,595 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:49,284 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:52,743 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:54,437 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:02:57,797 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:02:59,304 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:02,645 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:04,003 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:07,447 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:09,204 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:12,509 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:14,146 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:17,611 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:18,970 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:22,320 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:23,995 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:27,472 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:28,938 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:32,546 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:33,779 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:37,358 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:38,810 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:42,430 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:44,137 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:47,587 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:49,403 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:52,901 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:54,388 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:03:57,810 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:03:59,455 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:02,984 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:04,394 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:07,710 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:09,289 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:12,859 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:14,474 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:17,989 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:19,500 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:22,822 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:24,473 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:27,848 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:29,568 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:33,270 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:34,897 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:38,318 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:39,934 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:43,278 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:44,722 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:48,052 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:49,619 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:52,975 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:54,572 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:04:58,173 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:04:59,694 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:03,261 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:04,491 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:07,887 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:09,478 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:13,079 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:14,500 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:17,918 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:19,387 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:22,622 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:24,193 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:27,664 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:29,394 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:32,717 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:34,328 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:37,870 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:39,473 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:43,044 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:44,606 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:48,195 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:49,765 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:53,268 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:54,963 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:05:58,364 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:05:59,802 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:18:49,535 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 00:18:49,538 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 00:18:51,832 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:18:54,057 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:18:57,817 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:18:59,547 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:19:02,881 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:19:04,937 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:19:08,852 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:19:10,644 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:19:14,425 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:19:16,439 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 00:20:03,324 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:07,029 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:10,864 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:14,215 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:17,878 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:21,109 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:24,592 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:28,474 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:31,856 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:35,700 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:39,605 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:20:43,355 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:44:36,718 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 00:44:36,720 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 00:44:39,085 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:44:43,294 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 00:44:47,418 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:02,052 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 01:58:02,054 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 01:58:04,404 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:08,613 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:12,905 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:17,338 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:21,192 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:39,977 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:43,852 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:47,831 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:52,175 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:58:56,355 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:59:38,962 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:59:42,963 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:59:47,041 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:59:51,100 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 01:59:55,247 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:00:39,437 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:00:43,455 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:00:47,653 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:00:52,105 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:00:56,245 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:01:40,456 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:01:44,653 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:01:48,950 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:01:53,159 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:01:57,193 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:02:41,611 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:02:45,668 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:02:49,948 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:02:53,952 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:02:57,956 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:03:42,179 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:03:46,610 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:03:50,918 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:03:55,072 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:03:59,598 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:04:44,111 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:04:48,235 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:04:52,463 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:04:56,788 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:05:01,024 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:05:45,464 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:05:49,519 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:05:53,734 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:05:57,788 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:06:01,836 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:06:46,074 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:06:50,451 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:06:54,716 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:06:59,148 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:07:03,221 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:07:47,305 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:07:51,518 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:07:55,599 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:07:59,603 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:08:03,773 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:08:47,930 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:08:52,146 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:08:56,363 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:09:00,604 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:09:04,679 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:09:48,912 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:09:52,927 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:09:57,080 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:10:01,136 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:10:05,339 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:10:49,825 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:10:53,995 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:10:57,962 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:11:02,097 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:11:06,075 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:11:50,181 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:11:54,337 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:11:58,472 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:12:02,549 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:12:06,611 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:12:51,091 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:12:55,402 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:12:59,595 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:13:03,883 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 02:13:08,305 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data\output\微信图片_20251019141843_92_108.xlsx
|
||||||
|
2025-11-15 09:48:24,088 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 09:48:24,126 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:06:56,495 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:06:56,644 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:06:56,677 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:10:31,568 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:10:31,669 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:10:31,686 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 10:39:24,610 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:39:24,613 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:39:48,312 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:39:48,340 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:39:50,736 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 10:49:13,771 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:49:13,775 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:51:44,471 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:51:44,475 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:51:49,956 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:51:49,960 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:54:02,853 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:54:02,897 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:54:04,837 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 10:58:26,517 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:58:26,634 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:58:26,651 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 10:58:36,001 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 10:58:36,098 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 10:58:36,133 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 14:17:23,548 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 14:17:23,617 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 14:17:23,630 - app.services.order_service - INFO - OrderService开始合并所有采购单
|
||||||
|
2025-11-15 14:17:23,648 - app.services.order_service - INFO - OrderService开始合并所有采购单
|
||||||
|
2025-11-15 14:22:16,889 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 14:22:16,949 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 14:22:16,977 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: F:/下载/订单1762933924814.xlsx
|
||||||
|
2025-11-15 15:11:57,955 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:11:57,991 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:11:58,198 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:12:52,608 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:12:52,708 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:12:52,745 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:21:05,637 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:21:05,678 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:21:05,686 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:22:01,116 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:22:01,217 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:22:01,232 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251027125604_98_108.xlsx
|
||||||
|
2025-11-15 15:25:41,328 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:25:41,393 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:25:41,435 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:34:06,437 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:34:06,514 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:34:06,543 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:37:42,545 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:37:42,599 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:37:42,606 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:39:11,311 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:39:11,314 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:43:33,496 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:43:33,561 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:43:35,318 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 15:54:35,478 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 15:54:35,573 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 15:54:35,609 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:19:42,366 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:19:42,388 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:19:42,389 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 16:34:22,100 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:34:22,132 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:34:22,132 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1762933924814.xlsx
|
||||||
|
2025-11-15 16:46:22,393 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:46:22,453 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:46:28,800 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:46:28,913 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:46:29,004 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:46:37,684 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:46:37,798 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:46:37,873 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:48:30,424 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:48:30,499 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:48:30,574 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:48:41,962 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:48:42,077 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:48:42,154 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:52:35,911 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:52:35,973 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:52:36,050 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:57:42,391 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:57:42,459 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:57:42,542 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:59:06,951 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:59:07,027 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:59:07,102 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 16:59:14,530 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 16:59:14,619 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 16:59:14,678 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:01:30,192 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:01:30,257 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:01:30,308 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:04:33,184 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:04:33,258 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:04:33,323 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:04:44,983 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:04:45,063 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:04:45,134 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:09:39,792 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:09:39,862 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:09:39,929 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:12:37,423 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:12:37,485 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:12:37,545 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:28:46,799 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:28:46,861 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:28:48,645 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:59:22,782 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:59:22,828 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:59:22,867 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:59:33,421 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:59:33,523 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 17:59:33,585 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 17:59:39,804 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 17:59:39,862 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 18:00:04,123 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 18:00:04,180 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 18:00:05,990 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-15 18:01:51,643 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-15 18:01:51,715 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-15 18:01:51,763 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 10:48:45,445 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 10:48:45,564 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 10:48:45,630 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 10:56:22,512 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 10:56:22,516 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 11:23:59,369 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 11:23:59,374 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 11:26:06,793 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 11:26:06,795 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 12:51:06,907 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 12:51:06,910 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 13:03:10,559 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 13:03:10,563 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 13:03:10,580 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 13:03:10,584 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 13:18:18,246 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 13:18:18,248 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 13:18:18,268 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 13:18:18,271 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 13:51:09,015 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 13:51:09,018 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:25:50,009 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 14:25:50,033 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:25:50,107 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 14:25:55,548 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 14:25:55,619 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:25:55,699 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 14:39:42,977 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 14:39:42,981 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:39:42,993 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 14:39:42,996 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:59:35,433 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 14:59:35,437 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 14:59:35,437 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251115212128_148_108.xlsx
|
||||||
|
2025-11-16 15:03:21,889 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 15:03:21,893 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 15:03:21,894 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251115212128_148_108.xlsx
|
||||||
|
2025-11-16 15:08:33,542 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 15:08:33,546 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 15:08:33,546 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/微信图片_20251115212128_148_108.xlsx
|
||||||
|
2025-11-16 15:11:11,179 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 15:11:11,268 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 15:11:11,345 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 15:13:47,387 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 15:13:47,411 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 15:13:49,534 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-16 15:15:36,186 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-16 15:15:36,205 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-16 15:15:37,909 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:36:13,245 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:36:13,299 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:36:13,371 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:36:42,069 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:36:42,111 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:36:42,174 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:42:25,860 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:42:25,947 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:42:26,024 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:44:11,101 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:44:11,134 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:44:11,376 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:47:03,878 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:47:03,927 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:47:04,166 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-11-20 18:56:30,301 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-11-20 18:56:30,361 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-11-20 18:56:30,593 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-12-01 22:21:09,063 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-01 22:21:09,121 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-01 22:21:10,614 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2025-12-12 11:00:14,048 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:00:14,096 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:00:14,097 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:13:15,273 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:13:15,288 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:13:15,289 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:22:25,989 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:22:25,990 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:22:25,990 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:32:26,688 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:32:26,694 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:32:26,696 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:34:40,235 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:34:40,238 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:34:40,238 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:38:53,256 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:38:53,260 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:38:53,260 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 11:49:38,202 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 11:49:38,203 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 11:49:38,206 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765440157955.xlsx
|
||||||
|
2025-12-12 12:30:07,696 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 12:30:07,700 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 12:30:07,700 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765513775092.xlsx
|
||||||
|
2025-12-12 12:32:20,576 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-12-12 12:32:20,579 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-12-12 12:32:20,579 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\蓉城易购-订单1765513867817.xlsx
|
||||||
|
2026-03-30 10:20:20,106 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 10:20:20,145 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 10:20:20,145 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: e:\2025Code\python\orc-order-v2\data\output\495a630b-87cf-4245-834e-2705a3dcd12f.xlsx
|
||||||
|
2026-03-30 10:21:25,351 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 10:21:25,356 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 10:21:25,356 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: e:\2025Code\python\orc-order-v2\data\output\495a630b-87cf-4245-834e-2705a3dcd12f.xlsx
|
||||||
|
2026-03-30 10:21:52,466 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 10:21:52,470 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 10:21:52,470 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: e:\2025Code\python\orc-order-v2\data\output\495a630b-87cf-4245-834e-2705a3dcd12f.xlsx
|
||||||
|
2026-03-30 13:28:54,447 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:28:54,451 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:28:54,452 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\原始数据.xlsx
|
||||||
|
2026-03-30 13:28:54,461 - app.services.order_service - ERROR - 检查特殊预处理时出错: 'OrderService' object has no attribute 'config_manager'
|
||||||
|
2026-03-30 13:29:24,572 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:29:24,576 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:29:24,576 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\原始数据.xlsx
|
||||||
|
2026-03-30 13:29:24,577 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:29:24,581 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:29:24,854 - app.services.order_service - INFO - 识别到杨碧月订单,执行预处理...
|
||||||
|
2026-03-30 13:29:24,868 - app.services.order_service - WARNING - 预处理识别失败: name 'os' is not defined
|
||||||
|
2026-03-30 13:29:58,480 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:29:58,484 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:29:58,484 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\原始数据.xlsx
|
||||||
|
2026-03-30 13:29:58,485 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:29:58,488 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:29:58,758 - app.services.order_service - INFO - 识别到杨碧月订单,执行预处理...
|
||||||
|
2026-03-30 13:29:58,893 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:\2025Code\python\orc-order-v2\data\output\预处理之后.xlsx
|
||||||
|
2026-03-30 13:30:29,313 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:30:29,317 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:30:29,318 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\原始数据.xlsx
|
||||||
|
2026-03-30 13:30:29,319 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:30:29,322 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:30:29,597 - app.services.order_service - INFO - 识别到杨碧月订单,执行预处理...
|
||||||
|
2026-03-30 13:30:29,734 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:\2025Code\python\orc-order-v2\data\output\预处理之后.xlsx
|
||||||
|
2026-03-30 13:31:51,943 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:31:51,947 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:31:51,947 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:\2025Code\python\orc-order-v2\data\output\原始数据.xlsx
|
||||||
|
2026-03-30 13:31:51,948 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:31:51,952 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:31:52,230 - app.services.order_service - INFO - 识别到杨碧月订单,执行预处理...
|
||||||
|
2026-03-30 13:31:52,367 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:\2025Code\python\orc-order-v2\data\output\预处理之后.xlsx
|
||||||
|
2026-03-30 13:46:00,207 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:46:00,211 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:46:00,225 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/原始数据.xlsx
|
||||||
|
2026-03-30 13:46:00,227 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:46:00,230 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:46:00,255 - app.services.order_service - INFO - 识别到杨碧月订单,执行通用预处理...
|
||||||
|
2026-03-30 13:46:00,355 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后.xlsx
|
||||||
|
2026-03-30 13:46:02,782 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:46:02,785 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:47:05,230 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:47:05,233 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:47:05,252 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1765513867817.xlsx
|
||||||
|
2026-03-30 13:47:05,253 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:47:05,256 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:47:06,651 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:47:06,655 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:48:28,517 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:48:28,520 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:48:28,522 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 13:48:28,522 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:48:28,525 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:48:30,799 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:48:30,802 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:51:44,153 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:51:44,156 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:51:44,167 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 13:51:44,168 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:51:44,171 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 13:51:46,069 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 13:51:46,072 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:00:52,371 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:00:52,375 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:00:52,389 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:00:52,389 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:00:52,393 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:01:20,292 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:01:20,295 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:01:20,304 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:01:20,305 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:01:20,308 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:01:24,373 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:01:24,376 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:06:58,240 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:06:58,243 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:06:58,248 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:07:00,053 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:07:00,055 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:14:46,829 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:14:46,832 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:14:46,844 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:14:47,889 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:14:47,891 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:23:18,308 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:23:18,311 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:23:18,320 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:23:20,041 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:23:20,043 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:24:02,880 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:24:02,883 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:24:02,890 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:24:04,316 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:24:04,318 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:28:39,036 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:28:39,040 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:28:39,040 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:28:39,333 - app.services.order_service - INFO - 识别到蓉城易购订单,执行专用预处理...
|
||||||
|
2026-03-30 14:28:39,514 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: data/output\预处理之后_订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:28:39,734 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:28:39,738 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:28:39,738 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:28:39,746 - app.services.order_service - INFO - 识别到烟草公司订单,执行专用预处理...
|
||||||
|
2026-03-30 14:28:39,828 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: data/output\预处理之后_订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:41:11,945 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:41:11,949 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:41:11,957 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:41:11,994 - app.services.order_service - INFO - 识别到蓉城易购订单,执行专用预处理...
|
||||||
|
2026-03-30 14:41:12,128 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_订单1774849009841.xlsx
|
||||||
|
2026-03-30 14:41:33,385 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:41:33,388 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:41:47,793 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:41:47,796 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-30 14:41:47,810 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:41:47,819 - app.services.order_service - INFO - 识别到烟草公司订单,执行专用预处理...
|
||||||
|
2026-03-30 14:41:47,865 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:41:49,670 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-30 14:41:49,674 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 08:50:15,691 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 08:50:15,754 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 08:50:15,757 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-31 08:50:15,811 - app.services.order_service - INFO - 识别到蓉城易购订单,执行专用预处理...
|
||||||
|
2026-03-31 08:50:15,872 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_订单1774849009841.xlsx
|
||||||
|
2026-03-31 08:50:17,773 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 08:50:17,775 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 08:52:46,011 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 08:52:46,014 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 08:52:46,029 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/原始数据.xlsx
|
||||||
|
2026-03-31 08:52:46,087 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_原始数据.xlsx
|
||||||
|
2026-03-31 08:52:47,190 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 08:52:47,192 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:00:01,690 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:00:01,694 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:00:01,694 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: data/output/原始数据.xlsx
|
||||||
|
2026-03-31 09:00:01,984 - app.services.order_service - INFO - 识别到杨碧月订单,执行专用预处理...
|
||||||
|
2026-03-31 09:00:02,134 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: data/output\预处理之后_原始数据.xlsx
|
||||||
|
2026-03-31 09:03:11,825 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:03:11,829 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:03:11,832 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/原始数据.xlsx
|
||||||
|
2026-03-31 09:03:11,886 - app.services.order_service - INFO - 识别到杨碧月订单,执行专用预处理...
|
||||||
|
2026-03-31 09:03:11,970 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_原始数据.xlsx
|
||||||
|
2026-03-31 09:03:13,869 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:03:13,873 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:05:33,091 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:05:33,094 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:05:33,098 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2026-03-31 09:05:33,126 - app.services.order_service - INFO - 识别到蓉城易购订单,执行专用预处理...
|
||||||
|
2026-03-31 09:05:33,174 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: data/output\预处理之后_订单1774849009841.xlsx
|
||||||
|
2026-03-31 09:05:33,865 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:05:33,869 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:07:58,232 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:07:58,236 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 09:07:58,241 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2026-03-31 09:07:58,250 - app.services.order_service - INFO - 识别到烟草公司订单,执行专用预处理...
|
||||||
|
2026-03-31 09:07:58,289 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: data/output\预处理之后_订单明细20260331090709.xlsx
|
||||||
|
2026-03-31 09:07:58,350 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 09:07:58,354 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 10:59:54,577 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 10:59:54,581 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 10:59:54,585 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/订单1774849009841.xlsx
|
||||||
|
2026-03-31 10:59:54,616 - app.services.order_service - INFO - 识别到蓉城易购订单,执行专用预处理...
|
||||||
|
2026-03-31 10:59:54,668 - app.services.order_service - INFO - 检测到特殊供应商,已生成预处理文件: E:/2025Code/python/orc-order-v2/data/output\预处理之后_订单1774849009841.xlsx
|
||||||
|
2026-03-31 10:59:56,655 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 10:59:56,659 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:01:45,693 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:01:45,698 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:01:47,787 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2026-03-31 11:01:47,936 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:01:47,941 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:27:58,578 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:27:58,584 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:28:00,722 - app.services.order_service - INFO - OrderService开始处理最新Excel文件
|
||||||
|
2026-03-31 11:28:01,606 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:28:01,611 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:28:11,905 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:28:11,909 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2026-03-31 11:28:11,912 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: E:/2025Code/python/orc-order-v2/data/output/20260331-112747.xlsx
|
||||||
|
2026-03-31 11:28:13,704 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2026-03-31 11:28:13,708 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
2025-11-15 15:44:36,108 - app.services.tobacco_service - WARNING - 未找到烟草公司订单明细文件
|
||||||
|
2025-11-15 15:44:36,116 - app.services.tobacco_service - WARNING - 未找到烟草公司订单明细文件
|
||||||
|
2025-11-15 15:44:36,125 - app.services.tobacco_service - ERROR - 未找到可处理的烟草订单明细文件
|
||||||
|
2025-11-15 15:45:17,682 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:45:17,689 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:45:17,724 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:45:17,726 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:45:17,738 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:45:17,850 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:46:55,566 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:46:55,572 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:46:55,599 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:46:55,600 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:46:55,607 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:46:55,667 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:47:59,480 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:47:59,485 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:47:59,512 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:47:59,513 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:47:59,520 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:47:59,582 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:50:32,432 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:50:32,432 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:50:32,455 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:50:32,456 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:50:32,463 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:50:32,519 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:51:02,790 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:51:02,791 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:51:02,814 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:51:02,815 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:51:02,827 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:51:02,885 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:53:51,294 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:53:51,298 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:53:51,328 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:53:51,329 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:53:51,337 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:53:51,391 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:54:07,757 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:54:07,758 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20251115154455.xlsx
|
||||||
|
2025-11-15 15:54:07,783 - app.services.tobacco_service - INFO - 采购单生成成功: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:54:07,783 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2025-11-15 15:54:07,796 - app.services.tobacco_service - INFO - 采购单已生成: data/result\银豹采购单_烟草公司.xls
|
||||||
|
2025-11-15 15:54:07,930 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-11-10, 总金额: 12226.22, 处理条目: 34
|
||||||
|
2026-03-30 14:28:39,783 - app.services.tobacco_service - INFO - 执行烟草订单专用预处理: data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:28:39,828 - app.services.tobacco_service - INFO - 烟草订单预处理完成: data/output\预处理之后_订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:41:47,819 - app.services.tobacco_service - INFO - 执行烟草订单专用预处理: E:/2025Code/python/orc-order-v2/data/output/订单明细20260330133908.xlsx
|
||||||
|
2026-03-30 14:41:47,865 - app.services.tobacco_service - INFO - 烟草订单预处理完成: E:/2025Code/python/orc-order-v2/data/output\预处理之后_订单明细20260330133908.xlsx
|
||||||
|
2026-03-31 09:07:58,250 - app.services.tobacco_service - INFO - 执行烟草订单专用预处理: data/output\订单明细20260331090709.xlsx
|
||||||
|
2026-03-31 09:07:58,289 - app.services.tobacco_service - INFO - 烟草订单预处理完成: data/output\预处理之后_订单明细20260331090709.xlsx
|
||||||
Binary file not shown.
@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
# OCR订单处理系统 - 便携版
|
|
||||||
|
|
||||||
## 使用说明
|
|
||||||
1. 双击 "OCR订单处理系统.exe" 启动程序
|
|
||||||
2. 将需要处理的图片文件放入 data/input 目录
|
|
||||||
3. 处理结果将保存在 data/output 目录
|
|
||||||
4. 日志文件保存在 logs 目录
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
- 首次运行时需要配置百度OCR API密钥
|
|
||||||
- 支持的图片格式:jpg, jpeg, png, bmp
|
|
||||||
- 单个文件大小不超过4MB
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
- OCR订单处理系统.exe - 主程序
|
|
||||||
- data/input/ - 输入图片目录
|
|
||||||
- data/output/ - 输出结果目录
|
|
||||||
- logs/ - 日志目录
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
[API]
|
|
||||||
api_key = O0Fgk3o69RWJ86eAX8BTHRaB
|
|
||||||
secret_key = VyZD5lzcIMgsup1uuD6Cw0pfzS20IGPZ
|
|
||||||
timeout = 30
|
|
||||||
max_retries = 3
|
|
||||||
retry_delay = 2
|
|
||||||
api_url = https://aip.baidubce.com/rest/2.0/ocr/v1/table
|
|
||||||
|
|
||||||
[Paths]
|
|
||||||
input_folder = data/input
|
|
||||||
output_folder = data/output
|
|
||||||
temp_folder = data/temp
|
|
||||||
template_folder = templates
|
|
||||||
processed_record = data/processed_files.json
|
|
||||||
|
|
||||||
[Performance]
|
|
||||||
max_workers = 4
|
|
||||||
batch_size = 5
|
|
||||||
skip_existing = true
|
|
||||||
|
|
||||||
[File]
|
|
||||||
allowed_extensions = .jpg,.jpeg,.png,.bmp
|
|
||||||
excel_extension = .xlsx
|
|
||||||
max_file_size_mb = 4
|
|
||||||
|
|
||||||
[Templates]
|
|
||||||
purchase_order = 银豹-采购单模板.xls
|
|
||||||
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
{
|
|
||||||
"6920584471055": {
|
|
||||||
"map_to": "6920584471017",
|
|
||||||
"description": "条码映射:6920584471055 -> 6920584471017"
|
|
||||||
},
|
|
||||||
"6925861571159": {
|
|
||||||
"map_to": "69021824",
|
|
||||||
"description": "条码映射:6925861571159 -> 69021824"
|
|
||||||
},
|
|
||||||
"6923644268923": {
|
|
||||||
"map_to": "6923644268480",
|
|
||||||
"description": "条码映射:6923644268923 -> 6923644268480"
|
|
||||||
},
|
|
||||||
"6925861571466": {
|
|
||||||
"map_to": "6925861571459",
|
|
||||||
"description": "条码映射:6925861571466 -> 6925861571459"
|
|
||||||
},
|
|
||||||
"6907992508344": {
|
|
||||||
"map_to": "6907992508191",
|
|
||||||
"description": "条码映射:6907992508344 -> 6907992508191"
|
|
||||||
},
|
|
||||||
"6903979000979": {
|
|
||||||
"map_to": "6903979000962",
|
|
||||||
"description": "条码映射:6903979000979 -> 6903979000962"
|
|
||||||
},
|
|
||||||
"6923644283582": {
|
|
||||||
"map_to": "6923644283575",
|
|
||||||
"description": "条码映射:6923644283582 -> 6923644283575"
|
|
||||||
},
|
|
||||||
"6923644268930": {
|
|
||||||
"map_to": "6923644268497",
|
|
||||||
"description": "条码映射:6923644268930 -> 6923644268497"
|
|
||||||
},
|
|
||||||
"6923644268916": {
|
|
||||||
"map_to": "6923644268503",
|
|
||||||
"description": "条码映射:6923644268916 -> 6923644268503"
|
|
||||||
},
|
|
||||||
"6923644268909": {
|
|
||||||
"map_to": "6923644268510",
|
|
||||||
"description": "条码映射:6923644268909 -> 6923644268510"
|
|
||||||
},
|
|
||||||
"6923644299804": {
|
|
||||||
"map_to": "6923644299774",
|
|
||||||
"description": "条码映射:6923644299804 -> 6923644299774"
|
|
||||||
},
|
|
||||||
"6923644266318": {
|
|
||||||
"map_to": "6923644266066",
|
|
||||||
"description": "条码映射:6923644266318 -> 6923644266066"
|
|
||||||
},
|
|
||||||
"6923644210151": {
|
|
||||||
"map_to": "6923644223458",
|
|
||||||
"description": "条码映射:6923644210151 -> 6923644223458"
|
|
||||||
},
|
|
||||||
"6907992501819": {
|
|
||||||
"map_to": "6907992500133",
|
|
||||||
"description": "条码映射:6907992501819 -> 6907992500133"
|
|
||||||
},
|
|
||||||
"6907992502052": {
|
|
||||||
"map_to": "6907992100272",
|
|
||||||
"description": "条码映射:6907992502052 -> 6907992100272"
|
|
||||||
},
|
|
||||||
"6907992507385": {
|
|
||||||
"map_to": "6907992507095",
|
|
||||||
"description": "条码映射:6907992507385 -> 6907992507095"
|
|
||||||
},
|
|
||||||
"6973726149671": {
|
|
||||||
"map_to": "6973726149657",
|
|
||||||
"description": "条码映射:6973726149671 -> 6973726149657"
|
|
||||||
},
|
|
||||||
"6977426410574": {
|
|
||||||
"map_to": "6977426410567",
|
|
||||||
"description": "条码映射:6977426410574 -> 6977426410567"
|
|
||||||
},
|
|
||||||
"6973726149688": {
|
|
||||||
"map_to": "6973726149664",
|
|
||||||
"description": "条码映射:6973726149688 -> 6973726149664"
|
|
||||||
},
|
|
||||||
"6935205322012": {
|
|
||||||
"map_to": "6935205320018",
|
|
||||||
"description": "条码映射:6935205322012 -> 6935205320018"
|
|
||||||
},
|
|
||||||
"6943497411024": {
|
|
||||||
"map_to": "6943497411017",
|
|
||||||
"description": "条码映射:6943497411024 -> 6943497411017"
|
|
||||||
},
|
|
||||||
"6921734968821": {
|
|
||||||
"map_to": "6921734968814",
|
|
||||||
"description": "条码映射:6921734968821 -> 6921734968814"
|
|
||||||
},
|
|
||||||
"6921734968258": {
|
|
||||||
"map_to": "6921734968241",
|
|
||||||
"description": "条码映射:6921734968258 -> 6921734968241"
|
|
||||||
},
|
|
||||||
"6921734968180": {
|
|
||||||
"map_to": "6921734968173",
|
|
||||||
"description": "条码映射:6921734968180 -> 6921734968173"
|
|
||||||
},
|
|
||||||
"6921734908735": {
|
|
||||||
"map_to": "6935205372772",
|
|
||||||
"description": "条码映射:6921734908735 -> 6935205372772"
|
|
||||||
},
|
|
||||||
"6923644248222": {
|
|
||||||
"map_to": "6923644248208",
|
|
||||||
"description": "条码映射:6923644248222 -> 6923644248208"
|
|
||||||
},
|
|
||||||
"6902083881122": {
|
|
||||||
"map_to": "6902083881085",
|
|
||||||
"description": "条码映射:6902083881122 -> 6902083881085"
|
|
||||||
},
|
|
||||||
"6907992501857": {
|
|
||||||
"map_to": "6907992500010",
|
|
||||||
"description": "条码映射:6907992501857 -> 6907992500010"
|
|
||||||
},
|
|
||||||
"6902083891015": {
|
|
||||||
"map_to": "6902083890636",
|
|
||||||
"description": "条码映射:6902083891015 -> 6902083890636"
|
|
||||||
},
|
|
||||||
"6923450605240": {
|
|
||||||
"map_to": "6923450605226",
|
|
||||||
"description": "条码映射:6923450605240 -> 6923450605226"
|
|
||||||
},
|
|
||||||
"6923450605196": {
|
|
||||||
"map_to": "6923450614624",
|
|
||||||
"description": "条码映射:6923450605196 -> 6923450614624"
|
|
||||||
},
|
|
||||||
"6923450665213": {
|
|
||||||
"map_to": "6923450665206",
|
|
||||||
"description": "条码映射:6923450665213 -> 6923450665206"
|
|
||||||
},
|
|
||||||
"6923450666821": {
|
|
||||||
"map_to": "6923450666838",
|
|
||||||
"description": "条码映射:6923450666821 -> 6923450666838"
|
|
||||||
},
|
|
||||||
"6923450661505": {
|
|
||||||
"map_to": "6923450661499",
|
|
||||||
"description": "条码映射:6923450661505 -> 6923450661499"
|
|
||||||
},
|
|
||||||
"6923450676103": {
|
|
||||||
"map_to": "6923450676097",
|
|
||||||
"description": "条码映射:6923450676103 -> 6923450676097"
|
|
||||||
},
|
|
||||||
"6923450614631": {
|
|
||||||
"map_to": "6923450614624",
|
|
||||||
"description": "条码映射:6923450614631 -> 6923450614624"
|
|
||||||
},
|
|
||||||
"6901424334174": {
|
|
||||||
"map_to": "6973730760015",
|
|
||||||
"description": "条码映射:6901424334174 -> 6973730760015"
|
|
||||||
},
|
|
||||||
"6958620703716": {
|
|
||||||
"map_to": "6958620703907",
|
|
||||||
"description": "条码映射:6958620703716 -> 6958620703907"
|
|
||||||
},
|
|
||||||
"6937003706322": {
|
|
||||||
"map_to": "6937003703833",
|
|
||||||
"description": "条码映射:6937003706322 -> 6937003703833"
|
|
||||||
},
|
|
||||||
"6950783203494": {
|
|
||||||
"map_to": "6950873203494",
|
|
||||||
"description": "条码映射:6950783203494 -> 6950873203494"
|
|
||||||
},
|
|
||||||
"6907992501871": {
|
|
||||||
"map_to": "6907992500010",
|
|
||||||
"description": "条码映射:6907992501871 -> 6907992500010"
|
|
||||||
},
|
|
||||||
"6907992501864": {
|
|
||||||
"map_to": "6907992100012",
|
|
||||||
"description": "条码映射:6907992501864 -> 6907992100012"
|
|
||||||
},
|
|
||||||
"6923644264192": {
|
|
||||||
"map_to": "6923644264116",
|
|
||||||
"description": "条码映射:6923644264192 -> 6923644264116"
|
|
||||||
},
|
|
||||||
"6923450667316": {
|
|
||||||
"map_to": "69042386",
|
|
||||||
"description": "条码映射:6923450667316 -> 69042386"
|
|
||||||
},
|
|
||||||
"6923450653012": {
|
|
||||||
"map_to": "69021343",
|
|
||||||
"description": "条码映射:6923450653012 -> 69021343"
|
|
||||||
},
|
|
||||||
"6925019900087": {
|
|
||||||
"multiplier": 10,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"description": "特殊处理:数量*10,单位转换为瓶"
|
|
||||||
},
|
|
||||||
"6921168593804": {
|
|
||||||
"multiplier": 30,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"description": "NFC产品特殊处理:每箱30瓶"
|
|
||||||
},
|
|
||||||
"6901826888138": {
|
|
||||||
"multiplier": 30,
|
|
||||||
"target_unit": "瓶",
|
|
||||||
"fixed_price": 3.7333333333333334,
|
|
||||||
"specification": "1*30",
|
|
||||||
"description": "特殊处理: 规格1*30,数量*30,单价=112/30"
|
|
||||||
},
|
|
||||||
"6958620703907": {
|
|
||||||
"multiplier": 14,
|
|
||||||
"target_unit": "个",
|
|
||||||
"specification": "1*14",
|
|
||||||
"description": "友臣肉松,1盒14个"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
[API]
|
|
||||||
api_key = O0Fgk3o69RWJ86eAX8BTHRaB
|
|
||||||
secret_key = VyZD5lzcIMgsup1uuD6Cw0pfzS20IGPZ
|
|
||||||
timeout = 30
|
|
||||||
max_retries = 3
|
|
||||||
retry_delay = 2
|
|
||||||
api_url = https://aip.baidubce.com/rest/2.0/ocr/v1/table
|
|
||||||
|
|
||||||
[Paths]
|
|
||||||
input_folder = data/input
|
|
||||||
output_folder = data/output
|
|
||||||
temp_folder = data/temp
|
|
||||||
template_folder = templates
|
|
||||||
processed_record = data/processed_files.json
|
|
||||||
|
|
||||||
[Performance]
|
|
||||||
max_workers = 4
|
|
||||||
batch_size = 5
|
|
||||||
skip_existing = true
|
|
||||||
|
|
||||||
[File]
|
|
||||||
allowed_extensions = .jpg,.jpeg,.png,.bmp
|
|
||||||
excel_extension = .xlsx
|
|
||||||
max_file_size_mb = 4
|
|
||||||
|
|
||||||
[Templates]
|
|
||||||
purchase_order = 银豹-采购单模板.xls
|
|
||||||
|
|
||||||
Binary file not shown.
206
run.py
206
run.py
@ -1,206 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
OCR订单处理系统 - 主入口
|
|
||||||
---------------------
|
|
||||||
提供命令行接口,整合OCR识别、Excel处理和订单合并功能。
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from app.config.settings import ConfigManager
|
|
||||||
from app.core.utils.log_utils import get_logger, close_all_loggers, set_log_level
|
|
||||||
from app.services.ocr_service import OCRService
|
|
||||||
from app.services.order_service import OrderService
|
|
||||||
from app.services.tobacco_service import TobaccoService
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
def parse_args():
|
|
||||||
"""
|
|
||||||
解析命令行参数
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
解析后的参数
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser(description='OCR订单处理系统')
|
|
||||||
|
|
||||||
# 通用选项
|
|
||||||
parser.add_argument('--config', type=str, help='配置文件路径')
|
|
||||||
parser.add_argument('--log-level', type=str, choices=['debug', 'info', 'warning', 'error', 'critical'], help='日志级别')
|
|
||||||
|
|
||||||
# 子命令
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='子命令')
|
|
||||||
|
|
||||||
# OCR识别命令
|
|
||||||
ocr_parser = subparsers.add_parser('ocr', help='OCR识别')
|
|
||||||
ocr_parser.add_argument('--input', type=str, help='输入图片路径')
|
|
||||||
ocr_parser.add_argument('--batch', action='store_true', help='批量处理')
|
|
||||||
ocr_parser.add_argument('--batch-size', type=int, default=5, help='批处理大小')
|
|
||||||
ocr_parser.add_argument('--max-workers', type=int, default=4, help='最大线程数')
|
|
||||||
|
|
||||||
# Excel处理命令
|
|
||||||
excel_parser = subparsers.add_parser('excel', help='Excel处理')
|
|
||||||
excel_parser.add_argument('--input', type=str, help='输入Excel文件路径')
|
|
||||||
|
|
||||||
# 合并命令
|
|
||||||
merge_parser = subparsers.add_parser('merge', help='合并采购单')
|
|
||||||
merge_parser.add_argument('--input', type=str, help='输入采购单文件路径(逗号分隔)')
|
|
||||||
|
|
||||||
# 完整流程命令
|
|
||||||
pipeline_parser = subparsers.add_parser('pipeline', help='完整处理流程')
|
|
||||||
pipeline_parser.add_argument('--input', type=str, help='输入图片路径')
|
|
||||||
pipeline_parser.add_argument('--merge', action='store_true', help='是否合并采购单')
|
|
||||||
|
|
||||||
# 烟草订单处理
|
|
||||||
tobacco_parser = subparsers.add_parser('tobacco', help='处理烟草订单')
|
|
||||||
tobacco_parser.add_argument('--input', type=str, help='输入订单明细文件路径')
|
|
||||||
|
|
||||||
# 解析参数
|
|
||||||
parsed_args = parser.parse_args()
|
|
||||||
|
|
||||||
return parsed_args
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""
|
|
||||||
主函数入口
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
退出码
|
|
||||||
"""
|
|
||||||
# 解析命令行参数
|
|
||||||
args = parse_args()
|
|
||||||
|
|
||||||
if not args.command:
|
|
||||||
argparse.ArgumentParser().print_help()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# 加载配置
|
|
||||||
config_path = args.config
|
|
||||||
config_manager = ConfigManager(config_path)
|
|
||||||
config = config_manager.config
|
|
||||||
|
|
||||||
# 设置日志级别
|
|
||||||
log_level = getattr(args, 'log_level', None)
|
|
||||||
if log_level:
|
|
||||||
set_log_level(log_level)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if args.command == 'ocr':
|
|
||||||
# OCR识别处理
|
|
||||||
ocr_service = OCRService(config)
|
|
||||||
if args.batch:
|
|
||||||
# 批量处理
|
|
||||||
total, success = ocr_service.batch_process(
|
|
||||||
batch_size=args.batch_size,
|
|
||||||
max_workers=args.max_workers
|
|
||||||
)
|
|
||||||
return 0 if success > 0 else 1
|
|
||||||
else:
|
|
||||||
# 处理单个文件
|
|
||||||
result = ocr_service.process_image(args.input)
|
|
||||||
return 0 if result else 1
|
|
||||||
|
|
||||||
elif args.command == 'excel':
|
|
||||||
# Excel处理
|
|
||||||
order_service = OrderService(config)
|
|
||||||
if args.input:
|
|
||||||
# 处理指定文件
|
|
||||||
result = order_service.process_excel(args.input)
|
|
||||||
else:
|
|
||||||
# 处理最新文件
|
|
||||||
result = order_service.process_excel()
|
|
||||||
return 0 if result else 1
|
|
||||||
|
|
||||||
elif args.command == 'merge':
|
|
||||||
# 合并采购单
|
|
||||||
order_service = OrderService(config)
|
|
||||||
if args.input:
|
|
||||||
# 合并指定文件
|
|
||||||
file_list = args.input.split(',')
|
|
||||||
result = order_service.merge_purchase_orders(file_list)
|
|
||||||
else:
|
|
||||||
# 合并所有采购单
|
|
||||||
result = order_service.merge_all_purchase_orders()
|
|
||||||
return 0 if result else 1
|
|
||||||
|
|
||||||
elif args.command == 'pipeline':
|
|
||||||
# 完整流程
|
|
||||||
ocr_service = OCRService(config)
|
|
||||||
order_service = OrderService(config)
|
|
||||||
|
|
||||||
# 1. OCR处理
|
|
||||||
if args.input:
|
|
||||||
# 处理单个文件
|
|
||||||
excel_file = ocr_service.process_image(args.input)
|
|
||||||
else:
|
|
||||||
# 批量处理
|
|
||||||
total, success = ocr_service.batch_process()
|
|
||||||
if total == 0:
|
|
||||||
logger.warning("没有找到需要处理的图片")
|
|
||||||
elif success == 0:
|
|
||||||
logger.warning("OCR处理没有成功处理任何新文件")
|
|
||||||
excel_file = None # 批量处理不返回具体文件
|
|
||||||
|
|
||||||
# 2. Excel处理
|
|
||||||
if excel_file:
|
|
||||||
# 处理指定的Excel文件
|
|
||||||
result = order_service.process_excel(excel_file)
|
|
||||||
else:
|
|
||||||
# 处理最新的Excel文件
|
|
||||||
result = order_service.process_excel()
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
logger.error("Excel处理失败")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# 3. 合并采购单(可选)
|
|
||||||
if args.merge:
|
|
||||||
result = order_service.merge_all_purchase_orders()
|
|
||||||
if not result:
|
|
||||||
logger.warning("合并采购单失败")
|
|
||||||
# 不影响整体流程,继续执行
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
elif args.command == 'tobacco':
|
|
||||||
# 烟草订单处理
|
|
||||||
tobacco_service = TobaccoService(config)
|
|
||||||
if args.input:
|
|
||||||
# 处理指定文件
|
|
||||||
logger.info(f"开始处理烟草订单,输入文件: {args.input}")
|
|
||||||
result = tobacco_service.process_tobacco_order(args.input)
|
|
||||||
else:
|
|
||||||
# 处理最新文件
|
|
||||||
logger.info("开始烟草公司订单处理")
|
|
||||||
result = tobacco_service.process_tobacco_order()
|
|
||||||
|
|
||||||
# 检查结果是否为None
|
|
||||||
if result is None:
|
|
||||||
logger.error("烟草订单处理失败")
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
logger.info(f"烟草订单处理成功,输出文件: {result}")
|
|
||||||
# 确保result是绝对路径
|
|
||||||
if not os.path.isabs(result):
|
|
||||||
result = os.path.abspath(result)
|
|
||||||
logger.info(f"烟草订单处理完成,绝对路径: {result}")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.error(f"未知命令: {args.command}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"执行过程中发生错误: {e}", exc_info=True)
|
|
||||||
return 1
|
|
||||||
finally:
|
|
||||||
# 关闭所有日志记录器
|
|
||||||
close_all_loggers()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
BIN
templates/商品资料.xlsx
Normal file
BIN
templates/商品资料.xlsx
Normal file
Binary file not shown.
@ -1,89 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
测试数量计算逻辑
|
|
||||||
"""
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import pandas as pd
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
# 添加项目根目录到路径
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
||||||
|
|
||||||
from app.core.excel.validators import ProductValidator
|
|
||||||
|
|
||||||
|
|
||||||
class TestQuantityCalculation(unittest.TestCase):
|
|
||||||
"""测试数量计算逻辑"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
"""设置测试环境"""
|
|
||||||
self.validator = ProductValidator()
|
|
||||||
|
|
||||||
def test_quantity_calculation_from_amount(self):
|
|
||||||
"""测试通过单价和金额计算数量"""
|
|
||||||
# 测试数量为空,但单价和金额存在的情况
|
|
||||||
product = {
|
|
||||||
'barcode': '6901028075862',
|
|
||||||
'name': '可口可乐',
|
|
||||||
'quantity': None,
|
|
||||||
'price': 5.0,
|
|
||||||
'amount': 60.0,
|
|
||||||
'unit': '瓶'
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证产品
|
|
||||||
validated = self.validator.validate_product(product)
|
|
||||||
|
|
||||||
# 断言:数量应该被计算为金额/单价 = 60/5 = 12
|
|
||||||
self.assertAlmostEqual(validated['quantity'], 12.0, places=2)
|
|
||||||
|
|
||||||
def test_quantity_calculation_with_string_values(self):
|
|
||||||
"""测试字符串形式的单价和金额"""
|
|
||||||
# 测试数量为空,单价和金额为字符串的情况
|
|
||||||
product = {
|
|
||||||
'barcode': '6901028075862',
|
|
||||||
'name': '可口可乐',
|
|
||||||
'quantity': None,
|
|
||||||
'price': '5.0',
|
|
||||||
'amount': '60.0',
|
|
||||||
'unit': '瓶'
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证产品
|
|
||||||
validated = self.validator.validate_product(product)
|
|
||||||
|
|
||||||
# 断言:数量应该被计算为金额/单价 = 60/5 = 12
|
|
||||||
self.assertAlmostEqual(validated['quantity'], 12.0, places=2)
|
|
||||||
|
|
||||||
def test_quantity_calculation_with_format_issues(self):
|
|
||||||
"""测试格式问题的情况"""
|
|
||||||
# 测试数量为空,单价和金额有格式问题的情况
|
|
||||||
product = {
|
|
||||||
'barcode': '6901028075862',
|
|
||||||
'name': '可口可乐',
|
|
||||||
'quantity': None,
|
|
||||||
'price': '5,0', # 使用逗号作为小数点
|
|
||||||
'amount': '¥60.0', # 带货币符号
|
|
||||||
'unit': '瓶'
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证产品
|
|
||||||
validated = self.validator.validate_product(product)
|
|
||||||
|
|
||||||
# 断言:数量应该被计算为金额/单价 = 60/5 = 12
|
|
||||||
self.assertAlmostEqual(validated['quantity'], 12.0, places=2)
|
|
||||||
|
|
||||||
def test_specification_parsing(self):
|
|
||||||
"""测试规格解析逻辑"""
|
|
||||||
# 这部分测试需要导入规格解析器
|
|
||||||
# 由于需要引入额外的代码,此处仅作为示例
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
161
更新日志.md
161
更新日志.md
@ -1,161 +0,0 @@
|
|||||||
# OCR订单处理系统 - 更新日志
|
|
||||||
|
|
||||||
## v1.5 (2025-05-09)
|
|
||||||
|
|
||||||
### 功能改进
|
|
||||||
- 烟草订单处理结果展示:改进烟草订单处理完成后的结果展示界面
|
|
||||||
- 美化结果展示界面,显示订单时间、总金额和处理条目数
|
|
||||||
- 添加文件信息展示,包括文件大小和创建时间
|
|
||||||
- 提供打开文件、打开所在文件夹等便捷操作按钮
|
|
||||||
- 统一与Excel处理结果展示风格,提升用户体验
|
|
||||||
- 增强结果文件路径解析能力,确保正确找到并显示结果文件
|
|
||||||
- 条码映射编辑功能:
|
|
||||||
- 添加图形化条码映射编辑工具,方便管理条码映射和特殊处理规则
|
|
||||||
- 支持添加、修改和删除条码映射关系
|
|
||||||
- 支持配置特殊处理规则,如乘数、目标单位、固定单价等
|
|
||||||
- 自动保存到配置文件,便于后续使用
|
|
||||||
|
|
||||||
### 问题修复
|
|
||||||
- 修复烟草订单处理时出现双重弹窗问题
|
|
||||||
- 修复烟草订单处理完成后结果展示弹窗无法正常显示的问题
|
|
||||||
- 修复ConfigParser兼容性问题,支持标准ConfigParser对象
|
|
||||||
- 修复百度OCR客户端中getint方法调用不兼容问题
|
|
||||||
- 修复OCRService中缺少batch_process方法的问题,确保OCR功能正常工作
|
|
||||||
- 改进日志管理,确保所有日志正确关闭
|
|
||||||
- 优化UI界面,统一按钮样式
|
|
||||||
- 修复启动器中处理烟草订单按钮的显示样式
|
|
||||||
- 修复run.py中close_logger调用缺少参数的问题
|
|
||||||
|
|
||||||
### 代码改进
|
|
||||||
- 改进TobaccoService类对配置的处理方式,使用标准get方法
|
|
||||||
- 添加fallback机制以增强配置健壮性
|
|
||||||
- 优化启动器中结果预览逻辑,避免重复弹窗
|
|
||||||
- 统一UI组件风格,提升用户体验
|
|
||||||
- 增强错误处理,提供更清晰的错误信息
|
|
||||||
|
|
||||||
## v1.4 (2025-05-09)
|
|
||||||
|
|
||||||
### 新功能
|
|
||||||
- 烟草订单处理:新增烟草公司特定格式订单明细文件处理功能
|
|
||||||
- 支持自动处理标准烟草订单明细格式
|
|
||||||
- 根据烟草公司"盒码"作为条码生成银豹采购单
|
|
||||||
- 自动将"订单量"转换为"采购量"并计算采购单价
|
|
||||||
- 处理结果以银豹采购单格式保存,方便直接导入
|
|
||||||
|
|
||||||
### 功能优化
|
|
||||||
- 配置兼容性:优化配置处理逻辑,兼容标准ConfigParser对象
|
|
||||||
- 启动器优化:启动器界面增加"处理烟草订单"功能按钮
|
|
||||||
- 代码结构优化:将烟草订单处理功能模块化,集成到整体服务架构
|
|
||||||
|
|
||||||
## v1.3 (2025-07-20)
|
|
||||||
|
|
||||||
### 功能优化
|
|
||||||
- 采购单赠品处理逻辑优化:修改了银豹采购单中赠品的处理方式
|
|
||||||
- 之前:赠品数量单独填写在"赠送量"列,与正常采购量分开处理
|
|
||||||
- 现在:将赠品数量合并到采购量中,赠送量列留空
|
|
||||||
- 有正常商品且有赠品的情况:采购量 = 正常商品数量 + 赠品数量,单价 = 原单价 × 正常商品数量 ÷ 总数量
|
|
||||||
- 只有赠品的情况:采购量填写赠品数量,单价为0
|
|
||||||
- 更新说明:经用户反馈,赠品处理逻辑已还原为原始方式,正常商品数量和赠品数量分开填写
|
|
||||||
|
|
||||||
## v1.2 (2025-07-15)
|
|
||||||
|
|
||||||
### 功能优化
|
|
||||||
- 规格提取优化:改进了从商品名称中提取规格的逻辑,优先识别"容量*数量"格式
|
|
||||||
- 例如从"美汁源果粒橙1.8L*8瓶"能准确提取"1.8L*8"而非错误的"1.8L*1"
|
|
||||||
- 规格解析增强:优化`parse_specification`方法,能正确解析"1.8L*8"格式规格,确保准确提取包装数量
|
|
||||||
- 单位推断增强:在`extract_product_info`方法中增加新逻辑,当单位为空且有条码、规格、数量、单价时,根据规格格式(如容量*数量格式或简单数量*数量格式)自动推断单位为"件"
|
|
||||||
- 件单位处理优化:确保当设置单位为"件"时,正确触发UnitConverter单位处理逻辑,将数量乘以包装数量,单价除以包装数量,单位转为"瓶"
|
|
||||||
- 整体改进:提高了系统处理复杂格式商品名称和规格的能力,使单位转换更加准确可靠
|
|
||||||
- 规格提取逻辑修正:修复了在Excel中已有规格信息时仍会从商品名称推断规格的问题,现在系统会优先使用Excel中的数据,只有在规格为空时才尝试从商品名称推断
|
|
||||||
|
|
||||||
## v1.1 (2025-05-07)
|
|
||||||
|
|
||||||
### 功能更新
|
|
||||||
- 单位自动推断:当单位为空但有商品编码、规格、数量、单价等信息,且规格符合容量*数量格式时,自动将单位设置为"件"并按照件的处理规则进行转换
|
|
||||||
- 规格解析优化:改进对容量*数量格式规格的解析,如"1.8L*8"能正确识别包装数量为8
|
|
||||||
- 规格提取增强:从商品名称中提取"容量*数量"格式的规格时,能正确识别如"美汁源果粒橙1.8L*8瓶"中的"1.8L*8"部分
|
|
||||||
- 条码映射功能:增加特定条码的自动映射功能,支持将特定条码自动转换为指定的目标条码
|
|
||||||
- 6920584471055 → 6920584471017
|
|
||||||
- 6925861571159 → 69021824
|
|
||||||
- 6923644268923 → 6923644268480
|
|
||||||
- 条码映射后会继续按照件/箱等单位的标准处理规则进行数量和单价的转换
|
|
||||||
|
|
||||||
## v1.0 (2025-05-02)
|
|
||||||
|
|
||||||
### 主要功能
|
|
||||||
- 图像OCR识别:支持对采购单图片进行OCR识别并生成Excel文件
|
|
||||||
- Excel数据处理:智能处理Excel文件,提取和转换商品信息
|
|
||||||
- 采购单生成:按照模板格式生成标准采购单Excel文件
|
|
||||||
- 采购单合并:支持多个采购单合并为一个总单
|
|
||||||
- 图形界面:提供简洁直观的操作界面
|
|
||||||
- 命令行支持:支持命令行调用,方便自动化处理
|
|
||||||
|
|
||||||
### 技术改进
|
|
||||||
- 模块化架构:重构代码为配置、核心功能、服务和CLI等模块
|
|
||||||
- 单位智能处理:完善的单位转换规则,支持多种计量单位
|
|
||||||
- 规格智能推断:从商品名称自动推断规格信息
|
|
||||||
- 日志管理:完善的日志记录系统,支持终端和GUI同步显示
|
|
||||||
- 表头智能识别:自动识别Excel中的表头位置,兼容多种格式
|
|
||||||
- 改进用户体验:界面优化,批量处理支持,实时状态反馈
|
|
||||||
|
|
||||||
## v1.5.1 (2024-03-21)
|
|
||||||
- 修复了配置管理相关的问题:
|
|
||||||
- 修复了`config.ini`文件被意外重置的问题
|
|
||||||
- 优化了配置加载逻辑,确保保留现有配置值
|
|
||||||
- 添加了配置缺失项自动补充功能
|
|
||||||
- 新增系统设置功能:
|
|
||||||
- 添加了图形化配置设置界面
|
|
||||||
- 支持API设置、路径设置、性能设置和文件设置
|
|
||||||
- 所有设置更改实时保存
|
|
||||||
- 移除了统计报告功能,替换为更实用的系统设置功能
|
|
||||||
- 优化了用户界面和交互体验
|
|
||||||
|
|
||||||
## v1.5.0 (2024-03-20)
|
|
||||||
- 添加了统计与报告功能
|
|
||||||
- 添加了键盘快捷键支持
|
|
||||||
- 优化了用户界面
|
|
||||||
- 删除了不必要的文件
|
|
||||||
- 更新了README.md
|
|
||||||
- 创建了更新日志文档
|
|
||||||
|
|
||||||
## v1.4.0 (2024-03-19)
|
|
||||||
- 添加了自定义弹窗演示
|
|
||||||
- 优化了错误处理
|
|
||||||
- 改进了日志记录
|
|
||||||
|
|
||||||
## v1.3.0 (2024-03-18)
|
|
||||||
- 添加了条码映射功能
|
|
||||||
- 优化了文件处理逻辑
|
|
||||||
- 改进了用户界面
|
|
||||||
|
|
||||||
## v1.2.0 (2024-03-17)
|
|
||||||
- 添加了批量处理功能
|
|
||||||
- 优化了性能
|
|
||||||
- 改进了错误处理
|
|
||||||
|
|
||||||
## v1.1.0 (2024-03-16)
|
|
||||||
- 添加了Excel处理功能
|
|
||||||
- 优化了OCR识别
|
|
||||||
- 改进了用户界面
|
|
||||||
|
|
||||||
## v1.0.0 (2024-03-15)
|
|
||||||
- 初始版本发布
|
|
||||||
- 基本OCR功能
|
|
||||||
- 基本用户界面
|
|
||||||
|
|
||||||
## v1.5.2 (2024-03-21)
|
|
||||||
- 修复了方法名称不匹配的问题:
|
|
||||||
- 将`process_latest_excel`方法调用改为`process_excel`
|
|
||||||
- 确保Excel处理功能正常工作
|
|
||||||
- 优化了错误处理和日志记录
|
|
||||||
|
|
||||||
## v1.5.3 (2024-03-21)
|
|
||||||
- 优化了完整流程处理逻辑:
|
|
||||||
- 修改了OCR处理逻辑,当遇到已处理的图片时自动跳过并继续执行
|
|
||||||
- 改进了错误处理,避免因图片已处理而中断流程
|
|
||||||
- 优化了日志提示信息,提供更清晰的处理状态反馈
|
|
||||||
- 改进了OCRService的process_image方法:
|
|
||||||
- 添加了文件存在性检查
|
|
||||||
- 添加了文件类型验证
|
|
||||||
- 添加了已处理文件检查
|
|
||||||
- 优化了错误处理和日志记录
|
|
||||||
Loading…
Reference in New Issue
Block a user