From 631ae3f8b07c958d1febf931c9eac67a0a1091b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=B8=88?= Date: Tue, 9 Jun 2026 03:58:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=A4=E5=AE=9AvsOA=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=B8=80=E8=88=AC=E7=B1=BB=E5=AF=B9=E6=AF=94(?= =?UTF-8?q?=E8=B6=85=E8=A7=84+=E4=B8=80=E8=88=AC=E5=8F=8C=E7=BB=B4?= =?UTF-8?q?=E5=BA=A6=E5=B7=AE=E9=A2=9D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cleaned/危大方案看板数据工作簿.xlsx | Bin 69127 -> 69233 bytes data/认定数据/2026/certified_schemes.csv | 16 ++++++++-------- data/认定数据/2026/certified_schemes.parquet | Bin 8000 -> 10871 bytes src/clean_certified.py | 12 ++++++++++-- src/gen_workbook.py | 9 ++++++--- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/data/2026-06-08/cleaned/危大方案看板数据工作簿.xlsx b/data/2026-06-08/cleaned/危大方案看板数据工作簿.xlsx index c40b3709d19f04e396e3e81ca13879a2bef6002c..2f1a8f2b2e3856bd80bcbcc1b7f659d11d9b71a7 100644 GIT binary patch delta 3245 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 delta 3114 zcmZ8jc|25Y8$Jia7$e4BCcBV5ONc>Hwh|gKghA=Gyp|%~Fwuyjgkeas%bG1R)`&`x zlgBc{P2W8`eYz0kD;p} z#}Nkez4H73DsKLjhI3kw43 zF{9x5FZjGJR?C@A^W|GiCHwI1##yS2eP#QXdCTWynUAB(ax0>EPl0N^a& z0u>nPC<5hjaKCF1=G?51hVatUUN#i;p*)WauZqI}AdwpY_~II=JOpJqe-HNxD;v)N zRjwWBP?n!XDhuR(#fL{K>ca85ksi@uj!LEHTd88|GdtUFPg%!Hsoy({ylQk8bNtD| z2~Do29RW+3gM1eH+U3`6?Cz^#D>jt{$OZRX$EZ&AN;aGCPuV$pU$&2Y<4ut^sb$QT zIm}6HR*Q_Azp5HWsc|Hzwy$Czxwl_J#c#?)MiR7>l?nBSMmzCiZq%y0!DfHep_b^$ z`UOGO6V^rUqHkl11iz*Fir^5$z;THS21O_7xC4zs zx)I73)VR3{xUF)9Oc`6;xOe)~^ooS+_(_G_<8Is+iqZf)8}mp2|HUPD+<1rCXjYNR zDv$+uusD_ZZfz4RxmS9cXR+n03zB4$vtJuTN#4qLpS+unb~_O%*}}Po?X})an~zG? ziDEv^aauCh`}NS(iNwP&38S-ckumzRT~cai+)P#3sK(Q8@!REi)zVK#ED@!#pGz5a z+1pC5FC;pks({E;CRu@^of;*>FdH@Dcf}oYEMLPuj>Iw(5OWi_TnzcROHEcNJ1gbL z$vWo^zqiVxiJS_ufx&RpAu7@RqZUsC66b977fV~y#&&36TZiA$Y@p1Yv!bS!_w@{P zOG?nsZ%O&Q&*X4>qnweq_^^-PQ0TK`kXnx!sXa$haStwxXcLuI|C914^kG_rduxpRe#Za{I;1hBk=H88nlWSQiEbGKD}mTkz9JUg`e}XVT(csT)_)hxm>98m7Lv_Z>bLA z8>zmM@rmG()3?($U9cw1xUMMaebcUTW3BTSikc~nqMkxhPu0cRB=S)HA)_L(WW7I*wAq5#_F4mb_!`OP2-C%o65o1ZOYdqfzmdVQv+fxb8;6@Gou2E zN-d(c%n6-GhdreU{9SF8&km0wX2?|y`!WMlM#~Ofbnv6vN#f1PE&FV#Lzm*0$ZjgxWxvq zeq7Q}*j>eeC)LY20mB`&^}(Bd?qMIZ4+$G5VS5@2^HtP5Ew86ovrf~gnml5UOwmY} z8*wz`_3h4L?=1v{ZyeTg;S(Q%!3l2PoV=e|=f7uZN^e0mitsT^qHOWx&BkNpQGEHr zOiSTd*{yjU*>56Iw$B;o^RHYz*exV&LCjDIRri{dF+xAhPwITFnT56v8l?bKFt=2p zNp~K@E`%*|jv)H#9b{X8FVi3nx zawE7mv8efKC+qL@^qi@vl4(xnz*|nBXOM3XI zGSk8*MB+=7<-^{z&wlVnLR~uv4WD-?zvNuTjX2EDg^-MSW-^w$=W2gQo7?G^guzUO;}KeyR#&yx7a`K5`?Z3u~Z^Y!u3=>RxmovL}O9$-b z3(;VQPG?^A7VTswy8QW``Ky*=l=9RI!9xw|d;!A$I1g7hP;d(?4}8Scp2G4Flf zw^|q$s;0=27)28rjLysOsX6B575;%do$ob4$ueEZcBW{iN%Uk&tuAKcJd>w~f{t?F z%9S~7MQV<6on3006To2=LLS z&3~?2A$MxYod}RSPOuI}wnuJyAX1x!Mz&7wk&5cjfOg&(q~oIhXY6gYy()spaiUpcY1Rk- z$&H4$LU?A$ib#+ru4EQQu4ma#uMP4m`M&pp)^GN+BfjlOsH9m$!~bnzMpi(Al29Tz zBu$8+?g_~cXiA7ohsYm4_sK7RlhY7swYE>9S@$F5SwS?YOE#eaBy^>rh9(FC_CA;0 zugS|n_kSO3uVK-$;$sB>w%-p1ij!Zmf&!4w2xN;UZ?l3@&{FaMZD~c;KL8$K>|+9H GqW=KQa$+|C diff --git a/data/认定数据/2026/certified_schemes.csv b/data/认定数据/2026/certified_schemes.csv index da740a7..4e85e04 100644 --- a/data/认定数据/2026/certified_schemes.csv +++ b/data/认定数据/2026/certified_schemes.csv @@ -1,8 +1,8 @@ -项目名称,认定_危大方案总数,认定_超规数,所属国别,平台_匹配项目,平台_方案总数,平台_超规数,差额,匹配状态 -沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,5,2,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,3,1,-2,✅ -沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,1,0,沙特,沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,3,2,2,✅ -沙特达曼港第一和第二集装箱码头升级改造工程项目,1,1,沙特,沙特达曼港第一和第二集装箱码头升级改造工程,3,2,2,✅ -阿联酋沙迦卡尔巴摩托艇码头项目,2,0,阿联酋,阿联酋沙迦卡尔巴摩托艇港开发项目,3,1,1,✅ -阿联酋迪拜马克图姆国际机场地下结构工程项目,31,12,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,35,13,4,✅ -阿联酋阿布扎比哈里发港EGA泊位翻新项目,1,0,阿联酋,阿联酋阿布扎比哈里发港EGA泊位翻新工程项目,1,0,0,✅ -阿联酋阿布扎比马斯努阿岛水工项目,2,1,阿联酋,阿联酋阿布扎比马斯努阿岛水工项目,0,0,-2,✅ +项目名称,认定_危大方案总数,认定_超规数,所属国别,认定_一般数,平台_匹配项目,平台_方案总数,平台_超规数,平台_一般数,差额_超规,差额_一般,差额_合计,匹配状态 +沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,5,2,沙特,3,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,3,1,2,-1,-1,-2,✅ +沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,1,0,沙特,1,沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,3,2,1,2,0,2,✅ +沙特达曼港第一和第二集装箱码头升级改造工程项目,1,1,沙特,0,沙特达曼港第一和第二集装箱码头升级改造工程,3,2,1,1,1,2,✅ +阿联酋沙迦卡尔巴摩托艇码头项目,2,0,阿联酋,2,阿联酋沙迦卡尔巴摩托艇港开发项目,3,1,2,1,0,1,✅ +阿联酋迪拜马克图姆国际机场地下结构工程项目,31,12,阿联酋,19,阿联酋迪拜马克图姆国际机场地下结构工程项目,35,13,22,1,3,4,✅ +阿联酋阿布扎比哈里发港EGA泊位翻新项目,1,0,阿联酋,1,阿联酋阿布扎比哈里发港EGA泊位翻新工程项目,1,0,1,0,0,0,✅ +阿联酋阿布扎比马斯努阿岛水工项目,2,1,阿联酋,1,阿联酋阿布扎比马斯努阿岛水工项目,0,0,0,-1,-1,-2,✅ diff --git a/data/认定数据/2026/certified_schemes.parquet b/data/认定数据/2026/certified_schemes.parquet index 4fcf8803cef661a2c5c43be48536370f851a5c84..ef874d61f247feb471abbbe6a313632b9b90168b 100644 GIT binary patch delta 2722 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 IS+INSFAe#XSpWb4 diff --git a/src/clean_certified.py b/src/clean_certified.py index fc60772..4d9cca8 100644 --- a/src/clean_certified.py +++ b/src/clean_certified.py @@ -220,18 +220,26 @@ if PLATFORM_PARQUET.exists(): if ratio > best_ratio: best_ratio = ratio; best_match = plat_name row_dict = cert_row.to_dict() + # 认定一般数 = 总数 - 超规 + row_dict['认定_一般数'] = row_dict['认定_危大方案总数'] - row_dict['认定_超规数'] if best_match and best_ratio >= 0.75: prow = platform_counts[platform_counts['项目名称'] == best_match].iloc[0] row_dict['平台_匹配项目'] = best_match row_dict['平台_方案总数'] = int(prow['平台_方案总数']) row_dict['平台_超规数'] = int(prow['平台_超规数']) - row_dict['差额'] = int(prow['平台_方案总数']) - row_dict['认定_危大方案总数'] + row_dict['平台_一般数'] = int(prow['平台_方案总数']) - int(prow['平台_超规数']) + row_dict['差额_超规'] = int(prow['平台_超规数']) - row_dict['认定_超规数'] + row_dict['差额_一般'] = row_dict['平台_一般数'] - row_dict['认定_一般数'] + row_dict['差额_合计'] = int(prow['平台_方案总数']) - row_dict['认定_危大方案总数'] row_dict['匹配状态'] = '✅' else: row_dict['平台_匹配项目'] = '' row_dict['平台_方案总数'] = 0 row_dict['平台_超规数'] = 0 - row_dict['差额'] = -row_dict['认定_危大方案总数'] + row_dict['平台_一般数'] = 0 + row_dict['差额_超规'] = -row_dict['认定_超规数'] + row_dict['差额_一般'] = -row_dict['认定_一般数'] + row_dict['差额_合计'] = -row_dict['认定_危大方案总数'] row_dict['匹配状态'] = '⚠️ 未匹配' matched.append(row_dict) df_result = pd.DataFrame(matched) diff --git a/src/gen_workbook.py b/src/gen_workbook.py index 952f094..65377b4 100644 --- a/src/gen_workbook.py +++ b/src/gen_workbook.py @@ -110,17 +110,20 @@ write_data_sheet(s3,cert_valid.reset_index(drop=True), # ════════ S4: 认定vsOA ════════ s4=wb.create_sheet('认定vsOA') -COMP_COLS=['项目名称','认定_危大方案总数','认定_超规数','所属国别','平台_方案总数','平台_超规数','差额','匹配状态'] +COMP_COLS=['项目名称','认定_危大方案总数','认定_超规数','认定_一般数', + '平台_方案总数','平台_超规数','平台_一般数', + '差额_超规','差额_一般','差额_合计','匹配状态'] ncol_c=len(COMP_COLS) s4.merge_cells(start_row=1,start_column=1,end_row=1,end_column=ncol_c) s4.cell(1,1,f'认定 vs OA登记 项目级对比({REPORT_DATE})').font=TITLE_F; s4.cell(1,1).border=GOLD_BD hdr_row(s4,3,COMP_COLS) for ri,(_,row) in enumerate(cert_comp.iterrows()): for ci,col in enumerate(COMP_COLS): - v=row[col] + v=row.get(col,'') if pd.isna(v): v='' cell=s4.cell(ri+4,ci+1,v); cell.font=DATA_F; cell.border=BORDER - if col=='差额' and isinstance(v,(int,float)) and v!=0: + # 差额高亮 + if col.startswith('差额_') and isinstance(v,(int,float)) and v!=0: cell.font=RED_F if v<0 else GREEN_F if col=='匹配状态': cell.font=GREEN_F if '✅' in str(v) else DATA_F s4.auto_filter.ref=f'A3:{get_column_letter(ncol_c)}{len(cert_comp)+3}'