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

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解

Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。

核心特性与用法

基本属性

  • v-model:绑定右侧列表的值(key数组)

  • data:组件数据源,需包含 key 和 label 属性

  • props:配置数据源的字段别名

  • filterable:是否启用搜索功能

  • titles:自定义左右两侧标题

  • button-texts:自定义按钮文本

  • left-default-checked/right-default-checked:设置默认选中项

关键事件

  • change:当右侧列表变化时触发

  • left-check-change:左侧选中项变化时触发

  • right-check-change:右侧选中项变化时触发

插槽

  • 默认插槽:自定义列表项内容

  • left-footer/right-footer:自定义左右列表底部内容

filter-method 用法详解

1. 基本概念

filter-method 是 Element Plus Transfer 组件的一个属性,用于自定义穿梭框的搜索过滤逻辑。它接受一个函数,该函数有两个参数:

  • query: 用户输入的搜索关键词

  • item: 当前遍历的数据项

函数应返回布尔值:

  • true: 保留该项

  • false: 过滤掉该项

default 插槽用法详解

1. default 插槽基础用法

default 插槽允许完全自定义每个列表项的显示内容:

html

复制

下载

运行

<el-transfer><template #default="{ option }"><!-- 自定义内容 --><div>{{ option.label }}</div></template>
</el-transfer>

使用示例

MaterialApplyDialog.vue

