Files
gmv-analytics/__pycache__/project_bitable_common.cpython-312.pyc
T

502 lines
66 KiB
Plaintext
Raw Normal View History

Ë
2026-03-16 14:21:12 +08:00
lŸ·iÃÈãóŒ—ddlZddlZddlZddlmZddlmZddlmZmZm Z ddl
m Z ddl m
2026-03-16 14:21:12 +08:00
Z
ddlmZddlmZddlZddlZdd lmZe
e«j/«j0Zed
2026-03-16 14:21:12 +08:00
z Zed z Zd Zd
Zgd¢Zgd¢Zed¬«Gd„d««Z e dddd¬«e dddd¬«dœZ!ed¬«Gd„d««Z"ed¬«Gd„d ««Z#ed¬«Gd!„d"««Z$d#e%d$dfd%„Z&d|d&e'ed'e(d$e%fd(„Z)efd)e
d$dfd*„Z*d$e%fd+„Z+d$e
fd,„Z,d$e%fd-„Z-d$e%fd.„Z.d$e%fd/„Z/d$e%fd0„Z0d$e%fd1„Z1d$e%fd2„Z2d3e'e3e%efd4e%d$e%fd5„Z4d6e%d$efd7„Z5d6e%d$e%fd8„Z6d9e%d$e%fd:„Z7d;e%d$e'e%fd<„Z8d=e
d$e3e%e%ffd>„Z9d?e%d@e3e%e%fd$e%fdA„Z:d$ejvjxfdB„Z=dCedDedEe d$e'e"fdF„Z>dGe'e"d@e3e%e%fdEe d$e3e%e3e?e(e(fe3ee3e%e fffffdH„Z@dCedDedIe3e%e3e?e(e(fe3ee3e%e ffffd$e3e%e3e?e(e(fe3ee3e%e fffffdJ„ZAd$e%fdK„ZBGdL„dM«ZCdNe%d$e3e%e%ffdO„ZDdPe%dQe%dRe%dCedDed$df dS„ZEdTe%d$e%fdU„ZF d}dVe%dQe%dRe%dCedDedTe%d$dfdW„ZG d~dXe'e#d;e%dYe(dZe(d[e3e%e%fdzd$e#f d\„ZHd6e d$eIfd]„ZJd^edEe d$e%fd_„ZKd6ed$eIdzfd`„ZLdCedDed$e'efda„ZMdCedDed$e3e?e(e(fe'effdb„ZN d~d3e'e3e%efdce%ddeOe%dzd$e'e3e%effde„ZPdfe'e3e%efd$e3e%eOe%ffdg„ZQdfe'e3e%efd$e'e%fdh„ZRdieCdje#dce%ddeOe%dzdkeSd$df dl„ZTdCedDedRe%dce%dme%dkeSdneSd$dfdo„ZUd^edRe%dce%dme%dkeSdneSd$dfdp„ZVdieCdje#dce%dqe3ee3e%e ffdkeSdEe d$e$fdr„ZWdse%dCedDedRe%dte
dce%dme%dkeSdneSd$dfdu„ZXd^ed$e%fdv„ZYd^ed$e%fdw„ZZd^ed$e%fdx„Z[dieCdje#d^edye%dkeSd$df dz„Z\dCedDedRe%dce%dkeSdneSd$dfd{„Z]y)éN©Ú defaultdict)Ú dataclass)ÚdateÚdatetimeÚ timedelta)ÚDecimal)ÚPath)ÚAny)Úurlparse)Ú
load_workbookz.envu店铺映射表.xlsxz
2026-02-25õ 店铺å��ç§°)u业务店铺å��ç§°ru 门店å��ç§°u店铺uå��ç§°©õ 大眼ç�›õ 羽心堂ÚMMMJÚEMõ 春回ç›�ú
BROKEN ZOOT)Úfrozencó6—eZdZUeed<eed<eed<eed<y)Ú MetricConfigÚnameÚ descriptionÚ sql_templateÚ field_suffixN©Ú__name__Ú
__module__Ú __qualname__ÚstrÚ__annotations__©óú?/Users/idss/YXT_Project/gmv-analytics/project_bitable_common.pyrrs…à
ƒIØÓØÓØÔr$rÚsalesu 销售é¢�u 总销售é¢�uŠ
SET TIMEZONE = 'Asia/Shanghai';
WITH base_data AS (
SELECT
f.支付时间::DATE AS 统计日期,
f.店铺主键,
s.店铺�称 AS 原始店铺�称,
p.�牌�称,
f.业务模�,
f.实付分摊金� AS 指标金�
FROM analytics_layer.fact_sales f
LEFT JOIN analytics_layer.dim_shop s
ON f.店铺主键 = s.店铺主键
LEFT JOIN analytics_layer.dim_product p
ON f.商�主键 = p.商�主键
AND f.统一规格编� = p.统一规格编�
WHERE f.支付时间 >= %(start_ts)s
AND f.支付时间 < %(end_ts_exclusive)s
),
brand_split AS (
SELECT
统计日期,
店铺主键,
原始店铺�称,
业务模�,
CASE
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE '羽心堂'
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE '春回�'
THEN 原始店铺�称 || '_春回�'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'ERBA MIGINA'
THEN 原始店铺�称 || '_ERBA MIGINA'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'BROKEN ZOO'
THEN 原始店铺�称 || '_BROKEN ZOO'
WHEN 店铺主键 IN (1,28,29)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IN (3,9) AND �牌�称 LIKE '羽心堂'
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (3,9) AND �牌�称 LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (3,9)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IS NULL OR 原始店铺�称 IS NULL
THEN '分销/SEEDING'
ELSE 原始店铺�称
END AS 店铺�称,
指标金�
FROM base_data
),
shop_brand_detail AS (
SELECT
统计日期,
店铺主键,
店铺�称,
SUM(指标金�) AS 指标值
FROM brand_split
GROUP BY 1,2,3
)
SELECT
统计日期,
店铺�称,
指标值
FROM shop_brand_detail
WHERE NOT (
店铺主键 IN (1,9,28,29)
AND 店铺�称 LIKE '%%_其他'
)
UNION ALL
SELECT
统计日期,
原始店铺�称 AS 店铺�称,
SUM(指标金�)
FROM base_data
WHERE 店铺主键 IN (1,28,29,3)
GROUP BY 1,2
UNION ALL
SELECT
统计日期,
CASE
WHEN 业务模� IN ('三方计算','三方分销')
THEN 原始店铺�称 || '_三方'
ELSE 原始店铺�称 || '_自�'
END AS 店铺�称,
SUM(指标金�)
FROM base_data
WHERE 店铺主键 = 1
GROUP BY 1,2
ORDER BY 统计日期 DESC, 指标值 DESC;
)rrrrÚrefundu 退款é¢�u-
SET TIMEZONE = 'Asia/Shanghai';
WITH base_data AS (
SELECT
f.完结时间::DATE AS 统计日期,
f.店铺主键,
s.店铺�称 AS 原始店铺�称,
p.�牌�称,
f.退款金� AS 指标金�
FROM analytics_layer.fact_returns f
LEFT JOIN analytics_layer.dim_shop s
ON f.店铺主键 = s.店铺主键
LEFT JOIN analytics_layer.dim_product p
ON f.商�主键 = p.商�主键
AND f.统一规格编� = p.统一规格编�
WHERE f.完结时间 >= %(start_ts)s
AND f.完结时间 < %(end_ts_exclusive)s
),
brand_split AS (
SELECT
统计日期,
店铺主键,
原始店铺�称,
CASE
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE '羽心堂'
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE '春回�'
THEN 原始店铺�称 || '_春回�'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'ERBA MIGINA'
THEN 原始店铺�称 || '_ERBA MIGINA'
WHEN 店铺主键 IN (1,28,29) AND �牌�称 LIKE 'BROKEN ZOO'
THEN 原始店铺�称 || '_BROKEN ZOO'
WHEN 店铺主键 IN (1,28,29)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IN (3,9) AND �牌�称 LIKE '羽心堂'
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (3,9) AND �牌�称 LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (3,9)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IS NULL OR 原始店铺�称 IS NULL
THEN '分销/SEEDING'
ELSE 原始店铺�称
END AS 店铺�称,
指标金�
FROM base_data
),
shop_brand_detail AS (
SELECT
统计日期,
店铺主键,
店铺�称,
SUM(指标金�) AS 指标值
FROM brand_split
GROUP BY 1,2,3
)
SELECT
统计日期,
店铺�称,
指标值
FROM shop_brand_detail
WHERE NOT (
店铺主键 IN (1,9,28,29)
AND 店铺�称 LIKE '%%_其他'
)
UNION ALL
2026-03-16 14:21:12 +08:00
SELECT
2026-03-16 14:21:12 +08:00
统计日期,
原始店铺�称 AS 店铺�称,
SUM(指标金�)
FROM base_data
WHERE 店铺主键 IN (1,28,29,3)
2026-03-16 14:21:12 +08:00
GROUP BY 1,2
ORDER BY 统计日期 DESC, 指标值 DESC;
)r&r'có,—eZdZUeed<eed<eed<y)Ú MetricRowÚ stat_dateÚ
bi_store_nameÚamountN)rrr rr"r!r r#r$r%r)r)âs…àƒOØÓØ „Or$r)có"—eZdZUeed<eed<y)Ú TableInfoÚtable_idrNrr#r$r%r.r.és …àƒMØ
2026-03-16 14:21:12 +08:00
„Ir$r.có.—eZdZUeeed<eeed<y)Ú
SyncResultÚsql_only_storesÚfeishu_only_storesN)rrr Úlistr!r"r#r$r%r1r1ïs…à˜#‘YÓØ˜S™ Ô!r$r1ÚmessageÚreturncóp—tj«jd«}td|›d|›�d¬«y)Nz%Y-%m-%d %H:%M:%SÚ[z] T)Úflush)rÚnowÚstrftimeÚprint)r5r:s r%Úlog_stepr=õs0€Ü
�,‰,‹.×
!Ñ
2026-03-16 14:21:12 +08:00
!Ð"5Ó
6€CÜ ˆAˆcˆU�"�W�IÐ
 dÖ+r$ÚvaluesÚlimitcó\—t|«|kr t|«S|d|›dt|«›d�S)Nu ... å…±u项)Úlenr!)r>r?s r%Ú preview_listrBús6€Ü
