html table 分组合并 与导出分组后的数据

HTML:

html 复制代码
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    <script src="~/Scripts/jquery-1.6.4.min.js"></script>
    <script src="~/Scripts/jquery.table2excel.js?a=@DateTime.Now.ToString("yyyyMMddHHmmssff")"></script>
</head>
<body hidden>
    <table id="table" border="1" width="100%">
        <thead>
            <tr>
                <th colspan="14">客户基础信息</th>
                <th colspan="10">跟踪维护信息</th>
            </tr>
            <tr>
                <th>客户名称</th>
                <th>联系人</th>
                <th>联系电话</th>
                <th>客户喜好</th>
                <th>纪念日/生日</th>

                <th>项目标题</th>
                <th>项目信息</th>
                <th>项目状态</th>
                <th>项目等级</th>

                <th>核心诉求</th>
                <th>诉求应答</th>
                <th>预成交金额(万元)</th>
                <th>需要的支持</th>
                <th>备注</th>

                <th>首次维护时间</th>
                <th>最近维护时间</th>
                <th>未跟进时间(天)</th>
                <th>维护日期</th>
                <th>维护方式</th>
                <th>维护类型</th>
                <th>内容/跟进重点</th>
                <th>下次跟进时间</th>
                <th>销售人员</th>
                <th>本记录时间</th>
            </tr>
        </thead>
        <tbody id="tbody">
            @if (ViewBag.TrackExport != null)
            {
                for (int i = 0; i < ViewBag.TrackExport.Count; i++)
                {
                    <tr>
                        <td>@ViewBag.TrackExport[i].CUSTOMER_NAME </td>
                        <td>@ViewBag.TrackExport[i].CONTACT_LINK </td>
                        <td>@ViewBag.TrackExport[i].CONTACT_PHONE </td>
                        <td>@ViewBag.TrackExport[i].HOBBIES </td>
                        <td>@ViewBag.TrackExport[i].BIRTHDAY </td>
                        @* 利用<b>标签包含不同内容进行二次分组,分组后移除<b>标签 *@
                        <td>@ViewBag.TrackExport[i].PROJECT_TITLE <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].PROJECT_INFO <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].PROJECT_STATUS_NAME <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].PROJECT_LEVEL_NAME <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].NEEDS <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].RESPONSE <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].EST_AMOUNT <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].NEED_SUPPORT <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>
                        <td>@ViewBag.TrackExport[i].REMARKS <b>@ViewBag.TrackExport[i].SALES_OPPORTUNITY_PROJECT_SID</b></td>

                        <td>@ViewBag.TrackExport[i].FIRST_MANAGE_DATE </td>
                        <td>@ViewBag.TrackExport[i].LAST_MANAGE_DATE </td>
                        <td>@ViewBag.TrackExport[i].SINCE_DAYS </td>

                        <td>@ViewBag.TrackExport[i].MANAGE_DATE.ToString("yyyy-MM-dd") </td>
                        <td>@ViewBag.TrackExport[i].MANAGE_TYPE_NAME </td>
                        <td>@ViewBag.TrackExport[i].MANAGE_CONTENT_NAME </td>
                        <td>@ViewBag.TrackExport[i].FOLLOW_FOCUS </td>
                        <td>@ViewBag.TrackExport[i].NEXT_DATETIME </td>
                        <td>@ViewBag.TrackExport[i].SALES_MAN </td>
                        <td>@ViewBag.TrackExport[i].CREATED_TIME.ToString("yyyy-MM-dd HH:mm:ss") </td>
                    </tr>
                }
            }
        </tbody>
    </table>

    <script>
        //合并相同行
        function mergeFunc(tableId, maxCol, groupColumn) {
            var tab = document.getElementById(tableId);
            if (!tab) return;
            groupColumn = groupColumn === undefined ? 0 : groupColumn;

            for (var col = maxCol - 1; col >= 0; col--) {
                var count = 1;
                for (var i = 0; i < tab.rows.length; i++) {
                    if (i > 0) {
                        var groupSame = tab.rows[i].cells[groupColumn].innerHTML == tab.rows[i - 1].cells[groupColumn].innerHTML;
                        var colSame = tab.rows[i].cells[col].innerHTML == tab.rows[i - 1].cells[col].innerHTML;
                        if (groupSame && colSame) {
                            count++;
                        } else {
                            if (count > 1) {
                                var start = i - count;
                                tab.rows[start].cells[col].rowSpan = count;
                                for (var j = start + 1; j < i; j++) {
                                    tab.rows[j].removeChild(tab.rows[j].cells[col]);
                                }
                                count = 1;
                            }
                        }
                    }
                }
                if (count > 1) {
                    start = i - count;
                    tab.rows[start].cells[col].rowSpan = count;
                    for (var j = start + 1; j < i; j++) {
                        tab.rows[j].removeChild(tab.rows[j].cells[col]);
                    }
                }
            }
            $('#' + tableId +' td b').remove();//移除<td>内的<b>标签
        }

        //初始化加载
        $(function () {
            //合并相同行
            mergeFunc("tbody", 17, 0);

            //导出excel弹窗
            setTimeout(() => {
                Export();
            }, 1000);
        });

        //导出Excel
        function Export() {
            $('#table').table2excel({
                filename: 'CRM_' + new Date().getTime(), //文件名称
            });

            // 导出后延迟 3000ms 再关闭页面
            setTimeout(() => {
                window.close();
            }, 3000);
        }
    </script>

