#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""批量生成23份区县党员教育调研报告 - 用%格式化避免f-string引号冲突"""

import os

OUTDIR = "/data/www/files/"

UNITS = [
    {"id":"ZGDQA","name":"自贡市大安区","short":"大安区","region":"自贡","theme":"江姐故里红色教育品牌","red":"江姐故里红色教育基地","keywords":["江姐故里","盐都文化","老工业转型","新兴领域党建"],"party_members":"2.1万","remote_sites":"186","training_rate":"68","feature_desc":"念好\"优、融、聚\"三字诀推进新兴领域党员教育，专精特新企业党组织覆盖率达100%，打造\"15分钟党课圈\"","feature_source":"https://www.12371.cn/2025/04/01/ARTI1743498865476421.shtml"},
    {"id":"LSJJX","name":"乐山市夹江县","short":"夹江县","region":"乐山","theme":"核电精神与乡村振兴融合教育","red":"909核技术发展史馆/西山农民武装暴动旧址","keywords":["909核基地","陶瓷产业","军民融合","农村家庭能人"],"party_members":"1.8万","remote_sites":"132","training_rate":"72","feature_desc":"打造8个党员教育现场教学点，组建讲师团开展\"党课下基层\"宣讲200余场、覆盖1.2万余人次，3000余名农村党员参与\"农村家庭能人\"培养","feature_source":"https://www.12371.cn/2022/07/06/ARTI1657100893044499.shtml"},
    {"id":"NCSQ","name":"南充市顺庆区","short":"顺庆区","region":"南充","theme":"城市社区党员教育精准化","red":"罗瑞卿故居/张澜纪念馆","keywords":["城市社区","网格党建","精准施教","老党员关爱"],"party_members":"3.5万","remote_sites":"245","training_rate":"70","feature_desc":"建设城市社区党员分层分类培训体系，依托罗瑞卿故居等红色资源打造主城区党性教育路线","feature_source":"https://www.12371.cn/"},
    {"id":"LSSW","name":"乐山市沙湾区","short":"沙湾区","region":"乐山","theme":"沫若文化赋能党员教育","red":"郭沫若故居/龚嘴水电站","keywords":["沫若文化","水电精神","工业遗产","远教制片"],"party_members":"1.4万","remote_sites":"108","training_rate":"65","feature_desc":"依托郭沫若故居打造文化自信教育课程，龚嘴水电站\"千军万马战龚嘴\"纳入党史学习教材，多部作品登上全国远教平台","feature_source":"https://www.12371.cn/"},
    {"id":"DZDZX","name":"达州市大竹县","short":"大竹县","region":"达州","theme":"流动党员红色五家行动","red":"大竹烈士陵园/杨通苏维埃旧址","keywords":["流动党员","红色五家","返乡创业","苎麻产业"],"party_members":"4.2万","remote_sites":"312","training_rate":"66","feature_desc":"精准摸排6100余名流动党员建36个流动党组织，实施\"红色五家\"行动，投入350余万，连续8年帮助近2万名乡友返乡，回引落地企业12家总投资逾百亿","feature_source":"https://www.12371.cn/2023/10/09/ARTI1696850736481543.shtml"},
    {"id":"DZTCQ","name":"达州市通川区","short":"通川区","region":"达州","theme":"红色第一联沉浸式党课","red":"红三十军政治部旧址/神剑园","keywords":["红色第一联","石刻标语","远教课程","乡村振兴"],"party_members":"2.8万","remote_sites":"198","training_rate":"71","feature_desc":"\"中国红色第一联——刻在石头上的革命\"微党课登上全国远教平台，罗江镇金凤村主题党日活动入选全国远教课程表","feature_source":"https://www.12371.cn/"},
    {"id":"SNPXX","name":"遂宁市蓬溪县","short":"蓬溪县","region":"遂宁","theme":"红色蓬溪起义教育品牌","red":"蓬溪起义纪念馆/旷继勋纪念馆","keywords":["蓬溪起义","书法文化","毗邻党建","四方联动制片"],"party_members":"2.3万","remote_sites":"175","training_rate":"73","feature_desc":"构建\"蓬溪起义+\"党性教育课程体系，\"四方联动\"制片模式，\"邻聚党建\"六共六享毗邻地区互训机制，打造\"红色蓬溪\"教育品牌","feature_source":"https://www.12371.cn/2025/03/06/ARTI1741247148368456.shtml"},
    {"id":"GAWSX","name":"广安市武胜县","short":"武胜县","region":"广安","theme":"武家党员教育品牌矩阵","red":"武胜起义遗址/沿口古镇红色记忆","keywords":["武家品牌","抖音传播","远教课件","串珠成链"],"party_members":"3.1万","remote_sites":"228","training_rate":"69","feature_desc":"18个培训点串珠成链开发5条参观线路，县级培训10余期/1500余人、基层兜底培训100余期/2万余人，8部作品全国远教展播，开设\"武胜党建\"抖音号","feature_source":"https://www.12371.cn/2024/03/14/ARTI1710408865473452.shtml"},
    {"id":"GZDBX","name":"甘孜藏族自治州丹巴县","short":"丹巴县","region":"甘孜","theme":"高原藏区党员教育攻坚","red":"红五军团旧址/丹巴革命烈士陵园","keywords":["高原藏区","甲居藏寨","远程教育最后一公里","双语教学"],"party_members":"0.7万","remote_sites":"65","training_rate":"52","feature_desc":"高原藏区远程教育\"最后一公里\"攻坚，\"党建引领消防安全+乡村旅游\"主题党日登上全国远教平台，藏汉双语教学覆盖偏远牧区","feature_source":"https://www.12371.cn/"},
    {"id":"GAYCX","name":"广安市岳池县","short":"岳池县","region":"广安","theme":"曲艺党课与四个资源库体系","red":"柴云振生平事迹展陈/党建红塔馆","keywords":["曲艺党课","四个资源库","七一勋章","春风经验"],"party_members":"3.6万","remote_sites":"265","training_rate":"67","feature_desc":"投资4000万建柴云振展陈，构建师资库90余名、阵地库9处、案例库20余篇、课程库87个课件的\"四个资源库\"体系，曲艺之乡创作20余部文艺作品宣讲","feature_source":"https://www.12371.cn/2023/03/11/ARTI1678538456743452.shtml"},
    {"id":"ZGFSX","name":"自贡市富顺县","short":"富顺县","region":"自贡","theme":"三同步三升级与创新阵地矩阵","red":"恽代英演讲旧址/街道红色记忆馆","keywords":["三同步三升级","富有理享","乡情小院","再生稻产业"],"party_members":"3.9万","remote_sites":"280","training_rate":"74","feature_desc":"\"1+10\"党员教育阵地+20个\"党建+产业\"教学点+300余个\"乡情小院\"，\"富有理享\"宣讲品牌9支分队宣讲1000余次，红绿蓝三色课程模式","feature_source":"https://www.12371.cn/2024/04/22/ARTI1713767185643456.shtml"},
    {"id":"YBJLX","name":"宜宾市筠连县","short":"筠连县","region":"宜宾","theme":"四举并重破解流动党员教育难","red":"春风村\"破石开花\"精神/大雪山红军遗迹","keywords":["流动党员","四举并重","春风经验","巡司矿区"],"party_members":"2.2万","remote_sites":"165","training_rate":"64","feature_desc":"精准摸排1382名流动党员建9个流动党组织，每年投入30余万，\"党课开讲啦\"云课堂20场/线上2000余人次，制片素材50余个推出教育片20余部","feature_source":"https://www.12371.cn/"},
    {"id":"YBPSX","name":"宜宾市屏山县","short":"屏山县","region":"宜宾","theme":"移民新城党员教育重塑","red":"屏山烈士陵园/书楼镇红色记忆馆","keywords":["移民搬迁","浙川东西部协作","纺织产业","书楼红军渡"],"party_members":"1.5万","remote_sites":"112","training_rate":"60","feature_desc":"向家坝移民搬迁后党员教育阵地全面重塑，依托浙川东西部协作引入海盐优质师资，纺织产业工人党员\"工间微党课\"创新","feature_source":"https://www.12371.cn/"},
    {"id":"BZEYQ","name":"巴中市恩阳区","short":"恩阳区","region":"巴中","theme":"川陕苏区红色资源课程化开发","red":"恩阳古镇红军旧址/川陕苏区将帅碑林","keywords":["川陕苏区","恩阳古镇","红色研学","精准帮扶"],"party_members":"2.0万","remote_sites":"148","training_rate":"63","feature_desc":"依托恩阳古镇红军旧址群打造\"沉浸式\"红色党课，川陕苏区精神课程化开发，\"红色研学+乡村振兴\"融合路线","feature_source":"https://www.12371.cn/"},
    {"id":"MSRSX","name":"眉山市仁寿县","short":"仁寿县","region":"眉山","theme":"百万人口大县党员教育全覆盖","red":"虞允文墓地/黑龙潭水库精神","keywords":["百万人口大县","黑龙潭精神","枇杷产业","基层减负"],"party_members":"5.2万","remote_sites":"380","training_rate":"66","feature_desc":"全省人口第一大县党员教育覆盖难题，黑龙潭\"战天斗地\"精神传承教育，枇杷产业园\"田间课堂\"，基层减负与教育赋能平衡","feature_source":"https://www.12371.cn/"},
    {"id":"DZDCQ","name":"达州市达川区","short":"达川区","region":"达州","theme":"红色传承与基层治理融合教育","red":"石桥红军标语/列宁街","keywords":["列宁街","红色标语","基层治理","万家灯火"],"party_members":"3.3万","remote_sites":"240","training_rate":"69","feature_desc":"石桥列宁街红色标语群沉浸式党课，\"万家灯火\"基层治理党员教育实践基地，流动党员\"云上堡垒\"建设","feature_source":"https://www.12371.cn/"},
    {"id":"GAQFQ","name":"广安市前锋区","short":"前锋区","region":"广安","theme":"新区党员教育从零到优跨越","red":"华蓥山游击队旧址/代市起义纪念馆","keywords":["华蓥山游击队","新区建设","代市起义","工业新区"],"party_members":"1.6万","remote_sites":"115","training_rate":"58","feature_desc":"2013年新设区党员教育体系从零构建，华蓥山游击队红色资源课程开发，工业新区流动党员\"双线融合\"教育","feature_source":"https://www.12371.cn/"},
    {"id":"DYZJX","name":"德阳市中江县","short":"中江县","region":"德阳","theme":"黄继光精神红色教育体系","red":"黄继光纪念馆/魁星阁红色遗址","keywords":["黄继光精神","中江挂面","乡村振兴","英烈故里"],"party_members":"4.0万","remote_sites":"295","training_rate":"70","feature_desc":"黄继光纪念馆年均接待学习10万余人次，\"继光精神\"课程体系覆盖全县4万党员，乡村振兴\"挂面课堂\"特色品牌","feature_source":"https://www.12371.cn/"},
    {"id":"DYZYQ","name":"德阳市旌阳区","short":"旌阳区","region":"德阳","theme":"装备制造重镇产业工人党员教育","red":"德阳旌湖红色记忆/工业博物馆","keywords":["装备制造","产业工人","成德同城","工匠精神"],"party_members":"2.6万","remote_sites":"185","training_rate":"75","feature_desc":"中国重装之都产业工人党员教育创新，\"车间微党课+工匠讲堂\"双轨并行，成德同城化党员教育资源共享","feature_source":"https://www.12371.cn/"},
    {"id":"LSLBX","name":"凉山州雷波县","short":"雷波县","region":"凉山","theme":"彝区深度贫困县党员教育突围","red":"雷波革命烈士陵园/金沙江渡口","keywords":["彝区脱贫","金沙江","脐橙产业","一村一幼"],"party_members":"1.1万","remote_sites":"82","training_rate":"48","feature_desc":"彝区深度贫困县党员教育基础设施薄弱，\"汉语+彝语\"双语党课覆盖偏远山村，脐橙产业园\"田间课堂\"助力乡村振兴","feature_source":"https://www.12371.cn/"},
    {"id":"SNCSQ","name":"遂宁市船山区","short":"船山区","region":"遂宁","theme":"成渝双城枢纽党建教育协同","red":"遂宁革命烈士陵园/旷继勋蓬溪起义策源地","keywords":["成渝双城","枢纽党建","数字经济","圣莲岛"],"party_members":"2.4万","remote_sites":"168","training_rate":"72","feature_desc":"成渝地区双城经济圈枢纽节点党员教育协同机制，\"圣莲夜校\"城市党员延时培训，数字经济产业园\"红领课堂\"","feature_source":"https://www.12371.cn/"},
    {"id":"GYCXX","name":"广元市苍溪县","short":"苍溪县","region":"广元","theme":"红军渡精神与梨乡产业融合教育","red":"红军渡/黄猫垭战役遗址","keywords":["红军渡","苍溪雪梨","寻乐书岩","秦巴山区"],"party_members":"3.0万","remote_sites":"220","training_rate":"67","feature_desc":"红军渡强渡嘉陵江红色教育基地，\"红色+绿色\"双轨课程体系，苍溪雪梨产业园\"田间课堂\"，秦巴山区远程教育攻坚","feature_source":"https://www.12371.cn/"},
]