ˆ6ƒ{�eÒÜ�6‹{ÐØ�V�eˆnÐ
˜X¤c¨&£k ]°#Ð 6Ð6r$Úenv_filecóš—|j«std|›�«ytd|›�«|jd¬«j«D]{}|j «}|r|j d«sd|vrŒ+|j
2026-03-16 14:21:12 +08:00
dd«\}}tjj|j «|j ««Œ}y)Nu&未找到 .env 文件,跳过加载: u加载环境å�˜é‡�: úutf-8©ÚencodingÚ#Ú=é)
Úexistsr=Ú read_textÚ
splitlinesÚstripÚ
startswithÚsplitÚosÚenvironÚ
2026-03-16 14:21:12 +08:00
setdefault)rCÚraw_lineÚlineÚkeyÚvalues r%Ú load_dotenvrXs¨€Ø �?‰?Ô ÜÐ9¸(¸ÐDÔEØÜ Ð# H :Ð
.Ô/Ø×&Ñ&°Ð&Ó8×CÑCÖEˆØ�~‰~ÓˆÙ�t—‘ sÔ+¨s¸$©Ø Ø—Z‘Z  QÓ'‰
ˆˆUÜ
�
2026-03-16 14:21:12 +08:00
‰
×јcŸi™i›k¨5¯;©;«=Õ9ñ Fr$cóJ—tjd«}|s td«‚|S)NÚFEISHU_BASE_URLu"缺少环境å�˜é‡� FEISHU_BASE_URL)rQÚgetenvÚ
ValueError)Úbase_urls r%Ú get_base_urlr^
s%€Ü�y‰yÐ*Ó+€HÙ ÜÐ=Ó>Ð>Ø €Or$cóZ—ttjdtt«««S)NÚPROJECT_MAPPING_FILE)r
rQr[r!ÚDEFAULT_MAPPING_FILEr#r$r%Úget_mapping_filerbs€Ü ”— ‘ Ð0´#Ô6JÓ2KÓLÓ MÐMr$có6—tjdt«S)NÚFEISHU_STORE_FIELD_NAME)rQr[ÚDEFAULT_STORE_FIELD_NAMEr#r$r%Úget_store_field_namerfs€Ü
�9‰9Ð.Ô0HÓ IÐIr$có6—tjdt«S)NÚSYNC_START_DATE)rQr[ÚDEFAULT_START_DATEr#r$r%Úget_default_start_daterjs€Ü
�9‰9Ð&Ô(:Ó ;Ð;r$có`—tj«td¬«z
j«S©NrJ©Údays)rÚtodayrÚ isoformatr#r$r%Úget_default_end_daterq s!€Ü �J‰J‹Lœ9¨!Ô,Ñ ,× 7Ñ 7Ó 9Ð9r$cóP—gd¢}|D]}tj|«}|sŒ|cSy)N)ÚFEISHU_BOT_WEBHOOKÚFEISHU_ROBOT_WEBHOOKÚFEISHU_WEBHOOKÚLARK_BOT_WEBHOOKÚLARK_ROBOT_WEBHOOKÚ
GROUP_WEBHOOKÚ©rQr[)Ú
candidatesrVrWs r%Úget_group_webhook_urlr|$s/€ò€JóˆÜ— ‘ ˜#“ˆÚ ØŠLðð r$có.—tjdd«S)NÚFEISHU_CHAT_IDryrzr#r$r%Úget_feishu_chat_idr4s€Ü
2026-03-16 14:21:12 +08:00
�9‰9Ð% rÓ *Ð*r$có.—tjdd«S)NÚFEISHU_REPORT_IMAGE_PATHryrzr#r$r%Úget_feishu_report_image_pathr‚8s€Ü
�9‰9Ð/°Ó 4Ð4r$ÚfieldsÚpreferred_field_namecó¶—|D�cgc] }t|jd«xsd«‘Œ"}}||vr|StD]
}||vsŒ|cStd|›d|›�«‚cc}w)NÚ
field_nameryu'未找到店铺å��称字段: preferred=u, å�¯ç”¨å­—段=)r!ÚgetÚSTORE_FIELD_CANDIDATESr\)rƒr„ÚitemÚ field_namesÚ candidates r%Úresolve_store_field_namerŒ<su€ÙAGÓHÁ¸”3�t—x‘x  Ó-Ò3°Õ4À€KÐHؘ{Ñ*Ø#Ð#ß+ˆ Ø ˜ Ò #ØÒ ð,ô Ð>Ð?SÐ>TÐTcÐdoÐcpÐqÓ
rÐrùò
2026-03-16 14:21:12 +08:00
Is…%ArWcóJ—tj|d«j«S)Nz%Y-%m-%d)rÚstrptimer©rWs r%Ú
validate_dater�Fs€Ü × Ñ ˜U JÓ /× 4Ñ 4Ó 6Ð6r$cóT—tjdd|xsd«j«S)Nu[\s_\-()()]+ry)ÚreÚsubÚlowerr�s r%Únormalize_textr•Js#€Ü
�6‰6Ð% r¨5ª;°BÓ 7× =Ñ =Ó ?Ð?r$Ú
store_namec󘇗|xsdŠdgd¢fddgfdddgfddgfddgfg}|D]\}}tˆfd „|D««sŒ|cSd
2026-03-16 14:21:12 +08:00
‰vsd ‰vry
y) Nryr)ÚMamaÚmmmjrrrú ERBA MIGINArrc3ó&•K—|]}|‰v–—Œ
2026-03-16 14:21:12 +08:00
y­w©Nr#)Ú.0Úkeywordrs €r%Ú <genexpr>z#classify_project.<locals>.<genexpr>Xsøèø€Ð7©h 7ˆw˜$Œ©hùóƒru大西瓜籽妈妈)Úany)r–Úprioritized_rulesÚprojectÚkeywordsrs @r%Úclassify_projectr¥Ns…ø€Ø Ò ˜€Dà Ò)Ð*Ø �{�mÐ$Ø
��mÐ$Ð%Ø �{�mÐ$Ø ˜ �~Ð&ð Ðó/ш�Ü Ó7©hÓ7Õ 7ØŠNð/ð�dÑÐ2°dÑ:ØØ
r$r£cóN—ddgdggd¢ddgdggd¢d œ}|j||g«S)
Nru大眼�买买买r)rz
2026-03-16 14:21:12 +08:00
Mama Mujerz
MAMA MUJERrršr)rÚ BROKENZOOu 葆ç¦�颂r©r‡)r£Úaliasess r%Úget_project_table_aliasesrª_s?€à!Ð#7Ð8Ø!�]Ú4Ø�]Ð#Ø!�]Ú>ñ
€Gð �;‰;�w   Ó *Ð*r$ÚpathcóŽ—td|›�«t|d¬«}|j}i}|jdd¬«D]m}|sŒt |«dk\r
|dd\}}}nt |«dk\r |dd\}}nŒ6|r|sŒ;t |«j
«|t |«j
«<Œotdt |«›d�«|S) Nu加载店铺映射表: T)Ú data_onlyé)Úmin_rowÚ values_onlyéu店铺映射加载完æˆ�: õ æ�¡)r=r
ÚactiveÚ iter_rowsrAr!rN)r«ÚwbÚwsÚmappingÚrowÚ_Ú
business_nameÚbi_names r%Úload_store_mappingr¼ks΀Ü Ð& t fÐ
-Ô.Ü �t tÔ ,€BØ �‰€BØ €GØ�|‰| A°4ˆ|Ö8ˆÙØ Ü ˆs‹8�qŠ=Ø(+¨B¨Q¨Ñ %ˆAˆ}™gÜ
�‹X˜Š]Ø%(¨¨! WÑ "ˆM™7à Ù¡GØ Ü(+¨MÓ(:×(@Ñ(@Ó(Bˆ”�G“ ×"Ñ"Ó$Ò%ð9ô
Ð)¬#¨g«,¨°tÐ
<Ô=Ø €Nr$r+Ú
2026-03-16 14:21:12 +08:00
store_mappingcó&—|j|d«S©Nryr¨)r+r½s r%Úresolve_business_store_namerÀ€s€Ø × Ñ ˜]¨BÓ /Ð/r$c ó—gd¢}|D�cgc]}tj|«rŒ|‘Œ}}|rtddj|«›�«‚t dtj
d›dtj
d›dtj
2026-03-16 14:21:12 +08:00
d ›�«t
jtj
dtj
dtj
2026-03-16 14:21:12 +08:00
d
tj
d tj
d ¬ «Scc}w)
N)ÚANALYTICS_DB_HOSTÚANALYTICS_DB_PORTÚANALYTICS_DB_USERÚANALYTICS_DB_PASSWORDÚANALYTICS_DB_NAMEu缺少数æ�®åº“环境å�˜é‡�: ú, u连接 PostgreSQL: host=rÂz port=rÃz db=rÆrÄrÅ)ÚhostÚportÚuserÚpasswordÚdbname)rQr[r\Újoinr=rRÚpsycopg2Úconnect)ÚrequiredrVÚmissings r%Úget_db_connectionrÒ„sö€ò€Hñ'Ó=™h�s¬b¯i©i¸­nŠs˜h€GÐ=ÙÜÐ8¸¿¹À7Ó9KÐ8LÐMÓNÐNÜ Ø
"¤2§:¡:Ð.AÑ#BÐ"CÀ6Ì"Ï*É*ÐUhÑJiÐIjÐjnÔoq×oyÑoyð{NñpOðoPð Qôô × Ñ Ü
2026-03-16 14:21:12 +08:00
�Z‰ZÐ+Ñ
,Ü
�Z‰ZÐ+Ñ
2026-03-16 14:21:12 +08:00
,Ü
�Z‰ZÐ+Ñ
,Ü—‘Ð3Ñ4Ü�z‰zÐ-Ñ.ô  ðùò
>s
‰C?¤C?Ú
start_dateÚend_dateÚ
metric_configc
óf—|j«›d�}|td¬«zj«›d�}td|j›d|›d|›d�«t «5}|j «5}|j
|j||dœ«|j«}ddd«ddd«t|j›d t«›d
�«|D�cgc]8}t|d |dxsd j«|d
xs td«¬«‘Œ:c}S#1swYŒyxYw#1swYŒ}xYwcc}w)Nz 00:00:00rJrmu 开始查询z: ú -> u (å�³å¼€åŒºé—´))Ústart_tsÚend_ts_exclusiveu查询完æˆ�: u 行rryr®Ú0)r*r+r,)
2026-03-16 14:21:12 +08:00
rprr=rrÒÚcursorÚexecuterÚfetchallrAr)rNr ) rÓrÔrÕrØrÙÚconnÚcurÚrowsr¸s r%Úfetch_metric_rowsrá›s,€Ø×&Ñ&Ó(Ð)¨Ð3€HØ#¤i°QÔ&7Ñ7×BÑBÓDÐEÀYÐOÐÜ ˆ|˜M×5Ñ5Ð6°b¸¸
À$ÐGWÐFXÐXgÐ
hÔiÜ Ô  Ø
�[‰[Œ]˜cØ �K‰K˜
×2Ñ2ÀÐ_oÑ4pÔ qØ—<‘<“>ˆD÷÷
ô
2026-03-16 14:21:12 +08:00
�
×)Ñ)Ð*¨.¼¸T»¸ À4Ð
2026-03-16 14:21:12 +08:00
HÔIñó áˆCô ˜C ™F°3°q±6²<¸R×2FÑ2FÓ2HÐQTÐUVÑQWÒQgÔ[bÐcfÓ[gÖhØñ ð÷ ˆ]ú÷
Ð üò
 s*ÁD"Á.0DÂD"Ã=D.ÄD ÄD"Ä"D+ràcó8—td|j›�«td„«}|D]¨}t|j|«}|sŒt |«}|sŒ*|j j|j jf}||||j j|td««}||jz||||j |<Œªt|«} td„|j«D««}
t|j›d| ›d|
2026-03-16 14:21:12 +08:00
›�«|S)Nu 开始按项目/月/日期è�šå�ˆcó—td„«S)Ncó —tt«Srœ)rÚdictr#r$r%Ú<lambda>z9build_project_metrics.<locals>.<lambda>.<locals>.<lambda>±s €¤K´Ô$5r$rr#r$r%ræz'build_project_metrics.<locals>.<lambda>±s
€” Ñ5Ô6r$rÚc3ó2K—|]}t|«–—Œy­wrœ)rA)r�Úmonthss r%rŸz(build_project_metrics.<locals>.<genexpr>¾sèø€ÐAÑ0@ f”c˜&—kÑ0@ùó‚uè�šå�ˆå®Œæˆ�: 项目=u,项目月份组å�ˆ=)r=rrrÀr+r¥r*ÚyearÚmonthr‡r r,rAÚsumr>) ràr½rÕÚgroupedr¸Úbusiness_store_namer£Ú month_keyÚcurrent_amountÚ
project_countÚ month_counts r%Úbuild_project_metricsróªs€ô

Ð/°
×0IÑ0IÐ/JÐ
KÔLÜP[Ù6óQ€GóˆÜ9¸#×:KÑ:KÈ]Ó[ÐÙ"Ø Ü"Ð#6Ó7ˆÙØ Ø—]‘]×'Ñ'¨¯©×)<Ñ)<Ð=ˆ Ø  Ñ)¨)Ñ4°S·]±]ÑC×GÑGÐH[Ô]dÐehÓ]iÓjˆØJXÐ[^×[eÑ[eÑJeˆ�јÑ# C§M¡MÑ2Ð3FÒGðô˜“L€MÜÑA°·±Ô0@ÓAÓA€KÜ �
×)Ñ)Ð*Ð*?À
¸ÐNdÐepÐdqÐ
rÔsØ €Nr$Úgrouped_metricscó°—|j«D����cic]3\}}||j«D��cic]\}}|t|«“Œc}}“Œ5}}}}}|}||krn|j|jf}tD]8}|j |i«} | j |i«}
2026-03-16 14:21:12 +08:00
|
j |i«Œ:|t
d¬«z
}||krŒn|Scc}}wcc}}}}wrl)ÚitemsrårêrëÚSUPPORTED_PROJECTSrSr) rÓrÔrôr£Ú
month_dictrïÚdate_mapÚresultÚcurrentÚproject_monthsÚmetrics_by_dates r%Úbuild_target_project_monthsrþÃsë€ð$3×#8Ñ#8Ô#:öá#:Ñ ˆG�Zð Àz×GWÑGWÔGYÔZÑGYÑ0C° ¸8�)œT (›^Ñ+ÐGYÒZÑZØ#:ð óð€GØ
2026-03-16 14:21:12 +08:00
�XÒ
Ø—\‘\ 7§=¡=Ð1ˆ ß)ˆGØ#×.Ñ.¨w¸Ó;ˆNØ,×7Ñ7¸ À2ÓFˆOØ × &Ñ & w°Õ 3ð*ð ”9 !Ô$Ñ$ˆð
�XÓ
ð €Mùó[ùõs–C
²C
ÁC
Ã
C
cód—tjd«}tjd«}|r|s td«‚td«t j
2026-03-16 14:21:12 +08:00
d||dœd¬«}|j
«|j«}|jd «d
k7rtd |›�«‚td «|d
S)NÚ
FEISHU_APP_IDÚFEISHU_APP_SECRETu:缺少飞书环境å�˜é‡� FEISHU_APP_ID / FEISHU_APP_SECRETu&开始获å�–飞书 tenant_access_tokenzEhttps://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal)Úapp_idÚ
app_secreté©ÚjsonÚtimeoutÚcoderu获å�–飞书 token 失败: u'飞书 tenant_access_token 获å�–æˆ�功Útenant_access_token)
rQr[r\r=ÚrequestsÚpostÚraise_for_statusrr‡Ú RuntimeError)rrÚrespÚpayloads r%Úget_feishu_tokenr×s§€Ü
�Y‰Y�Ó
'€FÜ—‘Ð.Ó/€JÙ ™ÜÐUÓVÐVÜ Ð
5Ô6Ü �=‰=ØOبjÑ
9Øô €Dð
 ×ÑÔØ�i‰i‹k€G؇{�{�6Ó˜aÒÜÐ8¸¸ ÐBÓCÐCÜ Ð
6Ô7Ø Ð(Ñ )Ð)r$c
ó*—eZdZdeddfd„Zededefd„«Zdedededeeeffd „Z de
e fd
„Z d ede
eeeffd „Z
d ed
eddfd„Zd ede
eeefdzfd„Zd ede
eeefddfd„Zd ede
eeeffd„Zd ededeeefddfd„Zy)ÚFeishuBitableClientr]r6Ncó6—||_|j|«|_td|j›�«t «|_i|_tj«|_ |jjjd|j
›�ddœ«y)Nu(è§£æž�飞书 Base URL æˆ�功: app_token=úBearer úapplication/json; charset=utf-8©Ú
Authorizationz Content-Type) r]Úextract_app_tokenÚ app_tokenr=rÚtokenÚ
_fields_cacher
ÚSessionÚsessionÚheadersÚupdate)Úselfr]s r%Ú__init__zFeishuBitableClient.__init__ës€€Ø ˆŒ
Ø×/Ñ/°Ó9ˆŒÜÐ;¸D¿N¹NÐ;KÐLÔMÜ%Ó'ˆŒ
Ø>@ˆÔÜ×'Ñ'Ó)ˆŒ Ø � ‰ ×Ñ×#Ñ#à#*¨4¯:©:¨,Ð!7Ø Añ
õ
r$có¸—t|«jjd«}tjd|«}|st d|›�«‚|j
d«S)NÚ/z base/([^/]+)u$无法从链接中解æž� app_token: rJ)r r«rNr’Úsearchr\Úgroup)r]r«Úmatchs r%rz%FeishuBitableClient.extract_app_tokenùsQ€ä˜Ó!×&Ñ&×,Ñ,¨SÓ1ˆÜ— ‘ ˜/¨4Ó0ˆÙÜÐCÀHÀ:ÐNÓOÐ OØ�{‰{˜1‹~Ðr$Úmethodr«Úkwargsc óh—d|›�}|jd«}|rtd|›d|›d|›�«ntd|›d|›�«|jj||fddi|¤Ž} |j «}|jd k\rj|jd «xsi}td
|j›d|›d|jd«›d|jd«›d|jdd«›d|›� «‚|jd«dk7r]|jd «xsi}td|›d|jd«›d|jd«›d|jdd«›d|›�
«‚|jd«xsiS#t
$r9|j
«td|j›d |jdd
›�«‚wxYw)Núhttps://open.feishu.cnÚparamsu请求飞书接å�£: Ú z params=ré<u-飞书接å�£è¿”回了é�ž JSON å“�应: status=ú, body=éôé�Úerroru飞书接å�£ HTTP z: code=rz msg=Úmsgz log_id=Úlog_idryz payload=ru飞书接å�£å¤±è´¥ Údata)
r‡r=rÚrequestrr\r r
Ú status_codeÚtext) r r'r«r(Úurlr+rrr1s r%r5zFeishuBitableClient.requestsö€Ø& t fÐ-ˆØ—‘˜HÓ%ˆÙ Ü Ð+¨F¨8°1°T°F¸(À6À(ÐKÕ Lä Ð+¨F¨8°1°T°FÐ;Ô <Ø#ˆt�|‰|×#Ñ# F¨CÑF¸ÐF¸vÑFˆð {Ø—i‘i“kˆGð × Ñ ˜sÒ "Ø—K‘K Ó(Ò.¨BˆEÜØ$ T×%5Ñ%5Ð$6°a¸°v¸WÀWÇ[Á[ÐQWÓEXÐDYÐY^Ð_f×_jÑ_jÐkpÓ_qÐ^rðsØŸ)™) H¨bÓ1Ð2°)¸G¸9ðFóð
ð �;‰;�vÓ  !Ò #Ø—K‘K Ó(Ò.¨BˆEÜØ% d V¨7°7·;±;¸vÓ3FÐ2GÀuÈWÏ[É[ÐY^ÓM_ÐL`ðaØŸ)™) H¨bÓ1Ð2°)¸G¸9ðFóð
ð�{‰{˜6Ó"Ò( bÐ(øôò {Ø × !Ñ !Ô #ÜÐ!NÈt×O_ÑO_ÐN`Ð`gÐhl×hqÑhqÐrvÐsvÐhwÐgxÐyÓzÐ zð {ús
Á E/Å/AF1c óä—td«g}d} i}|r||d<|jdd|j›d�|¬«}|jd«xsgD]$}|j t |d |d
¬ ««Œ&|jd d
2026-03-16 14:21:12 +08:00
«sn|jd«xsd}|snŒ“tdt
|D�cgc]}|j‘Œc}«›�«tdt|«›d�«|Scc}w)Nu'开始获å�–多维表格数æ�®è¡¨åˆ—表ryÚ
2026-03-16 14:21:12 +08:00
page_tokenÚGETú/open-apis/bitable/v1/apps/z/tables©r+rör/r)r/rÚhas_moreFu 飞书返回的数æ�®è¡¨å��ç§°: uæ•°æ�®è¡¨åˆ—表获å�–完æˆ�: u 个) r=r5rr‡Úappendr.rBrrA)r rör:r+r4r‰s r%Ú list_tableszFeishuBitableClient.list_tabless€ÜÐ:Ô;Ø!#ˆØˆ
ØØ%'ˆFÙØ'1��|Ñ$Ø—<‘< Ð)DÀTÇ^Á^ÐDTÐT[Ð'\Ðek�<ÓlˆDØŸ™ Ó)Ò/¨RÒ/�Ø— ‘ œY°°ZÑ0@ÀtÈFÁ|ÔTÕUð0à—8‘8˜J¨Ô.ØØŸ™ ,Ó/Ò5°2ˆJÙØðô Ð3´LÑX]ÓA^ÑX]ÐPTÀ$Ç)Ã)ÐX]ÑA^Ó4_Ð3`ÐaÔbÜÐ0´°U³° ¸DÐAÔB؈ ùòB_sÂ3C-r/cóΗ||jvr6td|›dt|j|«›�«|j|Std|›�«g}d}t«}d} |dz
}ddi}|r+||d <||vrt d
|›d |›�«‚|j |«td |›d
|›d |xsd›�«|j
dd|j›d|›d�|¬«}|j|jd«xsg«|jdd«}|jd «xsd} td|›d
2026-03-16 14:21:12 +08:00
|›dt|«›d|›d| xsd›�
«|sn3| st d|›dt|«›�«‚| }|dk\rt d|›�«‚�Œ||j|<td|›d t|D�
cgc]}
|
jd!d«‘Œc}
«›�«td"|›dt|«›�«|Scc}
w)#Nu命中字段缓存: table_id=õ , 字段数=u#开始获å�–字段列表: table_id=ryrrJÚ page_sizeédr:u@字段列表分页出现é‡�å¤� page_token,已中断: table_id=z
2026-03-16 14:21:12 +08:00
, page_token=u#获å�–字段列表分页: table_id=z, page=z<first>r;r<ú/tables/ú/fieldsr=rör>Fu#字段列表分页完æˆ�: table_id=u, 累计字段数=z , has_more=z, next_page_token=z<empty>uG字段列表分页返回 has_more=True 但 page_token 为空: table_id=u, 已获å�–字段数=u7字段列表分页超过 100 页,已中断: table_id=u&飞书返回的字段å��ç§°: table_id=ú , fields=r†u#字段列表获å�–完æˆ�: table_id=) rr=rAÚsetr
Úaddr5rÚextendr‡rB) r r/rör:Ú seen_tokensÚ
page_indexr+r4r>Únext_page_tokenr‰s r%Ú list_fieldszFeishuBitableClient.list_fields0s¼€Ø �t×)Ñ)Ñ )Ü Ð4°X°J¸lÌ3Èt×OaÑOaÐbjÑOkÓKlÐJmÐnÔ oØ×%Ñ% hÑ/Ð /ÜÐ6°x°jÐAÔBØ&(ˆØˆ
Ü #£ˆ ؈
ØØ ˜!‰OˆJØ! 3Ð'ˆFÙØ'1��|Ñ$Ø Ñ,Ü&Ð)iÐjrÐisðtAðBLðAMð(NóOðOØ—‘ 
Ô+Ü Ð:¸8¸*ÀGÈJÈ<ÐWdÐeoÒe|Ðs|Ðd}Ð~Ô Ø—<‘<ØØ-¨d¯n©nÐ-=¸XÀhÀZÈwÐWØð óˆDð
�L‰L˜Ÿ™ 'Ó*Ò0¨bÔ 1Ø—x‘x 
¨EÓ2ˆHØ"Ÿh™h |Ó4Ò:¸ˆOÜ Ø5°h°Z¸wÀzÀlÐRdÔehÐinÓeoÐdpðqØ$˜:Ð%7¸Ò8TÈ9Ð7UðWô
ñØÙ"Ü"Ð%lÐmuÐlvðwLôMPðQVóMWðLXð$YóZðZØ(ˆJؘSÒ Ü"Ð%\Ð]eÐ\fÐ#gÓhÐhñ7ð8(-ˆ×ј8Ñ$ÜÐ9¸(¸À9Ì\ñCHó[IñCHÐz~Ð[_×[cÑ[cÐdpÐrtÕ[uðCHñ[IóNJðMKðLô MÜÐ6°x°jÀ ÌSÐQVËZÈLÐYÔZ؈ ùò[IsÆ G"r†cób‡—td|›d‰›�«|j|«}tˆfd„|D««rtd|›d‰›�«ytd|›d‰›�«|jdd|j›d|›d �‰d
d œ¬ «|j
j
|d«td
|›d‰›�«y)Nu#检查字段是å�¦å­˜åœ¨: table_id=ú, field=c3óF•K—|]}|jd«‰k(–—Œy­w)r†Nr¨)r�r‰r†s €r%rŸz:FeishuBitableClient.ensure_number_field.<locals>.<genexpr>]s øèø€ÐGÁ¸ˆt�x‰x˜ Ó%¨Õ3Áùsƒ!u)字段已存在,跳过创建: table_id=u#开始创建数字字段: table_id=ÚPOSTr<rErFr®)r†Útype©ru字段创建完æˆ�: table_id=)r=rNr¡r5rrÚpop)r r/r†rƒs ` r%Úensure_number_fieldz'FeishuBitableClient.ensure_number_fieldZsÉø€ÜÐ6°x°jÀÈÈ ÐUÔVØ×!Ñ! (Ó+ˆÜ ÓGÁÓGÔ GÜ Ð@ÀÀ
È(ÐS]ÐR^Ð_Ô `Ø ÜÐ6°x°jÀÈÈ ÐUÔVØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ7Ð SØ *°AÑ6ð ô
ð
×Ñ×јx¨Ô.ÜÐ0°°
¸(À:À,ÐOÕPr$có^—d|j›d|›d�}d|›�}td|›�«|jjd|d¬«} |j «}|j d k(rtd |›d
|›�«y|j dk\s|jd«dk7rtd|›d
|›�«y|jd«xsi}|jd«xs|jd«xsg}td|›dt|«›�«|S#t
$rtd |›d
|j ›�«YywxYw)Nr<rEú
/field_groupsr*u#å°�试读å�–字段编组: table_id=r;r-)ru:字段编组接å�£è¿”回é�ž JSON,跳过读å�–: table_id=z , status=i”u,字段编组读å�–接å�£ä¸�å�¯ç”¨: table_id=ú
, payload=r0rru2字段编组读å�–失败,跳过比对: table_id=r4röÚ field_groupsu#字段编组读å�–æˆ�功: table_id=u , 编组数=) rr=rr5rr\r6r‡rA)r r/r«r8rrr4rös r%Útry_list_field_groupsz)FeishuBitableClient.try_list_field_groupsisP€Ø,¨T¯^©^Ð,<¸HÀXÀJÈmÐ\ˆØ& t fÐ-ˆÜÐ6°x°jÐAÔBØ�|‰|×#Ñ# E¨3¸Ð#Ó;ˆð Ø—i‘i“kˆGð × Ñ ˜sÒ "Ü ÐCÀHÀ:ÈZÐX_ÐW`ÐaÔ bØØ × Ñ ˜sÒ " g§k¡k°&Ó&9¸QÒ&>Ü ÐIÈ(ÈÐS]Ð^eÐ]fÐgÔ hØØ�{‰{˜6Ó"Ò( bˆØ—‘˜Ó!ÒC T§X¡X¨nÓ%=ÒCÀˆÜÐ6°x°jÀ ÌSÐQVËZÈLÐYÔZ؈ øôò Ü ÐQÐRZÐQ[Ð[dÐei×euÑeuÐdvÐwÔ xÙð úsÁDÄ$D,Ä+D,rZcó—td|›d|D�cgc]5}|jd«xsdt|jd«xsg«f‘Œ7c}›�«|jdd|j›d|›d �d
|i¬ «td |›�«ycc}w)
Nu#开始创建字段编组: table_id=z , groups=rryÚchildrenrRr<rErXrZrTu)字段编组创建请求完æˆ�: table_id=)r=r‡rAr5r)r r/rZr%s r%Úcreate_field_groupsz'FeishuBitableClient.create_field_groups~s§€ÜØ1°(°ð<Ù`lÓmÑ`lÐW\˜Ÿ ™  &Ó)Ò/¨R´°U·Y±Y¸zÓ5JÒ5PÈbÓ1QÒRÐ`lÑmÐnð
pô
ð
� ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ=Ð YØ  ,Ð/ð ô
ô
Ð<¸X¸JÐGÕHùònsŽ:Bcó:—td|›�«g}d} ddi}|r||d<|jdd|j›d|›d �|¬
«}|j|j d «xsg«|j d«xsd}|snŒmtd |›d
t |«›�«|S)Nu#开始获å�–记录列表: table_id=ryrCr/r:r;r<rEz/recordsr=röu#记录列表获å�–完æˆ�: table_id=u , 记录数=)r=r5rrJr‡rA)r r/rör:r+r4s r%Ú list_recordsz FeishuBitableClient.list_recordsŠs€ÜÐ6°x°jÐAÔBØ&(ˆØˆ
ØØ! 3Ð'ˆFÙØ'1��|Ñ$Ø—<‘<ØØ-¨d¯n©nÐ-=¸XÀhÀZÈxÐXØð óˆDð
�L‰L˜Ÿ™ 'Ó*Ò0¨bÔ 1ØŸ™ ,Ó/Ò5°2ˆJÙØðô Ð6°x°jÀ ÌSÐQVËZÈLÐYÔZ؈ r$Ú record_idrƒc ó¬—td|›d|›dt|j««›�«|jdd|j›d|›d|›�d|i¬ «y)
Nu更新记录: table_id=z , record_id=rGÚPUTr<rEz /records/rƒrT)r=r4Úkeysr5r)r r/rarƒs r%Ú
update_recordz!FeishuBitableClient.update_recordžsh€ÜÐ*¨8¨*°LÀÀ È9ÔUYÐZ`×ZeÑZeÓZgÓUhÐTiÐjÔkØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ9ÐU^ÐT_Ð `ؘFÐ#ð õ
r$)rrr r!r!Ú staticmethodrr rår5r4r.r@rNrVr[r^r`rer#r$r%rrêsJ„ð 
 ð 
¨ó 
ðð Cð¨Còóðð)˜cð)¨ð)¸ð)ÀÀSÈ#ÀXÁó)ð6˜T )™_óð(( Cð(¨D°°c¸3°h±Ñ,@ó(ðT
Q¨Cð
Q¸Sð
QÀTó
Qð¨cð°d¸4ÀÀSÀ¹>Ñ6JÈTÑ6Qóð*
2026-03-16 14:21:12 +08:00
I¨Cð
I¸tÀDÈÈcÈÁNÑ?Sð
IÐX\ó
Ið Sð¨T°$°s¸C°x±.Ñ-Aóð(
 cð
°cð
À4ÈÈSÈÁ>ð
ÐVZô
r$rÚ path_textcó—|siSt|«}|j«std|›�«‚tj|j d¬««}|j
2026-03-16 14:21:12 +08:00
«D��cic]\}}t|«t|«“Œc}}Scc}}w)Nu未找到表å��映射文件: rErF)r
rKÚFileNotFoundErrorrÚloadsrLrör!)rgr«rrVrWs r%Úload_table_name_overridesrk§sw€Ù ؈ Ü � ‹?€DØ �;‰;Œ=ÜÐ"?À¸vÐ FÓGÐGÜ�j‰j˜Ÿ™°˜Ó9Ó:€GØ3:·=±=´?Ô C±?¡Z S¨%ŒC�‹H”c˜%“jÑ °?Ò CÐCùÓ CsÁ&B Ú webhook_urlÚtitler]c óz—|s td«ydddidd|dœdœd d
d |j«›d |j«›d
|›d�dœdœgdœdœ}td«tj||d¬«}|j «|j «}|j
2026-03-16 14:21:12 +08:00
d«dvrtd|›�«‚td«y)Nu;未é…�置飞书群机器人 webhook,跳过群消æ�¯æŽ¨é€�Ú interactiveÚwide_screen_modeTÚblueÚ
plain_text©ÚtagÚcontent©ÚtemplatermÚdivÚlark_mdõ**å�Œæ­¥èŒƒå›´**
õ 至 u.
2026-03-16 14:21:12 +08:00
**多维表格**
[点击打开多维表格](Ú)©rtr7©ÚconfigÚheaderÚelements)Úmsg_typeÚcardu!开始推é€�飞书群å�¡ç‰‡æ¶ˆæ�¯rrr)rNu飞书群消æ�¯æŽ¨é€�失败: u!飞书群å�¡ç‰‡æ¶ˆæ�¯æŽ¨é€�完æˆ�)r=rpr
r r rr‡r
)rlrmr]rÓrÔrƒrrs r%Úsend_feishu_sync_cardr„±sè€ñ ÜÐNÔOØà!à)¨4Ð0à"Ø!-¸%Ñ@ñð !à(à0°×1EÑ1EÓ1GÐ0HÈÈh×N`ÑN`ÓNbÐMcðdLØLTÈ:ÐUVðXññ ð ñ

ñ €Dô,
Ð
0Ô1Ü �=‰=˜¨4¸Ô <€DØ×ÑÔØ�i‰i‹k€G؇{�{�6Ó )Ñ+ÜÐ:¸7¸)ÐDÓEÐEÜ Ð
0Õ1r$Ú
image_pathcóV—|syt|«}|j«std|›�«‚t«}dd|›�i}|j d«5}d|j
2026-03-16 14:21:12 +08:00
|dfi}dd i}t
d
|›�«tjd |||d ¬
«}ddd«j«|j«}|jd«dk7rtd|›�«‚|jd«xsijd«xsd} | std|›�«‚t
d| ›�«| S#1swYŒ“xYw)Nryu未找到预览图文件: rrÚrbÚimagezapplication/octet-streamÚ
image_typer5u 开始上传飞书消æ�¯å›¾ç‰‡: z-https://open.feishu.cn/open-apis/im/v1/imagesr-)rr4Úfilesrrru飞书图片上传失败: r4Ú image_keyu0飞书图片上传æˆ�功但未返回 image_key: u*飞书消æ�¯å›¾ç‰‡ä¸Šä¼ å®Œæˆ�: image_key=)
r
2026-03-16 14:21:12 +08:00
rKrirÚopenrr=r
r r rr‡r
)
r…r«rrÚ
image_filerŠr4rrr‹s
r%Úupload_feishu_imagerŽÚs?€Ù ØÜ �
2026-03-16 14:21:12 +08:00
Ó €DØ �;‰;Œ=ÜÐ"<¸T¸FÐ CÓDÐDÜ Ó €EØ '¨%¨Ð 1Ð2€GØ
�‰�4Œ˜Jؘ4Ÿ9™9 jÐ2LÐMÐNˆØ˜iÐ(ˆÜÐ3°D°6Ð:Ô;Ü�}‰}ÐLÐV]ÐdhÐpuð@BôCˆ÷
ð
 ×ÑÔØ�i‰i‹k€G؇{�{�6Ó˜aÒÜÐ7¸°yÐAÓBÐBØ—+‘+˜fÓ%Ò+¨×0Ñ0°Ó=ÒDÀ"€IÙ ÜÐMÈgÈYÐWÓXÐXÜ Ð9¸)¸Ð
EÔFØ Ð÷
ˆús Á>DÄD(Úchat_idc ó*—|s td«yt«}|r t|«nd}ddd|j«›d|j«›d|›d|›d � d
2026-03-16 14:21:12 +08:00
œd œg}|r|j d |d
dd
œdœ«|j ddd
dd
œd|dœgdœ«|dt j ddidd
2026-03-16 14:21:12 +08:00
|d
œdœ|dœd¬«dœ} d|›�d d!œ}
td"|›�«tjd#|
| d$¬%«} | j «} | jd)k\rtd*| j›d+| ›�«‚| jd,«d-k7rtd.| ›�«‚td/«y#t$r9| j«td&| j›d'| jdd(›�«‚wxYw)0Nu<未é…�ç½® FEISHU_CHAT_ID,跳过应用机器人å�¡ç‰‡æŽ¨é€�ryrxryrzr{u
**多维表格**
[z](r|rsr}Úimgrru报表预览图)rtÚimg_keyÚaltÚactionÚbuttonu打开仪表盘Úprimary)rtr7rSr8)rtÚactionsrorpTrqrvr~F)Ú ensure_ascii)Ú
receive_idr‚rurrru4开始通过应用机器人å�‘é€�群å�¡ç‰‡: chat_id=zGhttps://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_idr-)rrru>应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥ï¼Œè¿”回é�ž JSON: status=r.r/r0u-应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥: status=rYrru&应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥: u$应用机器人群å�¡ç‰‡å�‘é€�完æˆ�)r=rrŽrpr?rÚdumpsr
r r\r r
r6r7r‡)
r�rmr]rÓrÔr…rr‹r�r5rrrs
r%Úsend_feishu_app_cardr›òs(€ñ ÜÐOÔPØÜ Ó €EÙ3=Ô# JÔ/À2€Iðà à(¨×)=Ñ)=Ó)?Ð(@ÀÀh×FXÑFXÓFZÐE[ð\*Ø*/¨°°8°*¸Að?ññ
ð &€HñØ�‰ °)ÈLÐevÑDwÑxÔyØ ‡O�Oàð$Ø$0Ð=NÑOØ%Ø#ñ ðñ
ô ðØ!Ü—:‘:à-¨tÐ4Ø'-À ÐY^Ñ8_Ñ`Ø$ñ
ð
ô

ñ €Gð# 5 'Ð*Ø9ñ€Gô
ÐCÀGÀ9Ð
MÔNÜ �=‰=ØQØØ
Øô  €Dð HØ—)‘)“+ˆð ×ј3ÒÜÐJÈ4×K[ÑK[ÐJ\Ð\fÐgnÐfoÐpÓqÐq؇{�{�6Ó˜aÒÜÐCÀGÀ9ÐMÓNÐNÜ Ð
3Õ4øô òHØ ×ÑÔÜÐ[Ð\`×\lÑ\lÐ[mÐmtÐuy×u~Ñu~ð@DðADðvEðuFðGóHð HðHús
Ã(EÅAFÚtablesrêrëÚ overridesc
ó,‡—td|›d|d›d|d›�«|xsi}|›d|d›d|d›�}||vrI||}|D]0}|j|k(sŒtd|›d|j›�«|cStd |›d
�«‚t|«D�cgc]
}t |«‘Œ} }t |«|›d �|d›d �|d›|d›�|d›d |d›d �|d›d|d›�|d›d
|d›�|d›d|d›�h}
td|›dt|«›�«g} g} |D]q}t |j«Št
ˆfd„| D««}
|
r| j|j«|
sŒLt