high-risk-scheme-approval-d.../b4b_certified_dashboard_2026.py

160 lines
7.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""危大方案独立看板 - 2026开工版 · 简化状态"""
import pandas as pd, warnings, json
from pathlib import Path
warnings.filterwarnings('ignore')
DATA_DATE = '2026-06-08'
BASE = Path(f'/mnt/y/Openclaw_Hub/05_表达Express/专项施工方案数据看板/data/{DATA_DATE}/cleaned')
df = pd.read_parquet(BASE / 'methods_cleaned.parquet')
valid = df[df['是否有效登记'] == True].copy()
valid['开工年份'] = pd.to_datetime(valid['分部分项工程计划开工日期'], errors='coerce').dt.year
y2026 = valid[valid['开工年份'] == 2026].copy()
def simple_status(s):
s = str(s)
if any(kw in s for kw in ['已审批', '已备案']):
return '已完成'
return '未完成'
y2026['简化状态'] = y2026['方案状态_clean'].apply(simple_status)
completed = (y2026['简化状态'] == '已完成').sum()
total = len(y2026)
oversized = (y2026['是否超一定规模'].astype(str) == '').sum()
# By country
country_stats = y2026.groupby('所属国别').agg(
项目数=('项目名称', 'nunique'),
方案总数=('方案名称', 'count'),
已完成=('简化状态', lambda x: (x == '已完成').sum()),
超规=('是否超一定规模', lambda x: (x.astype(str) == '').sum()),
).reset_index()
country_stats['审批率'] = (country_stats['已完成'] / country_stats['方案总数'] * 100).round(0).astype(int)
# Project summary
ps = y2026.groupby('项目名称').agg(
方案总数=('方案名称', 'count'),
已完成=('简化状态', lambda x: (x == '已完成').sum()),
超规=('是否超一定规模', lambda x: (x.astype(str) == '').sum()),
).reset_index()
ps['未完成'] = ps['方案总数'] - ps['已完成']
ps['审批率'] = (ps['已完成'] / ps['方案总数'] * 100).round(0).astype(int)
ps['国别'] = ps['项目名称'].map(y2026.groupby('项目名称')['所属国别'].first())
ps = ps.sort_values('方案总数', ascending=False)
# Status breakdown
status_counts = y2026['方案状态_clean'].value_counts().to_dict()
# Generate HTML
rows = []
for _, r in ps.iterrows():
name = r['项目名称'][:60]
total_n = int(r['方案总数'])
done = int(r['已完成'])
undone = int(r['未完成'])
sz = int(r['超规'])
rate = int(r['审批率'])
country = r.get('国别', '')
if rate >= 80: cls = 'badge-ok'
elif rate >= 50: cls = 'badge-warn'
else: cls = 'badge-alert'
rows.append(f'<tr><td>{name}</td><td class="num">{total_n}</td><td class="num">{done}</td><td class="num">{sz}</td><td class="num"><span class="badge {cls}">{rate}%</span></td><td>{country}</td></tr>')
country_rows = []
for _, r in country_stats.iterrows():
name = r['所属国别']
c = int(r['审批率'])
if c >= 80: cls = 'badge-ok'
elif c >= 50: cls = 'badge-warn'
else: cls = 'badge-alert'
country_rows.append(f'<tr><td>{name}</td><td class="num">{int(r[\"项目数\"])}</td><td class="num">{int(r[\"方案总数\"])}</td><td class="num">{int(r[\"已完成\"])}</td><td class="num">{int(r[\"超规\"])}</td><td class="num"><span class="badge {cls}">{c}%</span></td></tr>')
approved_pct = round(completed/total*100) if total else 0
approved_color = '#22c55e' if approved_pct >= 80 else '#f59e0b' if approved_pct >= 50 else '#ef4444'
html = f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>危大方案编审进度看板 | 2026年开工 | 中东区域公司</title>
<style>
*{{margin:0;padding:0;box-sizing:border-box}}
body{{font-family:'Microsoft YaHei','PingFang SC',sans-serif;background:#0f172a;color:#e2e8f0;padding:24px}}
.header{{text-align:center;padding:28px 0;border-bottom:2px solid #1e3a5f;margin-bottom:28px}}
.header h1{{color:#c8962e;font-size:26px}}
.header p{{color:#64748b;margin-top:6px;font-size:14px}}
.kpi-grid{{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:24px}}
.kpi{{background:#1e293b;border-radius:10px;padding:18px;border:1px solid #334155;text-align:center}}
.kpi .num{{font-size:32px;font-weight:bold;margin:6px 0}}
.kpi .label{{color:#94a3b8;font-size:13px}}
.table-wrap{{background:#1e293b;border-radius:10px;padding:20px;margin-bottom:20px;border:1px solid #334155}}
.table-wrap h2{{color:#c8962e;font-size:17px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid #334155}}
table{{width:100%;border-collapse:collapse;font-size:13px}}
th{{background:#0f172a;color:#c8962e;padding:9px 8px;text-align:left}}
td{{padding:7px 8px;border-bottom:1px solid #1e3a5a}}
tr:hover{{background:#1a2e44}}
.num{{text-align:right}}
.badge{{padding:2px 8px;border-radius:4px;font-size:11px;font-weight:bold}}
.badge-ok{{background:#166534;color:#86efac}}
.badge-warn{{background:#78350f;color:#fbbf24}}
.badge-alert{{background:#7f1d1d;color:#fca5a5}}
.bar-wrap{{background:#334155;border-radius:3px;width:100%;height:8px;display:inline-block}}
.bar{{display:inline-block;height:8px;border-radius:3px}}
.footer{{text-align:center;color:#475569;padding:16px;font-size:12px}}
.note{{background:#1a2e44;border-left:3px solid #c8962e;padding:12px 16px;margin-bottom:20px;border-radius:0 8px 8px 0;font-size:13px;color:#94a3b8}}
</style>
</head>
<body>
<div class="header">
<h1>🏗️ 危大方案编审进度看板</h1>
<p>中国港湾中东区域公司 · 2026年开工项目 · 数据日期:{DATA_DATE}</p>
</div>
<div class="kpi-grid">
<div class="kpi"><div class="label">2026开工方案</div><div class="num" style="color:#c8962e">{total}</div><div class="label">覆盖{len(ps)}个项目</div></div>
<div class="kpi"><div class="label">超一定规模</div><div class="num" style="color:#f59e0b">{oversized}</div><div class="label">占比 {round(oversized/total*100)}%</div></div>
<div class="kpi"><div class="label">已完成审批</div><div class="num" style="color:{approved_color}">{completed}</div><div class="label">{total-completed}项未完成</div></div>
<div class="kpi"><div class="label">审批完成率</div><div class="num" style="color:{approved_color}">{approved_pct}%</div><div class="label">{completed}/{total}</div></div>
</div>
<div class="note">
📌 <b>状态说明</b>:已完成 = 已审批或已备案;未完成 = 未审批 / 审批中 / 未知。已作废方案已排除。<br>
📌 <b>范围说明</b>仅显示分部分项工程计划开工日期在2026年的方案{total}项,占全部有效方案{len(valid)}项的{round(total/len(valid)*100)}%)。
</div>
<!-- 项目明细 -->
<div class="table-wrap">
<h2>📋 项目明细(按方案总数排序)</h2>
<table>
<tr><th>项目名称</th><th class="num">方案</th><th class="num">已完成</th><th class="num">超规</th><th class="num">审批率</th><th>国别</th></tr>
{rows_html}
<tr style="font-weight:bold;background:#1a2e44"><td>合计</td><td class="num">{total}</td><td class="num">{completed}</td><td class="num">{oversized}</td><td class="num">{approved_pct}%</td><td></td></tr>
</table>
</div>
<!-- 按国别 -->
<div class="table-wrap">
<h2>🌍 按国别汇总</h2>
<table>
<tr><th>国别</th><th class="num">项目数</th><th class="num">方案总数</th><th class="num">已完成</th><th class="num">超规</th><th class="num">审批率</th></tr>
{country_rows_html}
</table>
</div>
<div class="footer">
<p>中国港湾中东区域公司 技术部 | 2026开工项目 | 自动生成于 {DATA_DATE}</p>
</div>
</body></html>'''
out = BASE / 'certified_schemes_dashboard.html'
out.write_text(html, encoding='utf-8')
print(f'{out}')
print(f' {len(html):,} bytes')
print(f' {total} schemes, {len(ps)} projects, {approved_pct}% completion')