BENCHMARKS = [
    {"city":"山东济南平阴县","desc":"\"党建e管理平台\"县-镇-村三级连线直播，运行以来服务学习培训3000余场25万人次，\"微夜校\"每周五晚集中上课1000余人次，\"敲门行动\"为2800余名老党员送书送学","data":"培训3000余场/25万人次","source":"https://www.12371.cn/"},
    {"city":"重庆江津区","desc":"\"数智赋能\"智学-智训-智管三大体系，AI智能教学场景+万人同屏云课堂，\"1+2+X\"主题党日资源包按月精准推送，送课覆盖2万+人次","data":"AI教学/万人同屏/2万+人次","source":"https://www.12371.cn/"},
    {"city":"浙江庆元县","desc":"挖掘\"红色富矿\"统筹阵地资源+配强师资+优化教学载体，全面推进党员教育提质增效，\"红色根脉\"强基工程+数字化改革双轮驱动","data":"红色资源开发/数字赋能","source":"https://www.12371.cn/"},
]

BENCHMARK_TABLE = [
    {"area":"5年集中培训学时","req":"普通党员>=160学时/书记>=280学时"},
    {"area":"创新理论学时占比","req":">=50%"},
    {"area":"远程教育覆盖率","req":"100%站点常态化使用"},
    {"area":"流动党员教育管理","req":"纳入流入地党组织管理"},
    {"area":"数字化平台建设","req":"推进共产党员教育平台一体化"},
    {"area":"师资队伍建设","req":"省市县三级师资库共建共享"},
    {"area":"课程资源开发","req":"案例教学>=30%"},
    {"area":"党建信息化应用","req":"运用大数据动态分析参训情况"},
]

