自制算法报表

好几年前写的代码, 其中javascript代码找专业人员写的。

#######页面
_HTML = '''
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>效果分析%(bizdate)s</title>
<link href='https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet' type='text/css' />
<script type="text/javascript" src="https://gw.alipayobjects.com/os/lib/jquery/3.5.0/dist/jquery.min.js"></script>
</head>
<style>
html {overflow-x: initial !important;}:root { --bg-color: #ffffff; --text-color: #333333; --select-text-bg-color: #B5D6FC; --select-text-font-color: auto; --monospace: "Lucida Console",Consolas,"Courier",monospace; }
html { font-size: 12px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
.one{width:1400px; margin:0 auto;}
.mytable{margin:0 auto;}
table {border-collapse: collapse;}
table tr:nth-child(2n),thead { background-color: #f8f8f8;}
table tr th {
    font-weight: bold;
    border: 1px solid #dfe2e5;
    padding: 3px 6px;font-size: small;
    text-align: right;
}
table tr td {
    border: 1px solid #dfe2e5;
    padding: 3px 6px; font-size: x-small;
    text-align: right;
    white-space: nowrap; max-width: 100px; overflow:hidden; /* 文本太长处理 */
}
table tr td:hover {white-space: pre-wrap;} /* 鼠标移上,显示全文 */
.caption {width:850px; margin:0 auto; font-size: 16px;text-align: left;}
.caption a {font-size: 12px;}

.dataframe-div {max-height: 900px;
overflow: auto; position: relative;}
.dataframe thead th {
    position: -webkit-sticky; /* for Safari */
    position: sticky; top: 0;
    background: lightblue; color: black;}
.dataframe thead th:first-child {left: 0; z-index: 1; }
.dataframe tbody tr th:only-of-type {vertical-align: middle;}
.dataframe tbody tr th {position: -webkit-sticky; /* for Safari */
    position: sticky;left: 0;vertical-align: top;}
</style>
<body><div class="one">
<h2 style="text-align: center;"> 算法效果报告 bizdate=%(bizdate)s </h2>
<h4 style="width:1200px; margin:0 auto;">
%(tabs)s
</h4>
<div class="dataframe-div">%(contents)s</div>
<h2 style="text-align: center; color:#F00">注意数据安全, 请勿转发!!</h2>
<h4 style="text-align: center; ">有问题联系@xxx</h4>
</div>

<script type="text/javascript">
function search(table_id) {
  return function(){
    var value = $(this).val();
    var patt = new RegExp(value, "i");
    $(table_id).find('tbody').find('tr').each(function() {
      if (!($(this).find('td').text().search(patt) >= 0)) {
        $(this).hide();
      }else{
        $(this).show();
      }
    });
  }
}
// 调用搜索script函数
// $('#s0').on('keyup', search('#t_id_0'));
%(calls)s
</script>

<script type="text/javascript">
  const $body = $('body');
  const tableData = [];
  const tableSortInfo = []; // 记录每个表格排序参数
  const numberReg = /^(-?\d+)(\.\d+)?$/; // 判断是否是数值类型的正则表达式

  function convertToTbody(data) {
    return data.map((row) => {
      const tdStrs = row.map(entry => `<td>${entry}</td>`);

      return `<tr>${tdStrs.join('')}</tr>`;
    }).join('');
  }

  function getSorter(index, type) {
    if (type === 'asc') {
      // 升序排序
      return function(rowA, rowB) {
        if (rowA[index] === rowB[index]) {
          return 0;
        }
    
        if (typeof rowA[index] === 'number') {
          return rowA[index] - rowB[index];
        }
    
        return rowA[index] > rowB[index] ? 1 : -1;
      }
    }
  
    // 降序排序
    return function(rowA, rowB) {
      if (rowA[index] === rowB[index]) {
        return 0;
      }
  
      if (typeof rowA[index] === 'number') {
        return rowB[index] - rowA[index];
      }
  
      return rowA[index] < rowB[index] ? 1 : -1;
    }
  }

  // 通过dict, 将 table id, 进行编号  
  const hash = {};
  function size_dict(d){c=0; for (i in d) ++c; return c}
  function dict_get(key) { 
    if(!(key in hash)){
      hash[key] = size_dict(hash);
    }
    return hash[key];  
  }

  function click(evt) {
    const $target = $(evt.target);
    const $table = $target.parents('.dataframe');
    const index = $target.index();
    // const tableIndex = $table.index();
    const tableIndex = dict_get($table[0].id);

    // step1: 拿到原始数据
    if (!tableData[tableIndex]) {
      // 数据未解析过
      const data = [];
      const $bodyTrs = $table.find('tbody tr');

      $bodyTrs.each(function(index) {
        const $tr = $(this);
        const $tds = $tr.find('td');
        const row = [];

        $tds.each(function() {
          const text = $(this).text();
          const isNumber = !!numberReg.exec(text);

          row.push(isNumber ? parseFloat(text) : text);
        });
        data.push(row);
      });

      tableData[tableIndex] = data; // 解析数据,存入到本地
    }
    const data = tableData[tableIndex];
    const prevSortInfo = tableSortInfo[tableIndex];
    
    // step2: 对数据进行排序
    const newSortType = prevSortInfo && prevSortInfo.sortBy === index && prevSortInfo.sortType === 'desc' ? 'asc' : 'desc';
    data.sort(getSorter(index, newSortType));
    tableSortInfo[tableIndex] = { sortBy: index, sortType: newSortType }; // 记录当前排序信息

    // step3: 生成表格的新的排序内容
    const bodyStrs = convertToTbody(data);
    const $body = $table.find('tbody');    
    // step4: 更新表格
    $body.html(bodyStrs)
  }

  // 调用函数
  $body.delegate('.dataframe tr th', 'click', click);
</script>
</body>
</html>
''' 

def  get_html(bizdate, datasets):
    contents, call_scripts, tabs = '', '', ''
    for i, data in enumerate(datasets):
        contents +='''  
        <div id="t{i}" class="caption">{title}<br>
        {comment} <br>
        <input type="text" placeholder="正则表达搜索" id="s{i}">
        </div>
        '''.format(i=i, **data)
        contents += data['table'].to_html(index=False, classes='mytable',table_id='t_id_{i}'.format(i=i)) 
        contents += '<br>'

        call_scripts += "$('#s{i}').on('keyup', search('#t_id_{i}'));\n".format(i=i) 
        tabs += '{i}. <a href="#t{i}">{key}</a>;'.format(i=i, key=data['key']) 

    _map = {'bizdate': bizdate, 'tabs': tabs, 'calls': call_scripts, 'contents': contents}
    return _HTML % _map

# 将多个表格数据写入html 中,表格为pandas dataframe格式
datasets = [
    {'table': X01,
    'key': '分group汇总',
    'title': '附表二: 分group汇总报表',
    'comment': "<a>分group,不拆分实验.</a>"
    },
    {'table': X1,
    'key': '分媒体',
    'title': '表一: 分媒体报表',
    'comment': "<a>分媒体, 不分实验.</a>"
    },
    {'table': X3,
    'key': '分实验',
    'title': '表三: 分实验报表',
    'comment': "<a>不分媒体, 只按照实验id分.</a>"
    },
    ]

c = get_html(bizdate, datasets)

ff = '{}_{}.html'.format(node_name, str(bizdate)[-4:])  # 存最近一个年的.
with open(ff, 'w') as fp:
    fp.write(c)

posted @ 2022-11-23 11:31  bregman  阅读(20)  评论(0编辑  收藏  举报