diff --git a/张阳脚本/F6汽车系统/云材料信息拉取.ipynb b/张阳脚本/F6汽车系统/云材料信息拉取.ipynb index 5e5a66e..b87e688 100644 --- a/张阳脚本/F6汽车系统/云材料信息拉取.ipynb +++ b/张阳脚本/F6汽车系统/云材料信息拉取.ipynb @@ -2,14 +2,32 @@ "cells": [ { "cell_type": "code", + "execution_count": 1, "id": "initial_id", "metadata": { - "collapsed": true, "ExecuteTime": { "end_time": "2026-01-22T03:01:15.515786400Z", "start_time": "2026-01-22T03:01:12.175041100Z" - } + }, + "collapsed": true }, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'C:\\\\Users\\\\zy187\\\\Desktop\\\\钉钉文件\\\\失败项目材料(1).xlsx'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mFileNotFoundError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 38\u001b[39m\n\u001b[32m 36\u001b[39m all_data = []\n\u001b[32m 37\u001b[39m fild_data = []\n\u001b[32m---> \u001b[39m\u001b[32m38\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_excel\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msheet_name\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mSheet1\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 39\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m index, row \u001b[38;5;129;01min\u001b[39;00m tqdm(df.iterrows(), total=\u001b[38;5;28mlen\u001b[39m(df), desc=\u001b[33m\"\u001b[39m\u001b[33m处理中\u001b[39m\u001b[33m\"\u001b[39m, leave=\u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[32m 40\u001b[39m json_data = {\n\u001b[32m 41\u001b[39m \u001b[33m'\u001b[39m\u001b[33mkeyword\u001b[39m\u001b[33m'\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33m凤凰\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 42\u001b[39m \u001b[33m'\u001b[39m\u001b[33mtype\u001b[39m\u001b[33m'\u001b[39m: \u001b[32m0\u001b[39m,\n\u001b[32m (...)\u001b[39m\u001b[32m 54\u001b[39m \u001b[33m'\u001b[39m\u001b[33mcurrentPage\u001b[39m\u001b[33m'\u001b[39m: \u001b[32m1\u001b[39m,\n\u001b[32m 55\u001b[39m }\n", + "\u001b[36mFile \u001b[39m\u001b[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:495\u001b[39m, in \u001b[36mread_excel\u001b[39m\u001b[34m(io, sheet_name, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, date_format, thousands, decimal, comment, skipfooter, storage_options, dtype_backend, engine_kwargs)\u001b[39m\n\u001b[32m 493\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(io, ExcelFile):\n\u001b[32m 494\u001b[39m should_close = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m495\u001b[39m io = \u001b[43mExcelFile\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 496\u001b[39m \u001b[43m \u001b[49m\u001b[43mio\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 497\u001b[39m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m=\u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 498\u001b[39m \u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\u001b[43m=\u001b[49m\u001b[43mengine\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 499\u001b[39m \u001b[43m \u001b[49m\u001b[43mengine_kwargs\u001b[49m\u001b[43m=\u001b[49m\u001b[43mengine_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 500\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 501\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;129;01mand\u001b[39;00m engine != io.engine:\n\u001b[32m 502\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 503\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mEngine should not be specified when passing \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 504\u001b[39m \u001b[33m\"\u001b[39m\u001b[33man ExcelFile - ExcelFile already has the engine set\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 505\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:1550\u001b[39m, in \u001b[36mExcelFile.__init__\u001b[39m\u001b[34m(self, path_or_buffer, engine, storage_options, engine_kwargs)\u001b[39m\n\u001b[32m 1548\u001b[39m ext = \u001b[33m\"\u001b[39m\u001b[33mxls\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 1549\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m-> \u001b[39m\u001b[32m1550\u001b[39m ext = \u001b[43minspect_excel_format\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 1551\u001b[39m \u001b[43m \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[43m=\u001b[49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m=\u001b[49m\u001b[43mstorage_options\u001b[49m\n\u001b[32m 1552\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1553\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m ext \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 1554\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 1555\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mExcel file format cannot be determined, you must specify \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 1556\u001b[39m \u001b[33m\"\u001b[39m\u001b[33man engine manually.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 1557\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:1402\u001b[39m, in \u001b[36minspect_excel_format\u001b[39m\u001b[34m(content_or_path, storage_options)\u001b[39m\n\u001b[32m 1399\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(content_or_path, \u001b[38;5;28mbytes\u001b[39m):\n\u001b[32m 1400\u001b[39m content_or_path = BytesIO(content_or_path)\n\u001b[32m-> \u001b[39m\u001b[32m1402\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 1403\u001b[39m \u001b[43m \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mrb\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m=\u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mis_text\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\n\u001b[32m 1404\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handle:\n\u001b[32m 1405\u001b[39m stream = handle.handle\n\u001b[32m 1406\u001b[39m stream.seek(\u001b[32m0\u001b[39m)\n", + "\u001b[36mFile \u001b[39m\u001b[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\common.py:882\u001b[39m, in \u001b[36mget_handle\u001b[39m\u001b[34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[39m\n\u001b[32m 873\u001b[39m handle = \u001b[38;5;28mopen\u001b[39m(\n\u001b[32m 874\u001b[39m handle,\n\u001b[32m 875\u001b[39m ioargs.mode,\n\u001b[32m (...)\u001b[39m\u001b[32m 878\u001b[39m newline=\u001b[33m\"\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 879\u001b[39m )\n\u001b[32m 880\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 881\u001b[39m \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m882\u001b[39m handle = \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mioargs\u001b[49m\u001b[43m.\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 883\u001b[39m handles.append(handle)\n\u001b[32m 885\u001b[39m \u001b[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001b[39;00m\n", + "\u001b[31mFileNotFoundError\u001b[39m: [Errno 2] No such file or directory: 'C:\\\\Users\\\\zy187\\\\Desktop\\\\钉钉文件\\\\失败项目材料(1).xlsx'" + ] + } + ], "source": [ "import time\n", "\n", @@ -100,40 +118,42 @@ "ndf.to_excel(fr\"C:\\Users\\zy187\\Desktop\\云材料结果2.xlsx\")\n", "fdf = pd.DataFrame(fild_data)\n", "fdf.to_excel(fr\"C:\\Users\\zy187\\Desktop\\失败项目材料2.xlsx\")" - ], - "outputs": [ - { - "ename": "FileNotFoundError", - "evalue": "[Errno 2] No such file or directory: 'C:\\\\Users\\\\zy187\\\\Desktop\\\\钉钉文件\\\\失败项目材料(1).xlsx'", - "output_type": "error", - "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mFileNotFoundError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[1]\u001B[39m\u001B[32m, line 38\u001B[39m\n\u001B[32m 36\u001B[39m all_data = []\n\u001B[32m 37\u001B[39m fild_data = []\n\u001B[32m---> \u001B[39m\u001B[32m38\u001B[39m df = \u001B[43mpd\u001B[49m\u001B[43m.\u001B[49m\u001B[43mread_excel\u001B[49m\u001B[43m(\u001B[49m\u001B[43mpath\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43msheet_name\u001B[49m\u001B[43m=\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mSheet1\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[32m 39\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m index, row \u001B[38;5;129;01min\u001B[39;00m tqdm(df.iterrows(), total=\u001B[38;5;28mlen\u001B[39m(df), desc=\u001B[33m\"\u001B[39m\u001B[33m处理中\u001B[39m\u001B[33m\"\u001B[39m, leave=\u001B[38;5;28;01mFalse\u001B[39;00m):\n\u001B[32m 40\u001B[39m json_data = {\n\u001B[32m 41\u001B[39m \u001B[33m'\u001B[39m\u001B[33mkeyword\u001B[39m\u001B[33m'\u001B[39m: \u001B[33m\"\u001B[39m\u001B[33m凤凰\u001B[39m\u001B[33m\"\u001B[39m,\n\u001B[32m 42\u001B[39m \u001B[33m'\u001B[39m\u001B[33mtype\u001B[39m\u001B[33m'\u001B[39m: \u001B[32m0\u001B[39m,\n\u001B[32m (...)\u001B[39m\u001B[32m 54\u001B[39m \u001B[33m'\u001B[39m\u001B[33mcurrentPage\u001B[39m\u001B[33m'\u001B[39m: \u001B[32m1\u001B[39m,\n\u001B[32m 55\u001B[39m }\n", - "\u001B[36mFile \u001B[39m\u001B[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:495\u001B[39m, in \u001B[36mread_excel\u001B[39m\u001B[34m(io, sheet_name, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, date_format, thousands, decimal, comment, skipfooter, storage_options, dtype_backend, engine_kwargs)\u001B[39m\n\u001B[32m 493\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(io, ExcelFile):\n\u001B[32m 494\u001B[39m should_close = \u001B[38;5;28;01mTrue\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m495\u001B[39m io = \u001B[43mExcelFile\u001B[49m\u001B[43m(\u001B[49m\n\u001B[32m 496\u001B[39m \u001B[43m \u001B[49m\u001B[43mio\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 497\u001B[39m \u001B[43m \u001B[49m\u001B[43mstorage_options\u001B[49m\u001B[43m=\u001B[49m\u001B[43mstorage_options\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 498\u001B[39m \u001B[43m \u001B[49m\u001B[43mengine\u001B[49m\u001B[43m=\u001B[49m\u001B[43mengine\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 499\u001B[39m \u001B[43m \u001B[49m\u001B[43mengine_kwargs\u001B[49m\u001B[43m=\u001B[49m\u001B[43mengine_kwargs\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 500\u001B[39m \u001B[43m \u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 501\u001B[39m \u001B[38;5;28;01melif\u001B[39;00m engine \u001B[38;5;129;01mand\u001B[39;00m engine != io.engine:\n\u001B[32m 502\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\n\u001B[32m 503\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mEngine should not be specified when passing \u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 504\u001B[39m \u001B[33m\"\u001B[39m\u001B[33man ExcelFile - ExcelFile already has the engine set\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 505\u001B[39m )\n", - "\u001B[36mFile \u001B[39m\u001B[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:1550\u001B[39m, in \u001B[36mExcelFile.__init__\u001B[39m\u001B[34m(self, path_or_buffer, engine, storage_options, engine_kwargs)\u001B[39m\n\u001B[32m 1548\u001B[39m ext = \u001B[33m\"\u001B[39m\u001B[33mxls\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 1549\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1550\u001B[39m ext = \u001B[43minspect_excel_format\u001B[49m\u001B[43m(\u001B[49m\n\u001B[32m 1551\u001B[39m \u001B[43m \u001B[49m\u001B[43mcontent_or_path\u001B[49m\u001B[43m=\u001B[49m\u001B[43mpath_or_buffer\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mstorage_options\u001B[49m\u001B[43m=\u001B[49m\u001B[43mstorage_options\u001B[49m\n\u001B[32m 1552\u001B[39m \u001B[43m \u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1553\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m ext \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[32m 1554\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\n\u001B[32m 1555\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mExcel file format cannot be determined, you must specify \u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 1556\u001B[39m \u001B[33m\"\u001B[39m\u001B[33man engine manually.\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 1557\u001B[39m )\n", - "\u001B[36mFile \u001B[39m\u001B[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:1402\u001B[39m, in \u001B[36minspect_excel_format\u001B[39m\u001B[34m(content_or_path, storage_options)\u001B[39m\n\u001B[32m 1399\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(content_or_path, \u001B[38;5;28mbytes\u001B[39m):\n\u001B[32m 1400\u001B[39m content_or_path = BytesIO(content_or_path)\n\u001B[32m-> \u001B[39m\u001B[32m1402\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m \u001B[43mget_handle\u001B[49m\u001B[43m(\u001B[49m\n\u001B[32m 1403\u001B[39m \u001B[43m \u001B[49m\u001B[43mcontent_or_path\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mrb\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mstorage_options\u001B[49m\u001B[43m=\u001B[49m\u001B[43mstorage_options\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mis_text\u001B[49m\u001B[43m=\u001B[49m\u001B[38;5;28;43;01mFalse\u001B[39;49;00m\n\u001B[32m 1404\u001B[39m \u001B[43m\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;28;01mas\u001B[39;00m handle:\n\u001B[32m 1405\u001B[39m stream = handle.handle\n\u001B[32m 1406\u001B[39m stream.seek(\u001B[32m0\u001B[39m)\n", - "\u001B[36mFile \u001B[39m\u001B[32mD:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\pandas\\io\\common.py:882\u001B[39m, in \u001B[36mget_handle\u001B[39m\u001B[34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001B[39m\n\u001B[32m 873\u001B[39m handle = \u001B[38;5;28mopen\u001B[39m(\n\u001B[32m 874\u001B[39m handle,\n\u001B[32m 875\u001B[39m ioargs.mode,\n\u001B[32m (...)\u001B[39m\u001B[32m 878\u001B[39m newline=\u001B[33m\"\u001B[39m\u001B[33m\"\u001B[39m,\n\u001B[32m 879\u001B[39m )\n\u001B[32m 880\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 881\u001B[39m \u001B[38;5;66;03m# Binary mode\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m882\u001B[39m handle = \u001B[38;5;28;43mopen\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mhandle\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mioargs\u001B[49m\u001B[43m.\u001B[49m\u001B[43mmode\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 883\u001B[39m handles.append(handle)\n\u001B[32m 885\u001B[39m \u001B[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001B[39;00m\n", - "\u001B[31mFileNotFoundError\u001B[39m: [Errno 2] No such file or directory: 'C:\\\\Users\\\\zy187\\\\Desktop\\\\钉钉文件\\\\失败项目材料(1).xlsx'" - ] - } - ], - "execution_count": 1 + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "# 关键字搜索", - "id": "713d0645f9b5b8b0" + "id": "713d0645f9b5b8b0", + "metadata": {}, + "source": [ + "# 关键字搜索" + ] }, { + "cell_type": "code", + "execution_count": 1, + "id": "56303413fee1137", "metadata": { "ExecuteTime": { "end_time": "2026-01-22T03:07:17.414079900Z", "start_time": "2026-01-22T03:04:41.187628900Z" } }, - "cell_type": "code", + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7ad7a6cd83cf4722a92c3fd9dc6e56a9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00:63: SyntaxWarning: invalid escape sequence '\\I'\n", + "<>:63: SyntaxWarning: invalid escape sequence '\\I'\n", + "C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_121996\\604757537.py:63: SyntaxWarning: invalid escape sequence '\\I'\n", + " ndf.to_csv(\"D:\\Idea Project\\F6+宜搭+其它(1)\\张阳脚本\\文件输出\\积分客户信息.csv\")\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "83db9b6e459a433b87f544bf500d790a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/474 [00:00:64: SyntaxWarning: invalid escape sequence '\\I'\n", + "<>:66: SyntaxWarning: invalid escape sequence '\\I'\n", + "<>:64: SyntaxWarning: invalid escape sequence '\\I'\n", + "<>:66: SyntaxWarning: invalid escape sequence '\\I'\n", + "C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_31008\\3622255126.py:64: SyntaxWarning: invalid escape sequence '\\I'\n", + " df2.to_csv(\"D:\\Idea Project\\F6+宜搭+其它(1)\\张阳脚本\\文件输出\\积分客户信息结果8.csv\")\n", + "C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_31008\\3622255126.py:66: SyntaxWarning: invalid escape sequence '\\I'\n", + " df3.to_csv(\"D:\\Idea Project\\F6+宜搭+其它(1)\\张阳脚本\\文件输出\\报错信息.csv\")\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "99d3daa2c80c445f9884d1a5dc392195", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/2845 [00:00= MAX_CONSECUTIVE_FAILURES:\n", + " results.append({'材料编码': '系统保护', '状态': '连续100次失败已终止'})\n", + " print(f\"连续失败{MAX_CONSECUTIVE_FAILURES}次,已中止任务执行\")\n", + " break\n", + " continue\n", + "\n", + " try:\n", + " # 获取材料明细\n", + " params = {\n", + " 'partId': part_id,\n", + " 'customInvoiceCategory': '0',\n", + " 'getThirdPlatformCode': '0',\n", + " }\n", + " materials_response = requests.get(\n", + " 'https://ids-goods.f6car.com/f6-ids-goods/part/getPartInfo',\n", + " params=params,\n", + " cookies=cookies,\n", + " )\n", + " time.sleep(1)\n", + " if materials_response.status_code != 200:\n", + " error_msg = f'获取明细失败: {materials_response.status_code}'\n", + " results.append({'材料编码': custom_code, '状态': error_msg})\n", + " failure_count += 1\n", + " consecutive_failures += 1\n", + " print(f\"材料编码 {custom_code} {error_msg}, 响应内容: {materials_response.text[:200]}\")\n", + " if consecutive_failures >= MAX_CONSECUTIVE_FAILURES:\n", + " results.append({'材料编码': '系统保护', '状态': '连续100次失败已终止'})\n", + " print(f\"连续失败{MAX_CONSECUTIVE_FAILURES}次,已中止任务执行\")\n", + " break\n", + " continue\n", + "\n", + " detail = materials_response.json().get(\"data\")\n", + " if not detail:\n", + " error_msg = '明细为空'\n", + " results.append({'材料编码': custom_code, '状态': error_msg})\n", + " failure_count += 1\n", + " consecutive_failures += 1\n", + " print(f\"材料编码 {custom_code} {error_msg}, 响应JSON: {materials_response.json()}\")\n", + " if consecutive_failures >= MAX_CONSECUTIVE_FAILURES:\n", + " results.append({'材料编码': '系统保护', '状态': '连续100次失败已终止'})\n", + " print(f\"连续失败{MAX_CONSECUTIVE_FAILURES}次,已中止任务执行\")\n", + " break\n", + " continue\n", + "\n", + " updates = update_map[str(custom_code)]\n", + " import time\n", + "\n", + " # 获取当前时间戳(秒),乘以1000转为毫秒,并取整\n", + " timestamp_ms = int(time.time() * 1000)\n", + "\n", + " # 安全更新字段:仅当 Excel 提供有效值时才覆盖\n", + " if should_update(updates[\"材料条码\"]):\n", + " detail[\"partBarCodeVos\"] = [\n", + " {\n", + " 'barCode': safe_str(updates[\"材料条码\"]),\n", + " 'barId': None,\n", + " 'createTime': timestamp_ms,\n", + " 'creator': '15865484595890778191',\n", + " 'groupId': None,\n", + " 'infoId': '14582097883364187448',\n", + " 'isDel': 0,\n", + " 'modifier': '15865484595890778191',\n", + " 'modifyTime': timestamp_ms,\n", + " },\n", + " ]\n", + " # 修复价格格式和数组(必须!)\n", + " for f in [\"purchasePrice\", \"sellPrice\"]:\n", + " val = detail.get(f)\n", + " if isinstance(val, (int, float)):\n", + " detail[f] = f\"{val:.2f}\"\n", + " if detail.get(\"partBarCodeVos\") is None:\n", + " detail[\"partBarCodeVos\"] = []\n", + "\n", + " # 提交更新\n", + " update_resp = requests.post(\n", + " 'https://ids-goods.f6car.com/f6-ids-goods/part/updateAreaPartBasicInfo',\n", + " cookies=cookies,\n", + " json=detail\n", + " )\n", + " time.sleep(2)\n", + "\n", + " if update_resp.status_code == 200 and update_resp.json().get(\"code\") == 200:\n", + " results.append({'材料编码': custom_code, '状态': '修改成功'})\n", + " success_count += 1\n", + " consecutive_failures = 0 # 成功时重置计数器\n", + " else:\n", + " msg = update_resp.json().get(\"message\", \"未知错误\")\n", + " error_msg = f'修改失败: {msg}'\n", + " results.append({'材料编码': custom_code, '状态': error_msg})\n", + " failure_count += 1\n", + " consecutive_failures += 1\n", + " print(f\"材料编码 {custom_code} {error_msg}, 响应数据: {update_resp.json()}\")\n", + "\n", + " except requests.exceptions.RequestException as e:\n", + " error_msg = f'请求异常: {str(e)}'\n", + " results.append({'材料编码': custom_code, '状态': error_msg})\n", + " failure_count += 1\n", + " consecutive_failures += 1\n", + " print(f\"材料编码 {custom_code} {error_msg}, 堆栈信息: {traceback.format_exc()}\")\n", + " except Exception as e:\n", + " error_msg = f'内部错误: {str(e)}'\n", + " results.append({'材料编码': custom_code, '状态': error_msg})\n", + " failure_count += 1\n", + " consecutive_failures += 1\n", + " print(f\"材料编码 {custom_code} {error_msg}, 堆栈信息: {traceback.format_exc()}\")\n", + " # 检查连续失败次数\n", + " if consecutive_failures >= MAX_CONSECUTIVE_FAILURES:\n", + " results.append({'材料编码': '系统保护', '状态': '连续100次失败已终止'})\n", + " print(f\"连续失败{MAX_CONSECUTIVE_FAILURES}次,已中止任务执行\")\n", + " break\n", + "\n", + "# 统计汇总(总行数 / 待处理 / 成功 / 失败 / 跳过)\n", + "total_rows = len(df)\n", + "to_process = len(update_map)\n", + "# results 里可能包含 “缺少 partId” 等失败信息;这里跳过数按空编码行计数即可\n", + "skip_count = skipped_count\n", + "summary = {\n", + " \"总行数\": total_rows,\n", + " \"待处理\": to_process,\n", + " \"成功\": success_count,\n", + " \"失败\": failure_count,\n", + " \"跳过\": skip_count,\n", + "}\n", + "results.insert(0, {\"汇总\": summary})\n", + "print(f\"材料修改汇总: {summary}\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "材料列表页数: 10\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "获取材料列表: 100%|██████████| 10/10 [00:15<00:00, 1.55s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "材料列表获取完成,总计: 922条\n", + "待更新材料数: 813,跳过空编码行: 0\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "处理材料更新: 39%|███▉ | 360/922 [16:41<39:48, 4.25s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "材料编码 CL0000564 请求异常: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None)), 堆栈信息: Traceback (most recent call last):\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 773, in urlopen\n", + " self._prepare_proxy(conn)\n", + " ~~~~~~~~~~~~~~~~~~~^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 1042, in _prepare_proxy\n", + " conn.connect()\n", + " ~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 796, in connect\n", + " sock_and_verified = _ssl_wrap_socket_and_match_hostname(\n", + " sock=sock,\n", + " ...<14 lines>...\n", + " assert_fingerprint=self.assert_fingerprint,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 975, in _ssl_wrap_socket_and_match_hostname\n", + " ssl_sock = ssl_wrap_socket(\n", + " sock=sock,\n", + " ...<8 lines>...\n", + " tls_in_tls=tls_in_tls,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 483, in ssl_wrap_socket\n", + " ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 527, in _ssl_wrap_socket_impl\n", + " return ssl_context.wrap_socket(sock, server_hostname=server_hostname)\n", + " ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 455, in wrap_socket\n", + " return self.sslsocket_class._create(\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n", + " sock=sock,\n", + " ^^^^^^^^^^\n", + " ...<5 lines>...\n", + " session=session\n", + " ^^^^^^^^^^^^^^^\n", + " )\n", + " ^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1076, in _create\n", + " self.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1372, in do_handshake\n", + " self._sslobj.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~^^\n", + "ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\adapters.py\", line 644, in send\n", + " resp = conn.urlopen(\n", + " method=request.method,\n", + " ...<9 lines>...\n", + " chunked=chunked,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 841, in urlopen\n", + " retries = retries.increment(\n", + " method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\retry.py\", line 474, in increment\n", + " raise reraise(type(error), error, _stacktrace)\n", + " ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\util.py\", line 38, in reraise\n", + " raise value.with_traceback(tb)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 773, in urlopen\n", + " self._prepare_proxy(conn)\n", + " ~~~~~~~~~~~~~~~~~~~^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 1042, in _prepare_proxy\n", + " conn.connect()\n", + " ~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 796, in connect\n", + " sock_and_verified = _ssl_wrap_socket_and_match_hostname(\n", + " sock=sock,\n", + " ...<14 lines>...\n", + " assert_fingerprint=self.assert_fingerprint,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 975, in _ssl_wrap_socket_and_match_hostname\n", + " ssl_sock = ssl_wrap_socket(\n", + " sock=sock,\n", + " ...<8 lines>...\n", + " tls_in_tls=tls_in_tls,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 483, in ssl_wrap_socket\n", + " ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 527, in _ssl_wrap_socket_impl\n", + " return ssl_context.wrap_socket(sock, server_hostname=server_hostname)\n", + " ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 455, in wrap_socket\n", + " return self.sslsocket_class._create(\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n", + " sock=sock,\n", + " ^^^^^^^^^^\n", + " ...<5 lines>...\n", + " session=session\n", + " ^^^^^^^^^^^^^^^\n", + " )\n", + " ^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1076, in _create\n", + " self.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1372, in do_handshake\n", + " self._sslobj.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~^^\n", + "urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_105196\\2551472138.py\", line 155, in \n", + " materials_response = requests.get(\n", + " 'https://ids-goods.f6car.com/f6-ids-goods/part/getPartInfo',\n", + " params=params,\n", + " cookies=cookies,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\api.py\", line 73, in get\n", + " return request(\"get\", url, params=params, **kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\api.py\", line 59, in request\n", + " return session.request(method=method, url=url, **kwargs)\n", + " ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\sessions.py\", line 589, in request\n", + " resp = self.send(prep, **send_kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\sessions.py\", line 703, in send\n", + " r = adapter.send(request, **kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\adapters.py\", line 659, in send\n", + " raise ConnectionError(err, request=request)\n", + "requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "处理材料更新: 53%|█████▎ | 486/922 [25:00<31:25, 4.32s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "材料编码 CL0000457 请求异常: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None)), 堆栈信息: Traceback (most recent call last):\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 773, in urlopen\n", + " self._prepare_proxy(conn)\n", + " ~~~~~~~~~~~~~~~~~~~^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 1042, in _prepare_proxy\n", + " conn.connect()\n", + " ~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 796, in connect\n", + " sock_and_verified = _ssl_wrap_socket_and_match_hostname(\n", + " sock=sock,\n", + " ...<14 lines>...\n", + " assert_fingerprint=self.assert_fingerprint,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 975, in _ssl_wrap_socket_and_match_hostname\n", + " ssl_sock = ssl_wrap_socket(\n", + " sock=sock,\n", + " ...<8 lines>...\n", + " tls_in_tls=tls_in_tls,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 483, in ssl_wrap_socket\n", + " ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 527, in _ssl_wrap_socket_impl\n", + " return ssl_context.wrap_socket(sock, server_hostname=server_hostname)\n", + " ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 455, in wrap_socket\n", + " return self.sslsocket_class._create(\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n", + " sock=sock,\n", + " ^^^^^^^^^^\n", + " ...<5 lines>...\n", + " session=session\n", + " ^^^^^^^^^^^^^^^\n", + " )\n", + " ^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1076, in _create\n", + " self.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1372, in do_handshake\n", + " self._sslobj.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~^^\n", + "ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\adapters.py\", line 644, in send\n", + " resp = conn.urlopen(\n", + " method=request.method,\n", + " ...<9 lines>...\n", + " chunked=chunked,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 841, in urlopen\n", + " retries = retries.increment(\n", + " method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\retry.py\", line 474, in increment\n", + " raise reraise(type(error), error, _stacktrace)\n", + " ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\util.py\", line 38, in reraise\n", + " raise value.with_traceback(tb)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 773, in urlopen\n", + " self._prepare_proxy(conn)\n", + " ~~~~~~~~~~~~~~~~~~~^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connectionpool.py\", line 1042, in _prepare_proxy\n", + " conn.connect()\n", + " ~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 796, in connect\n", + " sock_and_verified = _ssl_wrap_socket_and_match_hostname(\n", + " sock=sock,\n", + " ...<14 lines>...\n", + " assert_fingerprint=self.assert_fingerprint,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\connection.py\", line 975, in _ssl_wrap_socket_and_match_hostname\n", + " ssl_sock = ssl_wrap_socket(\n", + " sock=sock,\n", + " ...<8 lines>...\n", + " tls_in_tls=tls_in_tls,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 483, in ssl_wrap_socket\n", + " ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\urllib3\\util\\ssl_.py\", line 527, in _ssl_wrap_socket_impl\n", + " return ssl_context.wrap_socket(sock, server_hostname=server_hostname)\n", + " ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 455, in wrap_socket\n", + " return self.sslsocket_class._create(\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n", + " sock=sock,\n", + " ^^^^^^^^^^\n", + " ...<5 lines>...\n", + " session=session\n", + " ^^^^^^^^^^^^^^^\n", + " )\n", + " ^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1076, in _create\n", + " self.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\ssl.py\", line 1372, in do_handshake\n", + " self._sslobj.do_handshake()\n", + " ~~~~~~~~~~~~~~~~~~~~~~~~~^^\n", + "urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_105196\\2551472138.py\", line 155, in \n", + " materials_response = requests.get(\n", + " 'https://ids-goods.f6car.com/f6-ids-goods/part/getPartInfo',\n", + " params=params,\n", + " cookies=cookies,\n", + " )\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\api.py\", line 73, in get\n", + " return request(\"get\", url, params=params, **kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\api.py\", line 59, in request\n", + " return session.request(method=method, url=url, **kwargs)\n", + " ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\sessions.py\", line 589, in request\n", + " resp = self.send(prep, **send_kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\sessions.py\", line 703, in send\n", + " r = adapter.send(request, **kwargs)\n", + " File \"D:\\Program Files\\anaconda3\\envs\\F6+宜搭+其它\\Lib\\site-packages\\requests\\adapters.py\", line 659, in send\n", + " raise ConnectionError(err, request=request)\n", + "requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "处理材料更新: 100%|██████████| 922/922 [54:02<00:00, 3.52s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "材料修改汇总: {'总行数': 813, '待处理': 813, '成功': 811, '失败': 2, '跳过': 0}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-02-03T07:29:11.795586Z", + "start_time": "2026-02-03T07:29:11.747501600Z" + } + }, + "cell_type": "code", + "source": "", + "id": "b5c78eb02e2607ec", + "outputs": [ + { + "data": { + "text/plain": [ + "{'code': 400, 'message': '材料名称不能为空!'}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 4 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/张阳脚本/sql.sql b/张阳脚本/sql.sql new file mode 100644 index 0000000..6c2ae31 --- /dev/null +++ b/张阳脚本/sql.sql @@ -0,0 +1,128 @@ +SELECT + '{{%%p_start_date}}' AS 实际开始日期, + '{{%%p_end_date}}' AS 实际结束日期, + sos.id_storage AS 仓库id, + sos.storage_name AS 仓库名称, + sos.part_name AS 材料名称, + sos.custom_code AS 材料编码, + sos.supplier_code AS 零件号, + sos.category_root_name AS 材料一级分类, + sos.category_name AS 材料二级分类, + sos.part_brand AS 品牌, + /* ---------- 期初(begin_*:仅在开始日取值;>60天仅月初保留) ---------- */ + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_start_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> 1 + THEN 0 + WHEN sos.bill_day = '{{%%p_start_date}}' + THEN sos.begin_number + ELSE 0 + END + ) AS 期初在库数量, + + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_start_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> 1 + THEN 0 + WHEN sos.bill_day = '{{%%p_start_date}}' + THEN sos.begin_price + ELSE 0 + END + ) AS 期初在库成本, + + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_start_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> 1 + THEN 0 + WHEN sos.bill_day = '{{%%p_start_date}}' + THEN sos.begin_price_no_tax + ELSE 0 + END + ) AS 期初在库成本除税, + + /* ---------- 入库数量 ---------- */ + SUM(sos.cgdin_number) AS 采购入库数量, + SUM(sos.cgtin_number) AS 采购退货数量, + SUM(sos.drdin_number) AS 调入数量, + SUM(sos.rkdin_number) AS 手工入库数量, + SUM(sos.ykrin_number) AS 移库入库数量, + SUM(sos.czrin_number) AS 拆装入库数量, + + /* ---------- 入库成本(除税) ---------- */ + SUM(sos.cgdin_amount_no_tax) AS 采购入库成本(除税), + SUM(sos.cgtin_amount_no_tax) AS 采购退货成本(除税), + SUM(sos.drdin_amount_no_tax) AS 调拨入库成本(除税), + SUM(sos.rkdin_amount_no_tax) AS 手工入库成本(除税), + SUM(sos.ykrin_amount_no_tax) AS 移库入库成本(除税), + SUM(sos.czrin_amount_no_tax) AS 拆装入库成本(除税), + + /* ---------- 出库/退料相关数量 ---------- */ + SUM(sos.pickout_number) AS 领料出库数量, + SUM(sos.tin_number) AS 退料入库数量, + SUM(sos.dcdout_number) AS 调拨出库数量, + SUM(sos.ckdout_number) AS 手工出库数量, + SUM(sos.czcout_number) AS 拆装出库数量, + SUM(sos.ykcout_number) AS 移库出库数量, + + /* ---------- 出库/退料相关成本(除税) ---------- */ + SUM(sos.pickout_amount_no_tax) AS 领料出库成本(除税), + SUM(sos.tin_amount_no_tax) AS 退料入库成本(除税), + SUM(sos.dcdout_amount_no_tax) AS 调拨出库成本(除税), + SUM(sos.ckdout_amount_no_tax) AS 手工出库成本(除税), + SUM(sos.czcout_amount_no_tax) AS 拆装出库成本(除税), + SUM(sos.ykcout_amount_no_tax) AS 移库出库成本(除税), + + /* ---------- 期末(end_*:仅在结束日取值;>60天仅月末保留) ---------- */ + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_end_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> DAY(LAST_DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d'))) + THEN 0 + WHEN sos.bill_day = '{{%%p_end_date}}' + THEN sos.end_number + ELSE 0 + END + ) AS 期末在库数量, + + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_end_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> DAY(LAST_DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d'))) + THEN 0 + WHEN sos.bill_day = '{{%%p_end_date}}' + THEN sos.end_price + ELSE 0 + END + ) AS 期末在库成本, + + SUM( + CASE + WHEN DATEDIFF(CURRENT_DATE(), STR_TO_DATE('{{%%p_end_date}}', '%Y-%m-%d')) > 60 + AND DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d')) <> DAY(LAST_DAY(STR_TO_DATE(sos.bill_day, '%Y-%m-%d'))) + THEN 0 + WHEN sos.bill_day = '{{%%p_end_date}}' + THEN sos.end_price_no_tax + ELSE 0 + END + ) AS 期末在库成本除税 + +FROM rpt_customized_ndsd_storage_order_stat AS sos +WHERE 1=1 + /* ---------- 固定过滤条件(按你现有配置保留) ---------- */ + AND sos.id_own_group = '11240984669918396614' + AND sos.id_own_org IN ('11240984669918400634') + + /* ---------- 日期区间过滤(bill_day 为文本 YYYY-MM-DD) ---------- */ + AND sos.bill_day >= '{{%%p_start_date}}' + AND sos.bill_day <= '{{%%p_end_date}}' + +GROUP BY + sos.id_storage, + sos.part_name, + sos.custom_code, + sos.supplier_code, + sos.category_root_name, + sos.category_name; \ No newline at end of file diff --git a/张阳脚本/宜搭刷数据/批量更新脚本.py b/张阳脚本/宜搭刷数据/批量更新脚本.py index d9bb5ef..e2a9818 100644 --- a/张阳脚本/宜搭刷数据/批量更新脚本.py +++ b/张阳脚本/宜搭刷数据/批量更新脚本.py @@ -21,8 +21,8 @@ class Main: FORMID1 = "FORM-33666CB1XDU37AU57RKPK990C79S2YMOEEC8LS" # [表单]异常服务跟进待办2023 # 读取excel表格 - df = pd.read_excel(r"C:\Users\hp_z66\Desktop\钉钉文件\(流程)续约服务流程_20260129144824.xlsx", - sheet_name='Sheet1', dtype='string', header=1) # 此处将表头设置为了第二行 + df = pd.read_excel(r"C:\Users\hp_z66\OneDrive\Desktop\钉钉文件\2026-1回访已回访.xlsx", + sheet_name='Sheet5', dtype='string', header=1) # 此处将表头设置为了第二行 df.fillna('', inplace=True) @staticmethod diff --git a/张阳脚本/宜搭刷数据/新签节点自动化同意.py b/张阳脚本/宜搭刷数据/新签节点自动化同意.py index 1692816..5107242 100644 --- a/张阳脚本/宜搭刷数据/新签节点自动化同意.py +++ b/张阳脚本/宜搭刷数据/新签节点自动化同意.py @@ -28,7 +28,7 @@ class Main: # 读取excel表格获取数据 - ceshi_data = pd.read_excel(r"C:\Users\hp_z66\Desktop\钉钉文件\2025-12回访导入.xlsx",sheet_name='7天节点且联系上(自动同意)') + ceshi_data = pd.read_excel(r"C:\Users\hp_z66\OneDrive\Desktop\钉钉文件\2026-1回访已回访.xlsx",sheet_name='7天') print("已读取表格") # 执行自动化脚本 diff --git a/张阳脚本/简道云/api.py b/张阳脚本/简道云/api.py deleted file mode 100644 index 4852ed3..0000000 --- a/张阳脚本/简道云/api.py +++ /dev/null @@ -1,479 +0,0 @@ -""" -API 模块 -""" - -import requests -import json -from typing import Optional, List, Dict, Any -from config import Config -from decimal import Decimal -import time -import numpy as np -# from log_config import configure_task_logger, configure_error_task_logger - -# 获取已经配置好的常规日志记录器 -# logger = configure_task_logger() -# -# # 获取已经配置好的错误任务日志记录器 -# error_task_logger = configure_error_task_logger() - - -class NpEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, np.integer): - return int(obj) - elif isinstance(obj, np.floating): - return float(obj) - elif isinstance(obj, np.ndarray): - return obj.tolist() - else: - return super(NpEncoder, self).default(obj) - - -def replace_decimals(obj): - if isinstance(obj, dict): - return {k: replace_decimals(v) for k, v in obj.items()} - elif isinstance(obj, list): - return [replace_decimals(item) for item in obj] - elif isinstance(obj, Decimal): - return float(obj) # 或者 str(obj) - return obj - - -class API: - def entry_data_get(self, data: dict, replace: bool = False) -> Dict: # 获取单条表单数据 - """ - 获取单条表单数据 - :param replace: 是否替换字段,默认为关 - :param data: 简道云插件发送过来的data,包含应用id、表单id、数据id等信息 - :return: - """ - - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/get' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 app_key - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "data_id": data['data_id'] # 数据ID - }) - - res = requests.post(url=url, data=payload, headers=headers) - data_get = res.json() - print(data_get) - - if replace: - data_get = self.field_replacement(data, data_get) # 字段替换,由id替换为标签名 - - return data_get - - def entry_data_list(self, data: dict, replace: bool = False, max_retries: int = 100) -> Dict: # 获取多条表单数据 - """ - 获取多条表单数据 - :param max_retries: 最大重试次数 - :param replace: 是否替换字段 - :param data: - api_key: 应用id - entry_id: 表单id - :return: - """ - - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/list' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 app_key - 'Content-Type': 'application/json' - } - all_data_batches = [] # 用于存储每次请求返回的数据批次 - last_data_id = None - exit_flag = False - while True: - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "limit": 100, - "data_id": last_data_id - }) - - # res = requests.post(url=url, data=payload, headers=headers) - # data_get = res.json() # 此时返回的数据是一个字典 - # if 'data' not in data_get or len(data_get['data']) == 0: - # break - # - # # 将当前批次的数据作为一个整体添加到 all_data_batches 中 - # all_data_batches.extend(data_get['data']) - # - # last_data_id = data_get['data'][-1].get('_id') - # time.sleep(0.2) - # print(f"已获取 {len(all_data_batches)} 条数据") - - retries = 0 - while retries <= max_retries: - try: - res = requests.post(url=url, data=payload, headers=headers) - res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常 - data_get = res.json() - # print("返回结果:", data_get) - if data_get["data"]: - all_data_batches.extend(data_get['data']) - last_data_id = data_get['data'][-1].get('_id') - print(f"已获取 {len(all_data_batches)} 条数据") - break # 成功则跳出循环 - else: - if 'data' not in data_get or len(data_get['data']) == 0: - exit_flag = True - break - print("请求失败, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - except requests.exceptions.RequestException as e: - print(f"请求异常: {e}, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - if retries > max_retries: - print(f"超过最大重试次数({max_retries}),放弃此次请求") - # error_task_logger.error(f"任务 {last_data_id}组 连续{max_retries}次请求失败,放弃此次请求。") - all_data_batches.append(None) # 或者可以选择记录失败的payload以便后续处理 - - if exit_flag: - break - - # 构建最终返回的字典 - final_data = { - 'data': all_data_batches # 'data' 键对应的值是列表的列表 - } - if replace: - print("进行了替换") - final_data = self.field_replacement(data, final_data) # 字段替换,由id替换为标签名 - - return final_data - - @staticmethod - def entry_widget_list(data: dict) -> Optional[Dict[str, Any]]: # 获取表单字段 - """ - 获取表单字段 - :param data: 简道云插件发送过来的data,包含应用id、表单id、数据id等信息 - :return: - """ - - url = 'https://api.jiandaoyun.com/api/v5/app/entry/widget/list' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 app_key - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "app_id": data['api_key'], - "entry_id": data['entry_id'], - }) - - res = requests.post(url=url, data=payload, headers=headers) - # print(type(res.json())) - return res.json() - - def field_replacement(self, data: dict, data_get: dict) -> dict: # 字段替换(id替换为标签名) json_str:请求后的返回数据 - """ - 字段替换,将id替换为标签名,即唯一值替换为表单中显示字段的名字 - :param data: 简道云插件发送过来的data,包含表单id、数据id、应用id - :param data_get: 简道云请求的数据,一般是根据数据id获取到表单的数据 - :return: 将根据数据id获取到的表单数据,进行替换,返回替换后的数据 - """ - # 获取表单对应字段标签名称 - widget_list = self.entry_widget_list(data) - - # 检查widget_list是否有效 - if not widget_list or 'widgets' not in widget_list or not isinstance(widget_list['widgets'], list): - raise ValueError("映射表没有接受到数据") - - # 创建一个映射表,将_widget_名称映射到label - name_to_label = {widget['name']: widget['label'] for widget in widget_list['widgets']} - print(name_to_label) - - # 遍历data_get对象中的"data"部分,替换键名 - data = data_get.get('data', {}) - new_data = {} - - if isinstance(data, list): # 多数据查询返回list - # 当 data 是列表时执行的代码 - for item in data: - new_data = {} - for key, value in item.items(): - if key in name_to_label: - new_key = name_to_label[key] - else: - new_key = key - new_data[new_key] = value - item['data'] = new_data # 对每个item进行更新 - - elif isinstance(data, dict): # 单数据查询返回dict - # 当 data 是字典时执行的代码 - for key, value in data.items(): - if key in name_to_label: - new_key = name_to_label[key] - else: - new_key = key - new_data[new_key] = value - data_get['data'] = new_data # 更新JSON对象中的"data"部分 - - # 将更新后的JSON对象转换回JSON字符串 - new_json = json.dumps(data_get, ensure_ascii=False, indent=2) - - new_json = json.loads(new_json) - return new_json - - @staticmethod - def data_batch_create(data: dict) -> Optional[requests.Response]: # 新建单条数据 - """ - 新建单条表单数据 - :param data: 应该包含应用id、表单id,以及新建的数据data['data'] - :return: 返回创建后简道云返回的信息 - """ - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/create' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 app_key - 'Content-Type': 'application/json' - } - - """ - data 样式 # 后续优化发送数据样式 目前输入字段,后续优化输入表单名称 - jiandaoyun_data['data'] = {"_widget_1731650067055":{"value":f'{username}{password}'}, - "_widget_1731650067056":{"value": f"{group}"}} - """ - - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "data": data['data'], - "is_start_workflow": data.get('is_start_workflow', "false"), - "is_start_trigger": data.get('is_start_trigger', "false"), - } - ) - - res = requests.post(url=url, data=payload, headers=headers) - data_get = res.json() - - return data_get - - @staticmethod - def entry_data_batch_create( - data: dict, - chunk_size: int = 90, - max_retries: int = 100 - ) -> List[Optional[requests.Response]]: # 新建多条数据 注意简道云限制1次最多100条数据 - """ - 新建多条数据 - :param max_retries: 最大重试次数,此处设置100次 - :param data:应包含数据id、表单id、以及需要新建的信息,新建信息应该是一个列表 - :param chunk_size: 简道云限制批量新建一次最多100条,这里默认值设置为90条一次 - :return:返回请求后的结果 - """ - data = replace_decimals(data) - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/batch_create' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 appKey - 'Content-Type': 'application/json' - } - - """ - data_list 样式 # 后续优化发送数据样式 目前输入字段,后续优化输入表单名称 - jiandaoyun_data_list['data_list'] = [{"_widget_1731650067055":{"value":f'{username}{password}'}, - "_widget_1731650067056":{"value": f"{group}"}}, - {"_widget_1731650067055":{"value":f'{username}{password}'}, - "_widget_1731650067056":{"value": f"{group}"}}] - """ - - # 获取data_list长度 - total_length = len(data['data_list']) - print(f"多数据写入行数: {total_length}") - - # 计算需要发送的次数 - num_chunks = (total_length + chunk_size - 1) // chunk_size # //整除向下取证,需要加上chunk_size - 1保证不会有缺失数据 - print(num_chunks) - data_get_list = [] - for i in range(num_chunks): - start_index = i * chunk_size - end_index = min(start_index + chunk_size, total_length) - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "data_list": data['data_list'][start_index:end_index], - "is_start_workflow": data.get('is_start_workflow', "false"), - "is_start_trigger": data.get('is_start_trigger', "false"), - }, cls=NpEncoder) - retries = 0 - while retries <= max_retries: - try: - res = requests.post(url=url, data=payload, headers=headers) - res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常 - data_get = res.json() - print(i, "返回结果:", data_get) - if data_get["status"] == "success": - data_get_list.append(data_get) - break # 成功则跳出循环 - else: - print("请求失败, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - except requests.exceptions.RequestException as e: - print(f"请求异常: {e}, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - if retries > max_retries: - print(f"超过最大重试次数({max_retries}),放弃此次请求") - # error_task_logger.error( - # f"任务 {data['data_list'][start_index:end_index]} 连续{max_retries}次请求失败,放弃此次请求。") - data_get_list.append(None) # 或者可以选择记录失败的payload以便后续处理 - - return data_get_list - - @staticmethod - def entry_data_update(data: dict, max_retries: int = 100) -> dict: # 修改数据 - """ - 修改数据 - :param max_retries: 最大重试次数,此处设置100次 - :param data: 简道云插件发送过来的data,包含应用id、表单id、数据id等信息 - :return: 修改数据后简道云返回的结果 - """ - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/update' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 appKey - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "data_id": data['data_id'], # 数据ID - "data": data['data'] - } - ) - print(payload) - data_get = None - retries = 0 - while retries <= max_retries: - try: - res = requests.post(url=url, data=payload, headers=headers) - res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常 - data_get = res.json() - print("返回结果:", data_get) - if res.status_code == 200: - break # 成功则跳出循环 - else: - print("请求失败, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - except requests.exceptions.RequestException as e: - print(f"请求异常: {e}, 将重新请求") - retries += 1 - time.sleep(10) # 在重试之间稍作停顿 - if retries > max_retries: - print(f"超过最大重试次数({max_retries}),放弃此次请求") - # error_task_logger.error(f"任务 {data['data_id']} 连续{max_retries}次请求失败,放弃此次请求。") - continue - return data_get - - @staticmethod - def entry_data_delete(data: dict, max_retries: int = 100, ) -> dict: - url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/delete' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 appKey - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "app_id": data['api_key'], # 应用ID - "entry_id": data['entry_id'], # 表单ID - "data_id": data['data_id'], # 数据ID - } - ) - retries = 0 - delete_status = None - - while retries <= max_retries: - try: - res = requests.post(url=url, data=payload, headers=headers) - delete_status = res.json() - # 手动处理状态码 4001 - if delete_status == { - "code": 4001, - "msg": "Data does not exist." - }: - print("返回结果:", delete_status) - break # 成功则跳出循环 - - # 检查其他状态码 - res.raise_for_status() # 只对非 4001 的状态码进行检查 - - print("返回结果:", delete_status) - if res.status_code == 200 : - break # 成功则跳出循环 - else: - print("请求失败, 将重新请求") - retries += 1 - time.sleep(0.1) # 在重试之间稍作停顿 - except requests.exceptions.RequestException as e: - print(f"请求异常: {e}, 将重新请求") - retries += 1 - time.sleep(10) # 在重试之间稍作停顿 - if retries > max_retries: - print(f"超过最大重试次数({max_retries}),放弃此次请求") - # error_task_logger.error(f"任务 {data['data_id']} 连续{max_retries}次请求失败,放弃此次请求。") - continue - return delete_status - - @staticmethod - def workflow_instance_get(data: dict) -> dict: - """ - 查询实例流程信息 - :param data: 简道云插件发送过来的data,包含应用id - :return: 查询简道云流程实例信息返回的结果 - """ - url = 'https://api.jiandaoyun.com/api/v5/workflow/instance/get' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 appKey - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "instance_id": data['data_id'], - "tasks_type": 1 - } - ) - - res = requests.post(url=url, data=payload, headers=headers) - return res.json() - - @staticmethod - def workflow_task_approve(data: dict) -> dict: - """ - 流程待办提交 - :param data:应包含username、instance_id(data_id)、task_id等信息 - :return:返回简道云流程待办提交的结果 - """ - url = 'https://api.jiandaoyun.com/api/v1/workflow/task/approve' - - headers = { - 'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 appKey - 'Content-Type': 'application/json' - } - - payload = json.dumps({ - "username": data["username"], - "instance_id": data["instance_id"], - "task_id": data['task_id'], - "comment": "自动转交" - } - ) - - res = requests.post(url=url, data=payload, headers=headers) - return res.json() diff --git a/张阳脚本/简道云/back_ground_tasks.py b/张阳脚本/简道云/back_ground_tasks.py deleted file mode 100644 index 4764939..0000000 --- a/张阳脚本/简道云/back_ground_tasks.py +++ /dev/null @@ -1,67 +0,0 @@ -import requests -import pandas as pd -import os -from typing import Dict, Any -from api import API -import time -from tqdm import tqdm - -api_instance = API() - - -def update_jiandaoyun(data: Dict[str, Any], results: str): - """ 更新简道云表单 """ - # 定义简道云数据配置 - jiandaoyun_data = { - 'api_key': data['api_key'], - 'entry_id': data['entry_id'], - 'data_id': data['data_id'], - "data": { - '_widget_1731379774828': {"value": "已执行"}, # f6系统批量操作测试 是否执行成功 - '_widget_1731381334870': {"value": results} # f6系统批量操作测试 执行明细 - } - } - - time.sleep(1) - print(jiandaoyun_data) - api_instance.entry_data_update(jiandaoyun_data) - print('更新简道云表单成功') - - -def create_brand_background(data: Dict[str, Any], cookies: Dict[str, str], df: pd.DataFrame, save_path: str): - # 定义请求URL - url = 'https://yunxiu.f6car.cn/camaro/brand/getOrCreate' - - # 遍历DataFrame中的每一行数据 - results = [] - for index, row in tqdm(df.iterrows(), total=df.shape[0], desc="创建品牌"): - brand_name = row['品牌名'] - try: - response = requests.post(url, cookies=cookies, json={"brandName": brand_name}) - response.raise_for_status() # 抛出HTTP错误 - results.append({'品牌名': brand_name, '状态': '创建成功'}) - except requests.exceptions.RequestException as e: - results.append({'品牌名': brand_name, '状态': f'创建失败: {str(e)}'}) - print({'msg': '已执行', 'msg_details': f'{results}'}) - os.remove(save_path) - print(f'{save_path}已删除') - print(data) - # 调用api回写改掉 执行明细与执行状态 - update_jiandaoyun(data, f'{results}') - - -def delete_history_background(data: Dict[str, Any], cookies: Dict[str, str], org_id: str, org_name: str): - url = f'https://yunxiu.f6car.cn/maintain-dump/maintainHistory/?orgid={org_id}' # 删除url - res = requests.delete(url=url, cookies=cookies) - res_data = res.json() - - if res.status_code == 200 and res_data.get('code') == 200: - results = f'{org_name} 历史维修记录已删除' - print(results) - else: - results = f'删除 {org_name} 历史维修记录失败: {res_data.get("message")}' - print(results) - - # 调用api回写改掉 执行明细与执行状态 - time.sleep(1) - update_jiandaoyun(data, f'{results}') diff --git a/张阳脚本/简道云/config.py b/张阳脚本/简道云/config.py deleted file mode 100644 index 3cd8bbb..0000000 --- a/张阳脚本/简道云/config.py +++ /dev/null @@ -1,33 +0,0 @@ -# config.py -""" -配置类,负责加载和提供项目配置。 -""" - - -class Config: - CONN_INFO = { - "database": "f6_bi", - "user": "BASIC$ro_caowei", - "password": "!ro_caowei123", - "host": "hgprecn-cn-nif1vnv0y002-cn-shanghai.hologres.aliyuncs.com", - "port": "80" - } # SaaS-NGV 数据库链接配置-postgresql - - # 接车宝数据库链接配置-mysql - JCB_CONN_INFO_database = "f6insight_gzczj" - JCB_CONN_INFO_user = "rw_insight_gzczj" - JCB_CONN_INFO_password = "wEBT5LBHzbbhJisheCsE" - JCB_CONN_host = "rm-uf6r230vbtxf5gdz63o.mysql.rds.aliyuncs.com" - - JIANDAOYUN_API_TOKEN = 'Bearer qygHulymo1fekJk4CIZyNKjyQAzG8CFN' # token - - EFFICIENT_CAR_PICKUP_APP_ID = "6717470a0b3975ef583c6df1" # 接车宝应用id - SCHEDULED_TASKS_APP_ID = "6694d3c4fcb69ca9a111a6c4" # 数据支持应用id - SaaS_Tasks_APP_ID = "675b900991ad2491c69389ca" # saas日常回访应用id - - SCHEDULED_TASKS_ENTRY_ID = "6760e5e7672af4621ab8128a" # 定时任务表单id - NGV_TASKS_ENTRY_ID = "675bb02bd2d53c2034c665e4" # NGV任务表单id - - EFFICIENT_CAR_PICKUP_ENTRY_ID = "67174710da507490d8ac12c1" # 接车宝表单id - EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID = "67b6f2462f9ac03b783d409a" # 接车宝客服表单id - EFFICIENT_CAR_PICKUP_CUSTOMER_HISTORY_ID = "67c156ba635191b64af8a110" # 接车宝历史派发表单 diff --git a/张阳脚本/简道云/main.py b/张阳脚本/简道云/main.py deleted file mode 100644 index 4c45b22..0000000 --- a/张阳脚本/简道云/main.py +++ /dev/null @@ -1,171 +0,0 @@ -from flask import Flask, request, jsonify -from module import module, F6_Plugin_module -from urllib.parse import unquote -from config import Config -import queue -import threading -import logging -import os -from logging.handlers import RotatingFileHandler -from apscheduler.schedulers.background import BackgroundScheduler -import requests -import atexit - -app = Flask(__name__) -app.config.from_object(Config) -f6_module = module.F6Module() -f6_plugin_module = F6_Plugin_module.F6PluginModule() - -# 定义一个映射表,将操作与处理函数关联起来 -action_map = { - 'login_in': f6_module.accept_login_message, - 'get_company_information': f6_module.get_company_information, - 'get_store_information': f6_module.get_store_information, - "keep_alive": f6_module.get_keep_heart, - 'check_file': f6_plugin_module.check_file, - 'create_brand': f6_plugin_module.create_brand, - 'delete_history': f6_plugin_module.delete_history, - # 'delete_customer': f6_plugin_module.delete_customer, - # 'delete_cars': f6_plugin_module.delete_cars, -} - -# 创建一个消息队列 -task_queue = queue.Queue() - - -# 创建一个线程来处理队列中的任务 -def process_tasks(): - while True: - task = task_queue.get() - if task is None: - logger.error("任务处理线程已终止") - break # 停止处理任务 - try: - result = task['handler'](task['data']) - task['response'].put(result) - except Exception as e: - logger.error(f"任务执行失败: {str(e)}") - task['response'].put({'msg': f'任务执行失败: {str(e)}'}) - finally: - task_queue.task_done() - logger.info("任务处理完成") - - -# 启动任务处理线程 -task_thread = threading.Thread(target=process_tasks, daemon=True) -task_thread.start() - -# 配置日志记录器 -log_dir = './日志' # 日志文件夹路径 -if not os.path.exists(log_dir): - os.makedirs(log_dir) # 如果日志文件夹不存在,则创建它 - -log_file = os.path.join(log_dir, '简道云日志.log') - -# 设置日志格式和级别 -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - -# 创建RotatingFileHandler,支持日志文件滚动 -file_handler = RotatingFileHandler(log_file, maxBytes=1024 * 1024 * 5, backupCount=5) -file_handler.setLevel(logging.INFO) - -# 定义日志格式 -formatter = logging.Formatter('%(asctime)s %(levelname)s:%(name)s:%(message)s') -file_handler.setFormatter(formatter) - -# 将处理器添加到记录器 -logger.addHandler(file_handler) - -# 将Flask的默认日志记录器也配置为使用相同的处理器 -app.logger.addHandler(file_handler) - -# 创建一个后台调度器 -scheduler = BackgroundScheduler() - - -# 定义一个定时任务,定期发送心跳请求以保持服务活跃 -def keep_alive(): - try: - data = { - 'Action': 'keep_alive' - } - header = { - 'Action': 'keep_alive' - } - # 发送一个GET请求到自己的API端点,模拟活动 - response = requests.post(url='http://192.168.10.86:5000/webhook', data=data, headers=header, timeout=5) - - if response.status_code == 200: - logger.info("Heartbeat sent successfully") - else: - logger.warning(f"Heartbeat failed with status code: {response.status_code}") - except requests.RequestException as e: - logger.error(f"Failed to send heartbeat: {e}") - - -# 添加定时任务,每隔1分钟执行一次 -scheduler.add_job(keep_alive, 'interval', minutes=1) -# 启动调度器 -scheduler.start() -# 确保在应用退出时关闭调度器 -atexit.register(lambda: scheduler.shutdown()) - - -@app.route('/webhook', methods=['POST']) -def webhook(): - logging.info('Received POST request to /webhook') - """ - 接受前端请求后将任务放入消息队列 - - Returns: - any: 返回任务处理的结果 - """ - # 获取请求体中的 JSON 数据 - data = request.json - header = request.headers - header = decode_headers(header) - - action = header.get('Action') - - if action == 'F6_Plugin': - check = header.get('Check') - if check == '否': - handler = f6_plugin_module.check_file - elif check == '是': - sub_action = data.get('Action') - handler = action_map.get(sub_action, lambda x: {'msg': '未执行'}) - else: - return jsonify({'msg': '未知的操作'}) - else: - handler = action_map.get(action, lambda x: {'msg': '未知的操作'}) - - # 创建一个队列用于存储任务处理结果 - response_queue = queue.Queue() - - # 将任务放入消息队列 - task_queue.put({ - 'handler': handler, - 'data': data, - 'response': response_queue - }) - - # 等待任务处理结果 - result = response_queue.get() - return jsonify(result) - - -def decode_headers(headers): - """ - 解码包含中文字符的 HTTP 请求头。 - - :param headers: 包含编码后头部字段的字典 - :return: 解码后的头部字段字典 - """ - return {key: unquote(value, encoding='utf-8') for key, value in headers.items()} - - -if __name__ == '__main__': - # from waitress import serve - # serve(app, host='192.168.10.86', port=5000) - app.run(debug=True, port=5000) diff --git a/张阳脚本/简道云/module/F6_Plugin_module.py b/张阳脚本/简道云/module/F6_Plugin_module.py deleted file mode 100644 index bad9dc7..0000000 --- a/张阳脚本/简道云/module/F6_Plugin_module.py +++ /dev/null @@ -1,315 +0,0 @@ -import requests -from urllib.parse import quote -import pandas as pd -import os -import urllib.parse -import time -from datetime import datetime -from api import API -from typing import Optional, Dict, Any, Tuple -from config import Config -from module.module import F6Module -import threading -import back_ground_tasks - -api_instance = API() - - -class F6PluginModule: - - @staticmethod - def accept_file(data: Dict[str, Any]) -> Tuple[Optional[str], Dict[str, Any]]: # 接收文件 - """ - 接收文件。 - - 此方法用于处理前端上传的文件,下载文件并保存到指定目录。主要步骤包括: - 1. 处理前端传递的数据,获取文件的URL。 - 2. 解析URL以获取文件名。 - 3. 根据当前时间生成新的文件名,以避免文件名冲突。 - 4. 下载文件并保存到指定目录。 - 5. 返回文件保存路径和处理后的数据。 - - Args: - data (dict): 包含文件URL和其他必要信息的字典。 - - Returns: - tuple: 包含文件保存路径和处理后的数据的元组。如果文件保存成功,返回保存路径和数据;如果失败,返回 None 和数据。 - """ - data = api_instance.entry_data_get(data=data) - - try: - url = data['data']['附件'][0]['url'] - print(url) - except Exception as e: - print(f'上传url未读取到,或无上传文件:{e}') - save_path = '' - return save_path, data - - parsed_url = urllib.parse.urlparse(url) - query_params = urllib.parse.parse_qs(parsed_url.query) - attname = query_params.get('attname', [''])[0] - filename = urllib.parse.unquote(attname) - - # 获取当前时间并格式化为指定格式的字符串 - timestamp = datetime.now().strftime("%Y-%m-%d %H-%M-%S") - - # 分离文件名和扩展名 - name_part, ext_part = filename.rsplit('.', 1) if '.' in filename else (filename, '') - - # 构建新文件名 - new_filename = f"{name_part}{timestamp}.{ext_part}" if ext_part else f"{name_part}{timestamp}" - - save_path = os.path.join(Config.SAVE_DIRECTORY, new_filename) - print(save_path) - response = requests.get(url, stream=True) - - if response.status_code == 200: - with open(save_path, 'wb') as file: - for chunk in response.iter_content(chunk_size=1024): - if chunk: - file.write(chunk) - return save_path, data - else: - return None, data - - def check_file(self, data: Dict[str, Any]) -> Dict[str, str]: # 校验上传文件 - """ - 校验上传文件。 - - 此方法负责接收前端上传的文件,并根据文件类型和操作指令进行相应的校验。主要步骤包括: - 1. 调用 `accept_file` 方法处理前端传递的数据,获取文件保存路径和处理后的数据。 - 2. 根据数据中的 `Action` 字段判断需要执行的操作类型。 - 3. 如果文件保存路径有效,继续执行以下步骤: - - 如果操作类型为 `create_brand`,则读取文件和模板文件,校验文件格式是否正确。 - - 如果文件格式正确,返回成功消息;否则返回错误消息。 - 4. 如果文件保存路径无效,返回相应的错误消息。 - 5. 如果读取文件过程中发生异常,捕获异常并返回错误消息。 - - Args: - data (dict): 前端请求发送过来的数据,包含文件信息和其他必要参数。 - - Returns: - dict: 包含文件校验结果的消息字典。如果校验成功,则返回文件路径和校验标志;如果失败,则返回错误消息。 - """ - save_path, data1 = self.accept_file(data) - - action = data1['data']['Action(隐藏)'] - - if save_path: - try: - if action == 'create_brand': - template_path = os.path.join(Config.MODE_DIRECTORY, '品牌名.xlsx') - - # 读取指定的工作表 - df1 = pd.read_excel(save_path, sheet_name='品牌名') - df2 = pd.read_excel(template_path, sheet_name='品牌名') - - if df1.columns.tolist() == df2.columns.tolist(): # 校验表头名字 - print('文件校验成功') - return {'msg': f'{save_path}', 'check': '是'} - else: - print("'msg':'文件上传格式错误'") - return {'msg': '文件上传格式错误'} - elif action == 'delete_customer': - pass - elif action == 'delete_cars': - pass - else: - pass - - except Exception as e: - return {'msg': f'读取Excel文件失败: {str(e)},文件路径:{save_path}'} - - else: - return {'msg': '当前节点无附件上传', 'check': '是'} # 注意前端上传url必须为必填的,否则这个返回会出现错误 - - @staticmethod - def create_brand(data: Dict[str, Any]) -> Dict[str, str]: # 创建品牌 - """ - 创建品牌函数。 - - 此方法用于处理前端发送的品牌创建请求,并执行相应的品牌创建逻辑。 - - Args: - data (dict): 包含品牌信息及用户凭证等数据的字典。 - - Returns: - dict: 包含操作结果的消息字典。如果操作成功,则返回成功消息和详情;如果失败,则返回错误消息。 - - Process: - 1. 调用 `entry_data_get` 方法处理前端传递的数据。 - 2. 从处理后的数据中提取用户名、密码、公司名称以及文件保存地址。 - 3. 使用提供的用户名和密码尝试登录。 - 4. 如果登录失败,立即返回错误消息。 - 5. 登录成功后,读取指定路径的Excel文件,该文件应包含待创建品牌的列表。 - 6. 若读取Excel文件失败,返回相应的错误消息。 - 7. 利用登录获取到的cookies构造请求头,准备发起创建品牌的POST请求。 - 8. 遍历Excel文件中的每一条记录(即每个品牌),向指定的API发送创建请求。 - 9. 每个品牌的创建结果(成功或失败)都会被记录下来。 - 10. 所有品牌的创建请求完成后,删除原始的Excel文件。 - 11. 最后,将所有操作的结果汇总成字典并返回给调用者。 - """ - entry_data = api_instance.entry_data_get(data=data) # 获取表单数据 - # print(data) - print('执行 品牌批量新建') - username = entry_data['data']['账号'] - password = entry_data['data']['密码'] - company_name = entry_data['data']['公司名称'] - save_path = entry_data['data']['文件保存地址'] - - # 尝试登录 - login_response = F6Module.login_in(username, password, company_name) - if login_response is None: - return {'msg': '登录失败'} - - # 读取Excel文件 - try: - df = pd.read_excel(save_path, dtype='string') - - except Exception as e: - return {'msg': f'读取Excel文件失败: {str(e)},文件路径:{save_path}'} - - # 获取登录cookies - cookies = requests.utils.dict_from_cookiejar(login_response.cookies) - - # 启动后台线程执行品牌创建任务 - try: - thread = threading.Thread(target=back_ground_tasks.create_brand_background, args=(data, cookies, df, save_path)) - thread.start() - except Exception as e: - print(f'创建线程失败: {str(e)}') - - # 立即返回消息 - return {'msg': '正在执行', 'msg_details': '正在执行,请稍后看结果'} - - @staticmethod - def delete_history(data: Dict[str, Any]) -> Dict[str, str]: # 删除历史维修记录 - # endregion - """ - 删除历史维修记录。 - - 此方法用于处理用户的请求,删除指定门店的历史维修记录。主要步骤包括: - 1. 处理前端传递的数据,提取必要的登录信息和门店信息。 - 2. 尝试登录系统,获取登录cookies。 - 3. 获取所有门店的信息,找到与用户提供的门店名称匹配的门店ID。 - 4. 使用门店ID发送删除请求,删除历史维修记录。 - 5. 返回操作结果。 - - Args: - data (dict): 包含登录信息和门店信息的字典。 - - Returns: - dict: 包含操作结果的消息字典。如果删除成功,返回成功消息和详细信息;如果失败,返回错误消息。 - """ - entry_data = api_instance.entry_data_get(data=data) # 获取表单数据,将ID替换为中文 - - username = entry_data['data']['账号'] - password = entry_data['data']['密码'] - company_name = entry_data['data']['公司名称'] - org_name = entry_data['data']['门店名称'] - - login_response = F6Module.login_in(username, password, company_name) # 尝试登录 - if login_response is None: - return {'msg': '未执行', 'msg_details': '登录失败'} - - # 获取登录cookies - cookies = requests.utils.dict_from_cookiejar(login_response.cookies) - - # 获取门店列表 - url = 'https://yunxiu.f6car.cn/hive/org/getPageOrgGroupMembers?currentPage=1&pageSize=1000&name=' # 获取门店名称url - res = requests.get(url=url, cookies=cookies) - store_data = res.json() - org_lists = store_data['data']['list'] - - org_id = '' - org_name1 = '' - for org in org_lists: # 确认删除门店信息 - org_name1 = org['orgName'] - if org_name == org['orgName']: - org_id = org['orgId'] - - if org_id: - # 启动后台线程执行删除任务 - thread = threading.Thread(target=back_ground_tasks.delete_history_background, args=(data, cookies, org_id, org_name1)) - thread.start() - - # 立即返回消息 - return {'msg': '正在执行中', 'msg_details': '请稍后查看结果'} - else: - return {'msg': '未执行', 'msg_details': '门店信息错误'} - - @staticmethod - def delete_customer(data): # 客户信息删除(删除所有客户信息) - - username = data['username'] - password = data['password'] - company_name = data['company_name'] - - res = F6Module.login_in(username, password, company_name) - - if res is not None: - cookies = requests.utils.dict_from_cookiejar(res.cookies) - url = "https://yunxiu.f6car.cn/member/customer/listForPermission?pageSize=5&pageNo=1" # 获取客户信息列表 - res = requests.get(url, cookies=cookies) - json = res.json() - for item in json['data']['data']: - idCustomer = item['idCustomer'] - phone = item['cellPhone'] - try: - url = f"https://yunxiu.f6car.cn/member/customer/{idCustomer}" # 客户信息删除url - res = requests.delete(url, cookies=cookies) # 客户信息删除 - print(res.json, idCustomer, phone) - time.sleep(0.2) - except Exception as e: - print("删除失败,", res.json, idCustomer, phone, e) - - @staticmethod - def delete_cars(data): - """ - 删除客户车辆信息 - - 参数: - data (dict): 包含用户名、密码和公司名称的字典。 - - username (str): 用户名 - - password (str): 密码 - - company_name (str): 公司名称 - - 返回: - 无 - - 功能描述: - 1. 使用提供的用户名、密码和公司名称登录系统。 - 2. 如果登录成功,获取登录后的 cookies 和操作组织 ID。 - 3. 发送 POST 请求获取客户车辆信息列表。 - 4. 遍历车辆信息列表,逐个删除客户车辆信息。 - 5. 每次删除操作后,打印删除成功或失败的信息,并暂停 0.2 秒。 - """ - - username = data['username'] - password = data['password'] - company_name = data['company_name'] - - res = F6Module.login_in(username, password, company_name) - - if res is not None: - cookies = requests.utils.dict_from_cookiejar(res.cookies) - operateOrgId = cookies['prodOrg'] - url = "https://yunxiu.f6car.cn/member/car/carListForPermission" # 获取客户车辆信息列表 - header = { - 'Referer': 'https://yunxiu.f6car.cn/erp/view/index.html', - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0' - } - data = {"pageSize": 10, "pageNo": 2} # 根据需求修改 - - res = requests.post(url=url, cookies=cookies, json=data, headers=header) # 注意需要用json发送数据 - data = res.json() - for item in data['data']['data']: - carId = item['tmCarInfo']['pkId'] - customerId = item['tmCustomerInfo']['pkId'] - try: - url = f"https://yunxiu.f6car.cn/macan/coupon/car/batchRemove?customerId={customerId}&carId={carId}&operateOrgId={operateOrgId}" # 删除客户车辆信息url - res = requests.delete(url, cookies=cookies) # 客户车辆信息删除 - print("删除成功:", res.json, customerId, carId) - time.sleep(0.2) - except Exception as e: - print("删除失败:", res.json, customerId, operateOrgId, e) diff --git a/张阳脚本/简道云/module/module.py b/张阳脚本/简道云/module/module.py deleted file mode 100644 index c4e5a8b..0000000 --- a/张阳脚本/简道云/module/module.py +++ /dev/null @@ -1,232 +0,0 @@ -import requests -import hashlib -from urllib.parse import quote -from datetime import datetime -from api import API -from typing import Optional, Dict - -api_instance = API() - - -class F6Module: - - @staticmethod - def login_in(username: str, password: str, company_name: str = '默认门店') -> Optional[requests.Response]: - """ - 登录模块。 - - 此方法用于处理用户的登录请求,包括认证和选择门店的整个过程。 - - Args: - username (str): 用户名。 - password (str): 密码。 - company_name (str, optional): 默认为 '默认门店',表示用户要登录的门店名称。 - - Returns: - Response or None: 如果登录成功,返回包含登录信息的响应对象;如果登录失败,返回 None。 - """ - url = "https://yunxiu.f6car.com/kzf6/login/confirm" - session = requests.Session() - header = { - 'Referer': url, - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/129.0.0.0' - } - data = { - 'username': username, - 'password': hashlib.md5(password.encode('utf-8')).hexdigest(), - } - try: - res = session.post(url=url, headers=header, data=data) - res_json = res.json() - - if res_json.get("data") is None: - return res - else: - group_id = '' - for group in res_json.get('data', []): - if group["groupName"] == company_name: - group_id = group.get("groupId") - - token = quote(res_json['token']) # URL 编码 - url = f'https://yunxiu.f6car.cn/kzf6/user/loginAfterChooseGroup?token={token}&groupId={group_id}&macAddress=' - res1 = session.get(url, cookies=res.cookies) - return res1 - except Exception as e: - print(f"Error during login: {e}") - return None - - def accept_login_message(self, data: Dict[str, str]) -> Dict[str, str]: # 获取登录信息 - """ - 获取登录信息。 - - 此方法用于处理用户的登录请求,验证登录信息的正确性,并返回相应的登录状态。 - - Args: - data (dict): 包含用户名、密码和门店名称的字典。 - - Returns: - dict: 包含登录状态的消息字典。 - """ - username = data['username'] - password = data['password'] - company_name = data['company_name'] - - res = self.login_in(username, password, company_name) - - if res is not None: - cookies = requests.utils.dict_from_cookiejar(res.cookies) - json = res.json() - url = 'https://yunxiu.f6car.cn/hive/company/getGroupName' - res1 = requests.get(url=url, cookies=cookies) - data1 = res1.json() - - if data1['code'] == 200: - if data1['data'] == company_name: - if json['status'] == 'success': - json['status'] = '登录成功' - elif json['status'] == 'Error': - json['status'] = '登录失败,请检查账号密码' - else: - json['status'] = '公司名称不正确,请重试' - else: - json['status'] = '请输入正确的账号密码并选择公司名称' - return json - else: - return {"status": "登录失败,请检查公司名称"} - - def get_company_information(self, data: Dict[str, str]) -> Dict[str, str]: # 获取登录账号下公司信息 - """ - 获取登录账号下公司信息。前端事件触发 - - 此方法用于处理用户的登录请求,获取与该用户关联的所有门店名称。 - - Args: - data (dict): 包含用户名和密码的字典。 - - Returns: - dict: 包含门店信息的消息字典。如果成功获取门店信息,返回门店列表;如果失败,返回错误消息。 - """ - username = data['username'] - password = data['password'] - timestamp = datetime.now().strftime("%Y-%m-%d %H-%M-%S") - print(username) - - url = "https://yunxiu.f6car.com/kzf6/login/confirm" - session = requests.Session() - header = { - 'Referer': url, - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0' - } - data = { - 'username': username, - 'password': hashlib.md5(password.encode('utf-8')).hexdigest(), - } - - try: - res = session.post(url=url, headers=header, data=data) - res_json = res.json() - - if res_json.get('message') == '请输入图形验证码': - pass - - # 添加公司名称映射表单ID应用ID - jiandaoyun_data = {'api_key': '6694d3c4fcb69ca9a111a6c4', 'entry_id': '6736e2112ad50045f041a827'} - - if res_json.get("data") is None: - print('单店') - res = self.login_in(username, password) - if res is not None: - cookies = requests.utils.dict_from_cookiejar(res.cookies) - url = 'https://yunxiu.f6car.cn/hive/company/getGroupName' # 获取门店名称url - res = requests.get(url=url, cookies=cookies) - data = res.json() - store_name = data['data'] # 获取店铺名称 - - jiandaoyun_data['data_list'] = [ - {"_widget_1731650067055": {"value": f'{username}{password}{timestamp}'}, # 公司名称映射表 公司名称唯一值 - "_widget_1731650067056": {"value": f"{store_name}"}}] # 公司名称映射表 公司名称 - api_instance.entry_data_batch_create(jiandaoyun_data) # 调用api写入数据 - res = {'msg': f'{username}{password}{timestamp}'} - else: - jiandaoyun_data_list = [] - for group in res_json.get('data', []): - append_data = {"_widget_1731650067055": {"value": f'{username}{password}{timestamp}'}, - "_widget_1731650067056": {"value": f"{group['groupName']}"}} - jiandaoyun_data_list.append(append_data) - - jiandaoyun_data['data_list'] = jiandaoyun_data_list - - res = api_instance.entry_data_batch_create(jiandaoyun_data) # 调用api写入数据 - - print(res) - - res = {'msg': f'{username}{password}{timestamp}'} - return res - - except Exception as e: - print(f"获取公司名称失败: {e}") - res = {'msg': '获取公司名称失败,请重新获取'} - return res - - def get_store_information(self, data: Dict[str, str]) -> Dict[str, str]: # 获取登录公司下门店信息 - """ - 获取门店登录信息。前端事件触发 - - 此方法用于处理用户的登录请求,获取与该用户关联的所有门店名称,并将这些信息连同用户登录信息一并记录至简道云表单中。 - - Args: - data (dict): 包含用户名、密码及公司名称的字典。 - - Returns: - dict: 包含操作结果的消息字典。如果成功获取门店信息并记录至简道云,返回成功消息及记录信息;如果登录或数据记录过程中出现错误,返回相应的错误消息。 - """ - username = data['username'] - password = data['password'] - company_name = data['company_name'] - timestamp = datetime.now().strftime("%Y-%m-%d %H-%M-%S") - - login_response = self.login_in(username, password, company_name) # 尝试登录 - if login_response is None: - return {'msg': '未执行', 'msg_details': '登录失败'} - - # 获取登录cookies - cookies = requests.utils.dict_from_cookiejar(login_response.cookies) - - # 获取门店列表 - url = 'https://yunxiu.f6car.cn/hive/org/getPageOrgGroupMembers?currentPage=1&pageSize=100&name=' # 获取门店名称url - res = requests.get(url=url, cookies=cookies) - data = res.json() - org_lists = data['data']['list'] - # print(org_lists) - - # noinspection SpellCheckingInspection - jiandaoyun_data = {'api_key': '6694d3c4fcb69ca9a111a6c4', - 'entry_id': '673c38ccca57a5cf266eb18c'} # 添加公司名称映射表单ID应用ID - - jiandaoyun_data_list = [] - for org in org_lists: - append_data = {"_widget_1731999948708": {"value": f'{username}{password}{company_name}{timestamp}'}, - # 公司门店映射表 公司名称唯一值 - "_widget_1731999948709": {"value": f"{org['orgName']}"}} # 公司门店映射表 公司名称 - jiandaoyun_data_list.append(append_data) - - jiandaoyun_data['data_list'] = jiandaoyun_data_list - - api_instance.entry_data_batch_create(jiandaoyun_data) # 调用api写入数据 - - res = {'msg': f'{username}{password}{company_name}{timestamp}'} - - return res - - @staticmethod - def get_keep_heart(data: Dict[str, str]) -> Dict[str, str]: - """ - 获取心跳信息。前端事件触发 - - Args: - data(dict):包含心跳内容 - - returns: - dict:返回心跳内容 - """ - return data diff --git a/张阳脚本/简道云/删除.py b/张阳脚本/简道云/删除.py deleted file mode 100644 index b158659..0000000 --- a/张阳脚本/简道云/删除.py +++ /dev/null @@ -1,17 +0,0 @@ -from api import API -import pandas as pd -from config import Config - -api_instance = API() - -df = pd.read_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Downloads\接车宝日常回访单_20250313091252.xlsx", - sheet_name='Sheet3', dtype='string') - -for index,row in df.iterrows():# 在列表格式固定 - data_id = row['data_id'] - delete_data = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID, - "entry_id": "67174710da507490d8ac12c1", - "data_id": data_id} - api_instance.entry_data_delete(delete_data) - - diff --git a/张阳脚本/简道云/服务器压力统计.ipynb b/张阳脚本/简道云/服务器压力统计.ipynb new file mode 100644 index 0000000..c721a8a --- /dev/null +++ b/张阳脚本/简道云/服务器压力统计.ipynb @@ -0,0 +1,655 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f698c340", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "8800f2ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "正在筛选日期为:2026-02-23 的任务...\n", + "正在从简道云获取源数据...\n", + "已获取 73 条数据\n", + "API 返回原始数据条数: 73\n", + "{'_id': '699b9891bb267647270882ac', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:00:17.084Z', 'updateTime': '2026-02-23T00:00:17.084Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T00:00:01.000Z', '_widget_1744873387502': '2026-02-23T00:00:16.000Z', '_widget_1744873387504': '15', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b98cbe276a38cb2450192', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:01:15.225Z', 'updateTime': '2026-02-23T00:01:15.225Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '省市区人员关系表转BI', '_widget_1744873387501': '2026-02-23T00:00:22.000Z', '_widget_1744873387502': '2026-02-23T00:01:14.000Z', '_widget_1744873387504': '52', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b98da14a266a4faaec87b', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:01:30.245Z', 'updateTime': '2026-02-23T00:01:30.245Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '非标业绩提报转BI', '_widget_1744873387501': '2026-02-23T00:01:22.000Z', '_widget_1744873387502': '2026-02-23T00:01:29.000Z', '_widget_1744873387504': '7', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b98e7506e3a1c9db63a1a', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:01:43.368Z', 'updateTime': '2026-02-23T00:01:43.368Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T00:00:01.000Z', '_widget_1744873387502': '2026-02-23T00:01:42.000Z', '_widget_1744873387504': '101', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b992c654487d78fad28d4', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:02:52.229Z', 'updateTime': '2026-02-23T00:02:52.229Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '合伙人结算登记同步到BI', '_widget_1744873387501': '2026-02-23T00:02:22.000Z', '_widget_1744873387502': '2026-02-23T00:02:51.000Z', '_widget_1744873387504': '29', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b9956ed29cdb3bc0359a0', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:03:34.573Z', 'updateTime': '2026-02-23T00:03:34.573Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '分母报备调整', '_widget_1744873387501': '2026-02-23T00:03:22.000Z', '_widget_1744873387502': '2026-02-23T00:03:34.000Z', '_widget_1744873387504': '12', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b99c5c92edf9a18ddd2e5', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:05:25.913Z', 'updateTime': '2026-02-23T00:05:25.913Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '经销商新签服务单转BI', '_widget_1744873387501': '2026-02-23T00:05:23.000Z', '_widget_1744873387502': '2026-02-23T00:05:25.000Z', '_widget_1744873387504': '2', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b9a023fa4592f7ff27d2b', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:06:26.403Z', 'updateTime': '2026-02-23T00:06:26.403Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '分子报备调整', '_widget_1744873387501': '2026-02-23T00:06:23.000Z', '_widget_1744873387502': '2026-02-23T00:06:26.000Z', '_widget_1744873387504': '3', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699b9f36faa412358146bcec', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:28:38.775Z', 'updateTime': '2026-02-23T00:28:38.775Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '海外邮件推送', '_widget_1744873387501': '2026-02-23T00:28:26.000Z', '_widget_1744873387502': '2026-02-23T00:28:38.000Z', '_widget_1744873387504': '12', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ba149bb2676472710a0fe', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T00:37:29.703Z', 'updateTime': '2026-02-23T00:37:29.703Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云海外项目CRM客户档案迁移BI', '_widget_1744873387501': '2026-02-23T00:37:28.000Z', '_widget_1744873387502': '2026-02-23T00:37:29.000Z', '_widget_1744873387504': '1', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ba696205acb4b4cadef32', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:00:06.276Z', 'updateTime': '2026-02-23T01:00:06.276Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T01:00:02.000Z', '_widget_1744873387502': '2026-02-23T01:00:05.000Z', '_widget_1744873387504': '3', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ba6fda0e00405891ad3fa', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:01:49.001Z', 'updateTime': '2026-02-23T01:01:49.001Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T01:00:02.000Z', '_widget_1744873387502': '2026-02-23T01:01:48.000Z', '_widget_1744873387504': '106', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ba91f5debe6469c395fb9', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:10:55.697Z', 'updateTime': '2026-02-23T01:10:55.697Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '接车宝日常派发', '_widget_1744873387501': '2026-02-23T01:10:32.000Z', '_widget_1744873387502': '2026-02-23T01:10:55.000Z', '_widget_1744873387504': '23', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bacabded5b58a521b70f0', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:26:03.296Z', 'updateTime': '2026-02-23T01:26:03.296Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '新签客户回访', '_widget_1744873387501': '2026-02-23T01:05:32.000Z', '_widget_1744873387502': '2026-02-23T01:26:02.000Z', '_widget_1744873387504': '1230', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb02f057a5fdbf0f7a2ff', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:41:03.569Z', 'updateTime': '2026-02-23T01:41:03.569Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '续约客户回访', '_widget_1744873387501': '2026-02-23T01:08:32.000Z', '_widget_1744873387502': '2026-02-23T01:41:03.000Z', '_widget_1744873387504': '1951', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb0432121acc1031813b5', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:41:23.436Z', 'updateTime': '2026-02-23T01:41:23.436Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '续约回访待办', '_widget_1744873387501': '2026-02-23T01:35:37.000Z', '_widget_1744873387502': '2026-02-23T01:41:23.000Z', '_widget_1744873387504': '346', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb3af78f713d2ee49d55b', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T01:55:59.287Z', 'updateTime': '2026-02-23T01:55:59.287Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '履约表数据支撑', '_widget_1744873387501': '2026-02-23T01:11:32.000Z', '_widget_1744873387502': '2026-02-23T01:55:59.000Z', '_widget_1744873387504': '2667', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb4a5ba28a77430759c97', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T02:00:05.474Z', 'updateTime': '2026-02-23T02:00:05.474Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T02:00:01.000Z', '_widget_1744873387502': '2026-02-23T02:00:05.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb50fd89e0cfb588ef327', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T02:01:51.376Z', 'updateTime': '2026-02-23T02:01:51.376Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T02:00:01.000Z', '_widget_1744873387502': '2026-02-23T02:01:51.000Z', '_widget_1744873387504': '110', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bb6aabb2676472722b26f', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T02:08:42.043Z', 'updateTime': '2026-02-23T02:08:42.043Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '异常服务待办派发', '_widget_1744873387501': '2026-02-23T02:00:41.000Z', '_widget_1744873387502': '2026-02-23T02:08:41.000Z', '_widget_1744873387504': '480', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bc2b6bb267647272be5f3', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T03:00:06.432Z', 'updateTime': '2026-02-23T03:00:06.432Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T03:00:02.000Z', '_widget_1744873387502': '2026-02-23T03:00:06.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bc31a21b865706e9a07c7', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T03:01:46.581Z', 'updateTime': '2026-02-23T03:01:46.581Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T03:00:02.000Z', '_widget_1744873387502': '2026-02-23T03:01:46.000Z', '_widget_1744873387504': '104', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bd0c8c4526a0fb31cab52', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T04:00:08.047Z', 'updateTime': '2026-02-23T04:00:08.047Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T04:00:02.000Z', '_widget_1744873387502': '2026-02-23T04:00:07.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bd12c6cc6edda46f611f3', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T04:01:48.665Z', 'updateTime': '2026-02-23T04:01:48.665Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T04:00:02.000Z', '_widget_1744873387502': '2026-02-23T04:01:48.000Z', '_widget_1744873387504': '106', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bd13b6b865746fe647937', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T04:02:03.180Z', 'updateTime': '2026-02-23T04:02:03.180Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '非标业绩提报转BI', '_widget_1744873387501': '2026-02-23T04:02:00.000Z', '_widget_1744873387502': '2026-02-23T04:02:03.000Z', '_widget_1744873387504': '3', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bd192ab309d2e5743b60f', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T04:03:30.300Z', 'updateTime': '2026-02-23T04:03:30.300Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '合伙人结算登记同步到BI', '_widget_1744873387501': '2026-02-23T04:03:00.000Z', '_widget_1744873387502': '2026-02-23T04:03:30.000Z', '_widget_1744873387504': '30', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bded6ba28a774309b02e3', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T05:00:06.698Z', 'updateTime': '2026-02-23T05:00:06.698Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T05:00:02.000Z', '_widget_1744873387502': '2026-02-23T05:00:06.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bdf40f3ced099adef4533', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T05:01:52.919Z', 'updateTime': '2026-02-23T05:01:52.919Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T05:00:02.000Z', '_widget_1744873387502': '2026-02-23T05:01:52.000Z', '_widget_1744873387504': '110', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699be198a6312699f3f66600', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T05:11:52.618Z', 'updateTime': '2026-02-23T05:11:52.618Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': 'NGV更新数据', '_widget_1744873387501': '2026-02-23T04:30:04.000Z', '_widget_1744873387502': '2026-02-23T05:11:52.000Z', '_widget_1744873387504': '2508', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bece6a6312699f3ff7a78', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T06:00:06.979Z', 'updateTime': '2026-02-23T06:00:06.979Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T06:00:02.000Z', '_widget_1744873387502': '2026-02-23T06:00:06.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bed46049df941e555738a', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T06:01:42.686Z', 'updateTime': '2026-02-23T06:01:42.686Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T06:00:02.000Z', '_widget_1744873387502': '2026-02-23T06:01:42.000Z', '_widget_1744873387504': '100', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bfaf8e276a38cb29811e1', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T07:00:08.733Z', 'updateTime': '2026-02-23T07:00:08.733Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T07:00:02.000Z', '_widget_1744873387502': '2026-02-23T07:00:08.000Z', '_widget_1744873387504': '6', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699bfb5ae606c83377b26a83', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T07:01:46.229Z', 'updateTime': '2026-02-23T07:01:46.229Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T07:00:02.000Z', '_widget_1744873387502': '2026-02-23T07:01:46.000Z', '_widget_1744873387504': '104', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c09072444810c0bf158a4', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T08:00:07.983Z', 'updateTime': '2026-02-23T08:00:07.983Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T08:00:02.000Z', '_widget_1744873387502': '2026-02-23T08:00:07.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c096d0231857db5783021', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T08:01:49.310Z', 'updateTime': '2026-02-23T08:01:49.310Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T08:00:02.000Z', '_widget_1744873387502': '2026-02-23T08:01:48.000Z', '_widget_1744873387504': '106', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c17151278494a264cd984', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T09:00:05.447Z', 'updateTime': '2026-02-23T09:00:05.447Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T09:00:02.000Z', '_widget_1744873387502': '2026-02-23T09:00:04.000Z', '_widget_1744873387504': '2', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c1772ed29cdb3bc6edf57', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T09:01:38.528Z', 'updateTime': '2026-02-23T09:01:38.528Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '非标业绩提报转BI', '_widget_1744873387501': '2026-02-23T09:01:23.000Z', '_widget_1744873387502': '2026-02-23T09:01:38.000Z', '_widget_1744873387504': '15', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c17795afe4f1583e6e4a4', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T09:01:45.259Z', 'updateTime': '2026-02-23T09:01:45.259Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T09:00:02.000Z', '_widget_1744873387502': '2026-02-23T09:01:44.000Z', '_widget_1744873387504': '102', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c17c00bdffe31d5db6ec4', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T09:02:56.522Z', 'updateTime': '2026-02-23T09:02:56.522Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '合伙人结算登记同步到BI', '_widget_1744873387501': '2026-02-23T09:02:23.000Z', '_widget_1744873387502': '2026-02-23T09:02:55.000Z', '_widget_1744873387504': '32', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c25267bf0348e327bed5a', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T10:00:06.295Z', 'updateTime': '2026-02-23T10:00:06.295Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T10:00:02.000Z', '_widget_1744873387502': '2026-02-23T10:00:06.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c2593a4b0d9369ba61515', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T10:01:55.536Z', 'updateTime': '2026-02-23T10:01:55.536Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T10:00:02.000Z', '_widget_1744873387502': '2026-02-23T10:01:55.000Z', '_widget_1744873387504': '113', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c33367bf0348e32885df8', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T11:00:06.453Z', 'updateTime': '2026-02-23T11:00:06.453Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T11:00:01.000Z', '_widget_1744873387502': '2026-02-23T11:00:06.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c33a843db686ad5f7cb1b', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T11:02:00.440Z', 'updateTime': '2026-02-23T11:02:00.440Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T11:00:01.000Z', '_widget_1744873387502': '2026-02-23T11:02:00.000Z', '_widget_1744873387504': '119', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c4147205acb4b4c3439a0', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T12:00:07.284Z', 'updateTime': '2026-02-23T12:00:07.284Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T12:00:02.000Z', '_widget_1744873387502': '2026-02-23T12:00:07.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c41ad9fc801efc734512c', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T12:01:49.178Z', 'updateTime': '2026-02-23T12:01:49.178Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T12:00:02.000Z', '_widget_1744873387502': '2026-02-23T12:01:49.000Z', '_widget_1744873387504': '107', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c4f5614a266a4fa4c955a', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T13:00:06.759Z', 'updateTime': '2026-02-23T13:00:06.759Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T13:00:02.000Z', '_widget_1744873387502': '2026-02-23T13:00:06.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c4fb6654487d78f493dbf', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T13:01:42.670Z', 'updateTime': '2026-02-23T13:01:42.670Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T13:00:02.000Z', '_widget_1744873387502': '2026-02-23T13:01:42.000Z', '_widget_1744873387504': '100', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c5d67bd4f2251f9fcfa06', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T14:00:07.768Z', 'updateTime': '2026-02-23T14:00:07.768Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T14:00:02.000Z', '_widget_1744873387502': '2026-02-23T14:00:07.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c5dd1a4b0d9369bd6e1d7', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T14:01:53.102Z', 'updateTime': '2026-02-23T14:01:53.102Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T14:00:02.000Z', '_widget_1744873387502': '2026-02-23T14:01:52.000Z', '_widget_1744873387504': '110', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c6b7c806941eed69e73fc', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T15:00:12.027Z', 'updateTime': '2026-02-23T15:00:12.027Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T15:00:02.000Z', '_widget_1744873387502': '2026-02-23T15:00:11.000Z', '_widget_1744873387504': '9', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c6bd8ce153aec688c0292', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T15:01:44.333Z', 'updateTime': '2026-02-23T15:01:44.333Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T15:00:02.000Z', '_widget_1744873387502': '2026-02-23T15:01:44.000Z', '_widget_1744873387504': '102', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c7985ce153aec689731ec', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T16:00:05.670Z', 'updateTime': '2026-02-23T16:00:05.670Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T16:00:02.000Z', '_widget_1744873387502': '2026-02-23T16:00:05.000Z', '_widget_1744873387504': '3', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c79ec16d3c9c3257a4579', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T16:01:48.284Z', 'updateTime': '2026-02-23T16:01:48.284Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T16:00:02.000Z', '_widget_1744873387502': '2026-02-23T16:01:48.000Z', '_widget_1744873387504': '106', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c87942444810c0b611f96', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T17:00:04.032Z', 'updateTime': '2026-02-23T17:00:04.032Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T17:00:02.000Z', '_widget_1744873387502': '2026-02-23T17:00:03.000Z', '_widget_1744873387504': '1', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c87f920538415f63cfa50', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T17:01:45.155Z', 'updateTime': '2026-02-23T17:01:45.155Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T17:00:02.000Z', '_widget_1744873387502': '2026-02-23T17:01:44.000Z', '_widget_1744873387504': '102', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c95a3e276a38cb21eff48', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T18:00:03.746Z', 'updateTime': '2026-02-23T18:00:03.746Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T18:00:01.000Z', '_widget_1744873387502': '2026-02-23T18:00:03.000Z', '_widget_1744873387504': '2', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699c96100c4d4882f5f28406', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T18:01:52.916Z', 'updateTime': '2026-02-23T18:01:52.916Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T18:00:01.000Z', '_widget_1744873387502': '2026-02-23T18:01:52.000Z', '_widget_1744873387504': '111', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ca3b50c32d8de42e92d47', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T19:00:05.295Z', 'updateTime': '2026-02-23T19:00:05.295Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T19:00:01.000Z', '_widget_1744873387502': '2026-02-23T19:00:05.000Z', '_widget_1744873387504': '4', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ca41b057a5fdbf0c8299f', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T19:01:47.041Z', 'updateTime': '2026-02-23T19:01:47.041Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T19:00:02.000Z', '_widget_1744873387502': '2026-02-23T19:01:46.000Z', '_widget_1744873387504': '104', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cb1c90231857db50cc269', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:00:09.267Z', 'updateTime': '2026-02-23T20:00:09.267Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T20:00:01.000Z', '_widget_1744873387502': '2026-02-23T20:00:08.000Z', '_widget_1744873387504': '7', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cb2280c4d4882f50ce59d', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:01:44.704Z', 'updateTime': '2026-02-23T20:01:44.704Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T20:00:02.000Z', '_widget_1744873387502': '2026-02-23T20:01:43.000Z', '_widget_1744873387504': '101', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cb4b31e0ffac0b145194e', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:12:35.781Z', 'updateTime': '2026-02-23T20:12:35.781Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '短信数据支撑', '_widget_1744873387501': '2026-02-23T20:10:10.000Z', '_widget_1744873387502': '2026-02-23T20:12:35.000Z', '_widget_1744873387504': '145', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cb67a9fa5a1c0477231cb', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:20:10.896Z', 'updateTime': '2026-02-23T20:20:10.896Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '异业合作数据支撑', '_widget_1744873387501': '2026-02-23T20:20:10.000Z', '_widget_1744873387502': '2026-02-23T20:20:10.000Z', '_widget_1744873387504': '0', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cbb44cfbbc4fa3b1ced3c', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:40:36.637Z', 'updateTime': '2026-02-23T20:40:36.637Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '私域小程序数据支撑', '_widget_1744873387501': '2026-02-23T20:40:10.000Z', '_widget_1744873387502': '2026-02-23T20:40:36.000Z', '_widget_1744873387504': '26', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cbb8563a6e46a0627003d', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T20:41:41.090Z', 'updateTime': '2026-02-23T20:41:41.090Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '小六提成数据支撑', '_widget_1744873387501': '2026-02-23T20:41:10.000Z', '_widget_1744873387502': '2026-02-23T20:41:40.000Z', '_widget_1744873387504': '30', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cbfdc314eb23a7b205dfe', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T21:00:12.877Z', 'updateTime': '2026-02-23T21:00:12.877Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T21:00:02.000Z', '_widget_1744873387502': '2026-02-23T21:00:12.000Z', '_widget_1744873387504': '10', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cbfe9600aa8fbf9d72bde', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T21:00:25.816Z', 'updateTime': '2026-02-23T21:00:25.816Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '高德匹配手机号', '_widget_1744873387501': '2026-02-23T21:00:10.000Z', '_widget_1744873387502': '2026-02-23T21:00:25.000Z', '_widget_1744873387504': '15', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cc034e276a38cb245a282', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T21:01:40.495Z', 'updateTime': '2026-02-23T21:01:40.495Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T21:00:03.000Z', '_widget_1744873387502': '2026-02-23T21:01:40.000Z', '_widget_1744873387504': '97', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ccdee775b2d60749f0ee5', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T22:00:14.885Z', 'updateTime': '2026-02-23T22:00:14.885Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T22:00:02.000Z', '_widget_1744873387502': '2026-02-23T22:00:14.000Z', '_widget_1744873387504': '12', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cce470c32d8de4210d760', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T22:01:43.313Z', 'updateTime': '2026-02-23T22:01:43.313Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T22:00:02.000Z', '_widget_1744873387502': '2026-02-23T22:01:42.000Z', '_widget_1744873387504': '100', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cdbf6314eb23a7b3b1120', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T23:00:06.937Z', 'updateTime': '2026-02-23T23:00:06.937Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '简道云员工ID表更新', '_widget_1744873387501': '2026-02-23T23:00:01.000Z', '_widget_1744873387502': '2026-02-23T23:00:06.000Z', '_widget_1744873387504': '5', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699cdc57a4b0d9369b4bc3a2', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T23:01:43.061Z', 'updateTime': '2026-02-23T23:01:43.061Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': '字段监控', '_widget_1744873387501': '2026-02-23T23:00:02.000Z', '_widget_1744873387502': '2026-02-23T23:01:42.000Z', '_widget_1744873387504': '100', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "{'_id': '699ce3b61278494a26043fb2', 'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2026-02-23T23:33:10.251Z', 'updateTime': '2026-02-23T23:33:10.251Z', 'deleteTime': None, '_widget_1744873387500': '2026-02-23T00:00:00.000Z', '_widget_1743644977694': 'NGV新增数据', '_widget_1744873387501': '2026-02-23T23:30:25.000Z', '_widget_1744873387502': '2026-02-23T23:33:09.000Z', '_widget_1744873387504': '164', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}\n", + "正在计算 [2026-02-23] 的 48 个时间槽并发情况...\n", + "正在写入 48 条统计数据到目标表单...\n", + "{'code': 200, 'msg': '处理完成。统计日期:2026-02-23, 成功批次: 1/1', 'detail': [{'status': 'success', 'success_count': 48, 'success_ids': ['699d7316e1be306334210cab', '699d7316e1be306334210cac', '699d7316e1be306334210cad', '699d7316e1be306334210cae', '699d7316e1be306334210caf', '699d7316e1be306334210cb0', '699d7316e1be306334210cb1', '699d7316e1be306334210cb2', '699d7316e1be306334210cb3', '699d7316e1be306334210cb4', '699d7316e1be306334210cb5', '699d7316e1be306334210cb6', '699d7316e1be306334210cb7', '699d7316e1be306334210cb8', '699d7316e1be306334210cb9', '699d7316e1be306334210cba', '699d7316e1be306334210cbb', '699d7316e1be306334210cbc', '699d7316e1be306334210cbd', '699d7316e1be306334210cbe', '699d7316e1be306334210cbf', '699d7316e1be306334210cc0', '699d7316e1be306334210cc1', '699d7316e1be306334210cc2', '699d7316e1be306334210cc3', '699d7316e1be306334210cc4', '699d7316e1be306334210cc5', '699d7316e1be306334210cc6', '699d7316e1be306334210cc7', '699d7316e1be306334210cc8', '699d7316e1be306334210cc9', '699d7316e1be306334210cca', '699d7316e1be306334210ccb', '699d7316e1be306334210ccc', '699d7316e1be306334210ccd', '699d7316e1be306334210cce', '699d7316e1be306334210ccf', '699d7316e1be306334210cd0', '699d7316e1be306334210cd1', '699d7316e1be306334210cd2', '699d7316e1be306334210cd3', '699d7316e1be306334210cd4', '699d7316e1be306334210cd5', '699d7316e1be306334210cd6', '699d7316e1be306334210cd7', '699d7316e1be306334210cd8', '699d7316e1be306334210cd9', '699d7316e1be306334210cda']}]}\n" + ] + } + ], + "source": [ + "import json\n", + "from datetime import datetime, timedelta\n", + "import requests\n", + "import time\n", + "from decimal import Decimal\n", + "\n", + "# ================= 辅助函数定义 =================\n", + "\n", + "def replace_decimals(obj):\n", + " if isinstance(obj, dict):\n", + " return {k: replace_decimals(v) for k, v in obj.items()}\n", + " elif isinstance(obj, list):\n", + " return [replace_decimals(item) for item in obj]\n", + " elif isinstance(obj, Decimal):\n", + " return float(obj)\n", + " return obj\n", + "\n", + "class NpEncoder(json.JSONEncoder):\n", + " def default(self, obj):\n", + " try:\n", + " import numpy as np\n", + " if isinstance(obj, np.integer):\n", + " return int(obj)\n", + " elif isinstance(obj, np.floating):\n", + " return float(obj)\n", + " elif isinstance(obj, np.ndarray):\n", + " return obj.tolist()\n", + " except ImportError:\n", + " pass\n", + " return super(NpEncoder, self).default(obj)\n", + "\n", + "def entry_data_list(data: dict, replace: bool = False, max_retries: int = 20):\n", + " \"\"\"获取多条表单数据\"\"\"\n", + " url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/list'\n", + " API_TOKEN = \"Bearer qygHulymo1fekJk4CIZyNKjyQAzG8CFN\"\n", + " headers = {\n", + " 'Authorization': API_TOKEN,\n", + " 'Content-Type': 'application/json'\n", + " }\n", + " \n", + " all_data_batches = []\n", + " last_data_id = None\n", + " exit_flag = False\n", + " \n", + " while True:\n", + " payload = json.dumps({\n", + " \"app_id\": data['api_key'],\n", + " \"entry_id\": data['entry_id'],\n", + " \"limit\": 90,\n", + " \"data_id\": last_data_id,\n", + " \"filter\": data.get('filter', None)\n", + " })\n", + " retries = 0\n", + " while retries <= max_retries:\n", + " data_get = None\n", + " try:\n", + " res = requests.post(url=url, data=payload, headers=headers, timeout=10)\n", + " res.raise_for_status()\n", + " data_get = res.json()\n", + " \n", + " if data_get.get(\"data\"):\n", + " all_data_batches.extend(data_get['data'])\n", + " last_data_id = data_get['data'][-1].get('_id')\n", + " print(f\"已获取 {len(all_data_batches)} 条数据\")\n", + " break\n", + " else:\n", + " exit_flag = True\n", + " break\n", + " except requests.exceptions.RequestException as e:\n", + " print(f\"请求异常: {e}, 重试 ({retries+1}/{max_retries})\")\n", + " retries += 1\n", + " time.sleep(0.5)\n", + " \n", + " if retries > max_retries:\n", + " print(\"达到最大重试次数,停止获取。\")\n", + " break\n", + " if exit_flag:\n", + " break\n", + "\n", + " final_data = {'data': all_data_batches}\n", + " \n", + " if replace:\n", + " print(\"警告:replace=True 但 field_replacement 函数未在此脚本定义,将返回原始数据。\")\n", + " # 如果需要替换,请确保环境中定义了 field_replacement 函数\n", + " # return_data = field_replacement(data, final_data) \n", + " # return return_data\n", + " return final_data\n", + " else:\n", + " return final_data\n", + "\n", + "def entry_data_batch_create(data: dict, chunk_size: int = 90, max_retries: int = 20):\n", + " \"\"\"新建多条数据\"\"\"\n", + " data = replace_decimals(data)\n", + " url = 'https://api.jiandaoyun.com/api/v5/app/entry/data/batch_create'\n", + " API_TOKEN = \"Bearer qygHulymo1fekJk4CIZyNKjyQAzG8CFN\"\n", + " headers = {\n", + " 'Authorization': API_TOKEN,\n", + " 'Content-Type': 'application/json'\n", + " }\n", + "\n", + " total_length = len(data['data_list'])\n", + " num_chunks = (total_length + chunk_size - 1) // chunk_size\n", + " data_get_list = []\n", + "\n", + " for i in range(num_chunks):\n", + " start_index = i * chunk_size\n", + " end_index = min(start_index + chunk_size, total_length)\n", + " \n", + " payload = json.dumps({\n", + " \"app_id\": data['api_key'],\n", + " \"entry_id\": data['entry_id'],\n", + " \"data_list\": data['data_list'][start_index:end_index],\n", + " \"is_start_workflow\": data.get('is_start_workflow', \"false\"),\n", + " \"is_start_trigger\": data.get('is_start_trigger', \"false\"),\n", + " }, cls=NpEncoder)\n", + " \n", + " retries = 0\n", + " while retries <= max_retries:\n", + " try:\n", + " res = requests.post(url=url, data=payload, headers=headers, timeout=15)\n", + " res.raise_for_status()\n", + " data_get = res.json()\n", + " \n", + " if data_get.get(\"status\") == \"success\":\n", + " data_get_list.append(data_get)\n", + " break\n", + " else:\n", + " retries += 1\n", + " time.sleep(3)\n", + " except requests.exceptions.RequestException as e:\n", + " print(f\"批量创建请求异常: {e}\")\n", + " retries += 1\n", + " time.sleep(0.5)\n", + " \n", + " if retries > max_retries:\n", + " print(f\"批次 {i+1}/{num_chunks} 请求失败,已放弃。\")\n", + " data_get_list.append(None)\n", + "\n", + " return data_get_list\n", + "\n", + "# ================= 主业务逻辑 =================\n", + "\n", + "def calculate_server_load():\n", + " # --- 配置 ---\n", + " APP_ID = \"6694d3c4fcb69ca9a111a6c4\"\n", + " SOURCE_FORM_ID = \"67ede908eb9c22261016466e\"\n", + " TARGET_FORM_ID = \"699d4f82ae9623e204969627\"\n", + " \n", + " # 【重要】请核实 ID\n", + " # 用于过滤和读取的“日期”字段 (精确到日)\n", + " WIDGET_DATE_FIELD = \"_widget_1744873387500\" \n", + " # 用于读取具体时间的“开始时间”和“结束时间”字段 (精确到时分秒)\n", + " # 注意:如果源表单只有一个“日期”字段而没有具体时间点,逻辑需要调整。\n", + " # 假设你仍有具体的开始/结束时间字段用于计算时长。如果没有,需确认如何计算30分钟槽。\n", + " # 此处假设你有具体的时分秒字段,如果只有日期字段,所有任务将被视为全天或无法计算精确并发。\n", + " # 如果你的业务逻辑是:只要日期是昨天,就算作昨天的任务,且没有具体时间点,\n", + " # 那么下面的时间解析部分需要适配。\n", + " # **这里假设你依然有具体的开始/结束时间组件用于计算并发**\n", + " WIDGET_START_TIME = \"_widget_1744873387501\" # 请替换为实际的开始时间(含时分) ID\n", + " WIDGET_END_TIME = \"_widget_1744873387502\" # 请替换为实际的结束时间(含时分) ID\n", + " \n", + " now = datetime.now()\n", + " today_str = now.strftime(\"%Y-%m-%d\")\n", + " \n", + " # 计算昨天的日期\n", + " yesterday_dt = now - timedelta(days=1)\n", + " yesterday_str = yesterday_dt.strftime(\"%Y-%m-%d\")\n", + " \n", + " print(f\"正在筛选日期为:{yesterday_str} 的任务...\")\n", + "\n", + " # --- 构造过滤器 ---\n", + " # 使用日期字段 (精确到日) 进行等值匹配\n", + " FILTER = {\n", + " \"rel\": \"and\",\n", + " \"cond\": [\n", + " {\n", + " \"field\": WIDGET_DATE_FIELD,\n", + " \"type\": \"date\", # 注意这里是 date 不是 datetime\n", + " \"method\": \"eq\", # 等于\n", + " \"value\": [yesterday_str] # 格式 YYYY-MM-DD\n", + " }\n", + " ]\n", + " }\n", + " \n", + " data = {\n", + " \"api_key\": APP_ID, \n", + " \"entry_id\": SOURCE_FORM_ID, \n", + " \"filter\": FILTER\n", + " } \n", + "\n", + " print(\"正在从简道云获取源数据...\")\n", + " # 使用 replace=False,通过 Widget ID 获取\n", + " raw_response = entry_data_list(data, replace=False)\n", + " tasks_raw = raw_response.get(\"data\", [])\n", + " \n", + " if not tasks_raw:\n", + " print(f\"未获取到日期为 {yesterday_str} 的任务数据。\")\n", + " # 即使没有数据,也可以生成全0的统计表,或者根据需求直接返回\n", + " # 这里选择继续生成全0的统计\n", + " tasks = []\n", + " else:\n", + " print(f\"API 返回原始数据条数: {len(tasks_raw)}\")\n", + " tasks = []\n", + " for item in tasks_raw:\n", + " print(item)\n", + " # 获取具体时间值\n", + " s_val = item.get(WIDGET_START_TIME, {})\n", + " e_val = item.get(WIDGET_END_TIME, {})\n", + " \n", + " # 如果源数据只有日期没有具体时间,可能需要默认设为当天 00:00 到 23:59\n", + " # 这里假设必须有具体时间才能计算并发\n", + " if not s_val or not e_val:\n", + " # 兼容处理:如果只有日期字段,尝试用日期字段补全\n", + " # 如果业务上不需要精确到分,可在此处设定默认值\n", + " continue \n", + " \n", + " try:\n", + " # --- 核心修复:处理 ISO 8601 格式 (含 T 和 Z) ---\n", + " # 1. 转为字符串\n", + " s_str = str(s_val)\n", + " e_str = str(e_val)\n", + " \n", + " # 2. 替换 'T' 为空格,去掉 'Z' 和毫秒部分\n", + " # 示例: 2026-02-23T00:00:01.000Z -> 2026-02-23 00:00:01\n", + " s_clean = s_str.replace('T', ' ').replace('Z', '').split('.')[0]\n", + " e_clean = e_str.replace('T', ' ').replace('Z', '').split('.')[0]\n", + " \n", + " # 3. 解析\n", + " s_dt = datetime.strptime(s_clean, \"%Y-%m-%d %H:%M:%S\")\n", + " e_dt = datetime.strptime(e_clean, \"%Y-%m-%d %H:%M:%S\")\n", + " \n", + " tasks.append({\"start\": s_dt, \"end\": e_dt})\n", + " \n", + " except Exception as e:\n", + " # 调试用:打印具体哪条数据失败\n", + " print(f\"解析失败: {s_val}, 错误: {e}\")\n", + " continue\n", + "\n", + " # --- 确定统计哪一天的时间槽 ---\n", + " # 既然过滤的是昨天的数据,推测你需要生成【昨天】的负载报表\n", + " stats_date_str = yesterday_str\n", + " base_time = datetime.strptime(stats_date_str, \"%Y-%m-%d\")\n", + " stats_date_end = base_time + timedelta(days=1)\n", + " \n", + " print(f\"正在计算 [{stats_date_str}] 的 48 个时间槽并发情况...\")\n", + " \n", + " # 目标表单 Widget ID (请替换为真实 ID)\n", + " WIDGET_T_DATE = \"_widget_1771917185994\"\n", + " WIDGET_T_SLOT = \"_widget_1771917185995\"\n", + " WIDGET_T_COUNT = \"_widget_1771917185996\"\n", + " WIDGET_T_IDLE = \"_widget_1771917264186\"\n", + " WIDGET_T_NORMAL = \"_widget_1771917918805\"\n", + " WIDGET_T_BUSY = \"_widget_1771917918806\"\n", + "\n", + " slots = []\n", + " for i in range(48): \n", + " slot_start = base_time + timedelta(minutes=i*30)\n", + " slot_end = slot_start + timedelta(minutes=30)\n", + " \n", + " count = 0\n", + " for t in tasks:\n", + " # 判断任务是否与该30分钟槽有重叠\n", + " if t[\"start\"] < slot_end and slot_start < t[\"end\"]:\n", + " count += 1\n", + " \n", + " is_idle = 1 if count == 0 else 0\n", + " is_normal = 1 if 1 <= count <= 3 else 0\n", + " is_busy = 1 if count > 3 else 0\n", + " \n", + " slots.append({\n", + " WIDGET_T_DATE: {\"value\": stats_date_str},\n", + " WIDGET_T_SLOT: {\"value\": slot_start.strftime(\"%H:%M\")},\n", + " WIDGET_T_COUNT: {\"value\": count},\n", + " WIDGET_T_IDLE: {\"value\": is_idle},\n", + " WIDGET_T_NORMAL: {\"value\": is_normal},\n", + " WIDGET_T_BUSY: {\"value\": is_busy},\n", + " })\n", + "\n", + " if not slots:\n", + " return {\"code\": 200, \"msg\": \"未生成时间槽数据\"}\n", + " \n", + " payload = {\n", + " \"api_key\": APP_ID,\n", + " \"entry_id\": TARGET_FORM_ID,\n", + " \"data_list\": slots,\n", + " \"is_start_workflow\": \"false\", \n", + " \"is_start_trigger\": \"false\"\n", + " }\n", + " \n", + " print(f\"正在写入 {len(slots)} 条统计数据到目标表单...\")\n", + " result = entry_data_batch_create(payload)\n", + " \n", + " success_count = sum(1 for r in result if r and r.get(\"status\") == \"success\")\n", + " \n", + " return {\n", + " \"code\": 200, \n", + " \"msg\": f\"处理完成。统计日期:{stats_date_str}, 成功批次: {success_count}/{len(result)}\", \n", + " \"detail\": result\n", + " }\n", + "\n", + "# 如果需要直接运行测试\n", + "if __name__ == \"__main__\":\n", + " # 确保在实际运行前替换了所有 WIDGET_ID\n", + " res = calculate_server_load()\n", + " print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "342edfbf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "正在获取源数据...\n", + "已获取 90 条数据\n", + "已获取 180 条数据\n", + "已获取 270 条数据\n", + "已获取 360 条数据\n", + "已获取 450 条数据\n", + "已获取 540 条数据\n", + "已获取 630 条数据\n", + "已获取 720 条数据\n", + "已获取 810 条数据\n", + "已获取 900 条数据\n", + "已获取 990 条数据\n", + "已获取 1080 条数据\n", + "已获取 1170 条数据\n", + "已获取 1260 条数据\n", + "已获取 1350 条数据\n", + "已获取 1440 条数据\n", + "已获取 1530 条数据\n", + "已获取 1620 条数据\n", + "已获取 1710 条数据\n", + "已获取 1800 条数据\n", + "已获取 1890 条数据\n", + "已获取 1980 条数据\n", + "已获取 2070 条数据\n", + "已获取 2160 条数据\n", + "已获取 2250 条数据\n", + "已获取 2340 条数据\n", + "已获取 2430 条数据\n", + "已获取 2520 条数据\n", + "已获取 2610 条数据\n", + "已获取 2700 条数据\n", + "已获取 2790 条数据\n", + "已获取 2880 条数据\n", + "已获取 2970 条数据\n", + "已获取 3060 条数据\n", + "已获取 3150 条数据\n", + "已获取 3240 条数据\n", + "已获取 3330 条数据\n", + "已获取 3420 条数据\n", + "已获取 3510 条数据\n", + "已获取 3600 条数据\n", + "已获取 3690 条数据\n", + "已获取 3780 条数据\n", + "已获取 3870 条数据\n", + "已获取 3960 条数据\n", + "已获取 4050 条数据\n", + "已获取 4140 条数据\n", + "已获取 4230 条数据\n", + "已获取 4320 条数据\n", + "已获取 4410 条数据\n", + "已获取 4500 条数据\n", + "已获取 4590 条数据\n", + "已获取 4680 条数据\n", + "已获取 4770 条数据\n", + "已获取 4860 条数据\n", + "已获取 4950 条数据\n", + "已获取 5040 条数据\n", + "已获取 5130 条数据\n", + "已获取 5220 条数据\n", + "已获取 5310 条数据\n", + "已获取 5400 条数据\n", + "已获取 5490 条数据\n", + "已获取 5580 条数据\n", + "已获取 5670 条数据\n", + "已获取 5760 条数据\n", + "已获取 5850 条数据\n", + "已获取 5940 条数据\n", + "已获取 6030 条数据\n", + "已获取 6120 条数据\n", + "已获取 6210 条数据\n", + "已获取 6300 条数据\n", + "已获取 6390 条数据\n", + "已获取 6480 条数据\n", + "已获取 6570 条数据\n", + "已获取 6660 条数据\n", + "已获取 6750 条数据\n", + "已获取 6840 条数据\n", + "已获取 6930 条数据\n", + "已获取 7020 条数据\n", + "已获取 7110 条数据\n", + "已获取 7200 条数据\n", + "已获取 7290 条数据\n", + "已获取 7380 条数据\n", + "已获取 7470 条数据\n", + "已获取 7560 条数据\n", + "已获取 7650 条数据\n", + "已获取 7740 条数据\n", + "已获取 7830 条数据\n", + "已获取 7920 条数据\n", + "已获取 8010 条数据\n", + "已获取 8100 条数据\n", + "已获取 8190 条数据\n", + "已获取 8280 条数据\n", + "已获取 8370 条数据\n", + "已获取 8460 条数据\n", + "已获取 8550 条数据\n", + "已获取 8640 条数据\n", + "已获取 8730 条数据\n", + "已获取 8820 条数据\n", + "已获取 8910 条数据\n", + "已获取 9000 条数据\n", + "已获取 9090 条数据\n", + "已获取 9180 条数据\n", + "已获取 9270 条数据\n", + "已获取 9360 条数据\n", + "已获取 9450 条数据\n", + "已获取 9540 条数据\n", + "已获取 9630 条数据\n", + "已获取 9720 条数据\n", + "已获取 9810 条数据\n", + "已获取 9900 条数据\n", + "已获取 9990 条数据\n", + "已获取 10080 条数据\n", + "已获取 10170 条数据\n", + "已获取 10260 条数据\n", + "已获取 10350 条数据\n", + "已获取 10440 条数据\n", + "已获取 10530 条数据\n", + "已获取 10620 条数据\n", + "已获取 10710 条数据\n", + "已获取 10800 条数据\n", + "已获取 10890 条数据\n", + "已获取 10980 条数据\n", + "已获取 11070 条数据\n", + "已获取 11160 条数据\n", + "已获取 11250 条数据\n", + "已获取 11340 条数据\n", + "已获取 11430 条数据\n", + "已获取 11520 条数据\n", + "已获取 11610 条数据\n", + "已获取 11700 条数据\n", + "已获取 11790 条数据\n", + "已获取 11880 条数据\n", + "已获取 11970 条数据\n", + "已获取 12060 条数据\n", + "已获取 12150 条数据\n", + "已获取 12240 条数据\n", + "已获取 12330 条数据\n", + "已获取 12420 条数据\n", + "已获取 12510 条数据\n", + "已获取 12600 条数据\n", + "已获取 12690 条数据\n", + "已获取 12780 条数据\n", + "已获取 12870 条数据\n", + "已获取 12960 条数据\n", + "已获取 13050 条数据\n", + "已获取 13140 条数据\n", + "已获取 13230 条数据\n", + "已获取 13320 条数据\n", + "已获取 13410 条数据\n", + "已获取 13500 条数据\n", + "已获取 13590 条数据\n", + "已获取 13680 条数据\n", + "已获取 13770 条数据\n", + "已获取 13860 条数据\n", + "已获取 13950 条数据\n", + "已获取 14040 条数据\n", + "已获取 14130 条数据\n", + "已获取 14220 条数据\n", + "已获取 14310 条数据\n", + "已获取 14400 条数据\n", + "已获取 14490 条数据\n", + "已获取 14580 条数据\n", + "已获取 14670 条数据\n", + "已获取 14760 条数据\n", + "已获取 14850 条数据\n", + "已获取 14940 条数据\n", + "已获取 15030 条数据\n", + "已获取 15096 条数据\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'str' object has no attribute 'get'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m result = \u001b[43mcalculate_server_load\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m result\n", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 226\u001b[39m, in \u001b[36mcalculate_server_load\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m 223\u001b[39m tasks = []\n\u001b[32m 224\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m item \u001b[38;5;129;01min\u001b[39;00m tasks_raw:\n\u001b[32m 225\u001b[39m \u001b[38;5;66;03m# 使用 Widget ID 获取值\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m226\u001b[39m s_val = \u001b[43mitem\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mWIDGET_START_TIME\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m(\u001b[33m'\u001b[39m\u001b[33mvalue\u001b[39m\u001b[33m'\u001b[39m)\n\u001b[32m 227\u001b[39m e_val = item.get(WIDGET_END_TIME, {}).get(\u001b[33m'\u001b[39m\u001b[33mvalue\u001b[39m\u001b[33m'\u001b[39m)\n\u001b[32m 229\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m s_val \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m e_val:\n", + "\u001b[31mAttributeError\u001b[39m: 'str' object has no attribute 'get'" + ] + } + ], + "source": [ + "result = calculate_server_load()\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "60531b14", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'tasks_raw' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mtasks_raw\u001b[49m\n", + "\u001b[31mNameError\u001b[39m: name 'tasks_raw' is not defined" + ] + } + ], + "source": [ + "tasks_raw" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "F6+宜搭+其它", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/张阳脚本/简道云刷数据/人员近一年使用频率.ipynb b/张阳脚本/简道云刷数据/人员近一年使用频率.ipynb new file mode 100644 index 0000000..6f92785 --- /dev/null +++ b/张阳脚本/简道云刷数据/人员近一年使用频率.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "92f27fd2", + "metadata": {}, + "source": [ + "管理后台-使用统计" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "679fdcc5", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "<>:60: SyntaxWarning: invalid escape sequence '\\I'\n", + "<>:60: SyntaxWarning: invalid escape sequence '\\I'\n", + "C:\\Users\\hp_z66\\AppData\\Local\\Temp\\ipykernel_25140\\3645530864.py:60: SyntaxWarning: invalid escape sequence '\\I'\n", + " df.to_csv(\"D:\\Idea Project\\F6+宜搭+其它(1)\\张阳脚本\\文件输出\\人员使用记录.csv\")\n" + ] + } + ], + "source": [ + "import requests\n", + "import pandas as pd\n", + "\n", + "cookies = {\n", + " 'fx-lang': 'zh_cn',\n", + " 'auth_token': 's%3A.9uztgExtmqUJXHCi00hv9SGq6eVYSvH%2BxQSwrox1Yls',\n", + " 'sensorsdata2015jssdkcross': '%7B%22distinct_id%22%3A%2257956c24ceedab0c48c17b4e%22%2C%22first_id%22%3A%2219b6dd1a10c148a-063e3a033b10ed-4c657b58-2073600-19b6dd1a10d145b%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTliNmRkMWExMGMxNDhhLTA2M2UzYTAzM2IxMGVkLTRjNjU3YjU4LTIwNzM2MDAtMTliNmRkMWExMGQxNDViIiwiJGlkZW50aXR5X2xvZ2luX2lkIjoiNTc5NTZjMjRjZWVkYWIwYzQ4YzE3YjRlIn0%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%24identity_login_id%22%2C%22value%22%3A%2257956c24ceedab0c48c17b4e%22%7D%7D',\n", + " '_csrf': 's%3A_D_KxBikFhOaA2gkTYpORFF6.AqupOk5Q%2B7GUjR1bKbiQLAXksxGmkcsVthKkDYiBQRE',\n", + " 'Hm_lvt_de47dd1629940fe88b02865de93dd9fe': '1770176033,1770257492,1770281854,1770359422',\n", + " 'HMACCOUNT': 'A6A0585E8C70051D',\n", + " 'Hm_lpvt_de47dd1629940fe88b02865de93dd9fe': '1770600610',\n", + " 'GSuvNKHqfvX2r6v7P8HkZv2bow': 's%3ANKEleTNCioVWeMitYN3WOVYYmCXbGFB0.qD1J8obD4MP4FNXKiVimB2UWfI2g3Nm%2FFOuYEmdeQek',\n", + " 'JDY_SID': 's%3Aar54WVlu4J-OyZzN0zEvAOU_FgbWMSvc.nCgiElAa2EoL3zf2gCIUV4XCFBE6aF6fsodt4%2F1daj4',\n", + " 'acw_tc': '743e76f717706025725901488e72f65ae43f08af57c9b931c35df2a672f5ff',\n", + "}\n", + "\n", + "headers = {\n", + " 'accept': 'application/json, text/plain, */*',\n", + " 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',\n", + " 'content-type': 'application/json',\n", + " 'origin': 'https://www.jiandaoyun.com',\n", + " 'priority': 'u=1, i',\n", + " 'referer': 'https://www.jiandaoyun.com/product/usage_statistics',\n", + " 'sec-ch-ua': '\"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"144\", \"Microsoft Edge\";v=\"144\"',\n", + " 'sec-ch-ua-mobile': '?0',\n", + " 'sec-ch-ua-platform': '\"Windows\"',\n", + " 'sec-fetch-dest': 'empty',\n", + " 'sec-fetch-mode': 'cors',\n", + " 'sec-fetch-site': 'same-origin',\n", + " 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0',\n", + " 'x-csrf-token': 'V3tEncMi-0KtoUAbnjwbKp66GsbVQMEL4bAc',\n", + " 'x-jdy-ver': '10.17.2',\n", + " 'x-request-id': 'c16157d6-0b12-4bf2-b56c-6858f66831e1',\n", + " # 'cookie': 'fx-lang=zh_cn; auth_token=s%3A.9uztgExtmqUJXHCi00hv9SGq6eVYSvH%2BxQSwrox1Yls; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2257956c24ceedab0c48c17b4e%22%2C%22first_id%22%3A%2219b6dd1a10c148a-063e3a033b10ed-4c657b58-2073600-19b6dd1a10d145b%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTliNmRkMWExMGMxNDhhLTA2M2UzYTAzM2IxMGVkLTRjNjU3YjU4LTIwNzM2MDAtMTliNmRkMWExMGQxNDViIiwiJGlkZW50aXR5X2xvZ2luX2lkIjoiNTc5NTZjMjRjZWVkYWIwYzQ4YzE3YjRlIn0%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%24identity_login_id%22%2C%22value%22%3A%2257956c24ceedab0c48c17b4e%22%7D%7D; _csrf=s%3A_D_KxBikFhOaA2gkTYpORFF6.AqupOk5Q%2B7GUjR1bKbiQLAXksxGmkcsVthKkDYiBQRE; Hm_lvt_de47dd1629940fe88b02865de93dd9fe=1770176033,1770257492,1770281854,1770359422; HMACCOUNT=A6A0585E8C70051D; Hm_lpvt_de47dd1629940fe88b02865de93dd9fe=1770600610; GSuvNKHqfvX2r6v7P8HkZv2bow=s%3ANKEleTNCioVWeMitYN3WOVYYmCXbGFB0.qD1J8obD4MP4FNXKiVimB2UWfI2g3Nm%2FFOuYEmdeQek; JDY_SID=s%3Aar54WVlu4J-OyZzN0zEvAOU_FgbWMSvc.nCgiElAa2EoL3zf2gCIUV4XCFBE6aF6fsodt4%2F1daj4; acw_tc=743e76f717706025725901488e72f65ae43f08af57c9b931c35df2a672f5ff',\n", + "}\n", + "\n", + "json_data = {\n", + " 'from': None,\n", + " 'to': None,\n", + " 'granularity': 'daily',\n", + " 'members': [],\n", + " 'has_count': False,\n", + " 'sort': {},\n", + " 'limit': 50,\n", + " 'skip': 0,\n", + "}\n", + "all_data_list = []\n", + "for i in range(0,28):\n", + " json_data[\"skip\"] = i*50\n", + " response = requests.post(\n", + " 'https://www.jiandaoyun.com/corp/activity/user_user_metrics',\n", + " cookies=cookies,\n", + " headers=headers,\n", + " json=json_data,\n", + " )\n", + "\n", + " data_list = response.json().get(\"data\",[])\n", + " all_data_list.extend(data_list)\n", + "df = pd.DataFrame(all_data_list)\n", + "df.to_csv(\"D:\\Idea Project\\F6+宜搭+其它(1)\\张阳脚本\\文件输出\\人员使用记录.csv\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "F6+宜搭+其它", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/张阳脚本/简道云刷数据/图片批量命名.py b/张阳脚本/简道云刷数据/图片批量命名.py new file mode 100644 index 0000000..e34a249 --- /dev/null +++ b/张阳脚本/简道云刷数据/图片批量命名.py @@ -0,0 +1,24 @@ +import os + +# 设置你的根路径(注意:路径中的反斜杠在 Python 字符串中需转义,或使用 raw string) +root_path = r"C:\Users\hp_z66\OneDrive\Desktop\新建文件夹\合作跟进_20260207110728_resources_4" + +# 遍历根路径下的所有文件 +for dirpath, dirnames, filenames in os.walk(root_path): + # 判断当前路径是否包含 "FINST-" 开头的父目录 + # 我们假设 FINST 目录是 root_path 的直接子目录 + rel_path = os.path.relpath(dirpath, root_path) + parts = rel_path.split(os.sep) + + if parts[0].startswith("FINST-"): + finst_id = parts[0] + for filename in filenames: + old_file_path = os.path.join(dirpath, filename) + _, ext = os.path.splitext(filename) # 获取原扩展名 + new_filename = finst_id + ext + new_file_path = os.path.join(dirpath, new_filename) + + # 防止覆盖同名文件(可选) + if old_file_path != new_file_path: + os.rename(old_file_path, new_file_path) + print(f"Renamed: {old_file_path} → {new_file_path}") \ No newline at end of file diff --git a/张阳脚本/简道云刷数据/宜搭附件迁移简道云.ipynb b/张阳脚本/简道云刷数据/宜搭附件迁移简道云.ipynb new file mode 100644 index 0000000..6d7d354 --- /dev/null +++ b/张阳脚本/简道云刷数据/宜搭附件迁移简道云.ipynb @@ -0,0 +1,388 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "59aa4a03", + "metadata": {}, + "source": [ + "### 文件重命名并放在一个路径下" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "479a84ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🔍 正在扫描所有文件...\n", + "✅ 共找到 66 个实例,总计 90 个文件\n", + "📁 正在生成批次 1: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_1\n", + "[Batch 1] ✅ FINST-0CC662718BILO83CEX5TJ4OXZP2C3X1PCLRWLFGL.png\n", + "[Batch 1] ✅ FINST-0D866I81JANY5WG8A2DT15S63HZH20YFR68FMQJA.png\n", + "[Batch 1] ✅ FINST-0HD66Z81DFXYBP816VRKD6S2HA2H3RYCBYKFMR6.jpg\n", + "[Batch 1] ✅ FINST-3MF66MB1C62UYQ70B6VFWCC72LWD3WFATRQ8MJF1.jpg\n", + "[Batch 1] ✅ FINST-3RB66I91KLXKFLFLFENM3DP0BQER2D0BEAXVLS11.xlsx\n", + "[Batch 1] ✅ FINST-3SC66EA1POUU8OOK7YW2GDJEKD972XTSC1V9MCB1.png\n", + "[Batch 1] ✅ FINST-42766EA129TVP57F6HGFPAATXT4K2J17LS7BMPS2.png\n", + "[Batch 1] ✅ FINST-54A66HC1426KP5L87MXEA682I67O23YKVXUUL9U9.jpg\n", + "[Batch 1] ✅ FINST-54A66HC1BDILGOIO8D24RCKSUXOU2641DLRWLFY5.png\n", + "[Batch 1] ✅ FINST-54A66HC1NBQSMDDUEDQU4CSW0OJI27EQ2TV6MHV.xlsx\n", + "[Batch 1] ✅ FINST-5B866X816C0WLA139FUCS6ISBUCK3KXV3UIBMX22.jpg\n", + "[Batch 1] ✅ FINST-5W966981KWJJ06WS8VXCYC10RV7U31E6282ULAHS.png\n", + "[Batch 1] ✅ FINST-5X866U8169BBPU9BFDL61ASKGDPW3RJM5LIILSNA.png\n", + "[Batch 1] ✅ FINST-65D66X71VHAPFNPZ9OFURCIREZAS28FI7P12MJS.png\n", + "[Batch 1] ✅ FINST-69E66NA11AKXLE2R7DOP3AOZM8SD3R64OXNDM7G.png\n", + "[Batch 1] ✅ FINST-69E66NA1ATDYE53ADVQ8DCX122G53OQC1ETEM62.png\n", + "[Batch 1] ✅ FINST-6B966W917QETCTT5ARDDR8J2IOJD26ZQYVT7M3I.png\n", + "[Batch 1] ✅ FINST-8AD662D1X8VOJJUGCZ7NFCI1XLDM3EUX97H1MKJ1.png\n", + "[Batch 1] ✅ FINST-8EC66FA15UNNQPWWBOPENDDJ6EQM2MDGX4SZLOP4.jpg\n", + "[Batch 1] ✅ FINST-8O866AA142HTFEQ18XDVG5SQ0Y7Z14EVF6Y7MBHB.jpg\n", + "[Batch 1] ✅ FINST-9FA66WC1LDJNFROD7HJUI4OJ6C2J22UP25SZLUQA.jpg\n", + "[Batch 1] ✅ FINST-AZC667816Z9TV9Z4DD1PDD4OLN5825J8S4O7MOJ1.png\n", + "[Batch 1] ✅ FINST-BL866S61XU8DOZG5BZ6E4DZ2UOIV3B6CEHALL3QI.jpg\n", + "[Batch 1] ✅ FINST-ETA66681ZAHDHL2OA0MQR6UB9W5N2MZM2DGLLU2.png\n", + "[Batch 1] ✅ FINST-FX7660A1N11VJB6IBDBRE8N012ZQ2HVJIWBAMYL2.jpg\n", + "[Batch 1] ✅ FINST-G7B66QC1U162UFRMHJFJ59Q5VZZD3VQ1MS4KM0F.png\n", + "[Batch 1] ✅ FINST-HI766JB1ORJFF6STEI8PR6E3YJTF2B87VNDOLSM5.xlsx\n", + "[Batch 1] ✅ FINST-HRD66W919462UFW0NG4PODHZZUW63074RZAKM1DK.png\n", + "[Batch 1] ✅ FINST-IO766F81JX9VU83Z6OR927WUWBUJ3FDQKEGAM0X.xlsx\n", + "[Batch 1] ✅ FINST-IQC66GC18W4YQ8GSCL23T582HU1H3960PVGEML8.png\n", + "[Batch 1] ✅ FINST-IRD66GC15CA2MFOFM8MHCBN7OSWA3PKSUZAKMKS.png\n", + "[Batch 1] ✅ FINST-IRD66PB1X8I2R8DLJKVF9667G4LC3TWHHZLKM0J.png\n", + "[Batch 1] ✅ FINST-IUF66391KP8W6U35CG7JL8UC2GK52JXZA6TBM6P.png\n", + "[Batch 1] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "[Batch 1] ✅ FINST-J3D66LA13NTHEZAICABNRCD3KVCY222Q7IORL7UD.jpg\n", + "[Batch 1] ✅ FINST-JB966E91FW8YJMLMD52WCCZCXO5V28E0JHMEMM.jpg\n", + "[Batch 1] ✅ FINST-JXA66PB1ONATQBEIBDMEZ45MLMVB3M0CO6O7MH01.png\n", + "[Batch 1] ✅ FINST-JZE66UC1Q8H2F0E3M38EX853TR242SGJFJKKMK8.xlsx\n", + "[Batch 1] ✅ FINST-K7E66Z91F5NYOC0UD20BO775JN8C3D763K6FM16.xlsx\n", + "[Batch 1] ✅ FINST-KW866QB13VPZ5OSE9CE0LAWVKEO23QA4XVOGM92.jpg\n", + "[Batch 1] ✅ FINST-L3D66981YN31J5O8MGQCCCPF6FE82J0EBZMIMQ61.xlsx\n", + "[Batch 1] ✅ FINST-LCC66CA1BTTCK1HQ9S8TP91UHORX3JHYWOQKLO65.pptx\n", + "[Batch 1] ✅ FINST-LLA66D71DDUN56UUBRVZVD2EO3TS291ZDU00M734.png\n", + "[Batch 1] ✅ FINST-NLD66NA171BT4QDDCKR6HBD8XSHG3UJ1FSP7MJ39.png\n", + "[Batch 1] ✅ FINST-OPA665A1KV9TAY9UA78YID6X4S4Y2HPA03N7MO3.png\n", + "[Batch 1] ✅ FINST-P6D66F71YYMY4D4PE6FL58E9BU8X3JUP0G6FM6R.xlsx\n", + "[Batch 1] ✅ FINST-PF866EA1IKDECQEC8I8IECI2W3YI38JSXOPMLP8.jpg\n", + "[Batch 1] ✅ FINST-PJE66J91RJNZ1RSPBUYJB5ZF2PTI2TGY7PLGMAN.jpg\n", + "[Batch 1] ✅ FINST-PQ5669911JFP4W356K5HS98S8MZC2MUHMO82MX5.png\n", + "[Batch 1] ✅ FINST-PRF66GB105ZWQSK7CUNWR97ZV6LG3050I9UCMAY.png\n", + "[Batch 1] ✅ FINST-QJG66FC1JCE085Q3N439VAMLKVFF3GUQFMOHMEF2.xlsx\n", + "[Batch 1] ✅ FINST-QJG66IB1GWQZN4GVAGZCW8NQ61VB3AK3KSRGMWY1.xlsx\n", + "[Batch 1] ✅ FINST-QKC666919BQY70PZ8G3T57AX7UNA29H3N0BFMSC.xlsx\n", + "[Batch 1] ✅ FINST-QW8665B1XE41XSIJK01GJCNZ5YNQ2CRLVXNIMZW.png\n", + "[Batch 1] ✅ FINST-RAC66GD197JYBI9Q9WU4B731F3O52QOQQ42FMFR5.jpg\n", + "[Batch 1] ✅ FINST-UAD66591M1KJAXF6CROAFDK9Y4PD3IFY2QZTLUR1.jpg\n", + "[Batch 1] ✅ FINST-UH9665D1TLYDLO5TDNPV0CEJTFGX2AMSWP4MLGP.png\n", + "[Batch 1] ✅ FINST-USC66V6144XYJV79FR19G4JRKPA52X6OX8LFMWU3.xlsx\n", + "[Batch 1] ✅ FINST-UZA66QC18I9WZM23F0GIC4UMA25B2C14SHUBM742.png\n", + "[Batch 1] ✅ FINST-WM6666B10OZIDIA9C6K6R8A6NXEU3UON1HETL2ZJ.jpg\n", + "[Batch 1] ✅ FINST-WSF66J812FUXCO5ZCWI70C2TW7TG2OMS0F2EMAP1.png\n", + "[Batch 1] ✅ FINST-WSF66J818UYXDCKS8IZ7K50QAGNH2K3MJG8EMJP1.xlsx\n", + "[Batch 1] ✅ FINST-WYG66T718EQ0Z4TMNO8P2CRTS6NE3EUF016IMSDA.pptx\n", + "[Batch 1] ✅ FINST-Z6966NB14IDEWL268Y71A8FOS0HD2ROSG3QMLGZ3.mp4\n", + "[Batch 1] ✅ FINST-ZH866O918DRFX8WWEBEDSBMRTNU93TRYXNNOLVY.jpg\n", + "[Batch 1] ✅ FINST-ZKD66Q71XPBRGBVI8Z5FGCIWR2KS2NCI9TZ4MQ5L.xlsx\n", + "📁 正在生成批次 2: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_2\n", + "[Batch 2] ✅ FINST-0D866I81JANY5WG8A2DT15S63HZH20YFR68FMQJA.png\n", + "[Batch 2] ✅ FINST-0HD66Z81DFXYBP816VRKD6S2HA2H3RYCBYKFMR6.jpg\n", + "[Batch 2] ✅ FINST-54A66HC1426KP5L87MXEA682I67O23YKVXUUL9U9.jpg\n", + "[Batch 2] ✅ FINST-65D66X71VHAPFNPZ9OFURCIREZAS28FI7P12MJS.jpg\n", + "[Batch 2] ✅ FINST-9FA66WC1LDJNFROD7HJUI4OJ6C2J22UP25SZLUQA.jpg\n", + "[Batch 2] ✅ FINST-BL866S61XU8DOZG5BZ6E4DZ2UOIV3B6CEHALL3QI.png\n", + "[Batch 2] ✅ FINST-ETA66681ZAHDHL2OA0MQR6UB9W5N2MZM2DGLLU2.xlsx\n", + "[Batch 2] ✅ FINST-HRD66W919462UFW0NG4PODHZZUW63074RZAKM1DK.png\n", + "[Batch 2] ✅ FINST-IQC66GC18W4YQ8GSCL23T582HU1H3960PVGEML8.png\n", + "[Batch 2] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "[Batch 2] ✅ FINST-J3D66LA13NTHEZAICABNRCD3KVCY222Q7IORL7UD.xlsx\n", + "[Batch 2] ✅ FINST-K7E66Z91F5NYOC0UD20BO775JN8C3D763K6FM16.xlsx\n", + "[Batch 2] ✅ FINST-KW866QB13VPZ5OSE9CE0LAWVKEO23QA4XVOGM92.jpg\n", + "[Batch 2] ✅ FINST-LLA66D71DDUN56UUBRVZVD2EO3TS291ZDU00M734.png\n", + "[Batch 2] ✅ FINST-NLD66NA171BT4QDDCKR6HBD8XSHG3UJ1FSP7MJ39.png\n", + "[Batch 2] ✅ FINST-PF866EA1IKDECQEC8I8IECI2W3YI38JSXOPMLP8.jpg\n", + "📁 正在生成批次 3: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_3\n", + "[Batch 3] ✅ FINST-65D66X71VHAPFNPZ9OFURCIREZAS28FI7P12MJS.png\n", + "[Batch 3] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 4: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_4\n", + "[Batch 4] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 5: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_5\n", + "[Batch 5] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 6: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_6\n", + "[Batch 6] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 7: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_7\n", + "[Batch 7] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 8: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_8\n", + "[Batch 8] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "📁 正在生成批次 9: C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\\输出_9\n", + "[Batch 9] ✅ FINST-J0A66981DAZDOPI7EF20N91K9UM72O8N526MLZO2.png\n", + "\n", + "🎉 处理完成!共生成 9 个批次文件夹。\n" + ] + } + ], + "source": [ + "import os\n", + "import shutil\n", + "import re\n", + "import hashlib\n", + "\n", + "# 配置\n", + "root_path = r\"C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\FPO提交_20260207112107_resources_1\"\n", + "\n", + "# 存储:{finst_id: [file_path1, file_path2, ...]}\n", + "instance_files = {}\n", + "\n", + "# Windows 非法字符\n", + "ILLEGAL_CHARS = r'[<>:\"/\\\\|?*\\x00-\\x1f]'\n", + "\n", + "def extract_or_fallback_prefix(dirname):\n", + " match = re.match(r'^(FINST-[A-Z0-9]{10,})', dirname)\n", + " return match.group(1) if match else dirname\n", + "\n", + "def sanitize_filename_part(part):\n", + " return re.sub(ILLEGAL_CHARS, '_', part)\n", + "\n", + "print(\"🔍 正在扫描所有文件...\")\n", + "\n", + "# 第一步:遍历并按 FINST-ID 分组\n", + "for dirpath, dirnames, filenames in os.walk(root_path):\n", + " rel_path = os.path.relpath(dirpath, root_path)\n", + " if rel_path.startswith(\"输出_\"):\n", + " continue\n", + "\n", + " parts = rel_path.split(os.sep)\n", + " \n", + " # 找到路径中第一个 FINST- 开头的目录\n", + " finst_dirname = None\n", + " for part in parts:\n", + " if part.startswith(\"FINST-\"):\n", + " finst_dirname = part\n", + " break\n", + " \n", + " if finst_dirname is None:\n", + " continue\n", + "\n", + " clean_prefix = extract_or_fallback_prefix(finst_dirname)\n", + " safe_prefix = sanitize_filename_part(clean_prefix)\n", + "\n", + " for filename in filenames:\n", + " src_file = os.path.join(dirpath, filename)\n", + " instance_files.setdefault(safe_prefix, []).append(src_file)\n", + "\n", + "print(f\"✅ 共找到 {len(instance_files)} 个实例,总计 {sum(len(v) for v in instance_files.values())} 个文件\")\n", + "\n", + "# 第二步:按轮次分发到输出文件夹\n", + "max_rounds = max(len(files) for files in instance_files.values()) if instance_files else 0\n", + "\n", + "for round_index in range(max_rounds):\n", + " batch_index = round_index + 1\n", + " output_dir = os.path.join(root_path, f\"输出_{batch_index}\")\n", + " os.makedirs(output_dir, exist_ok=True)\n", + " print(f\"📁 正在生成批次 {batch_index}: {output_dir}\")\n", + "\n", + " for finst_id, file_list in instance_files.items():\n", + " if round_index < len(file_list):\n", + " src_file = file_list[round_index]\n", + " _, ext = os.path.splitext(src_file)\n", + " safe_ext = sanitize_filename_part(ext)\n", + " if safe_ext and not safe_ext.startswith('.'):\n", + " safe_ext = '.' + safe_ext\n", + "\n", + " # 编号从 2 开始:第0个 → -2, 第1个 → -3, ...\n", + " counter = round_index + 1\n", + " target_name = f\"{finst_id}{safe_ext}\"\n", + "\n", + "\n", + "\n", + " dst_file = os.path.join(output_dir, target_name)\n", + "\n", + " try:\n", + " shutil.copy2(src_file, dst_file)\n", + " print(f\"[Batch {batch_index}] ✅ {target_name}\")\n", + " except Exception as e:\n", + " print(f\"[Batch {batch_index}] ❌ 复制失败: {e}\")\n", + "\n", + "print(f\"\\n🎉 处理完成!共生成 {max_rounds} 个批次文件夹。\")" + ] + }, + { + "cell_type": "markdown", + "id": "3bf861d3", + "metadata": {}, + "source": [ + "附件、图片\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "90309f69", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🔍 正在扫描所有文件...\n", + "✅ 共找到 9 个文件,分属:附件、图片、其他\n", + "\n", + "📦 处理类别: 附件 (共 1 批)\n", + "[附件 Batch 1] ✅ FINST-56B66Q91XU6TMONCFZBLBCVK9MS03SSG3SI7MR1.pdf\n", + "[附件 Batch 1] ✅ FINST-C98664A1A8XJTVAW9W0256C4AF5S2JIWPBIULNM3.pdf\n", + "[附件 Batch 1] ✅ FINST-JZ766R91YWUW0FZ6CXRXSBAVXQ0J2ZOZEEOCMGA.pdf\n", + "[附件 Batch 1] ✅ FINST-R3D664B1B7ZYYR569QITJB9VCZXT2B8WIUNFM4X2.xlsx\n", + "[附件 Batch 1] ✅ FINST-RC966V713AMLLTHG8M1UBD6OK7EG3M3PWTYWLQYL.pdf\n", + "[附件 Batch 1] ✅ FINST-SUC66KA1UDIL18KXAMFCK9PW64XN375YHFQWLLC.pdf\n", + "[附件 Batch 1] ✅ FINST-TM966BD1Y9HK1YK1BFUOL9IO9TSI3WK4G6CVLS45.xlsx\n", + "[附件 Batch 1] ✅ FINST-ZKD66Q719O2TZRLY5HZJNAFGJW2F2IE4JYC7M0F.jpg\n", + "\n", + "📦 处理类别: 图片 (共 1 批)\n", + "[图片 Batch 1] ✅ FINST-SUC66KA1C5YJQ4NNAKAGHBOOPPFQ3QX7EJQULEKV1.jpg\n", + "\n", + "🎉 所有类别处理完成!\n" + ] + } + ], + "source": [ + "import os\n", + "import shutil\n", + "import re\n", + "import hashlib\n", + "\n", + "# 配置\n", + "root_path = r\"C:\\Users\\hp_z66\\OneDrive\\Desktop\\新建文件夹\\商机提交_20260209161647_resources_1\"\n", + "\n", + "# 分类存储:{\"附件\": {finst_id: [file1, file2, ...]}, \"图片\": {...}, \"其他\": {...}}\n", + "categorized_files = {\n", + " \"附件\": {},\n", + " \"图片\": {},\n", + " \"其他\": {}\n", + "}\n", + "\n", + "# Windows 非法字符\n", + "ILLEGAL_CHARS = r'[<>:\"/\\\\|?*\\x00-\\x1f]'\n", + "\n", + "def extract_or_fallback_prefix(dirname):\n", + " match = re.match(r'^(FINST-[A-Z0-9]{10,})', dirname)\n", + " return match.group(1) if match else dirname\n", + "\n", + "def sanitize_filename_part(part):\n", + " return re.sub(ILLEGAL_CHARS, '_', part)\n", + "\n", + "print(\"🔍 正在扫描所有文件...\")\n", + "\n", + "# 第一步:遍历并按来源分类 + 按 FINST-ID 分组\n", + "for dirpath, dirnames, filenames in os.walk(root_path):\n", + " rel_path = os.path.relpath(dirpath, root_path)\n", + " if rel_path.startswith(\"输出_\"):\n", + " continue\n", + "\n", + " parts = rel_path.split(os.sep)\n", + " \n", + " # 找到第一个 FINST- 开头的目录\n", + " finst_dirname = None\n", + " for part in parts:\n", + " if part.startswith(\"FINST-\"):\n", + " finst_dirname = part\n", + " break\n", + " \n", + " if finst_dirname is None:\n", + " continue\n", + "\n", + " clean_prefix = extract_or_fallback_prefix(finst_dirname)\n", + " safe_prefix = sanitize_filename_part(clean_prefix)\n", + "\n", + " # 判断当前路径相对于 FINST-xxx 的位置\n", + " relative_to_finst = rel_path[len(finst_dirname):].lstrip(os.sep)\n", + " source_type = \"其他\"\n", + "\n", + " if relative_to_finst == \"\" or not relative_to_finst:\n", + " # 文件直接在 FINST-xxx 下\n", + " source_type = \"其他\"\n", + " elif relative_to_finst.startswith(\"附件\") or \"附件\" in relative_to_finst.split(os.sep):\n", + " source_type = \"附件\"\n", + " elif relative_to_finst.startswith(\"图片\") or \"图片\" in relative_to_finst.split(os.sep):\n", + " source_type = \"图片\"\n", + " else:\n", + " source_type = \"其他\"\n", + "\n", + " for filename in filenames:\n", + " src_file = os.path.join(dirpath, filename)\n", + " categorized_files[source_type].setdefault(safe_prefix, []).append(src_file)\n", + "\n", + "# 统计\n", + "total_files = sum(\n", + " len(files) \n", + " for category in categorized_files.values() \n", + " for files in category.values()\n", + ")\n", + "print(f\"✅ 共找到 {total_files} 个文件,分属:附件、图片、其他\")\n", + "\n", + "# 第二步:对每种类别独立进行轮次分发\n", + "for category_name, instance_dict in categorized_files.items():\n", + " if not instance_dict:\n", + " continue\n", + "\n", + " max_rounds = max(len(files) for files in instance_dict.values())\n", + " print(f\"\\n📦 处理类别: {category_name} (共 {max_rounds} 批)\")\n", + "\n", + " for round_index in range(max_rounds):\n", + " batch_index = round_index + 1\n", + " output_dir = os.path.join(root_path, f\"输出_{category_name}_{batch_index}\")\n", + " os.makedirs(output_dir, exist_ok=True)\n", + "\n", + " for finst_id, file_list in instance_dict.items():\n", + " if round_index < len(file_list):\n", + " src_file = file_list[round_index]\n", + " _, ext = os.path.splitext(src_file)\n", + " safe_ext = sanitize_filename_part(ext)\n", + " if safe_ext and not safe_ext.startswith('.'):\n", + " safe_ext = '.' + safe_ext\n", + "\n", + " # 文件名:FINST-XXX.ext (无任何后缀)\n", + " target_name = f\"{finst_id}{safe_ext}\"\n", + "\n", + " # 防止过长\n", + " if len(target_name) > 200:\n", + " hash_part = hashlib.md5(finst_id.encode()).hexdigest()[:8]\n", + " truncated = finst_id[:100] + \"_\" + hash_part\n", + " target_name = f\"{truncated}{safe_ext}\"\n", + "\n", + " dst_file = os.path.join(output_dir, target_name)\n", + "\n", + " try:\n", + " shutil.copy2(src_file, dst_file)\n", + " print(f\"[{category_name} Batch {batch_index}] ✅ {target_name}\")\n", + " except Exception as e:\n", + " print(f\"[{category_name} Batch {batch_index}] ❌ 复制失败: {e}\")\n", + "\n", + "print(f\"\\n🎉 所有类别处理完成!\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "F6+宜搭+其它", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}