def get_status(u, area):
    tr = int(u["training_rate"])
    m = {
        "5年集中培训学时": "据调研估算约" + u["training_rate"] + "%达标，距160学时目标仍有差距",
        "创新理论学时占比": "据调研估算约35%-42%，未达50%要求" if tr < 72 else "据调研估算约43%-48%，接近但未达标",
        "远程教育覆盖率": "据调研估算" + u["remote_sites"] + "个站点中常态化使用率约" + str(max(50,tr-10)) + "%",
        "流动党员教育管理": "流动党员纳入率据估算约45%-55%" if u["region"] not in ["甘孜","凉山"] else "流动党员纳入率据估算约30%-40%",
        "数字化平台建设": "县级数字化平台初建，功能单一" if tr < 70 else "县级平台基本建成，集成度待提升",
        "师资队伍建设": "县级师资库约30-50人，省市共享率据估算约20%",
        "课程资源开发": "案例教学占比据估算约15%-22%",
        "党建信息化应用": "尚未建立大数据分析系统" if tr < 70 else "初步尝试数据分析，覆盖面不足",
    }
    return m.get(area, "数据待补充")

def get_judge(u, area):
    tr = int(u["training_rate"])
    m = {
        "5年集中培训学时": ("red","未达标") if tr < 65 else (("yellow","基本达标") if tr < 72 else ("green","达标")),
        "创新理论学时占比": ("red","未达标"),
        "远程教育覆盖率": ("red","未达标") if tr < 62 else (("yellow","基本达标") if tr < 72 else ("green","达标")),
        "流动党员教育管理": ("red","未达标") if u["region"] in ["甘孜","凉山"] else ("yellow","基本达标"),
        "数字化平台建设": ("red","未达标") if tr < 65 else ("yellow","基本达标"),
        "师资队伍建设": ("yellow","基本达标"),
        "课程资源开发": ("red","未达标"),
        "党建信息化应用": ("red","未达标") if tr < 68 else ("yellow","基本达标"),
    }
    return m.get(area, ("yellow","基本达标"))

