返回开发日志
飞书多维表同步工具2026-07-10v4.1.0

领星API下载与直写飞书改造(含网页自动化下载后写入飞书补全)

新功能v4.1.0

需求描述

  1. 领星ERP报表下载方式升级:原有下载依赖Playwright网页自动化,速度慢、资源占用高、字段选择受限。领星开放API提供更高效、更稳定的数据获取方式,且支持客户端自定义字段选择和排序
  2. 【关键补全】网页自动化下载后写入飞书:当前ERP报表任务编辑界面虽有"导出后自动写入飞书多维表"勾选框和"目标凭据"下拉框,但执行器 _write_to_feishu 方法只是占位代码(在erp_tasks.json里错误查找飞书凭据、sync_task缺少目标表/视图/字段映射/去重配置),实际无法执行。本次改造补全完整链路:UI侧增加目标多维表/数据表/视图选择、写入模式、字段映射、去重配置;执行侧重写为读取本地xlsx→DataFrame→统一写入飞书
  3. 四种输出模式:仅下载本地 / 仅写入飞书(API独有)/ 下载+写入飞书 / 纯本地同步任务(已有功能不受影响)
  4. 目标平台适配器接口预留:为钉钉多维表等未来扩展预留抽象接口

改造范围

本版本为次版本号+1(v4.0.x → v4.1.0),属于新增功能发布。涉及10个Task的完整改造,覆盖凭据管理、API客户端、字段映射、下载器、UI配置、执行器分发、飞书写入、目标平台适配器等全链路。

改动文件清单

文件类型改动内容
credentials_manager.py修改新增 PLATFORM_LINGXING_API="领星API" 平台常量和 TYPE_LINGXING_API="lingxing_api" 凭据类型;扩展凭据存储结构支持 app_id + app_secret(Fernet加密);支持管理员预置内部版凭据(lingxing_api_credentials.enc)
tabs/credentials_tab.py修改平台筛选下拉框新增"领星API"选项;新增领星API凭据添加/编辑对话框(App ID输入框 + App Secret密码型输入框);测试连接调用 LingxingAPIClient.get_access_token() 验证
erp/lingxing_api_client.py新建LingxingAPIClient 类:get_access_token()认证(签名算法:参数排序→MD5大写→AES/ECB/PKCS5加密→Base64);_request()统一请求封装(域名openapi.lingxing.com,签名计算,错误处理,重试3次);fetch_replenishment_advice()补货建议分页获取;fetch_local_inventory()本地库存分页获取;get_report_fields()字段列表获取
erp/lingxing_field_mapping.py新建FIELD_MAPPING 字典(API字段名↔Excel列名映射);get_excel_field_name() API字段名转Excel列名;get_all_fields() 返回报表全部字段(含默认选中状态,参考report_config.py的default_columns)
erp/lingxing_api_downloader.py新建LingxingAPIDownloader 类:fetch_data(task)→DataFrame(调用API→字段映射→筛选列→排序列);save_to_xlsx(df, task)→str(复用现有命名逻辑);get_available_fields(report_type)→list(代理调用API客户端)
tabs/erp_report_tab.py修改API配置区(row=5):刷新字段列表按钮 + 字段勾选Treeview(选中列+字段名列)+ 上移/下移按钮 + 维度选择 + 隐藏0库存复选框;toggle_api_config()根据method_var显示/隐藏;输出模式与飞书目标配置区:移除旧post_action区域,新增输出模式下拉框(API方式3选项/网页自动化2选项)+ 飞书目标配置(凭据选择→多维表Token→数据表→视图→写入模式→字段映射→去重配置);字段映射对话框(左侧报表字段,右侧飞书字段,手动配对);去重配置(启用勾选框+去重字段多选Listbox);数据结构迁移(加载旧任务时post_action→output_mode+feishu_target);所有飞书API调用在daemon子线程中执行
core/erp_executor.py修改新增_resolve_output_mode(task)辅助方法(解析output_mode,兼容旧任务post_action);重写_execute_lingxing_api(task, credential)(API方式执行+output_mode分发);重写_execute_lingxing_web(task, credential)(网页自动化下载后根据output_mode分发,不支持feishu_only自动调整为download_and_feishu);新增_write_df_to_feishu(df, task)统一写入方法(字段映射→records转换→write_mode执行→去重);删除旧的_write_to_feishu(file_path, post_action)占位方法
utils/target_adapter.py新建TargetAdapter抽象基类(7个抽象方法:connect/get_tables/get_fields/get_views/write_records/delete_records/get_all_records);FeishuAdapter实现(封装FeishuAPI);create_adapter工厂函数;DingTalkAdapter预留(注释形式)
gui_sync.py修改版本号 4.0.18→4.1.0
config/erp_tasks.json数据结构扩展新增 api_config、output_mode、feishu_target 字段;废弃 post_action 字段(加载时自动迁移)