</body>
</html>

jquery.table2excel.js

javascript 复制代码
/*  调用方法:
 *   $('#test_table').table2excel({//'#test_table' table的id
 *       subtotal: 1,//可选参数(可删除此行),默认值:0
 *       width:200,//导出excel表格的宽度百分比的值(不含%号),可删除此行(默认100%)
 *       filename: 'excel_' + new Date().getTime() + '.xls', //excel文件名称,扩展名:.xlsx 或者.xls
 *   });
 */
(function ($, window, document, undefined) {
    var pluginName = "table2excel",
        defaults = {
            exclude: ".noExl",
            name: "Table2Excel",
            filename: "table2excel",
            fileext: ".xls",
            exclude_img: true,
            exclude_links: true,
            exclude_inputs: true,
            preserveColors: false,
            subtotal: 0,//"合计"行所在的行号(不包括标题行),0表示没有合计行...
            width: 100,//表格宽度百分比,默认100%
        };
    //插件配置
    function Plugin(element, options) {
        this.element = element;
        this.settings = $.extend({}, defaults, options);
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }
    Plugin.prototype = {
        init: function () {
            var e = this;
            var w = getWidth(e.settings);//导出EXCEL表格的宽度,默认100%
            var utf8Heading = "<meta http-equiv=\"content-type\" content=\"application/vnd.ms-excel; charset=UTF-8\">";
            e.template = {
                head: "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns=\"http://www.w3.org/TR/REC-html40\">" + utf8Heading + "<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets>",
                sheet: {
                    head: "<x:ExcelWorksheet><x:Name>",
                    tail: "</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>"
                },
                mid: "</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body>",
                table: {
                    head: " <table border='1' style='width:" + w + "%;'>",//<table>的边框&宽度
                    tail: " </table>"
                },
                foot: "</body></html>"
            };
            e.tableRows = [];

            //读取原始表
            var rowNumber = 0;//行号
            $(e.element).each(function (i, o) {
                var tempRows = "";//table的html
                $(o).find("tr").not(e.settings.exclude).each(function (i, p) {
                    //<tr>的样式
                    var trStyles = "";//整行样式
                    //开始创建一行表格
                    if (trStyles) {
                        tempRows += "<tr align='center' style='" + trStyles + "'>";//内容居中:align='center'
                    }
                    else {
                        tempRows += "<tr align='center'>";//内容居中:align='center'
                    }
                    //读取原始<table>的<th>表头行(表头必须是<th>!表头如果是<td>的话则会当做普通数据行处理...)
                    $(p).find("th").not(e.settings.exclude).each(function (i, q) {
                        //<th>的样式:
                        var thStyles = "";//background-color: cornflowerblue; color:white;
                        var rc = {
                            rows: $(this).attr("rowspan"),
                            cols: $(this).attr("colspan"),
                            flag: $(q).find(e.settings.exclude)
                        };
                        if (rc.flag.length > 0) {
                            tempRows += "<td> </td>"; //空格!
                        } else {
                            tempRows += "<td";
                            if (rc.rows > 0) {
                                tempRows += " rowspan='" + rc.rows + "' ";//跨行
                            }
                            if (rc.cols > 0) {
                                tempRows += " colspan='" + rc.cols + "' ";//跨列
                            }
                            if (thStyles) {
                                tempRows += " style='" + thStyles + "'";//样式
                            }
                            tempRows += ">" + $(q).html() + "</td>";//内容
                        }
                    });

                    //读取原始<table>的<td>数据行
                    $(p).find("td").not(e.settings.exclude).each(function (i, q) {
                        //<td>的样式
                        var tdStyles = "background-color:yellow;";//合计行的样式
                        var rc = {
                            rows: $(this).attr("rowspan"),
                            cols: $(this).attr("colspan"),
                            flag: $(q).find(e.settings.exclude)
                        };
                        if (rc.flag.length > 0) {
                            tempRows += "<td> </td>"; //空格!                       
                        } else {
                            tempRows += "<td ";
                            if (rc.rows > 0) {
                                tempRows += " rowspan='" + rc.rows + "' ";//跨行
                            }
                            if (rc.cols > 0) {
                                tempRows += " colspan='" + rc.cols + "' ";//跨列
                            }
                            var subtotal = getSubtotal(e.settings);//获取"合计"行所在的行号(不包括标题行)
                            if (rowNumber == subtotal) {//if(当前行行号 == 合计行行号)
                                if (tdStyles) {
                                    tempRows += " style='mso-number-format:\"\@\"; " + tdStyles + "' ";//样式
                                }
                                else {
                                    tempRows += " style='mso-number-format:\"\@\";' ";//纯文本
                                }
                            }
                            else {
                                tempRows += " style='mso-number-format:\"\@\";' ";//纯文本
                            }
                            tempRows += ">" + $(q).html() + "</td>";
                        }
                    });
                    tempRows += "</tr>";//生成一行结束
                    rowNumber++;//行号+1
                });
                // exclude img tags
                if (e.settings.exclude_img) {
                    tempRows = exclude_img(tempRows);
                }
                // exclude link tags
                if (e.settings.exclude_links) {
                    tempRows = exclude_links(tempRows);
                }
                // exclude input tags
                if (e.settings.exclude_inputs) {
                    tempRows = exclude_inputs(tempRows);
                }
                e.tableRows.push(tempRows);
            });
            e.tableToExcel(e.tableRows, e.settings.name, e.settings.sheetName);
        },
        tableToExcel: function (table, name, sheetName) {
            var e = this, fullTemplate = "", i, link, a;
            e.format = function (s, c) {
                return s.replace(/{(\w+)}/g, function (m, p) {
                    return c[p];
                });
            };
            sheetName = typeof sheetName === "undefined" ? "Sheet" : sheetName;
            e.ctx = {
                worksheet: name || "Worksheet",
                table: table,
                sheetName: sheetName
            };
            fullTemplate = e.template.head;
            if ($.isArray(table)) {
                Object.keys(table).forEach(function (i) {
                    //fullTemplate += e.template.sheet.head + "{worksheet" + i + "}" + e.template.sheet.tail;
                    fullTemplate += e.template.sheet.head + sheetName + i + e.template.sheet.tail;
                });
            }
            fullTemplate += e.template.mid;
            if ($.isArray(table)) {
                Object.keys(table).forEach(function (i) {
                    fullTemplate += e.template.table.head + "{table" + i + "}" + e.template.table.tail;
                });
            }
            fullTemplate += e.template.foot;
            for (i in table) {
                e.ctx["table" + i] = table[i];
            }
            delete e.ctx.table;
            var isIE = navigator.appVersion.indexOf("MSIE 10") !== -1 || (navigator.userAgent.indexOf("Trident") !== -1 && navigator.userAgent.indexOf("rv:11") !== -1); // this works with IE10 and IE11 both :)
            //if (typeof msie !== "undefined" && msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // this works ONLY with IE 11!!!
            if (isIE) {
                if (typeof Blob !== "undefined") {
                    //use blobs if we can
                    fullTemplate = e.format(fullTemplate, e.ctx); // with this, works with IE
                    fullTemplate = [fullTemplate];
                    //convert to array
                    var blob1 = new Blob(fullTemplate, { type: "text/html" });
                    window.navigator.msSaveBlob(blob1, getFileName(e.settings));
                } else {
                    //otherwise use the iframe and save
                    //requires a blank iframe on page called txtArea1
                    txtArea1.document.open("text/html", "replace");
                    txtArea1.document.write(e.format(fullTemplate, e.ctx));
                    txtArea1.document.close();
                    txtArea1.focus();
                    sa = txtArea1.document.execCommand("SaveAs", true, getFileName(e.settings));
                }

            } else {
                var blob = new Blob([e.format(fullTemplate, e.ctx)], { type: "application/vnd.ms-excel" });
                window.URL = window.URL || window.webkitURL;
                link = window.URL.createObjectURL(blob);
                a = document.createElement("a");
                a.download = getFileName(e.settings);
                a.href = link;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            }
            return true;
        }
    };
    //获取excel文件名
    function getFileName(settings) {
        return (settings.filename ? settings.filename : "table2excel");
    }
    //获取"合计"行所在的行号(不包括标题行)
    function getSubtotal(settings) {
        return (settings.subtotal ? settings.subtotal : 0);//默认值0
    }
    //导出Excel的表格宽度百分比的值(不含%号),默认100%
    function getWidth(settings) {
        return (settings.width ? settings.width : 100);
    }
    // Removes all img tags
    function exclude_img(string) {
        var _patt = /(\s+alt\s*=\s*"([^"]*)"|\s+alt\s*=\s*'([^']*)')/i;
        return string.replace(/<img[^>]*>/gi, function myFunction(x) {
            var res = _patt.exec(x);
            if (res !== null && res.length >= 2) {
                return res[2];
            } else {
                return "";
            }
        });
    }
    // Removes all link tags
    function exclude_links(string) {
        return string.replace(/<a[^>]*>|<\/a>/gi, "");
    }
    // Removes input params
    function exclude_inputs(string) {
        var _patt = /(\s+value\s*=\s*"([^"]*)"|\s+value\s*=\s*'([^']*)')/i;
        return string.replace(/<input[^>]*>|<\/input>/gi, function myFunction(x) {
            var res = _patt.exec(x);
            if (res !== null && res.length >= 2) {
                return res[2];
            } else {
                return "";
            }
        });
    }
    $.fn[pluginName] = function (options) {
        var e = this;
        e.each(function () {
            if (!$.data(e, "plugin_" + pluginName)) {
                $.data(e, "plugin_" + pluginName, new Plugin(this, options));
            }
        });
        // chain jQuery functions
        return e;
    };
})(jQuery, window, document);

