Compare commits
No commits in common. "main" and "v1.0.0" have entirely different histories.
42
.gitignore
vendored
42
.gitignore
vendored
@ -1,27 +1,29 @@
|
|||||||
# Python
|
# Python缓存文件
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.py[cod]
|
||||||
*.pyo
|
*$py.class
|
||||||
.pytest_cache/
|
|
||||||
.venv/
|
|
||||||
|
|
||||||
# Build & dist
|
# 虚拟环境
|
||||||
build/
|
venv/
|
||||||
dist/
|
env/
|
||||||
release/
|
ENV/
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Logs & temp
|
# 日志文件
|
||||||
logs/
|
logs/*.log
|
||||||
|
logs/*.active
|
||||||
|
*.log.*
|
||||||
|
|
||||||
|
# 临时文件和缓存
|
||||||
data/temp/
|
data/temp/
|
||||||
|
data/*.bak
|
||||||
# Runtime outputs
|
*.bak
|
||||||
data/output/
|
|
||||||
data/result/
|
|
||||||
|
|
||||||
# OS/IDE
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
|
||||||
|
# 输出文件(可选是否忽略)
|
||||||
|
# data/output/
|
||||||
|
|
||||||
|
# IDE文件
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
@ -1,43 +0,0 @@
|
|||||||
## 问题与目标
|
|
||||||
- 弹窗尺寸偏小,不便操作
|
|
||||||
- 弹窗及文件选择后没有在最上层,易被其他窗口遮挡
|
|
||||||
- 字段英文名不直观,需要显示中文对应(银豹模板列)
|
|
||||||
|
|
||||||
## 改进方案
|
|
||||||
### 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行与加载列同一行;点击预览行自动写入表头行号;保存后提示成功并写入配置
|
|
||||||
|
|
||||||
请确认以上方案,确认后我将立即实施并验证。
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
## 目标
|
|
||||||
- 在系统设置中提供“供应商管理”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及其数据流,并将现有向导整合到供应商管理中以形成一站式配置体验。
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
## 痛点复盘
|
|
||||||
- 不同供应商存在强差异:列名不统一、单位混杂在数量、规格隐藏在名称、供应商缺失等
|
|
||||||
- 现有向导只解决列映射层面,规则与词典编辑、执行顺序与生效范围不清晰
|
|
||||||
- 缺少可视化“从原始→规范化→模板填充”的贯通验证;流程易跑不通
|
|
||||||
|
|
||||||
## 总体方案
|
|
||||||
- 建立“供应商规则系统”:可配置、可视化、可预览,贯穿 映射→清洗→规则→模板 填充全链路
|
|
||||||
- 提供“规则库 + 词典 + 执行管道”三层抽象,支持每家供应商自定义规则组合与执行顺序
|
|
||||||
- 完善 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:回归修正与打包交付
|
|
||||||
|
|
||||||
确认后我将开始实现上述内容,确保不同供应商可独立配置精细规则并“所见即所得”验证,流程稳定可跑通。
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
## 目标
|
|
||||||
- 为具体供应商定制更细的解析规则(词典、包装倍数、忽略词、同义单位),并在列映射向导提供可视化编辑入口与预览。
|
|
||||||
|
|
||||||
## 配置扩展
|
|
||||||
- 扩展 `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与预览→测试。
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
## 原因
|
|
||||||
|
|
||||||
* 按钮调用了 `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` 相邻区域,确保可见与可用。
|
|
||||||
|
|
||||||
## 验证
|
|
||||||
|
|
||||||
* 启动程序→系统设置→点击“验证匹配”,应正常打开面板无提示。
|
|
||||||
|
|
||||||
* 选择“农夫山泉”与提供的文件后运行验证,查看差异与建议。
|
|
||||||
|
|
||||||
## 预期
|
|
||||||
|
|
||||||
* 面板不再提示重启;功能可用。
|
|
||||||
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
## 目标
|
|
||||||
- 用你提供的原始文件与期望结果跑通“验证闭环”,自动对比差异并生成修正建议。
|
|
||||||
- 将“规则设置”改造成通俗易懂的“向导 + 快速模板 + 自动识别”,让普通用户也能完成操作。
|
|
||||||
|
|
||||||
## 验证闭环(立即可用)
|
|
||||||
- 新增“验证匹配”面板:
|
|
||||||
- 选择原始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:回归测试与打包;提供“农夫山泉”预设并用你的样例验证匹配
|
|
||||||
|
|
||||||
确认后我将实现“验证匹配”面板并接入建议修复,先用你提供的农夫山泉样例跑通闭环,再推广到其它供应商。
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
## 目标
|
|
||||||
- 按照优化实施计划,从第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 打包与版本信息,回归测试与文档补充
|
|
||||||
|
|
||||||
确认后我将按以上计划开始实施并逐项提交验证结果。
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
## 概览
|
|
||||||
- 目标:让改动更可见并提升识别/处理准确性与可操作性
|
|
||||||
- 范围: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 与功能;提供操作说明与可见验证点。
|
|
||||||
|
|
||||||
请确认以上计划,确认后我将按此逐项实现并验证。
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
## 你现在就能这样做
|
|
||||||
- 目标:在没有“规格/数量/单位”列、只有“订单数量”列(如“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预览、错误计数与一键测试),并把默认规则与词典预设直接提供出来,确保“只有订单数量列”的场景开箱可用。
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
## 目标
|
|
||||||
- 通过规则引擎把不同供货商的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,39 +1,30 @@
|
|||||||
# Changelog
|
# 更新日志
|
||||||
|
|
||||||
## [v2.2.0] - 2026-03-31
|
## v1.1.0 (2025-05-30)
|
||||||
### 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
|
### 新特性
|
||||||
- **Yang Biyue Preprocessing**: Resolved issue where data was empty due to incorrect column renaming.
|
- 添加对特殊条码6958620703716的处理,支持同时设置规格和条码映射
|
||||||
- **Interference Filtering**: Added logic to exclude distractor columns like "Settlement Unit" or "Base Quantity" during preprocessing.
|
- 增强不规范规格格式的解析能力(如"IL*12"、"6oo*12"等)
|
||||||
|
- 支持带重量单位的规格解析(如"5kg*6")
|
||||||
|
- 添加数量为空时通过金额和单价自动计算数量的功能
|
||||||
|
|
||||||
### Removed
|
### 修复
|
||||||
- **Redundant Files**: Cleaned up `run.py`, `clean.py`, and unused CLI modules.
|
- 修复条码映射功能在特殊处理后不生效的问题
|
||||||
- **Legacy UI Elements**: Removed tobacco-specific keyboard shortcuts and help entries.
|
- 修复OrderService中缺少merge_all_purchase_orders方法导致合并采购单报错的问题
|
||||||
|
- 修复了条码映射对话框无法同时添加特殊处理和映射的问题
|
||||||
|
|
||||||
## [v2.1.0] - 2026-03-30
|
### 改进
|
||||||
### Added
|
- 改进了BarcodeMapper类,使其支持同时进行特殊处理和条码映射
|
||||||
- **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`.
|
- 改进商品验证器,在数量为空但单价和金额存在时,自动计算数量
|
||||||
|
|
||||||
### Fixed
|
## v1.0.0 (2025-05-01)
|
||||||
- **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
|
### 初始版本
|
||||||
### Added
|
- 基础OCR识别功能
|
||||||
- **Headless API**: First release of `headless_api.py` for OpenClaw integration.
|
- Excel处理功能
|
||||||
- **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`.
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
# 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*
|
|
||||||
82
OCR订单处理系统.spec
Normal file
82
OCR订单处理系统.spec
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
# -*- 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,
|
||||||
|
)
|
||||||
@ -1,53 +0,0 @@
|
|||||||
# 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,66 +1,43 @@
|
|||||||
# 益选 OCR 订单处理系统
|
# 益选-OCR订单处理系统
|
||||||
|
|
||||||
## 概览
|
一个集OCR识别、Excel处理和订单合并功能于一体的采购单处理系统。
|
||||||
- 面向零售与分销场景的采购单处理工具,支持图片 OCR → Excel 规范化 → 模板填充 → 合并导出全流程
|
|
||||||
- 通过供应商管理与规则引擎,适配不同供应商的格式差异(数量含单位、名称包含规格、缺失列补齐)
|
|
||||||
- 提供验证匹配面板与单价校验机制,确保输出与既定模板一致且价格合理
|
|
||||||
|
|
||||||
## 核心功能
|
## 主要功能
|
||||||
- **全自动智能识别**:系统现在能自动识别 Excel 内容特征(如:蓉城易购 RCDH、烟草公司专卖证号、杨碧月经手人),并自动路由至专用预处理流程,无需手动干预。
|
|
||||||
- **图片/Excel处理**:支持拖拽或选择文件,一键生成标准银豹采购单。
|
|
||||||
- **极简 UI 体验**:移除了冗余的供应商特定按钮,所有 Excel 统一走智能路由处理。
|
|
||||||
- **无界面自动化接口 (headless_api.py)**:专为 OpenClaw 等平台设计,支持全自动文件类型与供应商识别。
|
|
||||||
- **单价预警机制**:自动比对 `templates/商品资料.xlsx`,若价差超过 1.0 元则触发警告。
|
|
||||||
|
|
||||||
## 供应商专用逻辑 (v2.2)
|
- **OCR识别**:识别图片中的商品信息,包括条码、名称、数量、单价等
|
||||||
### 蓉城易购 (Rongcheng)
|
- **Excel处理**:将OCR识别结果处理成规范的Excel采购单
|
||||||
- **精准映射**:商品条码(E列)、数量(N列)、单价(Q列)、金额(S列)。
|
- **采购单合并**:合并多个采购单,汇总相同商品
|
||||||
- **条码分裂**:支持多条码行(如 `条码1/条码2`)自动均分数量。
|
- **条码映射**:支持将特定条码映射为其他条码,适应不同系统要求
|
||||||
- **逻辑简化**:直接提取原始数量,不进行多余的单位或包装换算。
|
- **规格处理**:智能解析商品规格,实现单位自动转换
|
||||||
|
- **烟草订单处理**:专门处理烟草公司订单
|
||||||
|
|
||||||
### 烟草公司 (Tobacco)
|
## 技术特点
|
||||||
- **换算逻辑**:条码(B列)、数量(G列 x 10)、单价(E列 / 10)、总额(H列)。
|
|
||||||
- **智能跳行**:自动识别并跳过合计行及非数据行。
|
|
||||||
|
|
||||||
### 杨碧月订单
|
- 基于Python开发,使用Tkinter构建图形界面
|
||||||
- **自动对齐**:识别到经手人“杨碧月”后,自动将非标 Excel 转换为标准列格式,支持单位换算(件 -> 瓶)。
|
- 采用模块化设计,易于扩展和维护
|
||||||
|
- 自动处理各种不规范数据格式
|
||||||
|
- 配置文件支持,可自定义各种处理参数
|
||||||
|
- 日志记录,便于问题排查
|
||||||
|
|
||||||
## 关键适配(蓉城易购)
|
## 使用方法
|
||||||
- 新模板(如“订单1765440157955.xlsx”):
|
|
||||||
- 使用第三行作为表头(`header=2`)
|
|
||||||
- 关键词选列并重命名到期望字段:商品条码(小条码)、订购数量(小单位)、单价(小单位)、优惠后金额(小单位)、单位
|
|
||||||
- 单位优先匹配“单位(订购单位)”列,清洗为去空白并将“件”替换为“份”
|
|
||||||
- 多条码行(逗号/顿号/斜杠/空格分隔)拆分为多行,数量均分并重算金额,单位保持订购单位
|
|
||||||
- 新模板映射:将“优惠后金额(小单位)”作为单价,“出库小计(元)”作为金额来源
|
|
||||||
|
|
||||||
## 使用说明
|
1. 运行`启动器.py`打开主界面
|
||||||
1. 运行程序(EXE或源码运行)
|
2. 根据需要选择相应功能按钮
|
||||||
2. 在主界面:
|
3. 按照提示操作,完成数据处理
|
||||||
- 拖拽或选择图片/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`)
|
|
||||||
|
|
||||||
## Git 提交建议
|
- Python 3.8+
|
||||||
- 建议忽略构建目录与运行输出(见 `.gitignore`)
|
- 所需第三方库:详见`requirements.txt`
|
||||||
- 保留模板与配置:`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订单处理系统
|
||||||
5
app/cli/__init__.py
Normal file
5
app/cli/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
OCR订单处理系统 - 命令行接口
|
||||||
|
-------------------------
|
||||||
|
提供命令行工具,便于用户使用系统功能。
|
||||||
|
"""
|
||||||
138
app/cli/excel_cli.py
Normal file
138
app/cli/excel_cli.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
"""
|
||||||
|
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())
|
||||||
147
app/cli/merge_cli.py
Normal file
147
app/cli/merge_cli.py
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
"""
|
||||||
|
订单合并命令行工具
|
||||||
|
--------------
|
||||||
|
提供订单合并相关的命令行接口。
|
||||||
|
"""
|
||||||
|
|
||||||
|
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())
|
||||||
164
app/cli/ocr_cli.py
Normal file
164
app/cli/ocr_cli.py
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
"""
|
||||||
|
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,29 +117,25 @@ class ConfigManager:
|
|||||||
获取路径配置并确保它是一个有效的绝对路径
|
获取路径配置并确保它是一个有效的绝对路径
|
||||||
如果create为True,则自动创建该目录
|
如果create为True,则自动创建该目录
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
path = self.get(section, option, fallback)
|
||||||
path_str = self.get(section, option, fallback)
|
|
||||||
path = Path(path_str)
|
|
||||||
|
|
||||||
if not path.is_absolute():
|
if not os.path.isabs(path):
|
||||||
# 相对路径,转为绝对路径(相对于项目根目录)
|
# 相对路径,转为绝对路径
|
||||||
path = Path(os.getcwd()) / path
|
path = os.path.abspath(path)
|
||||||
|
|
||||||
if create:
|
if create and not os.path.exists(path):
|
||||||
try:
|
try:
|
||||||
# 智能判断是文件还是目录
|
# 如果是文件路径,创建其父目录
|
||||||
# 如果有后缀名则认为是文件,创建其父目录
|
if '.' in os.path.basename(path):
|
||||||
if path.suffix:
|
directory = os.path.dirname(path)
|
||||||
directory = path.parent
|
if directory and not os.path.exists(directory):
|
||||||
if not directory.exists():
|
os.makedirs(directory, exist_ok=True)
|
||||||
directory.mkdir(parents=True, exist_ok=True)
|
logger.info(f"已创建目录: {directory}")
|
||||||
logger.info(f"已创建父目录: {directory}")
|
|
||||||
else:
|
else:
|
||||||
# 否则认为是目录路径
|
# 否则认为是目录路径
|
||||||
if not path.exists():
|
os.makedirs(path, exist_ok=True)
|
||||||
path.mkdir(parents=True, exist_ok=True)
|
logger.info(f"已创建目录: {path}")
|
||||||
logger.info(f"已创建目录: {path}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"创建目录失败: {path}, 错误: {e}")
|
logger.error(f"创建目录失败: {path}, 错误: {e}")
|
||||||
|
|
||||||
return str(path.absolute())
|
return path
|
||||||
@ -285,16 +285,6 @@ 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:
|
||||||
@ -532,4 +522,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,9 +63,8 @@ class JianUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = str(product.get('unit', '')).strip()
|
unit = product.get('unit', '')
|
||||||
# 匹配"件"、"件、"、"件装"等
|
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]:
|
||||||
"""
|
"""
|
||||||
@ -118,9 +117,8 @@ class BoxUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = str(product.get('unit', '')).strip()
|
unit = product.get('unit', '')
|
||||||
# 匹配"箱"、"箱、"、"箱装"等
|
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]:
|
||||||
"""
|
"""
|
||||||
@ -173,8 +171,8 @@ class TiHeUnitHandler(UnitHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
是否可以处理
|
是否可以处理
|
||||||
"""
|
"""
|
||||||
unit = str(product.get('unit', '')).strip()
|
unit = product.get('unit', '')
|
||||||
return unit in ['提', '盒'] or unit.startswith('提') or unit.startswith('盒')
|
return unit in ['提', '盒']
|
||||||
|
|
||||||
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, Callable
|
from typing import Dict, List, Optional, Tuple, Union, Any
|
||||||
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, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def process(self, file_paths: Optional[List[str]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理采购单合并
|
处理采购单合并
|
||||||
|
|
||||||
@ -427,11 +427,6 @@ 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:
|
||||||
@ -443,26 +438,16 @@ 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, Callable
|
from typing import Dict, List, Optional, Tuple, Union, Any
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ...config.settings import ConfigManager
|
from ...config.settings import ConfigManager
|
||||||
@ -253,20 +253,6 @@ 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['商品名称']):
|
||||||
@ -295,36 +281,6 @@ 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['数量']):
|
||||||
@ -516,7 +472,7 @@ class ExcelProcessor:
|
|||||||
logger.warning(f"通过金额和单价计算数量失败: {e}")
|
logger.warning(f"通过金额和单价计算数量失败: {e}")
|
||||||
|
|
||||||
# 判断是否为赠品(价格为0)
|
# 判断是否为赠品(价格为0)
|
||||||
is_gift = bool(product.get('is_gift', False)) or (price == 0)
|
is_gift = price == 0
|
||||||
|
|
||||||
logger.info(f"处理商品: 条码={barcode}, 数量={quantity}, 单价={price}, 是否赠品={is_gift}")
|
logger.info(f"处理商品: 条码={barcode}, 数量={quantity}, 单价={price}, 是否赠品={is_gift}")
|
||||||
|
|
||||||
@ -619,16 +575,17 @@ class ExcelProcessor:
|
|||||||
Returns:
|
Returns:
|
||||||
表头行索引,如果未找到则返回None
|
表头行索引,如果未找到则返回None
|
||||||
"""
|
"""
|
||||||
|
# 定义可能的表头关键词
|
||||||
header_keywords = [
|
header_keywords = [
|
||||||
'条码', '条形码', '商品条码', '商品名称', '名称', '数量', '单位', '单价',
|
'条码', '条形码', '商品条码', '商品名称', '名称', '数量', '单位', '单价',
|
||||||
'规格', '商品编码', '采购数量', '采购单位', '商品', '品名',
|
'规格', '商品编码', '采购数量', '采购单位', '商品', '品名'
|
||||||
'金额', '小计', '总计', '合计', '合计金额'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# 存储每行的匹配分数
|
# 存储每行的匹配分数
|
||||||
row_scores = []
|
row_scores = []
|
||||||
|
|
||||||
max_rows_to_check = min(30, len(df))
|
# 遍历前10行(通常表头不会太靠后)
|
||||||
|
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
|
||||||
@ -674,7 +631,7 @@ class ExcelProcessor:
|
|||||||
logger.warning("无法识别表头行")
|
logger.warning("无法识别表头行")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_specific_file(self, file_path: str, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def process_specific_file(self, file_path: str) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理指定的Excel文件
|
处理指定的Excel文件
|
||||||
|
|
||||||
@ -692,11 +649,6 @@ 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)} 行")
|
||||||
|
|
||||||
@ -708,25 +660,11 @@ class ExcelProcessor:
|
|||||||
|
|
||||||
logger.info(f"识别到表头在第 {header_row+1} 行")
|
logger.info(f"识别到表头在第 {header_row+1} 行")
|
||||||
|
|
||||||
# 重新设置表头,避免二次读取
|
# 重新读取Excel,正确指定表头行
|
||||||
if progress_cb:
|
df = pd.read_excel(file_path, header=header_row)
|
||||||
try:
|
logger.info(f"使用表头行重新读取数据,共 {len(df)} 行有效数据")
|
||||||
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:
|
||||||
@ -747,11 +685,6 @@ 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
|
||||||
|
|
||||||
@ -761,7 +694,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, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def process_latest_file(self) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理最新的Excel文件
|
处理最新的Excel文件
|
||||||
|
|
||||||
@ -775,7 +708,7 @@ class ExcelProcessor:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# 处理文件
|
# 处理文件
|
||||||
return self.process_specific_file(latest_file, progress_cb=progress_cb)
|
return self.process_specific_file(latest_file)
|
||||||
|
|
||||||
def _detect_column_mapping(self, df: pd.DataFrame) -> Dict[str, str]:
|
def _detect_column_mapping(self, df: pd.DataFrame) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
@ -956,11 +889,6 @@ 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)
|
||||||
@ -1018,4 +946,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
|
||||||
355
app/core/excel/test_converter.py
Normal file
355
app/core/excel/test_converter.py
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
"""
|
||||||
|
单位转换器测试模块
|
||||||
|
---------------
|
||||||
|
测试单位转换和条码映射逻辑
|
||||||
|
"""
|
||||||
|
|
||||||
|
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,36 +225,6 @@ 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)
|
||||||
@ -298,4 +268,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
|
||||||
@ -1,9 +0,0 @@
|
|||||||
"""
|
|
||||||
数据处理handlers模块初始化文件
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .data_cleaner import DataCleaner
|
|
||||||
from .column_mapper import ColumnMapper
|
|
||||||
from .calculator import DataCalculator
|
|
||||||
|
|
||||||
__all__ = ['DataCleaner', 'ColumnMapper', 'DataCalculator']
|
|
||||||
@ -1,378 +0,0 @@
|
|||||||
"""
|
|
||||||
数据计算处理器
|
|
||||||
|
|
||||||
提供各种数据计算功能,如数量计算、价格计算、汇总统计等
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,276 +0,0 @@
|
|||||||
"""
|
|
||||||
列映射处理器
|
|
||||||
|
|
||||||
提供列名映射和转换功能,支持不同供应商的列名标准化
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,401 +0,0 @@
|
|||||||
"""
|
|
||||||
数据清洗处理器
|
|
||||||
|
|
||||||
提供各种数据清洗功能,如空值处理、重复项处理、数据类型转换等
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
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, Callable
|
from typing import Dict, List, Optional, Tuple, Union, Any
|
||||||
|
|
||||||
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, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
def process_images_batch(self, batch_size: int = None, max_workers: int = None) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
批量处理图片
|
批量处理图片
|
||||||
|
|
||||||
@ -369,13 +369,6 @@ 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:
|
||||||
@ -385,9 +378,4 @@ 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
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
"""
|
|
||||||
处理器模块初始化文件
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .base import BaseProcessor
|
|
||||||
from .ocr_processor import OCRProcessor
|
|
||||||
from .tobacco_processor import TobaccoProcessor
|
|
||||||
|
|
||||||
__all__ = ['BaseProcessor', 'OCRProcessor', 'TobaccoProcessor']
|
|
||||||
@ -1,139 +0,0 @@
|
|||||||
"""
|
|
||||||
基础处理器接口模块
|
|
||||||
|
|
||||||
定义所有处理器的基类,提供统一的处理接口
|
|
||||||
"""
|
|
||||||
|
|
||||||
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}')"
|
|
||||||
@ -1,192 +0,0 @@
|
|||||||
"""
|
|
||||||
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
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
"""
|
|
||||||
供应商处理器模块初始化文件
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .generic_supplier_processor import GenericSupplierProcessor
|
|
||||||
|
|
||||||
__all__ = ['GenericSupplierProcessor']
|
|
||||||
@ -1,483 +0,0 @@
|
|||||||
"""
|
|
||||||
通用供应商处理器
|
|
||||||
|
|
||||||
可配置化的供应商处理器,支持通过配置文件定义处理规则
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,362 +0,0 @@
|
|||||||
"""
|
|
||||||
烟草订单处理器
|
|
||||||
|
|
||||||
处理烟草公司特定格式的订单明细文件,生成银豹采购单
|
|
||||||
"""
|
|
||||||
|
|
||||||
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,34 +219,6 @@ 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,7 +7,6 @@
|
|||||||
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
|
||||||
@ -59,8 +58,7 @@ 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)
|
||||||
@ -177,4 +175,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, Callable
|
from typing import Dict, List, Optional, Tuple, Union, Any
|
||||||
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, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
def process_images_batch(self, batch_size: int = None, max_workers: int = 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, progress_cb)
|
return self.ocr_processor.process_images_batch(batch_size, max_workers)
|
||||||
|
|
||||||
# 添加batch_process作为process_images_batch的别名,确保兼容性
|
# 添加batch_process作为process_images_batch的别名,确保兼容性
|
||||||
def batch_process(self, batch_size: int = None, max_workers: int = None, progress_cb: Optional[Callable[[int], None]] = None) -> Tuple[int, int]:
|
def batch_process(self, batch_size: int = None, max_workers: int = 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, progress_cb)
|
return self.process_images_batch(batch_size, max_workers)
|
||||||
|
|
||||||
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,8 +4,7 @@
|
|||||||
提供订单处理服务,协调Excel处理和订单合并流程。
|
提供订单处理服务,协调Excel处理和订单合并流程。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
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 ..core.utils.log_utils import get_logger
|
from ..core.utils.log_utils import get_logger
|
||||||
@ -44,9 +43,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, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def process_excel(self, file_path: Optional[str] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
处理Excel订单文件,生成标准采购单
|
处理Excel文件,生成采购单
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Excel文件路径,如果为None则处理最新的文件
|
file_path: Excel文件路径,如果为None则处理最新的文件
|
||||||
@ -54,84 +53,12 @@ class OrderService:
|
|||||||
Returns:
|
Returns:
|
||||||
输出采购单文件路径,如果处理失败则返回None
|
输出采购单文件路径,如果处理失败则返回None
|
||||||
"""
|
"""
|
||||||
if not file_path:
|
if file_path:
|
||||||
file_path = self.excel_processor.get_latest_excel()
|
|
||||||
if not file_path:
|
|
||||||
logger.warning("未找到可处理的Excel文件")
|
|
||||||
return None
|
|
||||||
logger.info("OrderService开始处理最新Excel文件")
|
|
||||||
else:
|
|
||||||
logger.info(f"OrderService开始处理指定Excel文件: {file_path}")
|
logger.info(f"OrderService开始处理指定Excel文件: {file_path}")
|
||||||
|
return self.excel_processor.process_specific_file(file_path)
|
||||||
# 检查是否需要特殊的供应商预处理(如杨碧月)
|
else:
|
||||||
try:
|
logger.info("OrderService开始处理最新Excel文件")
|
||||||
from .special_suppliers_service import SpecialSuppliersService
|
return self.excel_processor.process_latest_file()
|
||||||
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]:
|
||||||
"""
|
"""
|
||||||
@ -142,7 +69,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], progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def merge_purchase_orders(self, file_paths: List[str]) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并指定的采购单文件
|
合并指定的采购单文件
|
||||||
|
|
||||||
@ -153,9 +80,9 @@ class OrderService:
|
|||||||
合并后的采购单文件路径,如果合并失败则返回None
|
合并后的采购单文件路径,如果合并失败则返回None
|
||||||
"""
|
"""
|
||||||
logger.info(f"OrderService开始合并指定采购单: {file_paths}")
|
logger.info(f"OrderService开始合并指定采购单: {file_paths}")
|
||||||
return self.merge_orders(file_paths, progress_cb)
|
return self.merge_orders(file_paths)
|
||||||
|
|
||||||
def merge_all_purchase_orders(self, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def merge_all_purchase_orders(self) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并所有可用的采购单文件
|
合并所有可用的采购单文件
|
||||||
|
|
||||||
@ -163,9 +90,9 @@ class OrderService:
|
|||||||
合并后的采购单文件路径,如果合并失败则返回None
|
合并后的采购单文件路径,如果合并失败则返回None
|
||||||
"""
|
"""
|
||||||
logger.info("OrderService开始合并所有采购单")
|
logger.info("OrderService开始合并所有采购单")
|
||||||
return self.merge_orders(None, progress_cb)
|
return self.merge_orders(None)
|
||||||
|
|
||||||
def merge_orders(self, file_paths: Optional[List[str]] = None, progress_cb: Optional[Callable[[int], None]] = None) -> Optional[str]:
|
def merge_orders(self, file_paths: Optional[List[str]] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
合并采购单
|
合并采购单
|
||||||
|
|
||||||
@ -180,72 +107,4 @@ class OrderService:
|
|||||||
else:
|
else:
|
||||||
logger.info("OrderService开始合并所有采购单")
|
logger.info("OrderService开始合并所有采购单")
|
||||||
|
|
||||||
return self.order_merger.process(file_paths, progress_cb)
|
return self.order_merger.process(file_paths)
|
||||||
|
|
||||||
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 []
|
|
||||||
@ -1,297 +0,0 @@
|
|||||||
"""
|
|
||||||
处理器调度服务
|
|
||||||
|
|
||||||
负责管理和调度各种文件处理器,实现智能文件类型检测和处理器选择
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,223 +0,0 @@
|
|||||||
#!/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,77 +73,6 @@ 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):
|
||||||
"""
|
"""
|
||||||
处理烟草订单
|
处理烟草订单
|
||||||
@ -236,9 +165,8 @@ class TobaccoService:
|
|||||||
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from app.core.utils.file_utils import smart_read_excel
|
|
||||||
# 读取Excel文件
|
# 读取Excel文件
|
||||||
df_old = smart_read_excel(file_path, header=None, skiprows=3, names=columns)
|
df_old = pd.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()
|
||||||
|
|||||||
9645
build/OCR订单处理系统/Analysis-00.toc
Normal file
9645
build/OCR订单处理系统/Analysis-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
5758
build/OCR订单处理系统/EXE-00.toc
Normal file
5758
build/OCR订单处理系统/EXE-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
build/OCR订单处理系统/OCR订单处理系统.pkg
Normal file
BIN
build/OCR订单处理系统/OCR订单处理系统.pkg
Normal file
Binary file not shown.
5734
build/OCR订单处理系统/PKG-00.toc
Normal file
5734
build/OCR订单处理系统/PKG-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
build/OCR订单处理系统/PYZ-00.pyz
Normal file
BIN
build/OCR订单处理系统/PYZ-00.pyz
Normal file
Binary file not shown.
3324
build/OCR订单处理系统/PYZ-00.toc
Normal file
3324
build/OCR订单处理系统/PYZ-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
build/OCR订单处理系统/base_library.zip
Normal file
BIN
build/OCR订单处理系统/base_library.zip
Normal file
Binary file not shown.
316
build/OCR订单处理系统/warn-OCR订单处理系统.txt
Normal file
316
build/OCR订单处理系统/warn-OCR订单处理系统.txt
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
|
||||||
|
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)
|
||||||
42795
build/OCR订单处理系统/xref-OCR订单处理系统.html
Normal file
42795
build/OCR订单处理系统/xref-OCR订单处理系统.html
Normal file
File diff suppressed because it is too large
Load Diff
62
build_exe.py
62
build_exe.py
@ -121,40 +121,6 @@ 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'
|
||||||
@ -184,9 +150,6 @@ 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}")
|
||||||
@ -201,18 +164,8 @@ def create_portable_package():
|
|||||||
# 创建发布目录
|
# 创建发布目录
|
||||||
release_dir = Path('release')
|
release_dir = Path('release')
|
||||||
if release_dir.exists():
|
if release_dir.exists():
|
||||||
try:
|
shutil.rmtree(release_dir)
|
||||||
shutil.rmtree(release_dir)
|
release_dir.mkdir()
|
||||||
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')
|
||||||
@ -257,17 +210,6 @@ 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
Normal file
88
clean.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#!/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 = E:\2025Code\python\orc-order-v2\templates
|
template_folder = templates
|
||||||
processed_record = data/processed_files.json
|
processed_record = data/processed_files.json
|
||||||
|
|
||||||
[Performance]
|
[Performance]
|
||||||
@ -26,6 +26,3 @@ max_file_size_mb = 4
|
|||||||
[Templates]
|
[Templates]
|
||||||
purchase_order = 银豹-采购单模板.xls
|
purchase_order = 银豹-采购单模板.xls
|
||||||
|
|
||||||
[App]
|
|
||||||
version = 2026.03.30.1036
|
|
||||||
|
|
||||||
|
|||||||
@ -179,58 +179,6 @@
|
|||||||
"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": "瓶",
|
||||||
@ -253,17 +201,5 @@
|
|||||||
"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": "南孚电池"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,237 +0,0 @@
|
|||||||
{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 146 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 115 KiB |
BIN
data/input/7a3a78a02fcf6ccef5daad31bd50bdf2.jpg
Normal file
BIN
data/input/7a3a78a02fcf6ccef5daad31bd50bdf2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 KiB |
BIN
data/output/7a3a78a02fcf6ccef5daad31bd50bdf2.xlsx
Normal file
BIN
data/output/7a3a78a02fcf6ccef5daad31bd50bdf2.xlsx
Normal file
Binary file not shown.
3
data/output/processed_files.json
Normal file
3
data/output/processed_files.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"data/output\\7a3a78a02fcf6ccef5daad31bd50bdf2.xlsx": "data/result\\采购单_7a3a78a02fcf6ccef5daad31bd50bdf2.xls"
|
||||||
|
}
|
||||||
BIN
data/result/采购单_7a3a78a02fcf6ccef5daad31bd50bdf2.xls
Normal file
BIN
data/result/采购单_7a3a78a02fcf6ccef5daad31bd50bdf2.xls
Normal file
Binary file not shown.
@ -1,13 +1 @@
|
|||||||
{
|
{"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
Normal file
BIN
dist/OCR订单处理系统.exe
vendored
Normal file
Binary file not shown.
28
dist/config.ini
vendored
Normal file
28
dist/config.ini
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[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
Normal file
205
dist/config/barcode_mappings.json
vendored
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
{
|
||||||
|
"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
Normal file
28
dist/config/config.ini
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[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,208 +0,0 @@
|
|||||||
# 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
216
headless_api.py
@ -1,216 +0,0 @@
|
|||||||
#!/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,2 +1 @@
|
|||||||
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,389 +1,2 @@
|
|||||||
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
@ -1,24 +0,0 @@
|
|||||||
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 - 成功获取访问令牌
|
|
||||||
@ -1,422 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
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 中找到符合条件的文件
|
|
||||||
@ -1,597 +0,0 @@
|
|||||||
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,878 +1,3 @@
|
|||||||
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初始化完成
|
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
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
|
|
||||||
BIN
release/OCR订单处理系统.exe
Normal file
BIN
release/OCR订单处理系统.exe
Normal file
Binary file not shown.
19
release/README.txt
Normal file
19
release/README.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
# 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/ - 日志目录
|
||||||
28
release/config.ini
Normal file
28
release/config.ini
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[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
release/config/barcode_mappings.json
Normal file
205
release/config/barcode_mappings.json
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
{
|
||||||
|
"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
release/config/config.ini
Normal file
28
release/config/config.ini
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[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
|
||||||
|
|
||||||
BIN
release/templates/银豹-采购单模板.xls
Normal file
BIN
release/templates/银豹-采购单模板.xls
Normal file
Binary file not shown.
206
run.py
Normal file
206
run.py
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
#!/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())
|
||||||
Binary file not shown.
89
tests/test_quantity_calculation.py
Normal file
89
tests/test_quantity_calculation.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/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
Normal file
161
更新日志.md
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
# 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