技术要点

  1. 领星API认证流程:Token获取(POST multipart/form-data,参数appId+appSecret)→ 签名算法(参数排序→MD5大写→AES/ECB/PKCS5加密,key=appId,16字节不补齐→Base64)→ 公共参数(app_key/access_token/timestamp/sign)放query string,业务参数放JSON body
  2. 数据结构迁移设计post_action(write_to_feishu + feishu_credential_name)→ output_mode(download_only/feishu_only/download_and_feishu)+ feishu_target(target_platform/credential_id/app_token/table_id/view_id/write_mode/field_mapping/dedup_enabled/dedup_fields)。加载旧任务时自动迁移:post_action.write_to_feishu=true → output_mode="download_and_feishu";feishu_credential_name → 按名称查找credential_id填入feishu_target(其余子字段置空待用户补填)
  3. 四种输出模式架构:API方式支持全部3种(download_only/feishu_only/download_and_feishu),网页自动化方式支持2种(不支持feishu_only,因必须先下载到本地)。统一写入入口 _write_df_to_feishu(df, task) 方法,API直写和网页自动化下载后写入共用
  4. 执行器分发架构:根据export_method(api/web)分发到不同下载器(LingxingAPIDownloader / LingxingDownloader),再根据output_mode决定输出方式。网页自动化方式的feishu_only自动调整为download_and_feishu并记录WARN日志
  5. 字段映射设计:API返回的嵌套路径(点号表示如basic_info.asin)→ Excel列名(中文如ASIN/可售数量)。_get_nested_value()处理嵌套取值。维护两个报表(补货建议/本地库存)的映射表,领星更新字段时需同步更新
  6. 统一飞书写入流程:_write_df_to_feishu(df, task) → 获取feishu_target配置 → get_credential_by_id获取飞书凭据 → build_api_from_credential创建API实例 → 按field_mapping重命名DataFrame列名 → 复用SyncTaskExecutor._convert_to_records转换 → write_mode="delete_add"先删除视图全部记录再写入 / "add_only"仅追加 → dedup_enabled=True时按dedup_fields查询并删除重复记录再写入
  7. Tkinter UI动态切换:使用grid_remove()/grid()切换显示区域,控件位置不跳动。飞书API获取数据表/视图/字段列表在daemon线程中执行,通过dialog.after(0, callback)回调更新UI,避免阻塞主线程
  8. 目标平台适配器模式:抽象基类TargetAdapter定义统一接口(7个抽象方法),FeishuAdapter封装FeishuAPI。create_adapter工厂函数根据target_platform创建实例。未来扩展钉钉只需新增DingTalkAdapter子类,无需修改调用方代码

验证结果

  • 语法检查:所有新建和修改的 .py 文件通过 py_compile 语法检查
  • 导入测试:from erp.lingxing_api_client import LingxingAPIClientfrom erp.lingxing_api_downloader import LingxingAPIDownloaderfrom erp.lingxing_field_mapping import get_all_fieldsfrom utils.target_adapter import TargetAdapter, FeishuAdapter, create_adapter 均导入成功
  • UI实现验证:tabs/erp_report_tab.py 中 api_config_frame、toggle_api_config、refresh_fields、move_up/move_down、on_field_click、字段勾选Treeview、加载旧任务API配置等关键功能完整实现
  • 适配器实现验证:utils/target_adapter.py 包含 TargetAdapter抽象基类(7个抽象方法)、FeishuAdapter实现(封装7个方法)、create_adapter工厂函数、DingTalkAdapter预留
  • 执行器实现验证:core/erp_executor.py 中 _resolve_output_mode、_execute_lingxing_api、_execute_lingxing_web、_write_df_to_feishu 方法完整实现,旧 _write_to_feishu 已删除

踩坑与解决

  • FeishuAPI方法名差异:Task 9+10实现时发现FeishuAPI的实际方法名是 add_records/delete_records/get_all_records(非任务描述中的batch_create/batch_delete/search_records),已使用正确的方法名
  • erp_report_tab.py row编号冲突:Task 7修改时该文件已被Task 8修改过。通过先读取文件了解当前结构,调整row编号避免冲突(保存路径5→6,文件命名6→7,输出模式7→8,定时计划8→9,按钮9→10)
  • 网页自动化方式不支持feishu_only:网页自动化必须先下载到本地文件,不支持API直写。执行器中自动将feishu_only调整为download_and_feishu并记录WARN日志

下一阶段规划

  • Task 5+6 数据一致性验证:需要用户参与,对比同一时间点API下载与网页自动化下载的字段标题和核心数据值,确认字段映射表正确性(暂缓,待用户安排)
  • 本地库存API路径确认:补货建议API(query_fba_valid_list)已确认,本地库存明细的具体API路径需在实现阶段通过API文档进一步确认
  • 钉钉多维表扩展:当有钉钉同步需求时,实现DingTalkAdapter子类,UI上显示目标平台选择