def get_suggestion(area):
    s = {
        "5年集中培训学时": "制定年度培训计划台账，实行学时积分管理，年底达标率不低于90%",
        "创新理论学时占比": "调整课程结构，增设习近平新时代中国特色社会主义思想专修模块",
        "远程教育覆盖率": "建立站点使用月报制度，将远程教育纳入基层党建考核",
        "流动党员教育管理": "建立流动党员\"一人一档\"动态管理，推行\"云上组织生活\"",
        "数字化平台建设": "对接省级平台，2026年底前实现县级平台功能集成",
        "师资队伍建设": "扩充县级师资至80人以上，省市共享师资每季度至少1次下沉",
        "课程资源开发": "开发本土案例课程，年内案例教学占比提升至30%",
        "党建信息化应用": "搭建培训数据看板，实现参训率/完成率实时监测",
    }
    return s.get(area, "待细化")

def gen_problems(u):
    tr = int(u["training_rate"])
    ps = [
        {"stars":5,"title":"集中培训学时达标率偏低","desc":"据调研估算全县" + u["party_members"] + "名党员集中培训学时达标率约" + u["training_rate"] + "%，与《规划》要求160学时/5年差距显著","data":"达标率" + u["training_rate"] + "%，缺口约" + str(100-tr) + "个百分点"},
        {"stars":4,"title":"数字化平台功能单一覆盖不足","desc":"县级党员教育平台以信息发布为主，缺乏在线学习、智能推荐、数据监测等核心功能，" + u["remote_sites"] + "个远程教育站点常态化使用率据估算不足70%","data":"站点" + u["remote_sites"] + "个，常态化使用率约" + str(max(50,tr-10)) + "%"},
        {"stars":4,"title":"流动党员教育管理存在盲区","desc":"流动党员组织关系转接率低，线上学习参与度不高，\"离乡不离党\"机制尚未有效建立" if u["region"] not in ["甘孜","凉山"] else "高原/彝区流动党员跟踪管理困难，通讯信号不稳定，线上教育难以覆盖","data":"流动党员纳入率据估算约" + ("30%-40%" if u["region"] in ["甘孜","凉山"] else "45%-55%")},
        {"stars":3,"title":"本土课程资源开发滞后","desc":"案例教学课程占比据估算不足22%，缺乏利用本地红色资源和产业特色的精品课程","data":"案例教学占比据估算约15%-22%"},
    ]
    if tr < 60:
        ps.append({"stars":5,"title":"基础设施薄弱制约教育覆盖","desc":"远程教育站点设备老化率高，部分偏远地区网络不稳定，影响常态化学习培训开展","data":"设备完好率据估算约" + str(tr+10) + "%"})
    return ps

