div li的多行多列 无刷新分页

本文介绍了一种divli元素的多行多列无刷新分页技术,通过结合PHP、JavaScript和CSS,实现了数据较少情况下的高效分页。演示代码包括分页容器、内容加载和翻页功能,特别强调了无需刷新页面即可实现内容滚动展示。

div li的多行多列 无刷新分页

本例与《Jquery一页内翻页,类似于无刷新分页》很相近而区别与其他本站发布的翻页代码

翻页文件一次加载了全部的内容,因而不是很适合大型的网站,而适用于数据比较少的情况。

本例未使用数据库。

 

 

PHP Code
  1. <div class="container">  
  2.   
  3.           
  4.   
  5.         <ul id="content">  
  6.             <?php for ($i=1; $i<=53; $i++){?>  
  7.             <li><span><?php echo $i?></span></li>  
  8.             <?php }?>  
  9.         </ul>  
  10.         <div class="holder"></div>  
  11.     </div>  
JavaScript Code
  1. <script type="text/javascript">  
  2. $(document).ready(function() {  
  3.     $("div.holder").jPages({  
  4.         containerID : "content",  
  5.         perPage: 6  
  6.     });  
  7. });  
  8. </script>  

css

CSS Code
  1. body {  
  2.   text-alignleft;  
  3.   directionltr;  
  4.   font-family:tahoma,verdana,arial,sans-serif;  
  5.   font-size11px;  
  6. }  
  7.   
  8.   
  9.   
  10.   
  11.   
  12. .container {  
  13.   width370px;  
  14.   height: 100%;  
  15.   margin: 0 auto;  
  16.   
  17. }  
  18.   
  19.   
  20.   
  21. /* 
  22.   @@ Demo 
  23. */  
  24. ul {  
  25.   margin: 0;  
  26.   padding20px 0px;  
  27. }  
  28.   
  29. ul li {  
  30.   list-style-typenone;  
  31.   displayinline-block;  
  32.   line-height100px;  
  33.   text-aligncenter;  
  34.   font-weightbold;  
  35.   width100px;  
  36.   height100px;  
  37.   margin10px;  
  38.   background#ccc;  
  39. }  
  40.   
  41. ul li span {  
  42.   color#fff;  
  43.   padding3px;  
  44. }  
  45.   
  46. /* 
  47.   @@ Pagination 
  48. */  
  49. .holder { margin5px 0; }  
  50.   
  51. .holder a {  
  52.   font-size12px;  
  53.   cursorpointer;  
  54.   margin: 0 5px;  
  55.   color#333;  
  56. }  
  57.   
  58. .holder a:hover {  
  59.   background-color#222;  
  60.   color#fff;  
  61. }  
  62.   
  63. .holder a.jp-previous { margin-right15px; }  
  64. .holder a.jp-next { margin-left15px; }  
  65.   
  66. .holder a.jp-current, a.jp-current:hover {   
  67.   color#ed4e2a;  
  68.   font-weightbold;  
  69. }  
  70.   
  71. .holder a.jp-disabled, a.jp-disabled:hover { color#bbb; }  
  72.   
  73. .holder a.jp-current, a.jp-current:hover,  
  74. .holder a.jp-disabled, a.jp-disabled:hover {  
  75.   cursordefault;   
  76.   backgroundnone;  
  77. }  
  78.   
  79. .holder span { margin: 0 5px; }  

本例还使用了一个js jquery.pages.js 请到演示页面查看源码


原文地址:http://www.freejs.net/article_fenye_51.html

<template> <div v-if="alltable" class="table-template"> <div class="table-content"> <!-- 动态显示隐藏列功能 --> <el-dropdown v-if="selectColumns" :hide-on-click="false" class="el-dropdown-selectColumn" trigger="click" @visible-change="dropdownSelectShow" > <span title="显示或隐藏某列" class="dropdown-button"> <el-icon :size="16"><Menu /></el-icon> </span> <template #dropdown> <el-dropdown-menu style="text-align: center"> <div class="dropdowntable" style="text-align: left"> <el-dropdown-item v-for="(item, index) in tableLabel" :key="index"> <template #default> <el-checkbox v-model="item.isShow" :checked="item.isShow" @change="reload" >{{ item.label }}</el-checkbox> </template> </el-dropdown-item> <el-dropdown-item v-if="tableCheckShow"> <template #default> <el-checkbox v-model="currTableOperationShow" :checked="currTableOperationShow" @change="reload" >操作</el-checkbox> </template> </el-dropdown-item> </div> </el-dropdown-menu> </template> </el-dropdown> <div class="table-main"> <el-table ref="multipleTable" v-loading="loading" :data="tableData" :row-key="rowKey" border :default-expand-all="defaultExpandAll" :highlight-current-row="highlightCurrentRow" :tree-props="treeProps" :height="height" :expand-row-keys="expandRowKeys" :span-method="spanMethod" @selection-change="selectionChange" @row-click="rowClick" @row-dblclick="rowdbClick" > <!--选择--> <el-table-column v-if="selectionShow" type="selection" align="center" fixed="left" :width="selectionWidth" :selectable="selectStatus" :reserve-selection="reserveSelection" /> <el-table-column v-if="radioShow && !selectionShow" :align="radioAlign" :width="radioWidth" > <template #default="scope"> <el-radio v-model="radioVal" :label="scope.row[rowKey]" :disabled="scope.row.radioStatus" @change="getRow(scope.row)" > <span /> </el-radio> </template> </el-table-column> <!--序号 自定义列序号--> <el-table-column v-if="indexShow" type="index" align="center" label="序号" fixed="left" :width="indexWidth" > <template #dafault="scope"> <span>{{ (nowPage - 1) * pageSize + scope.$index + 1 }}</span> </template> </el-table-column> <!-- 表格数据列 --> <template v-for="(item, index) in tableLabel"> <el-table-column v-if="selectColumns ? item.isShow || !isshowShow : true" :key="index" :prop="item.prop" :width="item.width" :min-width="item.minWidth" :fixed="item.fixed" :formatter="item.formatter" :align="item.align ? item.align : 'center'" :label="item.label" :show-overflow-tooltip="toolTip" > <template #default="scope"> <div v-if="item.isSelfContent"> <slot :scope="scope" :name="item.prop"></slot> </div> </template> </el-table-column> </template> <!--操作--> <el-table-column v-if="currTableOperationShow" :width="operationColumnWidth" label="操作" :align="operationAlign" fixed="right" > <template #default="scope"> <el-button v-if="addShow" size="small" type="success" title="新增" text @click="handleAdd(scope.row)" >新增</el-button> <el-button v-if="classifyAddShow && scope.row.children.length" size="small" type="success" text title="新增" @click="handleAdd(scope.row)" >新增</el-button> <el-button v-if="editShow" size="small" type="primary" text title="编辑" :disabled="scope.row.shareHolderStatus === 0" @click="handleEdit(scope.row)" >编辑</el-button> <el-button v-if="detailShow" size="small" text type="success" title="详情" @click="handleDetail(scope.row)" >详情</el-button> <el-button v-if="deleteShow" type="danger" text title="删除" size="small" @click="handleDelete(scope.row, scope.$index)" >删除</el-button> <slot :row="scope.row" :index="scope.$index" /> </template> </el-table-column> </el-table> </div> </div> <div> <!-- 自定义总计列,展示在表格内容下方,分页按钮上方 --> <slot name="totalContent"></slot> <div class="pagination-container"> <el-pagination v-if="paging" background :current-page="nowPage" :page-size="pageSize" :page-sizes="pageSizes" layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="sizeChange" @current-change="currentChange" /> </div> </div> </div> </template> <script setup lang="ts"> import {ColumProps} from './types' import { PropType, reactive, toRefs, nextTick } from "vue" import { Check, Delete, Edit, Tickets, Menu } from '@element-plus/icons-vue' const props = defineProps({ //自定义列内容,比如加链接,加tag,加switch等 isSelfContent:{ type: Boolean, default: false, }, // 是否显示动态列功能,默认显示 selectColumns: { type: Boolean, default: true, }, // 表头列数据 tableLabel: { type: Array as PropType<ColumProps[]>, required: true, default: () => { return [] } }, // 表格没有操作列时,动态勾选的页面也没有操作勾选框 tableCheckShow: { type: Boolean, required: false, default: true }, // 表格最后操作列是否显示 tableOperationShow: { type: Boolean, required: false, default: true }, //加载中 loading: { type: Boolean, default: false }, // 表格数据 tableData: { type: Array, required: true, default: () => { return [] } }, // 行数据的key rowKey: { type: String, default: 'id' }, // 树结构表格是否默认打开 defaultExpandAll: { type: Boolean, default: false }, // 是否高亮显示某行 highlightCurrentRow: { type: Boolean, default: true }, // 树形表格渲染嵌套数据的配置选项{ hasChildren: 'hasChildren', children: 'children' } treeProps: { type: Object, default: () => { return {} } }, // 表格高度 height: { type: [Number, String], default: '100%' }, // 默认展开key数组 expandRowKeys: { type: Array, default: () => { return [] } }, //合并行单元格的列数组 columnList:{ type: Array, default: () => { return [] } }, // 单选按钮的默认值 radioValue: { type: [Number, String], default: -1 }, // 多选按钮,默认不显示多选 selectionShow: { type: Boolean, default: false }, // 多选宽度 selectionWidth: { type: Number, required: false, default: 50 }, // 数据更新后是否保留选择数据,仅对type=selection有效 reserveSelection: { type: Boolean, default: false }, // 单选 使用单选应将多选置为false radioShow: { type: Boolean, default: false }, // 单选对齐 radioAlign: { type: String, default: 'center' }, // 单选宽度 radioWidth: { type: Number, required: false, default: 35 }, // 序号列 indexShow: { type: Boolean, default: true }, // 序号宽度 indexWidth: { type: Number, required: false, default: 55 }, // 当前页 nowPage: { type: Number, default: 1 }, // 每页显示的条数 pageSize: { type: Number, default: 10 }, // 总条数 totalSize: { type: Number, default: 0 }, // 是否显示分页 paging: { type: Boolean, default: true }, // 是否控制列的动态显示 默认控制 isshowShow: { type: Boolean, default: true }, // 单元格内容超出宽度时是否...显示 toolTip: { type: Boolean, default: true }, // 表格操作列宽度 operationColumnWidth: { type: Number, required: false, default: 80 }, // 操作按钮对其方式 operationAlign: { type: String, default: 'center' }, // 显示详情操作按钮 detailShow: { type: Boolean, default: false }, // 显示编辑操作按钮 editShow: { type: Boolean, default: true }, // 显示新增操作按钮 addShow: { type: Boolean, default: false }, // 显示删除操作按钮 deleteShow: { type: Boolean, default: false }, classifyAddShow: { type: Boolean, default: false }, pageSizes: { type: Array as PropType<number[]>, default: () => { return [5, 10, 15, 20, 30, 50] } } }) const data = reactive({ alltable:true, currTableOperationShow:props.tableOperationShow, radioVal: props.radioValue, }) const {alltable, currTableOperationShow, radioVal} = toRefs(data) const emit = defineEmits(["selectionChange",'rowClick','rowdbClick','giveTableRowData','handleDetail','handleEdit','handleAdd','handleDelete','currentChange','sizeChange']) // 是否显示列的下拉框 function dropdownSelectShow(val:Boolean) { if (val === true) { var mo = (e:any) => { e.preventDefault() } document.body.style.overflow = 'hidden' document.addEventListener('touchmove', mo, false) // 禁止页面滑动 } } // 重新渲染 function reload() { data.alltable = false nextTick(() => { data.alltable = true }) } // 多选checkbox function selectionChange(val:object[]) { emit('selectionChange', val) } //单击行 function rowClick(row:any,column:any, event:any) { emit('rowClick', row) if (!row.radioStatus) { data.radioVal = row[props.rowKey] } } // 双击行 function rowdbClick(row:any, column:any, event:any) { emit('rowdbClick', row) } // 多选时是否禁用选择框,适用情形:从某个表格选择多条数据到另一个表格,已选过的数据不能再被选择,否则key重复 function selectStatus(row:any, index:number) { if (row.checkStatus) { return false } else { return true } } // 单选radio function getRow(row:any) { emit('giveTableRowData', row) } //合并列单元格 function spanMethod({row,columnIndex}:any){ const i = props.columnList.findIndex(v => v === columnIndex) if(i !== -1){ return { rowspan: row.rowSpan, colspan: 1, } }else{ return { rowspan: 1, colspan: 1, } } } // 查看详情 function handleDetail(row:any) { emit('handleDetail', row) } // 编辑 function handleEdit(row:any) { emit('handleEdit', row) } // 新增 function handleAdd(row:any) { emit('handleAdd', row) } // 删除 function handleDelete(row:any, index:number) { emit('handleDelete', row, index) } // 表格翻页 function currentChange(current:number) { emit('currentChange', current) } // 改变每页的条数 function sizeChange(size:number) { emit('sizeChange', size) } </script> <style lang="scss" scoped> .table-template{ height: 100%; position: relative; display: flex; flex-direction: column; .table-content{ flex:auto; position:relative; .table-main{ position:absolute; top:0; bottom:0; left:0; right:0; .el-button+.el-button{ margin-left:0px; } } } .el-dropdown-selectColumn { position: relative; float: right; z-index:999; // background-color: red; .dropdown-button { cursor: pointer; position: absolute; z-index: 9999; top: 5px; left: -20px; } .dropdowntable { width: 100%; max-height: 200px !important; overflow: auto !important; } } .selectColumn { margin-bottom: 10px; height: auto; } :deep(.pagination-container) { float:right; padding-top:5px; .el-pagination button, .el-pagination span:not([class*=suffix]) { font-size: 13px; min-width: 30px; height: 28px; line-height: 28px; } .el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li { min-width: 30px; border-radius: 2px; margin: 0 5px; } .el-pagination .btn-next, .el-pagination .btn-prev { background-size: 16px; } .el-pagination__jump { margin-left: 24px; } .el-pagination__goto { margin-right:0px; } .el-pager li { padding: 0 4px; font-size: 13px; height: 26px; line-height: 26px; } .el-pagination .el-select .el-input { width: 100px; height:28px; } .el-pagination .el-input__inner { height:26px; } .el-pagination .is-first { margin-right:0px; height:26px!important; line-height: 30px!important; } } } </style> <template> <TableTemplate :loading="loading" :table-data="tableData.list" :table-label="tableLabel" :span-method="columnList" :now-page="tableData.currPage" :page-size="tableData.pageSize" :total-size="tableData.totalCount" :detail-show="false" :edit-show="false" :tableOperationShow="false" :highlight-current-row="true" row-key="chargeId" @currentChange="handleCurrentChange" @sizeChange="handleSizeChange" > <template #totalContent> <div class="total-container"> <div>充电量(kw.h):{{ countData.electricQuantity || 0 }}</div> <div>应付总额:{{ countData.totalMoney || 0 }} 元</div> <div>结算总额:{{ countData.closeMoney || 0 }} 元</div> <div>优惠总额:{{ countData.discountMoney || 0 }} 元</div> </div> </template> </TableTemplate> </template> <script setup lang="ts"> import { reactive } from "vue"; import { storeToRefs } from "pinia"; import TableTemplate from "@/components/TableTemplate/index.vue"; import carCardPayDetailStore from "@/store/modules/order/carCardPayDetail"; const store = carCardPayDetailStore(); const { loading, tableData, countData } = storeToRefs(store); const { searchForm } = store; const tableLabel = reactive([ { label: "日期", prop: "dates", isShow: true, minWidth: 90, },{ label: "会员姓名", prop: "memberName", isShow: true, minWidth: 100, },{ label: "手机号", prop: "memberMobile", isShow: true, minWidth: 100, },{ label: "VIN号", prop: "vin", isShow: true, minWidth: 140, },{ label: "车牌号", prop: "licensePlate", isShow: true, minWidth: 90, }, { label: "充电量(kw.h)", prop: "electricQuantity", isShow: true, minWidth: 90, }, { label: "应付金额(¥)", prop: "totalMoney", isShow: true, minWidth: 90, }, { label: "优惠金额(¥)", prop: "discountMoney", isShow: true, minWidth: 90, }, { label: "预付金额(¥)", prop: "prepayMoney", isShow: true, minWidth: 90, }, { label: "结算金额(¥)", prop: "closeMoney", isShow: true, minWidth: 90, }, { label: "所属公司1", prop: "value1", isShow: true, minWidth: 90, }, { label: "所属公司2", prop: "value2", isShow: true, minWidth: 90, }, { label: "所属公司3", prop: "value3", isShow: true, minWidth: 90, }, { label: "所属公司4", prop: "value4", isShow: true, minWidth: 90, }, { label: "所属公司5", prop: "value5", isShow: true, minWidth: 90, }, { label: "所属公司6", prop: "value6", isShow: true, minWidth: 90, }, { label: "所属公司", prop: "company", isShow: true, minWidth: 100, }, { label: "所属站点", prop: "siteName", isShow: true, minWidth: 100, } ]); const columnList = [12,13,14,15,16] // 改变当前页 function handleCurrentChange(val: number) { searchForm.nowPage = val; store.getTableData(searchForm); } // 改变当前显示条数 function handleSizeChange(val: number) { searchForm.nowPage = 1; searchForm.pageSize = val; store.getTableData(searchForm); } </script> 请帮我修改代码:span-method第12列到16列需要合并
最新发布
10-28
------------------------ test.html ------------------------ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存查询系统</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- 引入 Popper.js 和 Bootstrap JS --> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js"></script> <script src="../js/main.js"></script> <style> .card-header { background: linear-gradient(to right, #1e3c72, #2a5298); color: white; } .search-section { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); border-radius: 10px; } .result-section { max-height: 70vh; overflow: auto; border-left: 3px solid #1e3c72; } .table-hover tbody tr:hover { background-color: rgba(42, 82, 152, 0.05); } .material-kucun { font-weight: 700; color: #1e3c72; } .material-kucun-low { color: #dc3545 !important; } .no-results { min-height: 200px; display: flex; align-items: center; justify-content: center; } .stats-card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); } body { background-color: #f8f9fa; padding-bottom: 2rem; } .search-control { position: relative; } .search-icon { position: absolute; left: 12px; top: 12px; color: #6c757d; } .form-control.with-icon { padding-left: 35px; } .highlight { background-color: rgba(255, 255, 0, 0.3) !important; } .info-badge { font-size: 0.8rem; font-weight: normal; } </style> </head> <body> <div class="container py-4"> <!-- 标题部分 --> <div class="text-center mb-4"> <h1 class="text-primary"><i class="bi bi-boxes"></i> 板材库存管理系统</h1> <p class="text-muted">查询订单、产品、板材及库存信息</p> </div> <!-- 统计卡片 --> <div class="row mb-4"> <div class="col-md-3"> <div class="card stats-card border-primary"> <div class="card-body"> <h5 class="card-title">订单总数</h5> <p class="card-text fs-3 text-primary" id="orderCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-info"> <div class="card-body"> <h5 class="card-title">产品种类</h5> <p class="card-text fs-3 text-info" id="productCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-success"> <div class="card-body"> <h5 class="card-title">板材库存</h5> <p class="card-text fs-3 text-success" id="materialCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-warning"> <div class="card-body"> <h5 class="card-title">库存总量</h5> <p class="card-text fs-3 text-warning" id="totalStock">0</p> </div> </div> </div> </div> <!-- 搜索区域 --> <div class="card search-section mb-4"> <div class="card-header"> <h5 class="mb-0"><i class="bi bi-search me-2"></i>高级搜索</h5> </div> <div class="card-body"> <div class="row g-3"> <!-- 订单搜索 --> <div class="col-md-6"> <div class="search-control"> <i class="bi bi-clipboard-search search-icon"></i> <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> </div> </div> <!-- 产品搜索 --> <div class="col-md-6"> <div class="search-control"> <i class="bi bi-grid search-icon"></i> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> </div> </div> <!-- 板材搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-box search-icon"></i> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> </div> </div> <!-- 木皮搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-tree search-icon"></i> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> </div> </div> <!-- 厚度范围 --> <div class="col-md-4"> <div class="input-group"> <span class="input-group-text"><i class="bi bi-arrows-vertical"></i></span> <input type="number" class="form-control" id="minThickness" placeholder="厚度(mm)" min="0" step="0.1"> <button class="btn btn-primary" type="button" id="thicknessBtn"> <i class="bi bi-arrow-right"></i> </button> </div> </div> </div> </div> </div> <!-- 结果区域 --> <div class="card"> <div class="card-header d-flex justify-content-between align-items-center"> <h5 class="mb-0"><i class="bi bi-table me-2"></i>查询结果</h5> <div class="text-secondary"> <span id="resultCount">0</span> 条记录 <span class="ms-2"><i class="bi bi-info-circle"></i> <small>实时数据更新时间: <span id="lastUpdate">--:--:--</span></small></span> </div> </div> <div class="card-body result-section"> <div class="table-responsive"> <table class="table table-hover" id="resultTable"> <thead class="table-light sticky-top"> <tr> <th>订单号</th> <th>产品信息</th> <th>产品数量</th> <th>组件</th> <th>板材</th> <th>板材/组件</th> <th>板材订购数量</th> <th>操作</th> </tr> </thead> <tbody id="resultBody"> <!-- 数据加载中 --> <tr id="loadingRow"> <td colspan="9" class="text-center py-5"> <div class="d-flex align-items-center justify-content-center"> <div class="spinner-border text-primary" role="status"> <span class="visually-hidden">加载中...</span> </div> <div class="ms-3">正在加载数据,请稍候...</div> </div> </td> </tr> </tbody> </table> </div> <!-- 空结果提示 --> <div id="noResults" class="no-results text-center py-5" style="display: none;"> <div> <i class="bi bi-inboxes text-muted" style="font-size: 3rem;"></i> <h4 class="mt-3 text-muted">没有找到匹配的记录</h4> <p class="text-muted">请尝试调整您的搜索条件</p> </div> </div> </div> </div> </div> <script type="text/javascript"> </script> <script src="../js/jsyilai.js"></script> ------------------------ index.html ------------------------ <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>峤丞板材库存管理</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="fonts/font-awesome-4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" type="text/css" href="main/bootstrap-3.3.7-dist/css/bootstrap.css.map"> <link rel="stylesheet" type="text/css" href="css/util.css"> <link rel="stylesheet" type="text/css" href="css/main.css"> <link rel="stylesheet" type="text/css" href="css/index2.css"> <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script> <script type="text/javascript" src="js/jsyilai.js"></script> <script type="module"> // 共享的DataManager类 import { DataManager } from './data/DataManager.js?'; document.addEventListener('DOMContentLoaded', async () => { try { // 创建实例并挂载到window window.dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); // 初始化数据 await window.dataManager.fetchAll(); console.log('Data Manager initialized successfully'); // 设置iframe通信 const iframe = document.getElementById('iframeid'); iframe.onload = () => { // 通知iframe数据已准备好 iframe.contentWindow.postMessage('DataManagerReady', '*'); }; // 如果iframe已经加载,立即发送消息 if (iframe.contentDocument.readyState === 'complete') { iframe.contentWindow.postMessage('DataManagerReady', '*'); } } catch (error) { console.error('Failed to initialize DataManager:', error); } }); </script> <style type="text/css"> *{ margin:0; padding:0; } .frame-header { height: 60px; background-color: #23262E; justify-content: space-between; } .frame-header-li{ font-family: Arial, Helvetica, sans-serif; font-size:40px; } .frame-ul{ } .frame-ul li{ border-style: solid; border-width:1px 0px 1px 0px; margin-top: 1px; height: 35px; text-align: center } #username{ position: absolute; right: 0; /* 靠右 */ } .frame-body { position: fixed; top: 60px; right: 0; bottom: 0; left: 0; display: flex; flex-direction: row; } .frame-side { scrollbar-width: none; /* firefox隐藏滚动条 */ -ms-overflow-style: none; /* IE 10+隐藏滚动条 */ overflow-x: hidden; overflow-y: auto; width: 200px; background-color:#9e5; } .frame-side::-webkit-scrollbar { display: none; /* Chrome Safari 隐藏滚动条*/ } .frame-main { flex-grow: 1; background-color:#fff; } .jiaoluo{ margin: auto; margin-right: 0px; } .menu { display: none; position: absolute; background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px; list-style-type: none; margin: 0; z-index: 10; } </style> </head> <body> <div class="frame-header"> <a class='frame-header-li' style="color:#fff">峤丞木材仓库管理</a> <a id="username" class='frame-header-li' style="color:#520">峤丞木材仓库管理</a> <!-- 菜单 --> <ul class="menu"> <li>选项 1</li> <li>选项 2</li> <li>选项 3</li> </ul> </div> <div class="frame-body"> <div class="frame-side"> <ul id="main_u" class='frame-ul' style="text-align:center;"> <li ><a href="main/test.html" target="main">首页</a></li> <li><a href="main/bancai.html" target="main">板材查询</a></li> <li><a href="main/test.html" target="main">订单板材录入</a></li> <li><a href="main/tianjia.html" target="main">test</a></li> <li><a href="main/Guanli.html" target="main">人员管理</a></li> </ul> </div> <div class="frame-main"> <!-- 内容主体区域 --> <iframe id="iframeid" name="main" src="main/bancai.html" width="100%" height="100%" frameborder="0"> </iframe> </div> </div> </body> </html> ------------------------ DataManager.js ------------------------ //{ 实体类的关联和属性列表 // "entities": { // "Dingdan": { // "properties": { // "id": "Integer", // "number": "String", // "xiadan": "Date", // "jiaohuo": "Date", // "dingdan_chanpins": "List<Dingdan_chanpin> (OneToMany)", // "dingdan_chanpins_zujians": "List<Dingdan_chanpin_zujian> (OneToMany)" // }, // "relations": [ // "关联订单产品(Dingdan_chanpin)", // "关联订单组件(Dingdan_chanpin_zujian)" // ] // }, // "Dingdan_chanpin": { // "properties": { // "id": "Integer", // "shuliang": "Integer" // }, // "relations": [ // "多对一关联订单(Dingdan)", // "多对一关联产品(Chanpin)" // ] // }, // "Dingdan_chanpin_zujian": { // "properties": { // "id": "Integer", // "shuliang": "Integer" // }, // "relations": [ // "多对一关联订单(Dingdan)", // "多对一关联组件(Chanpin_zujian)", // "多对一关联板材(Bancai)" // ] // }, // "Jinhuo": { // "properties": { // "id": "Integer", // "shuliang": "Integer", // "date": "Date" // }, // "relations": [ // "多对一关联订单(Dingdan)", // "多对一关联产品(Chanpin)", // "多对一关联组件(Zujian)", // "多对一关联板材(Bancai)", // "多对一关联用户(User)" // ] // }, // "Kucun": { // "properties": { // "id": "Integer", // "shuliang": "Long" // }, // "relations": [ // "一对一关联板材(Bancai)" // ] // }, // "Mupi": { // "properties": { // "id": "Integer", // "name": "String", // "you": "Boolean" // }, // "relations": [ // "被板材关联(Bancai - mupi1/mupi2)" // ] // }, // "User": { // "properties": { // "id": "Integer", // "name": "String", // "andy": "String", // "pass": "String", // "role": "int" // } // }, // "Zujian": { // "properties": { // "id": "Integer", // "name": "String" // }, // "relations": [ // "一对多关联产品组件(Chanpin_zujian)" // ] // }, // "Bancai": { // "properties": { // "id": "Integer", // "houdu": "Double" // }, // "relations": [ // "多对一关联材质(Caizhi)", // "多对一关联木皮(Mupi - mupi1/mupi2)", // "一对一关联库存(Kucun)" // ] // }, // "Caizhi": { // "properties": { // "id": "Integer", // "name": "String" // }, // "relations": [ // "一对多关联板材(Bancai)" // ] // }, // "Chanpin": { // "properties": { // "id": "Integer", // "bianhao": "String" // }, // "relations": [ // "一对多关联订单产品(Dingdan_chanpin)", // "一对多关联产品组件(Chanpin_zujian)" // ] // }, // "Chanpin_zujian": { // "properties": { // "id": "Integer", // "one_howmany": "Double" // }, // "relations": [ // "多对一关联产品(Chanpin)", // "多对一关联组件(Zujian)", // "多对一关联板材(Bancai)" // ] // } // }, // "relationsSummary": [ // "订单(Dingdan) 1:N 订单产品(Dingdan_chanpin)", // "订单(Dingdan) 1:N 订单组件(Dingdan_chanpin_zujian)", // "产品(Chanpin) 1:N 产品组件(Chanpin_zujian)", // "组件(Zujian) 1:N 产品组件(Chanpin_zujian)", // "板材(Bancai) 1:1 库存(Kucun)", // "材质(Caizhi) 1:N 板材(Bancai)" // ] //} /** * 解析数据关联关系,将ID引用转换为对象引用 * @param {Object} data - 从后端加载的原始数据 * @returns {Object} - 处理后的数据,包含完整的对象关联 *//** * 解析数据关联关系,将ID引用转换为对象引用 * @param {Object} data - 从后端加载的原始数据 * @returns {Object} - 处理后的数据,包含完整的对象关联 */ function resolveDataReferences(data) { // 创建ID映射表 const idMaps = {}; Object.keys(data).forEach(key => { // 确保数据存在且是数组 if (Array.isArray(data[key])) { idMaps[key] = new Map(); data[key].forEach(item => idMaps[key].set(item.id, item)); } }); // 处理多对一和一对一关系 const resolveRef = (source, sourceKey, targetKey, propertyName) => { // 确保源数据存在且是数组 if (!Array.isArray(source)) return; source.forEach(item => { // 确保关联属性存在且有id if (item[propertyName] && item[propertyName].id) { const refId = item[propertyName].id; // 确保目标映射存在 if (!idMaps[targetKey]) return; const target = idMaps[targetKey].get(refId); if (target) { item[propertyName] = target; // 建立反向引用(一对多关系) if (!target[sourceKey]) target[sourceKey] = []; if (!target[sourceKey].includes(item)) { target[sourceKey].push(item); } } } }); }; // 处理一对多关系(直接创建关联数组) const resolveOneToMany = (sourceKey, targetKey, propertyName) => { // 确保源数据存在 if (!Array.isArray(data[sourceKey]) || !Array.isArray(data[targetKey])) return; const sourceItems = data[sourceKey]; sourceItems.forEach(source => { if (!source[propertyName]) source[propertyName] = []; }); data[targetKey].forEach(target => { // 确保关联属性存在 if (target[sourceKey]?.id) { const sourceId = target[sourceKey].id; // 确保源映射存在 if (!idMaps[sourceKey]) return; const source = idMaps[sourceKey].get(sourceId); if (source && source[propertyName]) { source[propertyName].push(target); } } }); }; // 处理特定关联关系 - 添加空值检查 if (data.dingdans && data.dingdan_chanpins) { resolveOneToMany('dingdans', 'dingdan_chanpins', 'dingdan_chanpins'); resolveRef(data.dingdan_chanpins, 'dingdans', 'dingdans', 'dingdan'); } if (data.dingdans && data.dingdan_chanpin_zujians) { resolveOneToMany('dingdans', 'dingdan_chanpin_zujians', 'dingdan_chanpin_zujians'); resolveRef(data.dingdan_chanpin_zujians, 'dingdans', 'dingdans', 'dingdan'); } if (data.chanpins && data.chanpin_zujians) { resolveOneToMany('chanpins', 'chanpin_zujians', 'chanpin_zujians'); resolveRef(data.chanpin_zujians, 'chanpins', 'chanpins', 'chanpin'); } if (data.zujians && data.chanpin_zujians) { resolveOneToMany('zujians', 'chanpin_zujians', 'chanpin_zujians'); resolveRef(data.chanpin_zujians, 'zujians', 'zujians', 'zujian'); } if (data.caizhis && data.bancais) { resolveOneToMany('caizhis', 'bancais', 'bancais'); resolveRef(data.bancais, 'caizhis', 'caizhis', 'caizhi'); } if (data.bancais && data.kucuns) { resolveRef(data.bancais, 'kucuns', 'kucuns', 'kucun'); } if (data.kucuns && data.bancais) { resolveRef(data.kucuns, 'bancais', 'bancais', 'bancai'); } if (data.bancais && data.mupis) { resolveRef(data.bancais, 'mupis', 'mupis', 'mupi1'); resolveRef(data.bancais, 'mupis', 'mupis', 'mupi2'); } if (data.dingdan_chanpins && data.chanpins) { resolveRef(data.dingdan_chanpins, 'chanpins', 'chanpins', 'chanpin'); } if (data.dingdan_chanpin_zujians && data.chanpin_zujians) { resolveRef(data.dingdan_chanpin_zujians, 'chanpin_zujians', 'chanpin_zujians', 'chanpin_zujian'); } if (data.dingdan_chanpin_zujians && data.bancais) { resolveRef(data.dingdan_chanpin_zujians, 'bancais', 'bancais', 'bancai'); } if (data.jinhuos) { // 进货 ↔ 相关实体 (多对一) ['dingdans', 'chanpins', 'zujians', 'bancais', 'users'].forEach(entity => { if (data[entity]) { resolveRef(data.jinhuos, entity, entity, entity.slice(0, -1)); } }); } return data; } /** * 数据管理器类,负责与后端API通信并管理数据 */ class DataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.data = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_chanpin_zujians: [], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [] }; this.isSyncing = false; this.lastSync = null; // 回调注册表 this.callbacks = { // 全局回调 all: [], // 按实体类型分类的回调 bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], dingdan_chanpin_zujian: [], chanpin_zujian: [], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], // ...其他实体 }; this.syncQueue = Promise.resolve(); } /** * 获取所有数据 * @returns {Promise<boolean>} 是否成功 */ async fetchAll() { console.log(this) try { const response = await fetch(`${this.baseUrl}/app/all`); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); const resolvedData = resolveDataReferences(result.data); // 更新本地数据 Object.keys(this.data).forEach(key => { if (resolvedData[key]) { this.data[key] = resolvedData[key]; } }); this.lastSync = new Date(); // 关键改进:数据更新后触发刷新回调 this.triggerCallbacks('refresh', 'all', this.data); return true; } catch (error) { console.error('Fetch error:', error); // 触发错误回调 this.triggerCallbacks('fetch_error', 'all', { error }); return false; } } /** * 注册回调函数 * @param {string} entity - 实体类型(如'bancai')或'all'表示全局回调 * @param {Function} callback - 回调函数,参数为(operation, data) */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** * 移除回调函数 * @param {string} entity - 实体类型单数性质 * @param {Function} callback - 要移除的回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** * 触发回调 * @param {string} operation - 操作类型('add', 'update', 'delete') * @param {string} entity - 实体类型单数性质 * @param {Object} data - 相关数据 */ triggerCallbacks(operation, entity, data) { // 触发全局回调 this.callbacks.all.forEach(cb => cb(operation, entity, data)); // 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } /** * 执行CRUD操作并触发回调 */ async crudOperation(operation, entity, data) { try { const response = await fetch(`${this.baseUrl}/app/${operation}/${entity}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 自动同步数据 this.syncData(); // 触发操作成功的回调 this.triggerCallbacks(operation, entity, data); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } /** * 执行CRUD操作 * @param {string} operation - 'add', 'delete', 'update' * @param {string} entity - 实体名称单数性质(小写) * @param {Object} data - 要发送的数据 后端要求数据格式为{属性: "值", 关联对象: {id:0}, 关联对象集: [{id:0}]} * @returns {Promise<Object>} 响应结果 */ async crudOperation(operation, entity, data) { try { const response = await fetch(`${this.baseUrl}/app/${operation}/${entity}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 自动同步数据 this.syncQueue = this.syncQueue.then(async () => { await this.syncData(); // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, data); }); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } /** * 自动同步数据(防止频繁请求) */ async syncData() { if (this.isSyncing) { this.pendingSync = true; return; } this.isSyncing = true; try { await this.fetchAll(); } catch (error) { console.error('Sync failed:', error); } finally { this.isSyncing = false; // 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); } } } /** * 添加实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据 */ async addEntity(entity, data) { return this.crudOperation('add', entity, data); } /** * 更新实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据(必须包含id) */ async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } /** * 删除实体 * @param {string} entity - 实体名称单数性质 * @param {number} id - 实体ID */ async deleteEntity(entity, id) { return this.crudOperation('delete', entity, {id}); } /** * 新增方法:手动触发数据刷新 */ async refreshData() { return this.syncQueue = this.syncQueue.then(() => this.syncData()); } } export { DataManager }; // 创建单例实例 //const dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); //// 初始化时获取所有数据 //dataManager.fetchAll().then(() => { // console.log('Initial data loaded'); //}); // 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等 //export const data = dataManager.data; //// 导出操作方法 //export const addEntity = dataManager.addEntity.bind(dataManager); //export const updateEntity = dataManager.updateEntity.bind(dataManager); //export const deleteEntity = dataManager.deleteEntity.bind(dataManager); //export const fetchAll = dataManager.fetchAll.bind(dataManager); 根据DataManager.js填充test.html数据 js文件
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值