layui 乱入前端

news2024/9/9 4:56:23

功能包含

本实例代码为部分傻瓜框架,插入引用layui。因为样式必须保证跟系统一致,所以大部分功能都是自定义的。代码仅供需要用layui框架,但原项目又不是layui搭建的提供解题思路。代码较为通用

  • 自定义分页功能
  • 自定义筛选列功能
  • 行内编辑下拉、文本、时间、文本域
  • 自定义头部下拉搜索
  • 自定义头部输入搜索

功能截图

在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="zh">
<head>
    <!--# include file="/html/ads/meta.html" -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>客户明细1</title>
    <style>
        body {
            background-color: var(--fontcr);
        }

        body > div:nth-child(1) {
            padding: 10px;
        }

        .cument > div table td {
            border-bottom: 1px solid rgba(0, 0, 0, 0.2);
        }

        .cument > div table {
            border-bottom: 1px solid rgba(0, 0, 0, 0.2);
        }

        .layui-panel {
            background-color: rgb(242 242 242);
            margin-left: -15px;
        }

        layui-table > tbody > tr:hover {
            background-color: rgba(0, 0, 0, 0.05); /* 鼠标悬停时改变背景色 */
        }
    </style>
</head>

<body style="overflow: hidden;">
<!--layui工具按钮-->
<script type="text/html" id="barDemo">
    <!--  <div class="layui-clear-space">-->
    <button lay-event="save">保存</button>
    <!--  </div>-->
</script>