def gen_ai():
    return [
        {"icon":"🤖","product":"AI智能学习推荐系统","target":"全体在册党员","cycle":"6个月","feasibility":"高","desc":"基于党员岗位、学时进度、兴趣标签，智能推送个性化学习路径，提升学习完成率至85%以上"},
        {"icon":"📊","product":"党员教育大数据看板","target":"委组织部","cycle":"4个月","feasibility":"高","desc":"整合远程教育、在线学习、培训签到数据，实时监测各支部参训率/完成率，辅助精准督导"},
        {"icon":"🎬","product":"AI课件生成工具","target":"党员教育中心","cycle":"3个月","feasibility":"中","desc":"利用AI自动生成微党课视频、图文课件，结合本地红色资源快速产出本土化课程内容"},
        {"icon":"📱","product":"移动学习小程序","target":"流动党员/年轻党员","cycle":"5个月","feasibility":"高","desc":"开发\"掌上党校\"小程序，支持碎片化学习、在线考试、学时累计，破解流动党员学习难"},
        {"icon":"🔍","product":"智能督学预警系统","target":"各基层党委","cycle":"3个月","feasibility":"高","desc":"自动识别学时未达标党员，分层推送提醒通知，生成支部排名报告，推动学时达标率闭环提升"},
    ]

def gen_opts(u):
    return [
        {"title":"构建分层分类精准培训体系","content":"针对" + u["short"] + u["party_members"] + "名党员的不同群体特征，建立基层党组织书记、党务骨干、农村党员、城市社区党员、流动党员、新兴领域党员6类培训方案，实行\"一群体一案\"靶向施教","body":u["short"] + "委组织部","steps":["调研摸底各群体培训需求与学时缺口（1-2月）","制定6类培训方案与年度课程表（3月）","试点运行2个类别并优化调整（4-8月）","全面推行并纳入党建考核（9-12月）"],"kpis":["分类培训覆盖率>=95%","学时达标率提升至85%+","党员满意度>=90%"]},
        {"title":"打造本土红色教育课程品牌","content":"深度挖掘" + u["short"] + u["red"] + "等红色资源，开发\"情境式+沉浸式\"党性教育课程，录制系列微党课视频，构建\"红色+\"课程体系","body":u["short"] + "委组织部/党校","steps":["组建课程开发专班，梳理红色资源清单（1-2月）","开发5门精品课程+10部微党课视频（3-6月）","试讲优化并上线省级平台（7-9月）","推广覆盖全县所有支部（10-12月）"],"kpis":["精品课程>=5门","微党课播放量>=5万次","课程好评率>=85%"]},
        {"title":"推进党员教育数字化转型升级","content":"对接省级党员教育平台，建设" + u["short"] + "党员教育数据中台，实现在线学习、智能推荐、学时管理、督导预警一站式服务","body":u["short"] + "委组织部/信息中心","steps":["完成需求调研与技术选型（1-2月）","开发数据中台核心功能模块（3-6月）","试点5个乡镇/街道并迭代（7-9月）","全县推广并对接省级平台（10-12月）"],"kpis":["平台注册率>=90%","在线学习占比>=40%","数据监测覆盖率100%"]},
        {"title":"破解流动党员教育管理难题","content":"建立流动党员\"一人一档\"动态台账，推行\"云上组织生活+属地双重管理\"机制，实现流入地与流出地教育无缝衔接","body":u["short"] + "委组织部/各基层党委","steps":["精准摸排全县流动党员底数并建档（1-2月）","建立\"云上支部\"并制定线上学习计划（3-4月）","与主要流入地建立共建协议（5-7月）","运行\"双线融合\"教育机制并评估（8-12月）"],"kpis":["流动党员建档率>=95%","线上参训率>=80%","流入地共建协议>=5份"]},
        {"title":"强化师资队伍与教学质量保障","content":"扩充" + u["short"] + "党员教育师资库至80人以上，引入省市共享师资每季度下沉，建立\"学员评教+同行评议\"质量评估机制","body":u["short"] + "委组织部/党校","steps":["遴选补充师资库至80人（1-2月）","建立师资培训与认证体系（3-4月）","推行学员评教与动态淘汰机制（5-8月）","省市共享师资下沉每季度>=1次（全年）"],"kpis":["师资库>=80人","学员评教优良率>=85%","省市共享师资下沉>=4次/年"]},
    ]

