143 lines
6.5 KiB
Python
143 lines
6.5 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
批量更新飞书电子表格:回填用户ID和匹配状态
|
||
用于 2DOxEI 表 R915-R992 行
|
||
"""
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
|
||
# 78个手机号(按表格行顺序 915-992)
|
||
PHONES = [
|
||
'18898596908', '13104122113', '18616818587', '18600641856', '18527822530',
|
||
'15301808320', '15921183656', '18969141986', '18853077186', '19879837192',
|
||
'15013730773', '18240307314', '15133168361', '18607715299', '18640248566',
|
||
'15229999262', '18615767595', '15880070471', '15210946014', '13416197660',
|
||
'18030731125', '13372561305', '13438029626', '13426271919', '13380241801',
|
||
'13331090268', '13941957202', '13668236095', '18666339866', '18193473383',
|
||
'18719069856', '15092617699', '15602091300', '18906300189', '18823116345',
|
||
'16675181845', '15805920790', '13631576638', '13825629898', '18689550023',
|
||
'13858852527', '17701557793', '18800105821', '18243588666', '15070812805',
|
||
'15906585627', '13818184885', '18609909747', '18501055123', '18781333078',
|
||
'13510511993', '13763607518', '19131773001', '13429170125', '13548532992',
|
||
'18273336778', '15004066188', '15386183750', '15002087823', '15622866383',
|
||
'15236831122', '13980065537', '17351768736', '13752368975', '18988791586',
|
||
'13465563287', '18268989827', '18358369704', '13370181982', '15062199752',
|
||
'13009161168', '17701717015', '13969392995', '13560010506', '18042928605',
|
||
'13603503266', '15776824932', '18131135363',
|
||
]
|
||
|
||
# 数据库查询结果: 脱敏手机号 -> [account_id列表]
|
||
# rn=1 作为首选(最大account_id)
|
||
MATCHES = {}
|
||
raw_matches = [
|
||
('188****6908', 26655), ('131****2113', 27442), ('186****8587', 27410),
|
||
('186****1856', 27213), ('185****2530', 27227), ('153****8320', 27417),
|
||
('159****3656', 27316), ('189****1986', 27591), ('188****7186', 27248),
|
||
('198****7192', 27686), ('150****0773', 27464), ('182****7314', 27429),
|
||
('151****8361', 27432), ('186****5299', 27017), ('186****8566', 27630),
|
||
('152****9262', 27483), ('186****7595', 27467), ('158****0471', 27693),
|
||
('152****6014', 27490), ('134****7660', 27619), ('180****1125', 27618),
|
||
('133****1305', 26920), ('134****9626', 27583), ('134****1919', 27755),
|
||
('133****1801', 27633), ('133****0268', 27983), ('139****7202', 27499),
|
||
('136****6095', 27598), ('186****9866', 27745), ('181****3383', 27576),
|
||
('187****9856', 27585), ('150****7699', 28052), ('156****1300', 27672),
|
||
('189****0189', 27292), ('188****6345', 27836), ('166****1845', 27955),
|
||
('158****0790', 27951), ('136****6638', 5149), ('138****9898', 3612),
|
||
('186****0023', 27674), ('138****2527', 4882), ('177****7793', 27890),
|
||
('188****5821', 27761), ('182****8666', 27812), ('150****2805', 27813),
|
||
('159****5627', 27882), ('138****4885', 27911), ('186****9747', 27809),
|
||
('185****5123', 27776), ('187****3078', 27738), ('135****1993', 27806),
|
||
('137****7518', 27770), ('191****3001', 27638), ('134****0125', 27794),
|
||
('135****2992', 27750), ('182****6778', 27728), ('150****6188', 27803),
|
||
('153****3750', 27790), ('150****7823', 11807), ('156****6383', 28018),
|
||
('152****1122', 27869), ('139****5537', 27947), ('173****8736', 28070),
|
||
('137****8975', 27916), ('189****1586', 27941), ('134****3287', 28079),
|
||
('182****9827', 27860), ('183****9704', 27849), ('133****1982', 4923),
|
||
('150****9752', 28071), ('130****1168', 27936), ('177****7015', 27946),
|
||
('139****2995', 27889), ('135****0506', 28394), ('180****8605', 28011),
|
||
('136****3266', 27965), ('157****4932', 28088), ('181****5363', 27979),
|
||
]
|
||
|
||
for tel_masked, acc_id in raw_matches:
|
||
MATCHES[tel_masked] = acc_id # rn=1 优先,后出现的会覆盖
|
||
|
||
def mask_phone(phone):
|
||
"""脱敏手机号: 前3位 + **** + 后4位"""
|
||
return f"{phone[:3]}****{phone[-4:]}"
|
||
|
||
def get_tat():
|
||
"""获取 Tenant Access Token"""
|
||
import json
|
||
config = json.load(open('/root/.openclaw/credentials/xiaoxi/config.json'))
|
||
app = config['apps'][0]
|
||
import urllib.request
|
||
data = json.dumps({"app_id": app['appId'], "app_secret": app['appSecret']}).encode()
|
||
req = urllib.request.Request(
|
||
'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
|
||
data=data,
|
||
headers={'Content-Type': 'application/json; charset=utf-8'}
|
||
)
|
||
resp = json.loads(urllib.request.urlopen(req).read())
|
||
return resp['tenant_access_token']
|
||
|
||
def update_sheet_range(tat, token, sheet_id, range_str, values):
|
||
"""批量更新电子表格范围"""
|
||
import urllib.request
|
||
url = f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{token}/values'
|
||
body = json.dumps({
|
||
"valueRange": {
|
||
"range": f"{sheet_id}!{range_str}",
|
||
"values": values
|
||
}
|
||
}).encode()
|
||
req = urllib.request.Request(url, data=body, method='PUT')
|
||
req.add_header('Authorization', f'Bearer {tat}')
|
||
req.add_header('Content-Type', 'application/json; charset=utf-8')
|
||
resp = json.loads(urllib.request.urlopen(req).read())
|
||
return resp
|
||
|
||
if __name__ == '__main__':
|
||
# 构建回填数据
|
||
f_values = [] # F列: account_id
|
||
g_values = [] # G列: 回填状态
|
||
|
||
matched_count = 0
|
||
multi_count = 0
|
||
|
||
for phone in PHONES:
|
||
masked = mask_phone(phone)
|
||
acc_id = MATCHES.get(masked)
|
||
if acc_id:
|
||
f_values.append([str(acc_id)])
|
||
g_values.append(["已匹配"])
|
||
matched_count += 1
|
||
else:
|
||
f_values.append(["未匹配"])
|
||
g_values.append(["未匹配"])
|
||
|
||
print(f"Total: {len(PHONES)}, Matched: {matched_count}, Unmatched: {len(PHONES) - matched_count}")
|
||
|
||
# 获取 token
|
||
tat = get_tat()
|
||
token = 'RFIJsXT8FhGHhctY4RwczcOfnac'
|
||
sheet_id = '2DOxEI'
|
||
|
||
# 更新 F 列 (F915:F992) - 回填用户ID
|
||
resp_f = update_sheet_range(tat, token, sheet_id, 'F915:F992', f_values)
|
||
print(f"Update F column: code={resp_f.get('code')}, msg={resp_f.get('msg')}")
|
||
|
||
# 更新 G 列 (G915:G992) - 回填状态
|
||
resp_g = update_sheet_range(tat, token, sheet_id, 'G915:G992', g_values)
|
||
print(f"Update G column: code={resp_g.get('code')}, msg={resp_g.get('msg')}")
|
||
|
||
# 更新 E 列 (E915:E992) - 请求状态改为"已返回"
|
||
e_values = [["已返回"] for _ in range(len(PHONES))]
|
||
resp_e = update_sheet_range(tat, token, sheet_id, 'E915:E992', e_values)
|
||
print(f"Update E column: code={resp_e.get('code')}, msg={resp_e.get('msg')}")
|
||
|
||
if resp_f.get('code') == 0 and resp_g.get('code') == 0:
|
||
print("\n✅ 所有78条记录已成功回填!")
|
||
else:
|
||
print("\n⚠️ 部分更新可能失败,请检查。")
|