vue3 + ts + element-plus 二次封装 el-table
一、实现效果:
(1)数据为空时:
(2)有数据时:存在数据合并;可自定义表头和列的内容
(3)新增行:
(4)删除行:
(5)双击编辑单元格内容:
二、组件代码:
(1)components / CustomTable / index.vue
<template><div class="custom-table-dialog"><el-table :data="paginatedData" border :span-method="spanMethod"highlight-current-row @row-click="rowClick" @cell-dblclick="cellDbClick"@selection-change="handleSelection" :header-row-style="props?.headerRowStyle":header-cell-style="props?.headerCellStyle":row-style="props?.rowStyle" :cell-style="props?.cellStyle" :empty-text="props.emptyText"><!-- 多选 --><el-table-column v-if="isSelection" type="selection" width="55" align="center"></el-table-column><template v-for="column in columnList" :key="column.label"><custom-table-column :column="column"><template v-slot:[`header-${column.prop}`]="scope"><slot :name="`header-${column.prop}`" v-bind="scope"></slot></template><template v-slot:[`default-${column.prop}`]="scope"><slot :name="`default-${column.prop}`" v-bind="scope"/></template></custom-table-column></template></el-table><el-paginationsize="small":hide-on-single-page="true"backgroundlayout="prev, pager, next":total="tableData.length":current-page="currentPage":page-size="pageSize"@current-change="handlePageChange"/></div></template><script setup lang="ts">import CustomTableColumn from "@/components/CustomTable/components/CustomTableColumn.vue";
import {computed, ref} from "vue";
import type {ColumnItem} from "@/types/table";
import EventBus from "@/plugins/event-bus";const props = defineProps<{tableData: any[] // 表格数据columnList: ColumnItem[] // 表头数据pageSize: number // 每页显示条数selection?: boolean // 是否多选merge?: boolean // 是否合并mergeColumns?: string[] // 哪些列中的单元格需要合并distinguishColumns?: string[] // 哪些列中单元格的值不一样,就不合并headerRowStyle?: any // 表头行样式headerCellStyle?: any // 表头单元格样式rowStyle?: any // 行样式cellStyle?: any // 单元格样式emptyText?: string // 空数据时显示的文本内容
}>()const currentPage = ref(1)
const pageSize = ref(props.pageSize)const paginatedData = computed(() => { // 分页数据const start = (currentPage.value - 1) * pageSize.valueconst end = start + pageSize.valuereturn props.tableData.slice(start, end)
})const isSelection = computed(() => { // 是否多选(勾选行)let selection = falseif (props.selection) {selection = props.selection}return selection
})const colFields = computed(() => { // 所有列的 propslet fields: string[] = []const properties = props.columnList.map((item: any) => {return item.prop})if (props.selection) {fields.push('')fields.push(...properties)} else {fields = properties}return fields
})
let spanArr: any[] = [] //存储合并单元格的开始位置const handlePageChange = (page: number) => {currentPage.value = page
}/* 行点击事件 */
const rowClick = (row: any, column: any) => {EventBus.emit('row-click', {row, column})
}/* 单元格双击事件 */
const cellDbClick = (row: any, column: any) => {EventBus.emit('cell-dbClick', {row, column})
}/* 行选择事件 */
const handleSelection = (data: any) => { // data 为所有处于勾选状态的行的数组EventBus.emit('row-selection', data)
}// 分析每一列,找出相同的
const getSpanArr = () => {let mergeColumns: string[] = []let distinguishColumns: string[] = []if (props.mergeColumns) {mergeColumns = props.mergeColumns}if (props.distinguishColumns) {distinguishColumns = props.distinguishColumns}for (let i = 0; i < paginatedData.value.length; i++) {let row = i;// let col = i % this.colCount;if (row === 0) {// i 表示行 j表示列for (let j = 0; j < colFields.value.length; j++) {spanArr[i * colFields.value.length + j] = {rowspan: 1,colspan: 1,}}} else {for (let j = 0; j < colFields.value.length; j++) {// 当前和上一次的一样// 合并所有列的相同数据单元格if (mergeColumns.includes(colFields.value[j])) { // Check if the column is in mergeColumnsif (distinguishColumns.some(col => paginatedData.value[row][col] !== paginatedData.value[row - 1][col])) {// If any distinguish column is different, do not mergespanArr[row * colFields.value.length + j] = {rowspan: 1,colspan: 1,}} else if (paginatedData.value[row][colFields.value[j]] === paginatedData.value[row - 1][colFields.value[j]]) {let beforeItem =spanArr[(row - 1) * colFields.value.length + j]spanArr[row * colFields.value.length + j] = {rowspan: 1 + beforeItem.rowspan, // Merge rowscolspan: 1, // Merge columns}beforeItem.rowspan = 0beforeItem.colspan = 0} else {// No mergespanArr[row * colFields.value.length + j] = {rowspan: 1,colspan: 1,}}}}}}// 对数据进行倒序let stack = []for (let i = 0; i < colFields.value.length; i++) {for (let j = 0; j < paginatedData.value.length; j++) {// console.log("i=" + i + " j=" + j);// i 表示列 j表示行if (j === 0) {if (spanArr[j * colFields.value.length + i].rowspan === 0) {stack.push(spanArr[j * colFields.value.length + i])}} else {if (spanArr[j * colFields.value.length + i]?.rowspan === 0) {stack.push(spanArr[j * colFields.value.length + i])} else {stack.push(spanArr[j * colFields.value.length + i])while (stack.length > 0) {let pop = stack.pop()let len = stack.lengthspanArr[(j - len) * colFields.value.length + i] = pop}}}}}
}const spanMethod = (data: { row: any, column: any, rowIndex: any, columnIndex: any }) => {if (props.merge) {getSpanArr()return spanArr[data.rowIndex * colFields.value.length + data.columnIndex]} else {return}
}/*// 合并固定列
const spanMethod = (data: { row: any, column: any, rowIndex: any, columnIndex: any }) => {if (data.column.property === 'column1') { // 指定列相邻单元格的值相等就合并const currentValue = data.row[data.column.property] // 当前单元格的值const preRow = props.tableData[data.rowIndex - 1] // 上一行const preValue = preRow ? preRow[data.column.property] : null // 上一行相同列的值if (currentValue === preValue) { // 将当前单元格隐藏return {rowspan: 0,colspan: 0}} else { // 合并 —— 计算当前单元格应该跨多少行let rowSpan = 1 // 初始跨 1 行for (let i = data.rowIndex + 1; i < props.tableData.length; i++) {const nextRow = props.tableData[i] // 下一行const nextValue = nextRow ? nextRow[data.column.property] : null // 下一行相同列的值if (nextValue === currentValue) {rowSpan++} else {break}}return {rowspan: rowSpan,colspan: 1}}}
}*/</script><style lang="scss">.custom-table-dialog {//height: 100%;height: fit-content;display: flex;flex-direction: column;align-items: center;justify-content: center;//border: 1px solid red;.el-table {--el-table-border-color: rgba(218, 226, 237); // 边框颜色--el-table-bg-color: transparent;--el-table-text-color: rgba(165, 176, 193); // 表格数据部分文字颜色--el-table-header-text-color: rgba(251, 251, 251); // 表头文字颜色--el-table-row-hover-bg-color: rgba(252, 250, 255); // 鼠标悬浮时表行的背景色--el-table-header-bg-color: rgba(201, 213, 229); // 表头背景色--el-table-tr-bg-color: rgba(255, 255, 255); // 表格数据部分表行背景色background-color: transparent;.el-table__body tr.current-row > td.el-table__cell { // 高亮行单元格的背景色background: rgba(252, 250, 255);}.el-table__empty-block { // 数据为空时 表格 body 的样式background-color: #FFFFFF;}}.el-checkbox__input.is-checked .el-checkbox__inner {background-color: rgba(192, 172, 233);border-color: rgba(192, 172, 233);}.el-checkbox__input.is-indeterminate .el-checkbox__inner {background-color: rgba(192, 172, 233);border-color: rgba(192, 172, 233);}.el-checkbox__inner:hover {border-color: rgba(192, 172, 233);}//:deep(.custom-table-dialog .el-pagination) {// //margin-top: 100px;// position: absolute;// left: 50%;// transform: translateX(-50%);// bottom: 20px;//}.el-pagination { /* 如要固定分页器的位置在容器底部,在父组件中使用:deep(.custom-table-dialog .el-pagination) {}修改,示例如上 */margin-top: 10px;}.el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {background-color: rgba(201, 213, 229);color: rgba(251, 251, 251);}.el-pagination.is-background .btn-next.is-active, .el-pagination.is-background .btn-prev.is-active, .el-pagination.is-background .el-pager li.is-active {background: rgba(192, 172, 233);}}</style>
(2)components / CustomTable / components / CustomTableColumn.vue
<template><el-table-column v-if="column.children?.length" v-bind="getColumnProps(column)"><template #header="scope"><slot :name="`header-${column.prop}`" v-bind="scope"><span>{{ column.label }}</span></slot></template><template v-for="child in column.children" :key="child.label"><custom-table-column :column="child"/></template></el-table-column><el-table-column v-else v-bind="getColumnProps(column)"><template #header="scope"><slot :name="`header-${column.prop}`" v-bind="scope"><span>{{ column.label }}</span></slot></template><template #default="scope"><slot :name="`default-${column.prop}`" v-bind="scope"><span>{{ scope.row[column.prop] }}</span></slot></template></el-table-column></template><script setup lang="ts">import type {ColumnItem} from "@/types/table";defineProps<{column: ColumnItem
}>()const getColumnProps = (column: ColumnItem) => {const {children, ...props} = columnreturn props
}</script><style scoped lang="scss"></style>
(3)types / table.ts
/*
* 表列属性【 ?. 代表非必传,否则必传】
* */
export interface ColumnItem {label: string,prop: string,children?: ColumnItem[],align?: string, // 对齐方式width?: string | number, // 宽度sortable?: boolean | string, // 对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件/* 对象可以具有任意数量的键,这些键的类型为 string,对应的值的类型为 any */[key: string]: any
}export enum TableSize {Large = 'large',Default = 'default',Small = 'small',
}
(4) plugins / event-bus.ts
import mitt from 'mitt' // 首先 npm install mitt
const EventBus = mitt()
export default EventBus
三、使用代码:
MyTable.vue
<template><!-- 二次封装 el-table --><div class="custom-table-container"><div class="table-header"><div>title</div><div class="table-buttons"><div class="table-button" @click="addRow"><el-icon><Plus/></el-icon></div><div class="table-button" @click="deleteRows"><el-icon><Delete/></el-icon></div></div></div><custom-table :column-list="columnList" :page-size="15" :table-data="tableData" :selection="true" :merge="true":merge-columns="mergeColumns" :distinguish-columns="distinguishColumns" empty-text="Please set Data"><!-- 自定义表头单元格内容示例 --><template #header-id="{row, column}">{{ column.label }} Here</template><!-- 自定义列内容示例 --><template #default-column1="{row, column}"><el-input ref="inputRef" v-model="row.column1"v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"size="small"/><span v-else>{{ row.column1 }}</span></template><template #default-number1="{row, column}"><el-input ref="inputRef" v-model="row.number1"v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"size="small"/><span v-else>{{ row.number1 }}</span></template><template #default-select1="{row, column}"><el-select ref="inputRef" v-model="row.select1"v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"size="small"><el-optionv-for="item in options":key="item.value":label="item.label":value="item.value"/></el-select><span v-else>{{ row.select1 }}</span></template></custom-table></div></template><script setup lang="ts">import CustomTable from "@/components/CustomTable/index.vue";
import type {ColumnItem} from "@/types/table";
import {nextTick, onMounted, ref} from "vue";
import EventBus from "@/plugins/event-bus";
import {Delete, Plus} from "@element-plus/icons-vue";
import {ElMessage} from "element-plus";const columnList: ColumnItem[] = [{label: 'id',prop: 'id',align: 'center'},{label: 'column1',prop: 'column1',align: 'center',width: 100},{label: 'number1',prop: 'number1',align: 'center',width: 100},{label: 'select1',prop: 'select1',align: 'center'},{label: 'time1',prop: 'time1',align: 'center'},{label: 'time2',prop: 'time2',align: 'center'}
]const mergeColumns = ['column1', 'select1'] // Specify merge columns
const distinguishColumns = ['column1'] // Specify distinguish columnsconst headerCellStyle = (row: any) => { // 表头单元格样式示例return {backgroundColor: 'lightpink'}
}const rowStyle = (data: any) => { // 行样式示例if (data.row.column1 === 'row1') {return {backgroundColor: 'lightpink'}} else {return {backgroundColor: 'lightgreen'}}
}const tableData = ref<any[]>([ // 表格数据{id: 1,column1: 'row1',number1: 1,select1: 'option1',time1: 'test',time2: 'test'},{id: 2,column1: 'row1',number1: 2,select1: 'option1',time1: 'test',time2: 'test'},{id: 3,column1: 'row2',number1: 3,select1: 'option1',time1: 'test',time2: 'test'},{id: 4,column1: 'row2',number1: 4,select1: 'option1',time1: 'test',time2: 'test'},{id: 5,column1: 'row3',number1: 4,select1: 'option1',time1: 'test',time2: 'test'},{id: 6,column1: 'row4',number1: 5,select1: 'option1',time1: 'test',time2: 'test'}
])const options = [{value: 'option1',label: 'option1'},{value: 'option2',label: 'option2'}
]const editRow = ref<any>(null) // 正在编辑的行
const editColumn = ref<any>(null) // 正在编辑的列
const inputRef = ref<any>(null)const selectedRows = ref<any[]>([]) // 选中的行onMounted(() => {EventBus.on('cell-dbClick', (data: any) => { // 单元格双击事件editRow.value = nulleditColumn.value = nulleditRow.value = data.row.ideditColumn.value = data.column.idnextTick(() => {inputRef.value.focus() // 输入框自动聚焦})})
})const stopEdit = () => { // 停止编辑editRow.value = nulleditColumn.value = nullinputRef.value = null/* 每次编辑后根据 column1 的内容重新排序 */const groupedTableData = tableData.value.reduce((acc, curr) => {(acc[curr.column1] = acc[curr.column1] || []).push(curr)return acc}, {})tableData.value = []Object.keys(groupedTableData).forEach((key: any) => {tableData.value.push(...groupedTableData[key])})
}onMounted(() => {EventBus.on('row-selection', (data: any) => { // 行选择事件selectedRows.value = data})
})const addRow = async () => { // 新增行const rowData = {id: tableData.value.length + 1,column1: '',number1: '',select1: '',time1: '',time2: ''}tableData.value.push(rowData)
}const deleteRows = () => { // 删除行if (selectedRows.value.length > 0) {selectedRows.value.forEach((item: any) => {tableData.value = tableData.value.filter((data: any) => data.id !== item.id)})} else {ElMessage.error('Please select the row to delete')}
}</script><style scoped lang="scss">.custom-table-container {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);background: rgba(233, 237, 246);padding: 20px;.table-header {background: rgba(200, 180, 243);color: rgba(254, 255, 253);font-family: Consolas;font-size: 20px;font-weight: bolder;display: flex;justify-content: space-between;align-items: center;padding: 10px 15px;}.table-buttons {display: flex;.table-button {color: rgba(255, 254, 254);background: rgba(192, 172, 233);font-size: 20px;font-family: Consolas;width: fit-content;padding: 10px;margin-right: 10px;cursor: pointer;}.table-button:last-child { // 最右边的按钮 margin-right = 0margin-right: 0;}}}</style>
四、参考文章
el-table表格动态合并相同数据单元格(可指定列+自定义合并)_el-table 合并单元格动态-CSDN博客
相关文章:

vue3 + ts + element-plus 二次封装 el-table
一、实现效果: (1)数据为空时: (2)有数据时:存在数据合并;可自定义表头和列的内容 (3)新增行: (4)删除行: &a…...
python传递json参数给php
python传递json参数给php 在Python中,你可以使用requests库来发送JSON数据给一个PHP脚本。以下是一个简单的例子: 首先,安装requests库(如果你还没有安装的话): pip install requests 然后,…...

2.若依vue表格数据根据不同状态显示不同颜色style
例如国标显示蓝色,超标是红色 使用是蓝色,未使用是绿色 <el-table-column label"外卖配送是否完成评价" align"center" prop"isOverFlag"> <template slot-scope"scope"> …...

JZ2440开发板——LCD
以下内容源于韦东山嵌入式课程的学习与整理,如有侵权请告知删除。 之前在博文中学习过LCD(SoC是S5PV210),作为对比,本文学习S3C2440这款SoC的LCD方面的内容。主要涉及以下三个内容: 一、LCD的硬件原理 1.…...
YOLOv6-4.0部分代码阅读笔记-yolo_lite.py
yolo_lite.py yolov6\models\yolo_lite.py 所需的库和模块 #!/usr/bin/env python3 # -*- coding:utf-8 -*- import math import torch import torch.nn as nn import torch.nn.functional as F from yolov6.layers.common import * from yolov6.utils.torch_utils import i…...

奇瑞汽车:降阶模型在新能源汽车热管理仿真上的应用
随着新能源汽车的发展,对仿真技术的要求也越来越高。那么奇瑞汽车利用降阶模型在新能源汽车热管理仿真上做了哪些应用呢?本次内容主要从四个方面展开介绍: 1、 奇瑞汽车简介; 2、 热管理降阶模型开发的背景; 3、 高低…...
传统的自然语言处理评估指标
目录 传统的自然语言处理评估指标 EM(Exact Match) BLEU(Bilingual Evaluation Understudy) 传统的自然语言处理评估指标 传统评估指标 EM(Exact Match) 计算方式:如果生成的答案与参考答案完全相同(字符级完全匹配),则 EM 得分为 1,否则为 0。这是一种比较严格的…...

WPF+MVVM案例实战(十七)- 自定义字体图标按钮的封装与实现(ABC类)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、案例效果1、按钮分类2、ABC类按钮实现1、文件创建2、字体图标资源3、自定义依赖属性4、按钮特效样式实现 3、按钮案例演示1、页面实现与文件创建2、依赖注入3 运…...

Redis数据结构:List类型全面解析
文章目录 一、List数据类型1.1 简介1.2 应用场景1.3 底层结构 二、数据结构2.1 压缩列表ZipList2.2 双向链表LinkedList(后续已废弃)2.3 快速链表QuickList 三、List常见命令 一、List数据类型 1.1 简介 详细介绍:Redis五种数据类型、Strin…...

人工智能证书合集
本文将对目前市面上主流官方机构颁发的人工智能证书进行整理和介绍,由于整理的证书较多,本文共一万八千多字,请根据自己的考证需求阅读对应部分的内容,希望本文对人工智能行业的从业人员和计划从事人工智能相关岗位工作的人员有所…...
php开发实战分析(8):优化MySQL分页查询与数量统计,提升数据库性能
在开发过程中,我们遇到了一段用于从数据库中查询部门信息的PHP代码。该代码负责根据不同的条件(如部门名称和来源)筛选数据,并返回分页结果及总记录数。然而,原始代码存在一些问题,包括重复的查询条件构建逻…...

shell脚本案例:RAC配置多路径时获取磁盘设备WWID和磁盘大小
使用场景 在RAC配置多路径时,需要获取到磁盘设备的wwid。因为RAC的磁盘配置是提前规划好的,只知道wwid,不知道磁盘对应大小,是不知道应该如何配置多路径的mutipath.conf文件的;而凭借肉眼手工去对应磁盘设备的wwid和大…...

Android Framework AMS(10)广播组件分析-1
该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要解读应用层广播组件的发送广播和接收处理广播 2个过程,以及从APP层到AMS调用之间的打通。关注思维导图中左上部分即可。 有…...
在 Node.js 中使用 .env 文件
什么是 .env 文件? 文件.env是包含环境变量键值对的简单文本文件。此文件的内容不会被签入源代码管理,从而确保敏感数据的安全。 示例 PORT 4000 DATABASE_URL mongodb://localhost: 27017 /mydb API_KEY abcd1234 NODE_ENV development 在 Node.…...
CesiumJS 案例 P19:添加矩形、监听鼠标左击、监听鼠标右击、监听鼠标移动
CesiumJS CesiumJS API:https://cesium.com/learn/cesiumjs/ref-doc/index.html CesiumJS 是一个开源的 JavaScript 库,它用于在网页中创建和控制 3D 地球仪(地图) 一、添加矩形 <!DOCTYPE html> <html lang"en&…...

路测毫米波雷达标定和目标跟踪
1 2 3 4 5 6 查找匹配时,先对数据排序。逐帧对数据处理,运行速度快。单帧有噪点,多帧处理,准确率更高一些。 7 8 9 10 参考 路侧毫米波雷达标定与目标跟踪哔哔哩_bilibili路侧毫米波雷达标定与目标跟踪, 视频播放量 5855、弹幕量…...
【sqlmap使用手册-持续更新中】
SQLMap 简介 SQLMap 是一个开源的渗透测试工具,用于自动化检测和利用 SQL 注入漏洞。它支持多种数据库,包括 MySQL、PostgreSQL、Oracle、SQL Server 等。 可以通过以下命令安装sqlmap git clone https://github.com/sqlmapproject/sqlmap.git最常用的…...

面向对象三大特征之一:封 装
1、特点 封装是面向对象的核心思想,两层含义:一是一个整体(把对象的属性和行为看成一个整体,即封装在一个对象种),二是信息隐藏,对外隐藏,但可以通过某种方式进行调用。 2、访问权…...

qt QMenuBar详解
1、概述 QMenuBar是Qt框架中用于创建菜单栏的类,它继承自QWidget。QMenuBar通常位于QMainWindow对象的标题栏下方,用于组织和管理多个QMenu(菜单)和QAction(动作)。菜单栏提供了一个水平排列的容器&#x…...

ESP32的下的蓝牙应用笔记(1)——Beacon蓝牙信标
Beacon蓝牙信标简介 Beacon蓝牙信标是一种基于蓝牙低功耗(BLE)技术的设备,主要用于提供位置信息和数据传输服务。它通过周期性地广播信号,能够在一定范围内与其他蓝牙设备进行通信,从而提供精准的位置信息和相关服…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...