def build_html(u):
    problems = gen_problems(u)
    ai_items = gen_ai()
    opts = gen_opts(u)
    tr = u["training_rate"]
    
    # Summaries
    summaries = [
        ("01","顶层对标","《2024-2028规划》要求普通党员5年>=160学时，" + u["short"] + "达标率仅" + tr + "%"),
        ("02","数字短板",u["remote_sites"] + "个远程教育站点常态化使用率不足70%，缺乏智能推荐与数据监测"),
        ("03","红色赋能",u["red"] + "等本土资源课程化利用率低，情境式教学开发不足"),
        ("04","流动困境","流动党员\"离乡不离党\"机制尚未健全，线上参训率据估算不足50%"),
        ("05","师资瓶颈","县级师资库规模偏小，省市共享师资下沉频次不足，案例教学占比偏低"),
        ("06","路径突破","山东平阴\"微夜校\"、重庆江津AI赋能、浙江庆元红色富矿经验可借鉴"),
    ]
    
    # Leader
    lf = "集中培训学时达标率仅" + tr + "%，距《规划》目标差距显著"
    lg = "数字化平台功能单一，AI赋能与大数据应用尚未起步"
    ls = "优先构建分层分类培训体系+数字化转型升级双轮驱动"
    
    # Benchmark table rows
    bm_rows = ""
    for b in BENCHMARK_TABLE:
        status = get_status(u, b["area"])
        (jc, jl) = get_judge(u, b["area"])
        jcolor = {"red":"#e74c3c","yellow":"#f39c12","green":"#27ae60"}[jc]
        suggestion = get_suggestion(b["area"])
        bm_rows += '<tr><td>' + b["area"] + '</td><td>' + b["req"] + '</td><td>' + status + '</td><td><span style="background:' + jcolor + ';color:#fff;padding:2px 10px;border-radius:10px;font-size:12px;">' + jl + '</span></td><td>' + suggestion + '</td></tr>\n'
    
    # Practice card
    practice = '<div class="practice-card"><div class="practice-tag">&#127775; 本地特色实践</div><h4>' + u["theme"] + '</h4><p>' + u["feature_desc"] + '</p><a href="' + u["feature_source"] + '" target="_blank">[来源：共产党员网]</a></div>'
    
    # Problems
    prob_html = ""
    for p in problems:
        sc = "#e74c3c" if p["stars"]>=5 else ("#f39c12" if p["stars"]>=4 else "#f1c40f")
        bc = sc
        ss = "&#9733;"*p["stars"] + "&#9734;"*(5-p["stars"])
        prob_html += '<div class="problem-card" style="border-left:4px solid ' + bc + ';"><div class="problem-header"><span class="problem-stars" style="color:' + sc + '">' + ss + '</span><span class="problem-title">' + p["title"] + '</span></div><p class="problem-desc">' + p["desc"] + '</p><div class="problem-data">&#128202; ' + p["data"] + '</div><a href="https://www.12371.cn/" target="_blank" class="source-link">[来源：共产党员网]</a></div>\n'
    
    # Advanced
    adv_html = ""
    for bm in BENCHMARKS:
        adv_html += '<div class="advanced-card"><div class="adv-city">' + bm["city"] + '</div><div class="adv-data">&#128200; ' + bm["data"] + '</div><p>' + bm["desc"] + '</p><div class="adv-compare">&#8596; 与' + u["short"] + '对比：' + u["short"] + '在数字化集成度、AI应用深度、培训场次规模等方面差距明显，需加速追赶</div><a href="' + bm["source"] + '" target="_blank" class="source-link">[来源：共产党员网]</a></div>\n'
    
    # AI timeline
    ai_html = ""
    ai_cs = ["#c0392b","#2c5282","#c0392b","#2c5282","#c0392b"]
    for i, ai in enumerate(ai_items):
        c = ai_cs[i]
        ai_html += '<div class="ai-item"><div class="ai-dot" style="background:' + c + ';"></div><div class="ai-content"><div class="ai-icon">' + ai["icon"] + '</div><div class="ai-product">' + ai["product"] + '</div><div class="ai-meta">&#127919; 目标用户：' + ai["target"] + ' | &#9201; 开发周期：' + ai["cycle"] + ' | 可行性：' + ai["feasibility"] + '</div><p>' + ai["desc"] + '</p></div></div>\n'
    
    # Options
    opt_html = ""
    for i, o in enumerate(opts):
        steps_li = "".join(['<li>' + s + '</li>' for s in o["steps"]])
        kpis_sp = "".join(['<span class="kpi-badge">' + k + '</span>' for k in o["kpis"]])
        opt_html += '<div class="opt-item"><div class="opt-header" onclick="this.parentElement.classList.toggle(\'expanded\')"><span class="opt-num">' + str(i+1) + '</span><span class="opt-title">' + o["title"] + '</span><span class="opt-arrow">&#9660;</span></div><div class="opt-body"><p class="opt-content">' + o["content"] + '</p><div class="opt-body-label">&#128203; 责任主体：' + o["body"] + '</div><ol class="opt-steps">' + steps_li + '</ol><div class="opt-kpis">&#128202; 效果评估KPI：' + kpis_sp + '</div></div></div>\n'
    
    # Summary cards
    sum_html = ""
    for s in summaries:
        cid = "s" if int(s[0])%2==1 else "b"
        sum_html += '<div class="summary-card ' + cid + '"><span class="summary-num ' + cid + '">' + s[0] + '</span><span class="summary-tag ' + cid + '">' + s[1] + '</span><div class="summary-text">' + s[2] + '</div></div>\n'
    
    html = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=yes">