<script type="text/html" id="select_channal">
    {{#  var list = default_select_data.channal_id; }}
    <select name="channal_id" lay-filter="filter_channal_id" lay-append-to="body" lay-search>
        <option value="">请选择</option>
        {{# layui.each(list, function(i, v){ }}
        <option value="{{= v.key }}" {{=v.key=== d.channal_id?
        'selected' : '' }}>{{= v.value }} </option>
        {{# }); }}
    </select>
</script>
</script>
<script type="text/html" id="select_budget">
    {{#  var list = default_select_data.budget; }}
    <select name="budget" lay-filter="filter_budget" lay-append-to="body">
        <option value="">请选择</option>
        {{# layui.each(list, function(i, v){ }}
        <option value="{{= v }}" {{=v=== d.budget?
        'selected' : '' }}>{{= v }}</option>
        {{# }); }}
    </select>
</script>
<script type="text/html" id="select_intent">
    {{#  var list = default_select_data.intent; }}
    <select name="intent" lay-filter="filter_intent" lay-append-to="body">
        <option value="">请选择</option>
        {{# layui.each(list, function(i, v){ }}
        <option value="{{= v }}" {{=v=== d.intent?
        'selected' : '' }}>{{= v }}</option>
        {{# }); }}
    </select>
</script>
<script type="text/html" id="select_grade">
    {{#  var list = default_select_data.grade;}}
    <select name="grade" lay-filter="filter_grade" lay-append-to="body">
        <option value="">请选择</option>
        {{# layui.each(list, function(i, v){ }}
        <option value="{{= v }}" {{=v=== d.grade?
        'selected' : '' }}>{{= v }}</option>
        {{# }); }}
    </select>
</script>

<script type="text/html" id="bargain_time">
    <input class="layui-input bargain_time" lay-filter="filter_bargain" placeholder="选择成交日期" name="bargain_time"
           value="{{= d.bargain_time || '' }}"/>
</script>
<div style="margin-left: 10px;margin-top: 10px">

    <!-- 头部按钮-->
    <div style="display: flex">
        <form id="search" onsubmit="return false;" class="tool">
            <div>
                <input type="text" name="wc_date"  between onchange="cms.reload()" placeholder="可选日期"/>
            </div>
            <div>
                <button type="button" onclick="cms.reset();">重置</button>
            </div>
            <div>
                <button type="button" onclick="cms.reload();">刷新</button>
            </div>
            <div>
                <!--                需要打开此功能只需要打开table.hideCol处的注释和这个注释即可-->
                                <button type="button" id="dropdown_cols" lay-options="{trigger: 'hover'}">筛选列</button>
            </div>
<!--            <div>-->
<!--                <button type="button" οnclick="cms.export_xls();">导出</button>-->
<!--            </div>-->
        </form>
    </div>

    <div class="cument">
        <div id="thead_box">
            <!--            <table name="table">-->
            <!--                <thead name="thead">-->
            <!-- layui表格-->
            <table class="layui-hide" id="test" lay-filter="test"></table>
            <!--                </thead>-->
            <!--            </table>-->
        </div>

        <div id="tbody_box">
            <table name="table">
                <tbody name="tbody"></tbody>
            </table>
            <ul id="mouse_menu" hidden></ul>
        </div>

        <div id="tfoot_box">
            <table name="table">
                <tfoot name="tfoot">

                </tfoot>
            </table>
        </div>
        <!-- 分页组件-->
        <nav id="nav" style="margin-bottom: 10px"></nav>
        <!-- 其他区域-->
        <div class="extra">

        </div>
    </div>
</div>

<!-- 当前页码隐藏域 -->
<input type="hidden" id="p" name="p" value="1">

<!-- 总页数隐藏域 -->
<input type="hidden" id="pmax" name="pmax" value="1">

<!--# include file="/html/ads/footer.html" -->
<script type="text/javascript">
    layui.config({
        base: '/html/plugins/layui/ext/',
    }).extend({
        excel: 'excel',
    });
</script>
<script>
    const baseURL = config.api_url;
    //解决首次重复请求问题
    let first_load = true;
    let cms = new Cms({}, {}, {});
    //缓存数据
    let cache_data = [];
    //头部输入搜索 对应header_input
    let fields = [
        {key: 'wechatno', selector: '#wechatno_header'},
        // {key: 'nickname', selector: '#nickname_header'},
    ];
    //存储输入值
    let header_input = {
        "wechatno": '',
    };
    //头部下拉字段
    let select_fields = ['channal_id', 'budget', 'intent', 'grade'];
    //缓存选中的头部下拉
    let header_select = {
        "budget": [],
        "intent": [],
        "grade": [],
        "channal_id": [],
    };
    // 存放头部下拉 支持对象数组,但对象数组格式一定是key value格式
    let default_select_data = {
        'budget': ["中6位", "中万", "中千", "千万级", "大6位", "大万", "大千", "客户没说", "小6位", "小万", "小千", "百万级"],
        'intent': ["不回复", "不回复删除", "不感兴趣", "中意向(学习,了解,鉴定等)", "低意向 (1k以内)", "同行或推广", "回复后删除", "已成交", "高意向(有明确产品需求或有明确预算)"],
        'grade': ["vip大客户100w+", "成交客户10w内", "未成交", "重点客户10-100w"],
        "channal_id": [],
    };
    //用于存放显示列缓存
    const cache_key_cols = "cache_key_cols";
    //默认显示列 对应default_cols
    let select_cols = ["avatar", "nickname", "friendid", "gender", "dq", "uname", "c_name", "c_phone", "channal_id", "budget", "intent", "grade", "bargain_time",
        "memo1", "u_project", "u_group", "xsavatar", "xswechatnick", "wechatid", "wechatno", "incoming_time", "create_time"];
    //显示列下拉列表
    let default_cols = [
        {key: "avatar", value: "客户头像"}, {key: "nickname", value: "客户昵称"}, {
            key: "friendid",
            value: "客户微信"
        }, {key: "gender", value: "客户性别"}
        , {key: "dq", value: "客户地区"}, {key: "uname", value: "录入人"}, {
            key: "c_name",
            value: "客户姓名"
        }, {key: "c_phone", value: "客户手机"}, {
            key: "channal_id",
            value: "渠道"
        }, {key: "budget", value: "预算"}, {key: "intent", value: "意向"}
        , {key: "grade", value: "等级"}, {key: "bargain_time", value: "成交时间"}, {
            key: "memo1",
            value: "备注"
        }, {key: "u_project", value: "项目"}, {key: "u_group", value: "组"}, {
            key: "xsavatar",
            value: "销售头像"
        }, {key: "xswechatnick", value: "销售昵称"}, {key: "wechatid", value: "销售微信ID"}
        , {key: "wechatno", value: "微信号"}, {key: "create_time", value: "进线时间"}, {
            key: "create_time",
            value: "创建时间"
        }
    ];
    //远程渠道数据
    let channals = [];
    //表格列
    let table_cols = [
        {
            field: 'id', title: 'ID', hide: true
        },

        {
            field: 'avatar', title: '客户头像', width: 100, templet: function (d) {
                return '<img src="' + d.avatar + '" style="width: 30px; height: 30px; border-radius: 50%;">';
            },
        },
        {
            field: 'nickname',
            title: '客户昵称',
            width: 170
        },
        {
            field: 'friendid',
            title: '客户微信',
            width: 80, templet: function (d) {
                return '***';
            },
        },
        {
            field: 'gender', title: '客户性别', width: 40, templet: function (d) {
                // 假设性别1为男,2为女,这里简单处理
                return d.gender === '1' ? '男' : d.gender === '2' ? '女' : '未知';
            }
        },
        {
            field: 'dq',
            title: '客户地区',
            width: 100
        },
        {
            field: 'uname',
            title: '录入人',
            width: 100
        },
        {
            field: 'c_name',
            title: '客户姓名',
            edit: 'text',
            width: 100
        },
        {
            field: 'c_phone',
            edit: 'text',
            title: '客户手机',
            width: 120
        },
        {
            field: 'channal_id',
            title: '<div id="dropdown_channal_id" lay-options="{trigger: \'hover\'}" >渠道</div>',
            width: 200,
            templet: '#select_channal'
        },
        {
            field: 'budget',
            title: '<div id="dropdown_budget" lay-options="{trigger: \'hover\'}" >预算</div>',
            width: 200,
            templet: '#select_budget'
        },
        {
            field: 'intent',
            title: '<div id="dropdown_intent" lay-options="{trigger: \'hover\'}" >意向</div>',
            width: 200,
            templet: '#select_intent'
        },
        {
            field: 'grade',
            title: '<div id="dropdown_grade" lay-options="{trigger: \'hover\'}" >等级</div>',
            width: 200,
            templet: '#select_grade'
        },
        {field: 'bargain_time', title: '成交时间', width: 200, sort: true, templet: '#bargain_time'},
        {
            field: 'memo1',
            title: '备注',
            width: 200,
            edit: 'textarea'
        },
        {field: 'u_project', title: '项目', width: 100},
        {field: 'u_group', title: '组', width: 100},
        {
            field: 'xsavatar', title: '销售头像', width: 100, templet: function (d) {
                return '<img src="' + d.xsavatar + '" style="width: 30px; height: 30px; border-radius: 50%;">';
            }
        },
        {
            field: 'xswechatnick',
            title: '销售昵称',
            width: 200
        },
        {
            field: 'wechatid',
            title: '销售微信ID',
            width: 200
        },
        {
            field: 'wechatno',
            title: '<div><input id=\'wechatno_header\' type=\"text\" style=\'text-align: center;\' name=\"wechatno\" placeholder=\"搜索 微信号\" οnblur=\"cms.input_blur(this);\"></div>',
            width: 200
        },
        {field: 'create_time', title: '进线时间', width: 160},
        // {field: 'incoming_time', title: '进线时间', width: 200},
        {field: 'create_time', title: '创建时间', width: 160},
        {field: 'options', fixed: 'right', title: '操作', width: 100, minWidth: 80, toolbar: '#barDemo'}
    ];

    cms.input_blur = (that) => {
        let field = that.name
        header_input[field] = that.value;
        $("#p").val(1);
        cms.reload();
    }
    cms.export_xls = () => {
        layui.use(['jquery', 'excel', 'layer'], function () {
            var layer = layui.layer;
            var excel = layui.excel;
            let filterCols = [];
            let headers = {};
            default_cols.forEach(item => {
                filterCols.push(item.key)
                headers[item.key] = item.value;
            });
            // 重点!!!如果后端给的数据顺序和映射关系不对,请执行梳理函数后导出
            cache_data = excel.filterExportData(cache_data, filterCols);
            // 重点2!!!一般都需要加一个表头,表头的键名顺序需要与最终导出的数据一致
            cache_data.unshift(headers);
            let timestart = Date.now();
            excel.downloadExcel(cache_data, '客户详情报表', 'xlsx');
            let timeend = Date.now();
            let spent = (timeend - timestart) / 1000;
            layer.alert('导出耗时 ' + spent + ' s');
        });
    };
    /**
     * 重载数据
     * @returns {Promise<void>}
     */
    cms.reload = () => {
        if (first_load) {
            return new Promise((resolve, reject) => {});
        }
        let param = {
            p: $("#p").val(), //分页
            pmax: 20, //分页
            u_name: `${localStorage.getItem('u_name')}`,
        };
        //获取日期查询
        let wc_date = $("#wc_id").val();
        if (wc_date) {
            let searchDate = wc_date.split(" ");
            param["wc_date"] = 'BETWEEN \'' + searchDate[0].trim() + ' 00:00:00\' AND \'' + searchDate[2].trim() + ' 23:59:59\'';
        }
        //获取输入框的值
        Object.keys(header_input).forEach(key => {
            param[key] = header_input[key];
        });
        //获取头部复选框的值
        Object.keys(header_select).forEach(key => {
            param[key] = header_select[key].filter(e => !e || e !== '');
        });
        console.log(JSON.stringify(param));
        layui.use(['table', "laydate"], function () {
            var laydate = layui.laydate;
            let table = layui.table;
            table.reloadData('test', {
                where: param,
                scrollPos: 'fixed',  // 保持滚动条位置不变
                done: function () {
                    //重新加载筛选列
                    cms.load_cols(default_cols)
                    //重新更新分页组件
                    pagehelper.updateButtons();
                    //重新渲染头部下拉组件
                    Object.keys(default_select_data).forEach(key => {
                        cms.load_header_select(key, default_select_data[key])
                    });
                    //重新填充头部输入框
                    fields.forEach(field => {
                        $(field.selector).val(header_input[field.key]);
                    });
                    // 加载行日期时间选择器
                    laydate.render({
                        elem: '.bargain_time',
                        type: 'datetime',
                        done: function (value, date, endDate) {
                        }
                    });
                    //清理查询和数据缓存
                    this.where = {};
                    this.data = {};
                },
            }, true);

        });

    };
    /**
     * 日期条件重置
     * @returns {Promise<void>}
     */
    cms.date_reset = () => {
        let date = new Date();
        $('#search input[name="wc_date"]').daterangepicker({
            timePicker: true,
            startDate: moment().startOf('month'),
            endDate: moment(),
            locale: {format: 'YYYY-MM-DD'},
        });
        cms.date_select($('#search input[name="wc_date"]'));
    }
    cms.reset = () => {
        $("#p").val(1);
        cms.date_reset()
        //重置输入条件
        fields.forEach(field => {
            header_input[field.key] = "";
            $(field.selector).val('');
        });
        //重置复选条件
        Object.keys(header_select).forEach(key => {
            header_select[key] = [];
        });
        cms.reload()
    }
    cms.addSelectListeners = (fields, formInstance) => {
        console.log('获取编辑的下拉框数据')
        // 确保fields是一个数组
        if (!Array.isArray(fields)) {
            throw new Error('fields must be an array');
        }
        // 遍历字段数组
        fields.forEach(function (fieldName) {
            // 构造lay-filter的值,这里假设lay-filter的值由'filter_'前缀和字段名组成
            let filterName = 'filter_' + fieldName;
            // 为每个select元素设置监听器
            formInstance.on('select(' + filterName + ')', function (data) {
                let field = data.elem.name; // 获取select元素的name属性,通常这与fieldName相同,但最好检查一下
                let value = data.value; // 获取选中的值
                var text = data.elem[data.elem.selectedIndex].text;//得到选中的文本内容
                console.log(value, text);
            });
        });
    }
    /**
     * 获取某个元素下的表单数据 通用函数
     * @param parent
     * @returns {{}}
     */
    cms.form_data = (parent = '.label_top') => {
        // 获取表单元素,支持选择器模式和元素模式
        let form = typeof parent === 'string' ? document.querySelector(parent) : parent;
        if (!form) return {}; // 如果没有找到表单,则返回一个空对象
        // 创建一个对象来存储表单数据
        let formData = {};

        // 遍历表单内的所有元素
        form.querySelectorAll('input, select, textarea').forEach(function (input) {
            // 忽略没有name属性的元素
            if (!input.name) return;
            // 对于checkbox和radio,只有当它们被选中时才收集值
            if (input.tagName === 'SELECT') {
                // 对于单选select,直接获取value
                formData[input.name] = input.value;
            } else if (input.type === 'checkbox' || input.type === 'radio') {
                if (input.checked) {
                    // 如果是单选(radio),直接赋值
                    if (input.type === 'radio') {
                        formData[input.name] = input.value;
                    } else {
                        // 如果是多选(checkbox),检查是否已经存在该键,如果不存在则初始化为数组,然后添加值
                        if (!formData[input.name]) {
                            formData[input.name] = [];
                        }
                        formData[input.name].push(input.value);
                    }
                }
            } else if (input.type === 'select-multiple') {
                // 对于多选的select元素,收集所有选中的值到数组中
                let selectedOptions = Array.from(input.selectedOptions);
                formData[input.name] = selectedOptions.map(opt => opt.value);
            } else {
                // 对于其他类型的输入,直接收集值
                formData[input.name] = input.value;
            }
        });
        return formData;
    };
    /**
     * 填充某个元素下的表单数据 通用函数
     * @param formData
     * @param parent
     * @returns {{}}
     */
    cms.fill_form = (formData, parent = '.label_top') => {
        let form = document.querySelector(parent);
        if (!form) {
            console.error('Form not found with selector:', form);
            return;
        }
        // 遍历formData对象
        for (let key in formData) {
            if (formData.hasOwnProperty(key)) {
                const value = formData[key];
                const input = form.querySelector(`[name="${key}"]`);

                if (!input) {
                    console.warn('Field not found with name:', key);
                    continue;
                }

                // 根据input类型设置值
                switch (input.type) {
                    case 'checkbox':
                        // 对于checkbox,如果value是truthy值,则勾选
                        input.checked = !!value;
                        break;
                    case 'radio':
                        // 对于radio,需要找到value匹配的项并设置
                        const radios = form.querySelectorAll(`[name="${key}"][type="radio"]`);
                        radios.forEach(radio => {
                            radio.checked = radio.value === value;
                        });
                        break;
                    case 'select-multiple':
                        // 对于select,可能是单选或多选
                        if (input.multiple) {
                            // 多选情况,需要处理数组
                            if (Array.isArray(value)) {
                                const options = input.querySelectorAll('option');
                                options.forEach(option => {
                                    option.selected = value.includes(option.value);
                                });
                            }
                        } else {
                            // 单选情况,直接设置value
                            input.value = value;
                        }
                        break;
                    default:
                        // 对于其他类型(如text, email, number等),直接设置value
                        input.value = value;
                }

                // 触发change事件(如果需要)
                // input.dispatchEvent(new Event('change'));
            }
        }
    }

    document.addEventListener('DOMContentLoaded', async () => {
        cms.date_reset();
        //初始渠道数据
        const baseProject = 'ads'
        const func = 'set_channal'
        const url = `${baseURL}?class=${baseProject}&function=${func}`;
        cms.post_request(url, {"p": 1, "pmax": 10000}).then((res) => {
            channals = res.data;
            default_select_data.channal_id = channals.map(c => {
                return {key: `${c.id}`, value: `${c.platform_name}${c.channal}`};
            });
        });
        //设置默认列到缓存
        let cacheCols = JSON.parse(cache_manager.getCache(cache_key_cols));
        if (!cacheCols) {
            cache_manager.setCache(cache_key_cols, JSON.stringify(select_cols));
        }
        cacheCols = JSON.parse(cache_manager.getCache(cache_key_cols));
        table_cols.forEach((col, index) => {
            if (cacheCols.includes(col.field) || col.field == "options") {
                col.hide = false;
            } else if (col.field === "id") {
                col.hide = true;
            } else {
                col.hide = true;
            }
        })
        //加载筛选列
        cms.load_cols(default_cols)

    });
    /**
     * 请求工具类
     * @returns {Promise<void>}
     */
    cms.post_request = (url, requestParam) => {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            const params = new URLSearchParams();
            for (let key in requestParam) {
                if (requestParam.hasOwnProperty(key)) {
                    params.append(key, requestParam[key]);
                }
            }
            xhr.withCredentials = true;
            xhr.open('POST', url, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send(params.toString());

            xhr.onload = function () {
                if (xhr.status === 200) {
                    try {
                        var response = JSON.parse(xhr.responseText);
                        if (response.code === 200) {
                            console.log('操作成功:', response.msg);
                            resolve(response); // 在这里解决 Promise
                        } else {
                            console.error('操作失败:', response.msg);
                            reject(new Error(response.msg)); // 在这里拒绝 Promise
                        }
                    } catch (error) {
                        console.error('解析 JSON 响应时发生错误:', error);
                        reject(error); // 在这里拒绝 Promise
                    }
                } else {
                    console.error('请求失败,状态码:', xhr.status);
                    reject(new Error(`请求失败,状态码:${xhr.status}`)); // 在这里拒绝 Promise
                }
            };

            xhr.onerror = function () {
                console.error('请求过程中发生错误');
                reject(new Error('请求过程中发生错误')); // 在这里拒绝 Promise
            };
        });
    };
    /**
     * 更新插入
     * @returns {Promise<void>}
     */
    cms.in_item = (data) => {
        const baseProject = 'ads'
        const func = 'update_wx_customerinfos'
        const url = `${baseURL}?class=${baseProject}&function=${func}`;
        cms.post_request(url, data).then(() => {
            cms.reload();
            layer.msg('提示框', {
                content: "保存成功",
                icon: 1, //-1透明  0 警告 1 成功 2错误
                time: 2000 // 设置 2 秒后自动关闭
            });
        });
    };
    cms.checkbox = (input, filed) => {
        let item = input.value;
        if (input.checked) {
            if (!header_select[filed].includes(item)) {
                header_select[filed].push(item);
            }
        } else {
            header_select[filed] = header_select[filed].filter(c => c !== item);
        }
        $("#p").val(1);
        cms.reload();
    };
    /**
     * 通用头部复选搜索
     * @returns {Promise<void>}
     */
    cms.load_header_select = (currentField, data) => {
        if (Array.isArray(data)) {
            let htmls = `<div style="width: ${(200 - 3)}px; max-height: 640px;overflow-y: auto; overflow-x: hidden;">`; //搜索 (cols宽度-3)左右
            data.forEach((item, index) => {
                let value = typeof item === 'object' ? item.key || index : item; // 假设对象是带id的,否则使用索引
                let checked = header_select[currentField] && header_select[currentField].includes(value) ? ' checked' : '';
                htmls += `<label style="line-height: 2;letter-spacing: 1px;margin-left:10px;margin-top:20px;font-weight: bold;font-family: '宋体';font-size: 0.85rem;color: #343434;">
                <input type="checkbox" name="${currentField}" value="${value}" οnchange="cms.checkbox(this,'${currentField}')" ${checked} />
                ${typeof item === 'object' ? item.value || item.toString() : item}
                </label><br />`;
            });
            htmls += "</div>";
            layui.use(function () {
                var dropdown = layui.dropdown;
                // 自定义内容
                dropdown.render({
                    elem: `#dropdown_${currentField}`,
                    content: htmls,
                    className: `dropdown_class_${currentField}`,
                    // style: 'width: 370px; height: 200px; box-shadow: 1px 1px 30px rgb(0 0 0 / 12%);',
                    // shade: 0.3, // 弹出时开启遮罩 --- 2.8+
                    // ready: function () {
                    //     layui.use('element', function (element) {
                    //         element.render('tab');
                    //     });
                    // }
                });
            });
        }
    };
    // cms.load_header_select 的副本,只是筛选列查询列分开好区分
    cms.load_cols = (data) => {
        if (Array.isArray(data)) {
            let htmls = `<div style="width: ${(120 - 3)}px; max-height: 360px;overflow-y: auto; overflow-x: hidden;">`; //搜索 (cols宽度-3)左右
            data.forEach((item, index) => {
                let value = typeof item === 'object' ? item.key || index : item; // 假设对象是带id的,否则使用索引
                let cacheCols = JSON.parse(cache_manager.getCache(cache_key_cols));
                let checked = cacheCols.length > 0 && cacheCols.includes(value) ? ' checked' : '';
                htmls += `<label style="line-height: 2;letter-spacing: 1px;margin-left:10px;margin-top:20px;font-weight: bold;font-family: '宋体';font-size: 0.85rem;color: #343434;">
                <input type="checkbox" name="cols" value="${value}" οnchange="cms.checkCols(this)" ${checked} />
                ${typeof item === 'object' ? item.value || item.toString() : item}
                </label><br />`;
            });
            htmls += "</div>";
            layui.use(function () {
                var dropdown = layui.dropdown;
                // 自定义内容
                dropdown.render({
                    elem: `#dropdown_cols`,
                    content: htmls,
                    className: `dropdown_class_cols`,
                });
            });
        }
    };
    cms.checkCols = (input) => {
        let item = input.value;
        let cacheCols = JSON.parse(cache_manager.getCache(cache_key_cols));
        if (input.checked) {
            if (!cacheCols.includes(item)) {
                cacheCols.push(item);
            }
        } else {
            cacheCols = cacheCols.filter(c => c !== item);
        }
        cache_manager.setCache(cache_key_cols, JSON.stringify(cacheCols))
        table_cols.forEach((col, index) => {
            if (cacheCols.includes(col.field) || col.field == "options") {
                col.hide = false;
            } else if (col.field === "id") {
                col.hide = true;
            } else {
                col.hide = true;
            }
        })

        layui.use(['table'], async function () {
            var table = layui.table;
            // 设置对应列的显示或隐藏
            table.hideCol('test', table_cols);
        });
        cms.reload();
    };

    let cache_manager = {
        setCache: function (key, value) {
            localStorage.setItem(key, value);
        },
        getCache: function (key) {
            return localStorage.getItem(key);
        },
    };

</script>

<script>
    /**
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     *                layui组件
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     */
    layui.use(['table', 'dropdown', 'laydate', 'laytpl', 'form'], async function () {
        var table = layui.table;
        var form1 = layui.form;
        var laydate = layui.laydate;
        var laytpl = layui.laytpl;
        var dropdown = layui.dropdown;
        //layui允许跨域
        $.ajaxSetup({
            xhrFields: {
                withCredentials: true
            }
        });

        //获取日期查询
        let wc_date = $("#wc_id").val();
        let date;
        if (wc_date) {
            let searchDate = wc_date.split(" ");
            date = 'BETWEEN \'' + searchDate[0].trim() + ' 00:00:00\' AND \'' + searchDate[2].trim() + ' 23:59:59\'';
        }
        // 创建渲染实例
        table.render({
            elem: '#test',
            url: `${baseURL}?class=ads&function=get_wx_customerinfos`, // 此处为静态模拟数据,实际使用时需换成真实接口
            method: "post",
            where: {
                p: 1,
                pmax: 20,
                u_name: `${localStorage.getItem('u_name')}`,
                wc_date: date,
            },
            scrollPos: 'fixed',  // 保持滚动条位置不变
            contentType: 'application/x-www-form-urlencoded',
            // toolbar: '#toolbarDemo',
            // defaultToolbar: ['filter'],
            cellExpandedMode: "tips",
            skin: "gird",
            // even: true,//隔行背景色
            // loading: true,//是否显示加载
            height: 'full-156', // 最大高度减去其他容器已占有的高度差
            lineStyle: 'height: 56px;',//行高
            css: [].join(''), //样式重设
            cellMinWidth: 80,
            response: {
                "code": 0,
                "msg": "",
                // "count": 1000,
                "data": []
            },
            parseData: function (res) { //res 即为原始返回的数据
                $("#pmax").val(res.psum)
                return {
                    "code": 0, //解析接口状态
                    "msg": "", //解析提示文本
                    // "count": res.psum, //解析数据长度
                    "data": res.data //解析数据列表
                };
            },
            // totalRow: true, // 开启合计行
            // page: true,
            cols: [table_cols],
            /**
             * 初始化完毕时
             */
            done: function (res, curr, count) {
                //更新分页组件
                pagehelper.updateButtons();
                //渲染头部组件
                Object.keys(default_select_data).forEach(key => {
                    cms.load_header_select(key, default_select_data[key])
                });

                // 日期时间选择器
                laydate.render({
                    elem: '.bargain_time',
                    type: 'datetime',
                    done: function (value, date, endDate) {
                    }
                });
                cache_data = res.data;
                first_load = false;
            },
            error: function (res, msg) {
                console.log(res, msg)
            }
        });
        // 触发单元格工具事件
        table.on('tool(test)', function (obj) { // 双击 toolDouble
            var data = obj.data; // 获得当前行数据
            var id = data.id;
            var layEvent = obj.event; // 触发的事件名称
            var tr = obj.tr; //
            let to_update = {};
            if (layEvent === 'save') {
                to_update['id'] = id;
                //用户名
                to_update['u_name'] = `${localStorage.getItem('u_name')}`;
                //下拉数据
                select_fields.forEach(function (field) {
                    to_update[field] = tr.find(`td[data-field=${field}] > div > select`).val();
                });
                //成交时间
                to_update["bargain_time"] = tr.find(`td[data-field=bargain_time] > div  > input`).val();
                //备注文本域
                to_update["memo1"] = tr.find(`td[data-field=memo1] > div  > textarea`).val() || tr.find(`td[data-field=memo1] > div`).text();
                to_update["c_name"] = tr.find(`td[data-field=c_name] > div  > input`).val() || tr.find(`td[data-field=c_name] > div`).text();
                to_update["c_phone"] = tr.find(`td[data-field=c_phone] > div  > input`).val() || tr.find(`td[data-field=c_phone] > div`).text();
                console.log("保存数据" + JSON.stringify(to_update));
                cms.in_item(to_update)
            }
        });
        // 行单击事件
        table.on('row(test)', function (obj) {
            let id = obj.data.id;
            console.log("单击的id" + id)
        });
        // 文本编辑
        table.on('edit(test)', function (obj) {
            var field = obj.field; // 得到字段
            var value = obj.value; // 得到修改后的值
            var data = obj.data; // 得到所在行所有键值
            console.log("edit的id" + obj.data.id);
            // 其他更新操作
            var to_update = {};
            to_update[field] = value;
            obj.update(to_update);

        });
        //下拉编辑
        // cms.addSelectListeners(select_fields, form1)
    });

    /**
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     *                layui组件
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     */
</script>

<script>
    /**
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     *                分页组件
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     */
    let pagehelper = {
        /**
         * 跳转到哪一页
         */
        goto_page: function (page) {
            let pmax = parseInt($("#pmax").val())
            if (page < 1 || page > pmax) {
                // alert('页码超出范围');
                return;
            }
            $("#p").val(page)
            console.log('跳转到第' + page + '页');
            // 更新按钮
            pagehelper.updateButtons();
            cms.reload();
        },
        /**
         * 点击上一页
         */
        goto_previous: function () {
            let p = parseInt($("#p").val())
            if (p > 1) {
                pagehelper.goto_page(p - 1);
            }
        },
        /**
         * 点击下一页
         */
        goto_next: function () {
            let p = parseInt($("#p").val())
            let pmax = parseInt($("#pmax").val())
            if (p < pmax) {
                pagehelper.goto_page(p + 1);
            }
        },
        /**
         * 生成五个页码
         */
        generatePageNumbers: function (currentPage, totalPages) {
            // 计算要显示的页码范围
            let minPage = Math.max(1, currentPage - 2); // 至少从1开始
            let maxPage = Math.min(totalPages, currentPage + 2); // 最多到总页数

            // 如果总页数小于等于5,直接显示全部页码
            // if (totalPages <= 20) {
            //     minPage = 1;
            //     maxPage = totalPages;
            // }

            // 如果总页数允许且当前页接近两端,则调整最小或最大页码以包含足够的页码
            // 特别是当当前页是前几页或后几页时
            if (currentPage <= 3 && totalPages > 5) {
                maxPage = Math.min(totalPages, 5); // 确保不超过总页数
            } else if (currentPage >= totalPages - 2 && totalPages > 5) {
                minPage = Math.max(1, totalPages - 4); // 确保不小于1
            }

            // 生成页码数组
            let pageNumbers = [];
            for (let i = minPage; i <= maxPage; i++) {
                pageNumbers.push(i);
            }

            return pageNumbers;
        },

        /**
         * 重绘分页组件
         */
        updateButtons: function () {
            let p = parseInt($("#p").val())
            let pmax = parseInt($("#pmax").val())
            var nav = document.getElementById('nav');
            nav.innerHTML = ''; // 清空nav的内容

            // 创建上一页按钮
            var prevButton = document.createElement('button');
            prevButton.onclick = function () {
                pagehelper.goto_previous();
            };
            prevButton.textContent = '上一页';
            if (p == 1) {
                // 如果当前是第一页,则不显示
                prevButton.style.display = 'none';
            }
            //创建五个页码
            let pages = pagehelper.generatePageNumbers(p, pmax);
            // 创建页码按钮
            var ul = document.createElement('ul');
            for (var i = 0; i < pages.length; i++) {
                var pageNum = pages[i];
                var li = document.createElement('li');
                var pageButton = document.createElement('button');
                pageButton.onclick = function (page) {
                    return function () {
                        pagehelper.goto_page(page);
                    };
                }(pageNum); // 闭包确保正确的页码被传递
                pageButton.textContent = pageNum;
                if (pageNum == p) {
                    // 如果不是当前页,则禁用
                    pageButton.disabled = true;
                }
                li.appendChild(pageButton);
                ul.appendChild(li);
            }

            // 创建跳转输入框和下一页按钮
            var input = document.createElement('input');
            input.type = 'number';
            input.name = 'manual';
            input.placeholder = '最大页' + pmax;
            // 设置事件监听器
            input.onkeydown = function (event) {
                if (event.keyCode === 13) { // 只在按下回车键时验证
                    let toPage = parseInt(this.value, 10);
                    if (!isNaN(toPage) && toPage > 0 && toPage <= pmax) {
                        pagehelper.goto_page(toPage);
                    } else {
                        pagehelper.goto_page(pmax);
                    }
                }
            };

            var nextButton = document.createElement('button');
            nextButton.onclick = function () {
                pagehelper.goto_next();
            };
            nextButton.textContent = '下一页';
            nextButton.style.display = p < pmax ? '' : 'none'; // 如果当前是最后一页,则不显示
            // 将元素添加到nav中
            nav.appendChild(prevButton);
            nav.appendChild(ul);
            nav.appendChild(input);
            nav.appendChild(nextButton);
        }
    };

    /**
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     *                分页组件
     * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     */
</script>

</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1961332.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【React】详解如何获取 DOM 元素

文章目录 一、基础概念1. 什么是DOM&#xff1f;2. 为什么需要获取DOM&#xff1f; 二、使用 ref 获取DOM元素1. 基本概念2. 类组件中的 ref3. 函数组件中的 ref 三、 ref 的进阶用法1. 动态设置 ref2. ref 与函数组件的结合 四、处理特殊情况1. 多个 ref 的处理2. ref 与条件渲…

跟着丑萌气质狗学习WPF——Style样式

Style样式 1. 用法介绍2. 样式多样性3. 全局样式说明和资源字典的使用 1. 用法介绍 提前写好样式&#xff0c;让他作用于所有按钮 <Window x:Class"WPF_Study_Solution.window3"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmln…

typescript 解构时配置类型

以下三种写法&#xff0c;可以参考&#xff1a; const handleMenuClick ({item, key, keyPath}: {item: Object, key: string, keyPath:string}) > {} const handleMenuClick ({item, key, keyPath}: any) > {} interface SomeObj {item: Objectkey: stringkeyPath:st…

计算机系统操作系统简介

目录 1.计算机系统简介 1.1组成结构 1.2系统软件 1.3冯诺依曼计算机特点 1.4硬件构架 2.硬件的进一步认识 2.1存储器 2.2输入设备 2.3输出设备 2.4CPU组成 2.5线的概念引入 3.操作系统 3.1操作系统简介 3.2操作系统如何管理 3.3库函数和系统调用 1.计算机系统简介…

Linux 用户管理模式

目录 1. 概述 2. 管控级别 3. 用户组管理 4. 用户管理 4.1 创建用户 useradd 4.2 删除用户 userdel ​编辑4.3 查看用户所属组 id 4.4 修改用户所属组 usermod 5. 查看用户/用户组 5.1 查看系统用户 5.2 查看系统用户组 1. 概述 Linux 可以配置多个用户&#xff0c…

ppt中国风背景图片去哪找?附6个优质中国风PPT模板分享!

在这个全球化的时代&#xff0c;中国传统文化元素正在各个领域焕发出新的生机&#xff0c;不管是在时尚、建筑还是平面设计领域&#xff0c;中国风都以其独特的美学魅力吸引着世界的目光。在商业演示和学术报告中&#xff0c;PowerPoint(PPT)作为最常用的工具之一&#xff0c;同…

opencv arm 交叉编译

step1.opencv源码文件夹下新建build-arm目录 step2. cmake图像化配置 cmake-gui .. step3. 选择交叉编译 step4.检索交叉编译链路径 step5. 配置 配置install路径 配置编译、链接选项 添加人脸检测模块 config->generate step6. make编译 built-arm目录下&#xff1a; …

DC-DC转换器电感参数详解

我们对DC-DC转换器的要求以及电感参数中的电感值、公差和电阻进行了介绍。本文中&#xff0c;我们将对电感的其它参数进行详细讲解。 自谐频率&#xff08;SRF&#xff09; 每个电感线圈都有一些联带的分布电容&#xff0c;与电感值一起形成一个有自谐频率的并联谐振回路。对…

探索局域网传输新境界 | 闪电藤 v2.2.7

在这个数字化时代&#xff0c;文件的快速、安全传输是我们日常工作中不可或缺的一部分。今天&#xff0c;电脑天空向大家介绍一款革命性的局域网文件传输工具——闪电藤&#xff0c;它将彻底改变你的文件传输体验。 &#x1f3a8; 界面设计 —— 极简之美 闪电藤采用极简的设…

【自动化测试必学语言】python:语言基础

目录 Python 介绍 语言的分类 注释 单行注释 多行注释 变量 定义变量 使用变量 变量名的命名规范 数据类型 数字类型 非数字类型 type() 函数 input输入 print输出 格式化输出 快捷键(小操作) 运算符 算术运算符 比较运算符 Python 介绍 作者&#xff1a; 吉…

【Java】字符串String类(011)

目录 ♦️API和API帮助文档 ♦️创建String &#x1f38f;直接赋值类 &#x1f38f;new类 &#x1f421;空参类 构造方法&#xff1a; 举例代码&#xff1a; &#x1f421;有参类 构造方法&#xff1a; 举例代码&#xff1a; &#x1f421;字符数组类 构造方法&…

如何借助逻辑数据编织平台实现“数据优先堆栈( DFS )”

一、什么是面向“数据优先”的数据研发平台&#xff1f; 企业在数字化转型的浪潮中&#xff0c;愈发认知到数据作为核心战略资产的重要性。然而&#xff0c;要充分利用数据的价值并非易事。一方面&#xff0c;企业需要投入大量资源来建设和维护复杂的数据基础设施&#xff1b;另…

ref函数

Vue2 中的ref 首先我们回顾一下 Vue2 中的 ref。 ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用&#xff0c;引用指向的就是 DOM 元素&#xff1b;如果用在子组件上&#xff0c;引用就指向组件实例&#xff1…

计算机基础(day1)

1.什么是内存泄漏&#xff1f;什么是内存溢出&#xff1f;二者有什么区别&#xff1f; 2.了解的操作系统有哪些&#xff1f; Windows&#xff0c;Unix&#xff0c;Linux&#xff0c;Mac 3. 什么是局域网&#xff0c;广域网&#xff1f; 4.10M 兆宽带是什么意思&#xff1f;理论…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 整数数组按个位数字排序(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆Coding ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 93 分 最新华为OD机试目录…

使用大型语言模型进行文档解析

动机 多年来&#xff0c;正则表达式一直是我解析文档的首选工具&#xff0c;我相信对于许多技术人员和行业也是如此。尽管正则表达式在某些情况下非常强大&#xff0c;但它们常常在面对真实世界文档的复杂性和多样性时缺少灵活性。 另一方面&#xff0c;大型语言模型提供了一…

Mysql输出今年1月至当前月份日期序列

#今日2024-07-29SELECTDATE_FORMAT( DATE_ADD( NOW(), INTERVAL -(CAST( help_topic_id AS SIGNED INTEGER )) MONTH ), %Y-%m ) monthsFROMmysql.help_topicWHEREhelp_topic_id < TIMESTAMPDIFF(MONTH, CONCAT(DATE_FORMAT(CURDATE(), "%Y-01-01")),CONCAT(STR_…

《动手做科研 》| 03. 如何阅读人工智能研究论文

地址链接:《动手做科研》03. 如何阅读人工智能研究论文 导读: 在刚迈入科研时&#xff0c;人人都说读论文很重要&#xff0c;但是很少有人能完整地教你应该如何读论文。论文不仅揭示了行业的最新进展和趋势&#xff0c;而且为我们提供了改进技术和解决复杂问题的思路。然而&…

你知道缓存的这个问题到底把多少程序员坑惨了吗?

在现代系统中&#xff0c;缓存可以极大地提升性能&#xff0c;减少数据库的压力。 然而&#xff0c;一旦缓存和数据库的数据不一致&#xff0c;就会引发各种诡异的问题。 我们来看看几种常见的解决缓存与数据库不一致的方案&#xff0c;每种方案都有各自的优缺点 先更新缓存&…

探索NSL-KDD数据集:入侵检测的起点

引言 在信息安全的世界里&#xff0c;数据集是我们最宝贵的资源。就像厨师离不开食材&#xff0c;数据科学家也离不开数据集。对于入侵检测系统&#xff08;IDS&#xff09;而言&#xff0c;NSL-KDD数据集无疑是一个经典的选择。今天&#xff0c;我们将深入探讨这个数据集&…