当前位置: 首页 > news >正文

layui 乱入前端

功能包含

本实例代码为部分傻瓜框架,插入引用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_inputlet 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_colslet 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.nameheader_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,直接获取valueformData[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 {// 单选情况,直接设置valueinput.value = value;}break;default:// 对于其他类型(如text, email, number等),直接设置valueinput.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) { // 双击 toolDoublevar 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>

相关文章:

layui 乱入前端

功能包含 本实例代码为部分傻瓜框架&#xff0c;插入引用layui。因为样式必须保证跟系统一致&#xff0c;所以大部分功能都是自定义的。代码仅供需要用layui框架&#xff0c;但原项目又不是layui搭建的提供解题思路。代码较为通用 自定义分页功能自定义筛选列功能行内编辑下拉、…...

中国十大顶级哲学家,全球公认的伟大思想家颜廷利:人类为何拥有臀部

人类为何拥有臀部&#xff1f;若众生皆无此部位&#xff0c;又如何能寻得一处真正属于自己的“座位”&#xff1f;在博大精深的中国传统文化中&#xff0c;汉字“座”与“坐”均蕴含“土”字元素。在易经的智慧里&#xff0c;作为五行之一的“土”&#xff0c;象征着人类社会的…...

Threejs中导入GLTF模型克隆后合并

很多场景中会需要同一个模型很多次&#xff0c;但是如果多次加载同一个模型会占用很高的带宽&#xff0c;导致加载很慢&#xff0c;因此就需要使用clone&#xff0c;也就是加载一个模型后&#xff0c;其他需要使用的地方使用clone的方式复制出多个同样的模型&#xff0c;再改变…...

今日arXiv最热大模型论文:北京大学最新综述:视觉大模型中的漏洞与攻防对抗

近年来&#xff0c;视觉语言大模型&#xff08;LVLM&#xff09;在文本转图像、视觉问答等任务中大放异彩&#xff0c;背后离不开海量数据、强大算力和复杂参数的支撑。 但是&#xff01;大模型看似庞大的身躯背后却有一颗脆弱的“心脏”&#xff0c;极易受到攻击。攻击者可以…...

为什么IDEA中使用@Autowired会被警告

我们在使用IDEA编码时&#xff0c;如果用到了Autowired注解注入bean&#xff0c;会发现IDEA会给代码标个波连线&#xff0c;鼠标移动上去&#xff0c;会发下idea提示&#xff1a;不推荐使用Filed injection&#xff0c;这是Spring的核心DI&#xff08;Dendency Injection&#…...

uniapp使用cover-view,使用@click无效

最近要做直播详情页面&#xff0c;用的是第三方直播链接&#xff0c;需要在该页面上放两个按钮&#xff0c;点击按钮需要弹出相关商品及优惠券。类似于抖音直播页面。 第三方链接使用的是web-view进行展示。由于该组件优先级太高&#xff0c;正常的前端组件无法在该页面浮现展…...

Postman 接口测试工具简易使用指南

一、Postman是什么? 我通过kimi问了这样一个问题&#xff0c;它给我的回答是这样的: 它的回答也算比较中规中矩&#xff0c;简单的说postman实际上就是一款接口测试工具&#xff0c;同时它还可以编写对应的测试脚本以及自动生成对应的API文档&#xff0c;结合我的习惯来说&am…...

Move生态:从Aptos和Sui到Starcoin的崛起

区块链技术自诞生以来&#xff0c;已经经历了多个发展阶段和技术迭代。近年来&#xff0c;随着智能合约平台的不断演进&#xff0c;以Move语言为核心的生态系统逐渐崭露头角。Move语言以其安全性、灵活性和高效性吸引了大量开发者和项目方的关注。在Move生态中&#xff0c;Apto…...

MacOS DockerDesktop配置文件daemon.json的位置

如果因为通过可视化页面修改配置错误导致客户端启动不起来&#xff0c;可以去找对应的配置文件通过 vim 修改后重启客户端 cd ~/.docker/...

从光速常数的可变性看宇宙大爆炸的本质

基于先前关于光速本质的讨论&#xff0c;让我们从函数图像看看宇宙大爆炸到底是什么。 先前已经讨论过&#xff0c;在量子尺度上&#xff0c;长度的实际对应物是频率的差异&#xff0c;因为只有频率差异才能在这个尺度上区分相邻时空的两点&#xff0c;而两点之间“差异的大小”…...

敢不敢跟我一起搭建一个Agent!不写一行代码,10分钟搞出你的智能体!纯配置也能真正掌握AI最有潜力的技术?AI圈内人必备技能

说一千道一万&#xff0c;不如实地转一转。学了那么久的AI Agent的概念了&#xff0c;是时候该落地一个Agent看看自己的掌握程度了对不对&#xff0c;我们都理解大脑是自动节能的&#xff0c;但是知识的确需要倒逼自己一把才能真的掌握&#xff0c;不瞒大家说&#xff0c;笔者对…...

vue3和vite双向加持,uni-app性能爆表,众绑是否有计划前端升级到vue3!

uni-app官方已经开始不支持vue2了&#xff0c;而且即将适配的鸿蒙next原生系统&#xff0c;也不支持vue2打包&#xff0c;CRMEB是否有计划跟上潮流呢&#xff0c;如果有会在什么时间呢&#xff0c;有准确的时间表吗&#xff1f;我们非常期待得到答案&#xff01; 新版 uni-app…...

2024年最强网络安全学习路线,详细到直接上清华的教材!

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题前排提示&#xff1a;文末有CSDN官方认证Python入门资料包 &#xff01; 1、打基础时间太长 学基础花费很长时间&#xff0c;光语…...

人脸识别又进化:扫一下 我就知道你得了啥病

未来&#xff0c;扫下你的脸&#xff0c;可能就知道你得啥病了。没在瞎掰&#xff0c;最近的一项研究成果&#xff0c;还真让咱看到了一点眉目。北大的一个研究团队&#xff0c;搞出来一个 AI &#xff0c;说是用热成像仪扫一下脸&#xff0c;就能检测出有没有高血压、糖尿病和…...

yolov8标注细胞、识别边缘、计算面积、灰度值计算

一、数据标注 1. 使用labelme软件标注每个细胞的边界信息&#xff0c;标注结果为JSON格式 2. JSON格式转yolo支持的txt格式 import json import os import glob import os.path as osp此函数用来将labelme软件标注好的数据集转换为yolov5_7.0sege中使用的数据集:param jsonfi…...

WEB前端11-Vue2基础01(项目构建/目录解析/基础案例)

Vue2基础(01) 1.Vue2项目构建 步骤一&#xff1a;安装前端脚手架 npm install -g vue/cli步骤二&#xff1a;创建项目 vue ui步骤三&#xff1a;运行项目 npm run serve步骤四&#xff1a;修改vue相关的属性 DevServer | webpack //修改端口和添加代理 const { defineCo…...

QT--线程

一、线程QThread QThread 类提供不依赖平台的管理线程的方法&#xff0c;如果要设计多线程程序&#xff0c;一般是从 QThread继承定义一个线程类&#xff0c;在自定义线程类里进行任务处理。qt拥有一个GUI线程,该线程阻塞式监控窗体,来自任何用户的操作都会被gui捕获到,并处理…...

通过进程协作显示图像-C#

前言 如果一个软件比较复杂或者某些情况下需要拆解&#xff0c;可以考试将软件分解成两个或多个进程&#xff0c;但常规的消息传递又不能完全够用&#xff0c;使用消息共享内存&#xff0c;实现图像传递&#xff0c;当然性能这个方面我并没有测试&#xff0c;仅是一种解决思路…...

LangChain链与记忆处理[10]:四种基础内置链、四种文档处理链,以及链的自定义和五种运行方式,让你的大模型更加智能

LangChain链与记忆处理[10]:四种基础内置链、四种文档处理链,以及链的自定义和五种运行方式,让你的大模型更加智能 参考文章可以使用国产LLM进行下述项目复现: 初识langchain[1]:Langchain实战教学,利用qwen2.1与GLM-4大模型构建智能解决方案[含Agent、tavily面向AI搜索…...

京东发行稳定币的背后

加密市场很热&#xff0c;京东也要来分一杯羹&#xff1f; 7月24日&#xff0c;据财联社报道&#xff0c;京东科技旗下的京东币链科技 ( 香港 ) 将在香港发行与港元 1:1锚定的加密货币稳定币&#xff0c;在市场上掀起广泛热议。 由于众所周知的监管原因&#xff0c;国内大厂在早…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...

高分辨率图像合成归一化流扩展

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 摘要 我们提出了STARFlow&#xff0c;一种基于归一化流的可扩展生成模型&#xff0c;它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流&#xff08;TARFlow&am…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...