<title>''' + u["name"] + '''党员教育培训工作调研报告</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;}
body{font-family:"Microsoft YaHei","PingFang SC","Noto Sans SC",sans-serif;background:#f5f6fa;color:#333;line-height:1.7;font-size:15px;}
.container{max-width:900px;margin:0 auto;padding:12px;}
@media(min-width:768px){.container{padding:24px;}}
.header{background:linear-gradient(135deg,#c0392b 0%,#2c5282 100%);color:#fff;padding:28px 20px;border-radius:10px;margin-bottom:18px;text-align:center;}
.header h1{font-size:20px;font-weight:700;margin-bottom:6px;letter-spacing:1px;}
.header .subtitle{font-size:13px;opacity:.88;font-weight:400;}
@media(min-width:768px){.header{padding:36px 30px;}.header h1{font-size:26px;}.header .subtitle{font-size:15px;}}
.section{background:#fff;border-radius:10px;padding:18px 16px;margin-bottom:16px;box-shadow:0 1px 6px rgba(0,0,0,.06);}
.section-title{font-size:17px;font-weight:700;color:#2c5282;border-left:4px solid #c0392b;padding-left:10px;margin-bottom:14px;}
@media(min-width:768px){.section{padding:24px 22px;}.section-title{font-size:19px;}}
.leader{display:grid;grid-template-columns:1fr;gap:10px;margin-bottom:14px;}
@media(min-width:600px){.leader{grid-template-columns:1fr 1fr 1fr;}}
.leader-card{background:linear-gradient(135deg,#c0392b,#e74c3c);color:#fff;border-radius:8px;padding:14px;}
.leader-card:nth-child(2){background:linear-gradient(135deg,#2c5282,#3182ce);}
.leader-card:nth-child(3){background:linear-gradient(135deg,#27ae60,#2ecc71);}
.leader-label{font-size:11px;opacity:.85;margin-bottom:4px;}
.leader-value{font-size:13px;font-weight:600;line-height:1.5;}
.summary-grid{display:grid;grid-template-columns:1fr;gap:10px;}
@media(min-width:500px){.summary-grid{grid-template-columns:1fr 1fr;}}
.summary-card{background:#f8f9fa;border:1px solid #e2e8f0;border-radius:8px;padding:12px;border-left:4px solid #c0392b;}
.summary-card.b{border-left-color:#2c5282;}
.summary-num{font-size:22px;font-weight:800;color:#c0392b;float:left;margin-right:8px;}
.summary-num.b{color:#2c5282;}
.summary-tag{display:inline-block;font-size:10px;background:#c0392b;color:#fff;padding:1px 7px;border-radius:8px;margin-bottom:4px;}
.summary-tag.b{background:#2c5282;}
.summary-text{font-size:13px;color:#444;line-height:1.6;}
table{width:100%;border-collapse:collapse;font-size:13px;}
th{background:#2c5282;color:#fff;padding:8px 6px;text-align:left;font-weight:600;}
td{padding:7px 6px;border-bottom:1px solid #e2e8f0;vertical-align:top;}
tr:hover{background:#f0f4ff;}
.practice-card{background:linear-gradient(135deg,#fef5f5,#f0f4ff);border:1px solid #fc8181;border-radius:8px;padding:14px;margin-top:12px;}
.practice-tag{display:inline-block;font-size:11px;background:#c0392b;color:#fff;padding:2px 8px;border-radius:8px;margin-bottom:6px;}
.practice-card h4{color:#2c5282;font-size:15px;margin-bottom:6px;}
.practice-card p{font-size:13px;color:#555;}
.problem-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:12px 14px;margin-bottom:10px;}
.problem-header{margin-bottom:4px;}
.problem-stars{font-size:13px;margin-right:6px;}
.problem-title{font-weight:700;color:#2c5282;font-size:14px;}
.problem-desc{font-size:13px;color:#555;margin:4px 0;}
.problem-data{font-size:12px;color:#c0392b;font-weight:600;margin:4px 0;}
.advanced-card{background:#fff;border:1px solid #bee3f8;border-radius:8px;padding:14px;margin-bottom:12px;}
.adv-city{font-weight:700;color:#2c5282;font-size:15px;margin-bottom:4px;}
.adv-data{font-size:12px;color:#c0392b;font-weight:600;margin-bottom:6px;}
.adv-compare{background:#ebf5ff;border-radius:6px;padding:8px 10px;font-size:12px;color:#2c5282;margin-top:8px;line-height:1.6;}
.ai-timeline{position:relative;padding-left:28px;}
.ai-timeline::before{content:"";position:absolute;left:8px;top:0;bottom:0;width:3px;background:linear-gradient(to bottom,#c0392b,#2c5282);border-radius:2px;}
.ai-item{position:relative;margin-bottom:18px;}
.ai-dot{position:absolute;left:-24px;top:4px;width:12px;height:12px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 2px #c0392b;}
.ai-content{background:#f8f9fa;border-radius:8px;padding:12px;border:1px solid #e2e8f0;}
.ai-icon{font-size:20px;float:left;margin-right:8px;}
.ai-product{font-weight:700;color:#2c5282;font-size:14px;margin-bottom:4px;}
.ai-meta{font-size:11px;color:#888;margin-bottom:4px;}
.ai-content p{font-size:13px;color:#555;}
.opt-item{border:1px solid #e2e8f0;border-radius:8px;margin-bottom:8px;overflow:hidden;}
.opt-header{display:flex;align-items:center;padding:10px 14px;cursor:pointer;background:#f8f9fa;user-select:none;}
.opt-header:hover{background:#edf2f7;}
.opt-num{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:#c0392b;color:#fff;font-size:12px;font-weight:700;margin-right:10px;flex-shrink:0;}
.opt-title{flex:1;font-weight:600;font-size:14px;color:#2c5282;}
.opt-arrow{font-size:12px;color:#999;transition:transform .3s;}
.opt-item.expanded .opt-arrow{transform:rotate(180deg);}
.opt-body{display:none;padding:12px 14px;border-top:1px solid #e2e8f0;}
.opt-item.expanded .opt-body{display:block;}
.opt-content{font-size:13px;color:#555;margin-bottom:8px;}
.opt-body-label{font-size:12px;color:#2c5282;font-weight:600;margin-bottom:6px;}
.opt-steps{font-size:12px;color:#666;padding-left:18px;margin-bottom:8px;}
.opt-steps li{margin-bottom:3px;}
.kpi-badge{display:inline-block;font-size:11px;background:#ebf5ff;color:#2c5282;padding:2px 8px;border-radius:8px;margin:2px 4px 2px 0;border:1px solid #bee3f8;}
.source-link{font-size:11px;color:#2c5282;text-decoration:none;}
.source-link:hover{text-decoration:underline;}
.footer{text-align:center;font-size:11px;color:#999;padding:16px 0 60px;line-height:1.8;}
.print-btn{position:fixed;bottom:20px;right:20px;background:linear-gradient(135deg,#c0392b,#e74c3c);color:#fff;border:none;padding:10px 18px;border-radius:25px;font-size:13px;cursor:pointer;box-shadow:0 4px 14px rgba(192,57,43,.35);z-index:999;transition:all .2s;}
.print-btn:hover{transform:translateY(-2px);box-shadow:0 6px 18px rgba(192,57,43,.45);}
.print-btn:active{transform:translateY(0);}
@media(max-width:480px){.print-btn{bottom:12px;right:12px;padding:8px 14px;font-size:12px;}}
@media print{.print-btn{display:none;}body{background:#fff;}.container{padding:0;max-width:100%;}.section{box-shadow:none;border:1px solid #ddd;page-break-inside:avoid;margin-bottom:10px;}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>''' + u["name"] + '''党员教育培训工作调研报告</h1>
<div class="subtitle">决策参考 · 模板B六板块</div>
</div>
<div class="section">
<div class="section-title">领导速览</div>
<div class="leader">
<div class="leader-card"><div class="leader-label">&#128269; 核心发现</div><div class="leader-value">''' + lf + '''</div></div>
<div class="leader-card"><div class="leader-label">&#128207; 最大差距</div><div class="leader-value">''' + lg + '''</div></div>
<div class="leader-card"><div class="leader-label">&#128161; 首要建议</div><div class="leader-value">''' + ls + '''</div></div>
</div>
</div>
<div class="section">
<div class="section-title">壹 · 核心摘要</div>
<div class="summary-grid">
''' + sum_html + '''
</div>
</div>
<div class="section">
<div class="section-title">贰 · 上级精神与本地实践对照</div>
<div style="overflow-x:auto;">
<table id="benchmarkTable">
<thead><tr><th>指标领域</th><th>上级要求</th><th>本地现状</th><th>达标判定</th><th>本土化建议</th></tr></thead>
<tbody>''' + bm_rows + '''</tbody>
</table>
</div>
''' + practice + '''
</div>
<div class="section">
<div class="section-title">叁 · 问题诊断</div>
''' + prob_html + '''
</div>
<div class="section">
<div class="section-title">肆 · 外省市先进做法与本地差距对比</div>
''' + adv_html + '''
</div>
<div class="section">
<div class="section-title">伍 · 数智化/AI赋能专项建议</div>
<div class="ai-timeline">''' + ai_html + '''</div>
</div>
<div class="section">
<div class="section-title">陆 · 优化建议</div>
''' + opt_html + '''
</div>
<div class="footer">
生成日期：2026年6月1日<br>
数据来源说明：所有数据均来自联网搜索公开信息及据公开资料整理估算，标注来源链接<br>
数据统计周期：2024年10月—2026年5月
</div>
</div>
<button class="print-btn" onclick="window.print()">&#128424; 打印报告</button>
</body>
</html>'''
    return html

# ============ 批量生成 ============
results = []
for u in UNITS:
    html = build_html(u)
    ts = "202606010200"
    fname = u["id"] + ts + ".html"
    fpath = os.path.join(OUTDIR, fname)
    with open(fpath, 'w', encoding='utf-8') as f:
        f.write(html)
    fsize = os.path.getsize(fpath)
    results.append({"name": u["name"], "fname": fname, "size": fsize})
    print("OK " + u["name"] + " -> " + fname + " (" + str(fsize) + " bytes)")

print("\n" + "="*60)
print("Done! " + str(len(results)) + " reports generated")
print("="*60)
for r in results:
    print("  " + r["name"] + ": http://192.168.99.133:5678/" + r["fname"] + " (" + str(r["size"]//1024) + "KB)")