图示:


Layui-table 参考:

javascript 复制代码
        <script type="text/javascript">
            //初始化
            $(function () {
                PageList();
            });
            //重置
            function Reset() {
                window.location.reload();
            }
            //查询
            function PageList() {
                var START_DATE = $("#START_DATE").val();
                var END_DATE = $("#END_DATE").val();
                var CUSTOMER_NAME = $("#TXT_CUSTOMER_NAME").val();
                var CONTACT_LINK = $("#TXT_CONTACT_LINK").val();
                var PROJECT_STATUS = $("#TXT_PROJECT_STATUS").val();
                var PROJECT_LEVEL = $("#TXT_PROJECT_LEVEL").val();

                layui.use(['table'], function () {
                    var table = layui.table;

                    table.render({
                        elem: '#table'//对应着Table的ID
                        //, width: '100%'
                        , method: 'POST'
                        , url: '/SalesOpportunity/SalesOpportunityTrackPage'//URL为数据接口的地址
                        , where: { //where就是ajax的data,但不包括分页条件
                            "START_DATE": START_DATE,
                            "END_DATE": END_DATE,
                            "CUSTOMER_NAME": CUSTOMER_NAME,
                            "CONTACT_LINK": CONTACT_LINK,
                            "PROJECT_STATUS": PROJECT_STATUS,
                            "PROJECT_LEVEL": PROJECT_LEVEL,
                        }
                        , request: {  //分页条件: page  limit
                            pageName: 'page',    //页码的参数名称,默认:page 或者 index、pageIndex
                            limitName: 'size'  //每页数据量的参数名,默认:limit 或者 size、pageSize
                        }
                        , parseData: function (res) {
                            return {
                                "code": 0,//数据类型,必须的
                                "count": res.total,//总记录数,用于分页
                                "data": res.data,//必须的
                            }
                        }
                        , cols: [
                            [
                                /* { title: '操作', toolbar: '#barDemo', width: 80, align: 'center', rowspan: 2 },*/
                                {
                                    field: 'SALES_OPPORTUNITY_SID', title: '操作', width: 80, align: 'center', rowspan: 2
                                    , templet: function (d) {
                                        //return d.SALES_OPPORTUNITY_SID;
                                        return `<button class="layui-btn layui-btn-xs layui-btn-radius layui-form-button-blue" onclick="OpenEdit(` + d.SALES_OPPORTUNITY_SID + `)">详情<span hidden>` + d.SALES_OPPORTUNITY_SID + `</span></button>`;
                                    }
                                },
                                { title: '客户基础信息', colspan: 14, align: 'center' },
                                { title: '跟踪维护信息', colspan: 10, align: 'center' },
                            ],
                            [
                                { field: 'CUSTOMER_NAME', title: '客户名称', width: 200, align: 'center' },
                                { field: 'CONTACT_LINK', title: '联系人', width: 100, align: 'center' },
                                { field: 'CONTACT_PHONE', title: '联系电话', width: 150, align: 'center' },
                                { field: 'HOBBIES', title: '客户喜好', width: 150, align: 'center' },
                                {
                                    field: 'BIRTHDAY', title: '纪念日/生日', width: 200, align: 'center'
                                    , templet: function (d) {
                                        if (d.BIRTHDAY) {
                                            return d.BIRTHDAY.replace(",", ",<br>");
                                        }
                                        else {
                                            return "";
                                        }
                                    }
                                },

                                { field: 'PROJECT_TITLE', title: '项目标题', width: 250, align: 'center' },
                                { field: 'PROJECT_INFO', title: '项目信息', width: 250, align: 'center' },
                                {
                                    field: 'PROJECT_STATUS', title: '项目状态', width: 100, align: 'center'
                                    , templet: function (d) {
                                        if (d.PROJECT_STATUS == 0) return "进行中<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else if (d.PROJECT_STATUS == 1) return "<font color='green'>完成</font><span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else if (d.PROJECT_STATUS == 2) return "<font color='red'>中止</font><span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else return "<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                    }
                                },
                                {
                                    field: 'PROJECT_LEVEL', title: '项目等级', width: 100, align: 'center'
                                    , templet: function (d) {
                                        if (d.PROJECT_LEVEL == 0) return "D<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else if (d.PROJECT_LEVEL == 1) return "C<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else if (d.PROJECT_LEVEL == 2) return "B<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else if (d.PROJECT_LEVEL == 3) return "A<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                        else return "<span hidden>" + d.SALES_OPPORTUNITY_PROJECT_SID + "</span>";
                                    }
                                },

                              
                                { field: 'NEEDS', title: '核心诉求', width: 250, align: 'center' },
                                { field: 'RESPONSE', title: '诉求应答', width: 250, align: 'center' },
                                { field: 'EST_AMOUNT', title: '预成交金额(万元)', width: 150, align: 'center' },
                                { field: 'NEED_SUPPORT', title: '需要的支持', width: 250, align: 'center' },
                                { field: 'REMARKS', title: '备注', width: 250, align: 'center' },
                                {
                                    field: 'FIRST_MANAGE_DATE', title: '首次维护时间', width: 150, align: 'center'
                                    , templet: function (d) {
                                        if (d.FIRST_MANAGE_DATE) {
                                            return dateToDateString(d.FIRST_MANAGE_DATE);
                                        }
                                        else {
                                            return '';
                                        }
                                    }
                                },
                                {
                                    field: 'LAST_MANAGE_DATE', title: '最近维护时间', width: 150, align: 'center'
                                    , templet: function (d) {
                                        if (d.LAST_MANAGE_DATE) {
                                            return dateToDateString(d.LAST_MANAGE_DATE);
                                        }
                                        else {
                                            return '';
                                        }
                                    }
                                },
                                { field: 'SINCE_DAYS', title: '未跟进时间(天)', width: 150, align: 'center' },
                                {
                                    field: 'MANAGE_DATE', title: '维护日期', width: 150, align: 'center'
                                    , templet: function (d) {
                                        if (d.MANAGE_DATE) {
                                            return timestampToDateString(d.MANAGE_DATE);
                                        } else {
                                            return '';
                                        }
                                    }
                                },
                                {
                                    field: 'MANAGE_TYPE', title: '维护方式', width: 100, align: 'center'
                                    , templet: function (d) {
                                        if (d.MANAGE_TYPE == 0) return "电话";
                                        else if (d.MANAGE_TYPE == 1) return "微信";
                                        else if (d.MANAGE_TYPE == 2) return "面谈";
                                        else if (d.MANAGE_TYPE == 3) return "邮件";
                                        else if (d.MANAGE_TYPE == 4) return "其他";
                                        else return "";
                                    }
                                },
                                {
                                    field: 'MANAGE_CONTENT', title: '维护类型', width: 100, align: 'center'
                                    , templet: function (d) {
                                        if (d.MANAGE_CONTENT == 0) return "需求";
                                        else if (d.MANAGE_CONTENT == 1) return "反馈";
                                        else if (d.MANAGE_CONTENT == 2) return "问候";
                                        else if (d.MANAGE_CONTENT == 3) return "其他";
                                        else return "";
                                    }
                                },
                                { field: 'FOLLOW_FOCUS', title: '内容/跟进重点', width: 250, align: 'center' },
                                { field: 'NEXT_DATETIME', title: '下次跟进时间', width: 150, align: 'center' },

                                { field: 'SALES_MAN', title: '销售人员', width: 100, align: 'center' },
                                {
                                    field: 'CREATED_TIME', title: '本记录时间', width: 180, align: 'center', templet: function (d) {
                                        if (d.CREATED_TIME) {
                                            return timestampToTimeString(d.CREATED_TIME);
                                        } else {
                                            return '';
                                        }
                                    }
                                },
                            ]],
                        page: true,//开启分页功能
                        limit: 25,//当前每页条数
                        limits: [25, 50, 100],//每页条数集合
                        done: function (res, curr, count) {
                            $('.layui-table-cell').css('height', 'auto'); // 暴力刷新

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_SID'], 'SALES_OPPORTUNITY_SID');

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'CUSTOMER_NAME');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'CONTACT_LINK');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'CONTACT_PHONE');

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'PROJECT_TITLE');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'PROJECT_INFO');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'PROJECT_STATUS');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'PROJECT_LEVEL');

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'HOBBIES');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'BIRTHDAY');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'NEEDS');

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'RESPONSE');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'EST_AMOUNT');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'NEED_SUPPORT');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'REMARKS');

                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'FIRST_MANAGE_DATE');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'LAST_MANAGE_DATE');
                            mergeCell('table', ['SALES_OPPORTUNITY_SID', 'SALES_OPPORTUNITY_PROJECT_SID'], 'SINCE_DAYS');
                        },
                    });
                });
            }

            // 合并规则:N个主列 + 副列 都相同 → 才合并【副列】
            // tableId:表格ID
            // mainFields:主字段数组(支持多个,如 ['SALES_OPPORTUNITY_SID','SALES_OPPORTUNITY_PROJECT_SID'])
            // subField:要合并的字段(联系人)
            function mergeCell(tableId, groupFields, mergeField) {
                const $tbody = $('#' + tableId + ' + div .layui-table-body tbody');
                const $trs = $tbody.find('tr');

                if ($trs.length <= 1) return;

                let startRow = 0;
                let spanCount = 1;

                for (let i = 1; i < $trs.length; i++) {
                    const $prevTr = $trs.eq(startRow);
                    const $currTr = $trs.eq(i);

                    // ======================================
                    // 【关键】判断所有分组列是否完全一样
                    // ======================================
                    let groupSame = true;
                    for (const field of groupFields) {
                        const t1 = $prevTr.find('td[data-field="' + field + '"]').text().trim();
                        const t2 = $currTr.find('td[data-field="' + field + '"]').text().trim();
                        if (t1 !== t2) {
                            groupSame = false;
                            break;
                        }
                    }

                    // 判断要合并的列是否一样
                    const m1 = $prevTr.find('td[data-field="' + mergeField + '"]').text().trim();
                    const m2 = $currTr.find('td[data-field="' + mergeField + '"]').text().trim();
                    const mergeSame = m1 === m2;

                    // 分组相同 + 合并列相同 → 合并
                    if (groupSame && mergeSame) {
                        spanCount++;
                        $currTr.find('td[data-field="' + mergeField + '"]').hide();
                    } else {
                        // 设置合并
                        $prevTr.find('td[data-field="' + mergeField + '"]').attr('rowspan', spanCount);
                        startRow = i;
                        spanCount = 1;
                    }
                }

                // 最后一行处理
                $trs.eq(startRow).find('td[data-field="' + mergeField + '"]').attr('rowspan', spanCount);
            }


            //时间戳转日期
            function timestampToDateString(dateTime) {
                if (!dateTime) return "";

                // 提取时间戳
                var timestampStr = dateTime.replace("/Date(", "").replace(")/", "");
                var timestamp = parseInt(timestampStr);
                const date = new Date(timestamp);

                // 获取 年/月/日
                var year = date.getFullYear();
                var month = (date.getMonth() + 1).toString().padStart(2, '0'); // 月补0
                var day = date.getDate().toString().padStart(2, '0');         // 日补0

                // 返回标准格式:2025-04-05
                return year + "-" + month + "-" + day;
            }

            //时间戳转时间
            function timestampToTimeString(dateTime) {
                if (!dateTime) return "";

                // 提取时间戳(兼容 /Date(xxx)/ 格式)
                var timestampStr = dateTime.replace("/Date(", "").replace(")/", "");
                var timestamp = parseInt(timestampStr);
                const date = new Date(timestamp);

                // 获取 年/月/日
                var year = date.getFullYear();
                var month = (date.getMonth() + 1).toString().padStart(2, '0');
                var day = date.getDate().toString().padStart(2, '0');

                // 获取 时/分/秒 + 自动补0
                var hour = date.getHours().toString().padStart(2, '0');
                var minute = date.getMinutes().toString().padStart(2, '0');
                var second = date.getSeconds().toString().padStart(2, '0');

                // 返回格式:2025-04-05 14:05:09
                return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
            }

            //日期转日期
            function dateToDateString(dateTime) {
                if (!dateTime) return "";

                const date = new Date(dateTime);

                // 获取 年/月/日
                var year = date.getFullYear();
                var month = (date.getMonth() + 1).toString().padStart(2, '0'); // 月补0
                var day = date.getDate().toString().padStart(2, '0');         // 日补0

                // 返回标准格式:2025-04-05
                return year + "-" + month + "-" + day;
            }

        </script>
相关推荐
雪芽蓝域zzs几秒前
第三十五节:Axios 统一错误拦截、401 Token 过期处理
前端·javascript·vue.js
XIE3926 分钟前
TipKit:开源富文本编辑器套件,一套逻辑,任意风格!
前端·笔记·开源
范什么特西20 分钟前
一些常用名词
开发语言·前端·javascript
晴天1621 分钟前
前端打包工具全景解析
前端
晴天1623 分钟前
Vite vs Webpack 全方位对比
前端·webpack·node.js
体毛旺盛的猿25 分钟前
HarmonyOS开发面试题
前端·华为·harmonyos
anOnion40 分钟前
构建无障碍组件之Landmarks Pattern
前端·html·交互设计
牧瀬クリスだ41 分钟前
前端三件套基础之JS!!!!
前端·javascript
风骏时光牛马44 分钟前
提示词工程:大模型交互的核心塑造技术
前端
单线程_011 小时前
从案例分析 Vue3 Tokenizer+Parser 源码四
前端·javascript·vue.js