将JSON数据渲染称表格

常用方法   2024-07-20 11:23   93   0  
/**
 * 将JSON数据渲染称表格
 * fanlinjun
 * */
export default (function(){
    let tableInfo = {
        colCount: 1,
        rowCount: {}
    };
    let tableConf = {
        //表格嵌套字段
        nestedField: 'subs'
    };
    /**
     * 初始化表格结构信息
     * @param {*} rows
     * @param {*} level
     */
    function initStructureInfo(rows, level){
        let nesting = tableConf.nestedField;
        let _rows = rows.filter(r => r[nesting] && r[nesting].length > 0);
        if(_rows.length == 0){ return 0; }
        level++;
        tableInfo.colCount = Math.max(level, tableInfo.colCount);
        let _key, _count, _allSubs = 0, _subs = 0;
        _rows.forEach(s => {
            _count = s[nesting].length;
            _subs = initStructureInfo(s[nesting], level);
            _count += _subs;
            _allSubs += (_subs + s[nesting].length);
            _key = `${s[nesting][0].fieldName}_${level}`;
            tableInfo.rowCount[_key] = _count;
        });
        return _allSubs;
    }
    function renderHead(obj){
        if(({}).toString.call(obj) != '[object Object]') return null;
        let head = '', _col, _label, _colspan, _width;
        for(let key in obj){
            if(typeof(obj[key]) != 'object') continue;
            _col = '<col>'.repeat(tableInfo.colCount -1);
            break;
        }
        for(let key in obj){
            _label = typeof(obj[key]) == 'string' ? obj[key] : obj[key].name;
            _width = typeof(obj[key]) == 'object' ? (obj[key].width || '') : '';
            if(!!_width){
                _width = `width:${_width};`;
            }
            if(_col){
                _col += `<col style="${_width}">`;
            }
            _colspan = key == 'fieldName' ? ` colspan="${obj[key].colspan || tableInfo.colCount}"` : '';
            head += `<th${_colspan}>${_label}</th>`;
        }
        return !!_col ? `<colgroup>${_col}</colgroup><tr>${head}</tr>` : `<tr>${head}</tr>`;
    }
    function createRowHtml (row, level, idx){
        if(({}).toString.call(row) != '[object Object]') return null;
        let _html = '', _blank = '', _key = `${row.fieldName}_${level}`;
        let colspan = tableInfo.colCount - level + 1;
        colspan = colspan > 1 ? ` colspan="${colspan}"` : '';
        let rowspan = tableInfo.rowCount[_key] || 0;
        for (let key in row) {
            if(key == tableConf.nestedField) continue;
            _html += (key == 'fieldName') ? `<td ${colspan}><p>${row[key]}</p></td>` : `<td><p>${row[key]}</p></td>`;
        }
        _blank = idx == 0 && level > 1 ? (rowspan > 1 ? `<td rowspan="${rowspan}"></td>` : rowspan > 0 ? '<td rowspan></td>' : '') : '';
        let val = `<tr>${_blank}${_html}</tr>`;
        return val;
    }
    function renderRow (rows, level){
        let html = '', result = '';
        rows.forEach((row, idx) => {
            _level = level;
            if(!row.subs || row.subs.length == 0){
                result = createRowHtml(row, _level, idx);
            }else{
                result = createRowHtml(row, level, 0);
                _level = level + 1;
                result += renderRow(row.subs, _level);
            }
            html += result;
        });
        return html;
    }
    return function render (data, config) {
        if(({}).toString.call(data) != '[object Object]'){
            throw Error('parameter "data" must be an Object!');
        }
        tableConf = Object.assign(tableConf, config);
        tableInfo = { colCount: 1, rowCount: {} };
        initStructureInfo(data.table, 1);
        let thead = renderHead(data.tableHead);
        let tbody = renderRow(data.table, 1);
        return `<table cellspacing="0">${thead}${tbody}</table>`;
    }
})();