<script setup lang="ts" name="MaterialApplyDialog">
import { ref } from "vue";// 模态框显示标识
const dialogVisible = ref(false);
interface Option {key: number;label: string;disabled: boolean;
}const generateData = () => {const data: Option[] = [];for (let i = 1; i <= 500; i++) {data.push({key: i,label: `Option${i}`,disabled: i % 4 === 0});}return data;
};const data = ref<Option[]>(generateData());
const value = ref([]);// 打开模态框
const openDialog = async () => {dialogVisible.value = true;
};// 隐藏模态框
const closeDialog = () => {dialogVisible.value = false;
};// 过滤方法
const filterMethod = (keywords: string, item: Option) => {// 默认的过滤方法,使用关键字与选项对象的label属性进行匹配// return item.label.toLowerCase().includes(keywords.toLowerCase());// 自定义过滤方法,搜索以关键字结尾的选项,区分大小写return item.label.endsWith(keywords);
};// 确定
const onConfirmClick = async () => {// 关闭模态框closeDialog();
};defineExpose({openDialog
});
</script><template><el-dialogclass="receive-dialog"title="穿梭框应用示例"width="1200px"top="0vh"style="border-radius: 10px"v-model="dialogVisible":close-on-press-escape="true":close-on-click-modal="false":show-close="true"@close="closeDialog"><template #default><el-container class="container"><el-transferclass="custom-transfer"v-model="value":data="data":titles="[`待选内容`, `已选内容`]":button-texts="[`移除`, `添加`]":filterable="true":filter-placeholder="`请输入关键字搜索以其结尾的内容`":filter-method="filterMethod" /></el-container></template><template #footer><div><el-button class="dialog-btn" type="primary" @click="onConfirmClick">确定</el-button><el-button class="dialog-btn" @click="closeDialog">取消</el-button></div></template></el-dialog>
</template><style scoped lang="scss">
/* 穿梭框容器样式 */
.container {width: 100%;height: 80vh;
}
/* 穿梭框样式 - 已通过 Element Plus v2.7.4 测试 */
.custom-transfer {flex: 1;display: flex;justify-content: space-between; /* 首尾元素贴边,中间元素等距 *//* 面板样式 */:deep(.el-transfer-panel) {/**如果所在容器没有设置justify-content: space-between; 又需要穿梭框占满容器,需通过浏览器调试工具,获取到穿梭框容器宽度为1168px,按钮区域占用200px,则面板宽度应该设置为 (1168-200)/2 = 484px,如果所在容器已经设置justify-content: space-between; 又需要穿梭框占满容器,面板宽度可以不用精细计算*/width: 450px;height: 100% !important;display: flex;flex-direction: column;}/* 面板头部样式 */:deep(.el-transfer-panel__header) {background-color: #d3e2f1;display: flex;}/* 面板主体 */:deep(.el-transfer-panel__body) {flex: 1;display: flex;flex-direction: column;}/* 列表区域 - 关键滚动区域 */:deep(.el-transfer-panel__list) {flex: 1;overflow-y: auto;}/* 按钮区域样式 */:deep(.el-transfer__buttons) {display: flex;flex-direction: row; /* 水平排列 */justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */padding: 0 10px;}/* 按钮样式 */:deep(.el-transfer__buttons .el-button) {margin: 0 10px;width: 70px;padding: 8px 15px;/* 蓝色渐变背景 */// background: linear-gradient(135deg, #409eff 0%, #3375b9 100%);// border: none;// color: white;// box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);}/* 按钮方向指示 */:deep(.el-transfer__buttons .el-button:first-child::after) {content: "<=";}:deep(.el-transfer__buttons .el-button:last-child::after) {content: "=>";}/* 按钮文字提示 */:deep(.el-transfer__buttons .el-button span) {display: none; /* 隐藏按钮文字 */}
}
.dialog-btn {width: 100px;
}
</style>

应用效果:

项目实例

MaterialApplyDialog.vue

特点:

1、自定义过滤方法 filter-method

2、数据项属性别名 props

3、插槽 default

4、插槽 left-footer

5、输入框控制数字输入

6、遍历数组元素检查数据合法性,聚焦元素,全选元素内容

7、结合实际情况调整样式

<script setup lang="ts" name="ReagentApplyDialog">
import { branchWarehouseApplyGenerateForReagentService } from "@/api/branchWarehouse";
import { useReagentOptionList } from "@/hooks/useReagentOptionList";
import { formatToNumber } from "@/utils/formatter";
import { Search } from "@element-plus/icons-vue";
import type { TransferInstance } from "element-plus";
import { ElMessage } from "element-plus";
import { debounce } from "lodash-es";
import { nextTick, ref } from "vue";
import type { IReagentOption } from "../types";// 模态框显示标识
const dialogVisible = ref(false);
// 试剂选项列表,组合式函数 hook
const { reagentOptionList, fetchReagentOptionList, resetReagentOptionData } = useReagentOptionList();
// 搜索内容
const searchVal = ref("");
// 已选试剂id集合
const selectedOptionIds = ref<number[]>([]);
// 穿梭框实例对象
const transferRef = ref<TransferInstance | null>(null);// 打开模态框
const openDialog = async () => {initPageData();await nextTick();dialogVisible.value = true;
};// 隐藏模态框
const closeDialog = () => {dialogVisible.value = false;initPageData();
};// 过滤方法
const filterMethod = (keywords: string, item: IReagentOption) => {// 默认的过滤方法,使用关键字与选项对象的label属性进行匹配return item.reagentName.toLowerCase().includes(keywords.toLowerCase());// 自定义过滤方法,搜索以关键字结尾的选项,区分大小写// return item.reagentName.endsWith(keywords);
};// 确定
const onConfirmClick = async () => {// 检查数据合法性if (!checkValid()) {return;}let selectedOptions = selectedOptionIds.value.map((id) => reagentOptionList.value.find((option) => option.id === id)).filter((option): option is IReagentOption => !!option); // 过滤掉 undefined 并缩小类型// 生成申领单if (selectedOptions.length > 0) {await branchWarehouseApplyGenerateForReagentService(selectedOptions);}// 关闭模态框closeDialog();
};// 检查数据合法性
const checkValid = () => {if (selectedOptionIds.value.length === 0) {ElMessage.warning("请选择试剂");return false;}// 循环遍历已选试剂for (let i = 0; i < selectedOptionIds.value.length; i++) {let option = reagentOptionList.value.find((option) => option.id === selectedOptionIds.value[i]);if ((option?.applyAmount ?? 0) === 0 || (option?.applyAmount ?? 0) > option?.amount!) {if ((option?.applyAmount ?? 0) === 0) ElMessage.warning("请输入申领数量!");else ElMessage.error("申领数量不能大于库存数量!");document.getElementById(`input-apply-amount-${option?.id}`)?.focus();(document.getElementById(`input-apply-amount-${option?.id}`) as HTMLInputElement)?.select();return false;}}return true;
};// 搜索,加装防抖器,防抖处理(leading: true,立即执行、maxWait: 3000,3秒内至少执行一次)
const onSearchClick = debounce(async () => {// 清空已选试剂id集合selectedOptionIds.value = [];// 发送网络请求,获取试剂选项列表await fetchReagentOptionList(searchVal.value);},1000,{ leading: true, trailing: true, maxWait: 3000 }
);// 页面初始化
const initPageData = () => {// 清空左侧过滤框transferRef.value?.clearQuery("left");// 清空右侧过滤框transferRef.value?.clearQuery("right");// 清空搜索框searchVal.value = "";// 清空已选试剂id集合selectedOptionIds.value = [];// 重置试剂选项数据resetReagentOptionData();
};defineExpose({openDialog
});
</script><template><el-dialogclass="receive-dialog"title="试剂耗材申领"width="1200px"top="0vh"style="border-radius: 10px"v-model="dialogVisible":close-on-press-escape="true":close-on-click-modal="false":show-close="true"@close="closeDialog"><template #default><el-container class="container"><el-transferref="transferRef"class="custom-transfer"v-model="selectedOptionIds":data="reagentOptionList":props="{key: `id`,label: `reagentName`}":titles="[`待选试剂`, `已选试剂`]":button-texts="[`移除`, `添加`]":filterable="reagentOptionList.length > 12":filter-placeholder="`请输入关键字搜索试剂`":filter-method="filterMethod"><!-- 自定义列表数据项的内容 --><template #default="{ option }"><div class="transfer-list-option"><div class="transfer-list-option-left"><el-tag type="primary">{{ (option as IReagentOption).reagentName }}</el-tag><el-tag type="info" v-if="(option as IReagentOption).batchNo">{{(option as IReagentOption).batchNo}}</el-tag></div><div class="transfer-list-option-right"><el-tag type="warning">{{ (option as IReagentOption).validityDate }}</el-tag><el-tag class="transfer-list-option-right-amount" type="success">{{(option as IReagentOption).amount}}</el-tag><el-inputv-if="selectedOptionIds.includes((option as IReagentOption).id)":id="`input-apply-amount-${(option as IReagentOption).id}`"class="input-apply-amount"style="width: 85px; text-align: center"v-model="(option as IReagentOption).applyAmount"placeholder="输入申领数量"size="small"clearable@input="(option as IReagentOption).applyAmount = Number(formatToNumber($event, 0))" /></div></div></template><!-- 自定义左侧列表底部的内容 --><template #left-footer><div class="transfer-left-footer"><el-input v-model="searchVal" placeholder="请输入试剂名称" clearable @keydown.enter="onSearchClick"><template #prepend>查找试剂:</template><template #append><el-button :icon="Search" @click="onSearchClick" /></template></el-input></div></template><!-- 自定义右侧列表底部的内容 --><!-- <template #right-footer><div><span>可以自定义右侧列表底部的内容</span></div></template> --></el-transfer></el-container></template><template #footer><div><el-button class="dialog-btn" type="primary" @click="onConfirmClick">确定</el-button><el-button class="dialog-btn" @click="closeDialog">取消</el-button></div></template></el-dialog>
</template><style scoped lang="scss">
/* 穿梭框容器样式 */
.container {width: 100%;height: 80vh;
}
/* 穿梭框样式 - 已通过 Element Plus v2.7.4 测试 */
.custom-transfer {flex: 1;display: flex;justify-content: space-between; /* 首尾元素贴边,中间元素等距 *//* 面板样式 */:deep(.el-transfer-panel) {/**如果所在容器没有设置justify-content: space-between; 又需要穿梭框占满容器,需通过浏览器调试工具,获取到穿梭框容器宽度为1168px,按钮区域占用200px,则面板宽度应该设置为 (1168-200)/2 = 484px,如果所在容器已经设置justify-content: space-between; 又需要穿梭框占满容器,面板宽度可以不用精细计算*/width: 550px;height: 100% !important;display: flex;flex-direction: column;}/* 面板头部样式 */:deep(.el-transfer-panel__header) {background-color: #f5f7fa;display: flex;}/* 面板主体 */:deep(.el-transfer-panel__body) {flex: 1;display: flex;flex-direction: column;}/* 列表区域 - 关键滚动区域 */:deep(.el-transfer-panel__list) {flex: 1;overflow-y: auto;}/* 列表选项 */:deep(.el-transfer-panel__item) {flex: 1;display: flex;align-items: center; /* 垂直居中 */margin: 0;padding-right: 15px;height: 32px;}/* 列表选项 - 最后一个选项 */:deep(.el-transfer-panel__item:last-child) {padding-right: 15px;}/* 按钮区域 */:deep(.el-transfer__buttons) {display: flex;flex-direction: column-reverse; /* 垂直反序排列 */justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */padding: 0;}/* 按钮 */:deep(.el-transfer__buttons .el-button) {margin: 20px 10px;width: 40px;padding: 8px 15px;/* 蓝色渐变背景 */// background: linear-gradient(135deg, #409eff 0%, #3375b9 100%);// border: none;// color: white;// box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);}/* 按钮文字 */:deep(.el-transfer__buttons .el-button span) {display: none; /* 隐藏按钮文字 */}/* 按钮内容 */:deep(.el-transfer__buttons .el-button:first-child::after) {content: "<="; /* 设置按钮显示内容为 <= */}:deep(.el-transfer__buttons .el-button:last-child::after) {content: "=>"; /* 设置按钮显示内容为 => */}.transfer-list-option {flex: 1;display: flex;flex-direction: row; /* 水平排列 */align-items: center; /* 垂直居中 */height: 32px;&-left {flex: 1;display: flex;justify-content: start; /* 贴左边 */align-items: center; /* 垂直居中 */max-width: 220px;}&-right {flex: 1;display: flex;justify-content: end; /* 贴右边 */align-items: center; /* 垂直居中 */&-amount {width: 40px;}.input-apply-amount {width: 85px;// 输入框的内容居中& :deep(.el-input__inner) {text-align: center;}}}.el-tag {font-size: 14px;}}.transfer-left-footer {display: flex;height: 100%;}
}
.dialog-btn {width: 100px;
}
</style>

应用效果:

相关文章:

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...