vue 使用 ztree 超大量数据,前端树形结构展示

ztree 是一个很经典的基于jquey开发的树结构编辑展示UI组件库。

创建一个文件 ztree.vue,代码如下:

<template><div><div class="ztree vue-giant-tree" :id="ztreeId"></div><div class="treeBox"><span slot="footer" class="dialog-footer"><el-buttontype="primary"@click="pushHandle"style="background: #e64e3f; border: none">推 送</el-button></span></div></div>
</template>
<script>
import * as $ from "jquery";
if (!window.jQuery) {window.jQuery = $;
}
require("@ztree/ztree_v3/js/jquery.ztree.all");
export default {props: {setting: {type: Object,require: false,default: function () {return {};},},nodes: {type: Array,require: true,default: function () {return [];},},},data() {return {ztreeId: "ztree_" + parseInt(Math.random() * 1e10),ztreeObj: null,list: [],ztreeSetting: {view: {showIcon: false, // default to hide icon},callback: {onAsyncError: (...arg) => {this.$emit("onAsyncError", ...arg);},onAsyncSuccess: (...arg) => {this.$emit("onAsyncSuccess", ...arg);},onCheck: (...arg) => {this.$emit("onCheck", ...arg);},onClick: (...arg) => {this.$emit("onClick", ...arg);},onCollapse: (...arg) => {this.$emit("onCollapse", ...arg);},onDblClick: (...arg) => {this.$emit("onDblClick", ...arg);},onDrag: (...arg) => {this.$emit("onDrag", ...arg);},onDragMove: (...arg) => {this.$emit("onDragMove", ...arg);},onDrop: (...arg) => {this.$emit("onDrop", ...arg);},onExpand: (...arg) => {this.$emit("onExpand", ...arg);},onMouseDown: (...arg) => {this.$emit("onMouseDown", ...arg);},onMouseUp: (...arg) => {this.$emit("onMouseUp", ...arg);},onRemove: (...arg) => {this.$emit("onRemove", ...arg);},onRename: (...arg) => {this.$emit("onRename", ...arg);},onRightClick: (...arg) => {this.$emit("onRightClick", ...arg);},},},};},methods: {pushHandle() {var zTree = $.fn.zTree.getZTreeObj(this.ztreeId);var dataNodes = [],nodes = zTree.getCheckedNodes(true);var users = "";if (0 === nodes.length) {this.$alert("请选择", "提示", {confirmButtonText: "确定",callback: (action) => {},});return;}let count = 0;for (var i = 0; i < nodes.length; i++) {if (nodes[i].is_last == 1) {dataNodes.push(nodes[i].id);users += nodes[i].id + ",";}count++;if (count >= nodes.length) {if (dataNodes.length == 0) {this.$alert("请选择人员", "提示", {confirmButtonText: "确定",callback: (action) => {},});return;} else {users = users.slice(0, -1);this.$emit("pushHandleData", users);}}}},},watch: {nodes: {handler: function (nodes) {this.list = nodes;// update treeif (this.ztreeObj) {this.ztreeObj.destroy();}this.$nextTick(() => {this.ztreeObj = $.fn.zTree.init($("#" + this.ztreeId),Object.assign({}, this.ztreeSetting, this.setting),this.list);// var zTree = $.fn.zTree.getZTreeObj(this.ztreeId);// var datas = nodes.split(',');// for (let i = 0; i < datas.length; i++) {//   var node = zTree.getNodesByParam("id", datas[i], null)[0];//根据id获取节点//   zTree.checkNode(node, true, true);//选中节点// zTree.setChkDisabled(node, true);// 禁止勾选节点// }this.$emit("onCreated", this.ztreeObj);});},deep: true,immediate: true,},},
};
</script><style>
/* beauty ztree! */
.ztree {text-align: left;font-size: 14px;
}
.treeBox {display: flex;justify-content: center;margin-top: 10px;
}
.vue-giant-tree li {list-style-type: none;white-space: nowrap;outline: none;
}
.vue-giant-tree li ul {position: relative;padding: 0 0 0 20px;margin: 0;
}
.vue-giant-tree .line:before {position: absolute;top: 0;left: 10px;height: 100%;content: "";border-right: 1px dotted #dbdbdb;
}
.vue-giant-tree .roots_docu:before,
.vue-giant-tree .roots_docu:after,
.vue-giant-tree .center_docu:before,
.vue-giant-tree .bottom_docu:before,
.vue-giant-tree .center_docu:after,
.vue-giant-tree .bottom_docu:after {position: absolute;content: "";border: 0 dotted #dbdbdb;
}
.vue-giant-tree .roots_docu:before {left: 10px;height: 50%;top: 50%;border-left-width: 1px;
}
.vue-giant-tree .roots_docu:after {top: 50%;left: 11px;width: 50%;border-top-width: 1px;
}
.vue-giant-tree .center_docu:before {left: 10px;height: 100%;border-left-width: 1px;
}
.vue-giant-tree .center_docu:after {top: 50%;left: 11px;width: 50%;border-top-width: 1px;
}
.vue-giant-tree .bottom_docu:before {left: 10px;height: 50%;border-left-width: 1px;
}
.vue-giant-tree .bottom_docu:after {top: 50%;left: 11px;width: 50%;border-top-width: 1px;
}
.vue-giant-tree li a {display: inline-block;line-height: 22px;height: 22px;margin: 0;cursor: pointer;transition: none;vertical-align: middle;color: #555555;
}
.vue-giant-tree .node_name {display: inline-block;padding: 0 3px;border-radius: 4px;
}
.vue-giant-tree .curSelectedNode .node_name {color: #000;background-color: #c9e9f7;
}
.vue-giant-tree .curSelectedNode_Edit {height: 20px;opacity: 0.8;color: #000;border: 1px #6cc2e8 solid;background-color: #9dd6f0;
}
.vue-giant-tree .tmpTargetNode_inner {opacity: 0.8;color: #fff;background-color: #4fcbf0;filter: alpha(opacity=80);
}
.vue-giant-tree .rename {font-size: 12px;line-height: 22px;width: 80px;height: 22px;margin: 0;padding: 0;vertical-align: top;border: 0;background: none;
}
.vue-giant-tree .button {position: relative;display: inline-block;line-height: 22px;height: 22px;width: 22px;cursor: pointer;text-align: center;vertical-align: middle;
}.vue-giant-tree .button.edit {color: #25ae88;
}
.vue-giant-tree .button.remove {color: #cb4042;
}
.vue-giant-tree .button.chk {position: relative;width: 14px;height: 14px;margin: 0 4px 0 0;border: 1px solid #d7dde4;border-radius: 2px;background: #fff;
}
.vue-giant-tree .chk.radio_true_full,
.vue-giant-tree .chk.radio_false_full,
.vue-giant-tree .chk.radio_true_full_focus,
.vue-giant-tree .chk.radio_false_full_focus,
.vue-giant-tree .chk.radio_false_disable,
.vue-giant-tree .chk.radio_true_disable,
.vue-giant-tree .chk.radio_true_part,
.vue-giant-tree .chk.radio_false_part,
.vue-giant-tree .chk.radio_true_part_focus,
.vue-giant-tree .chk.radio_false_part_focus {border-radius: 8px;
}
.vue-giant-tree .button.chk:after {position: absolute;top: 1px;left: 4px;width: 4px;height: 8px;content: "";transition: -webkit-transform 0.2s ease-in-out;transition: transform 0.2s ease-in-out;transition: transform 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out;-webkit-transform: rotate(0deg) scale(0);transform: rotate(0deg) scale(0);border-right: 2px solid #fff;border-bottom: 2px solid #fff;
}
.vue-giant-tree .button.checkbox_false_full_focus {border-color: #ccc;
}
.vue-giant-tree .button.checkbox_true_full,
.vue-giant-tree .button.checkbox_true_full_focus,
.vue-giant-tree .button.checkbox_true_part,
.vue-giant-tree .button.checkbox_true_part_focus,
.vue-giant-tree .button.checkbox_true_disable {border-color: #39f;background-color: #39f;
}
.vue-giant-tree .button.checkbox_true_full:after,
.vue-giant-tree .button.checkbox_true_full_focus:after,
.vue-giant-tree .button.checkbox_true_disable:after {-webkit-transform: rotate(45deg) scale(1);transform: rotate(45deg) scale(1);
}
.vue-giant-tree .button.checkbox_true_part:after,
.vue-giant-tree .button.checkbox_true_part_focus:after {top: 5px;left: 2px;width: 10px;height: 1px;-webkit-transform: rotate(0deg) scale(1);transform: rotate(0deg) scale(1);border-right: 0;
}
.vue-giant-tree .button.radio_true_full,
.vue-giant-tree .chk.radio_true_full_focus,
.vue-giant-tree .chk.radio_true_part,
.vue-giant-tree .chk.radio_true_part_focus {border-color: #39f;
}
.vue-giant-tree .button.radio_true_full:after,
.vue-giant-tree .chk.radio_true_full_focus:after,
.vue-giant-tree .chk.radio_true_part:after,
.vue-giant-tree .chk.radio_true_part_focus:after {top: 3px;left: 3px;width: 8px;-webkit-transform: rotate(0deg) scale(1);transform: rotate(0deg) scale(1);border: 0;border-radius: 4px;background: #39f;
}
.vue-giant-tree .button.checkbox_true_disable,
.vue-giant-tree .button.checkbox_false_disable,
.vue-giant-tree .chk.radio_false_disable,
.vue-giant-tree .chk.radio_true_disable {cursor: not-allowed;
}
.vue-giant-tree .button.checkbox_false_disable {background-color: #f3f3f3;
}
.vue-giant-tree .button.noline_close:before,
.vue-giant-tree .button.noline_open:before,
.vue-giant-tree .button.root_open:before,
.vue-giant-tree .button.root_close:before,
.vue-giant-tree .button.roots_open:before,
.vue-giant-tree .button.roots_close:before,
.vue-giant-tree .button.bottom_open:before,
.vue-giant-tree .button.bottom_close:before,
.vue-giant-tree .button.center_open:before,
.vue-giant-tree .button.center_close:before {position: absolute;top: 5px;left: 5px;content: "";transition: -webkit-transform ease 0.3s;transition: transform ease 0.3s;transition: transform ease 0.3s, -webkit-transform ease 0.3s;-webkit-transform: rotateZ(0deg);transform: rotateZ(0deg);-webkit-transform-origin: 25% 50%;transform-origin: 25% 50%;border: 6px solid;border-color: transparent transparent transparent #666;
}
.vue-giant-tree .button.noline_open:before,
.vue-giant-tree .button.root_open:before,
.vue-giant-tree .button.roots_open:before,
.vue-giant-tree .button.bottom_open:before,
.vue-giant-tree .button.center_open:before {-webkit-transform: rotateZ(90deg);transform: rotateZ(90deg);
}
.vue-giant-tree .button.ico_loading {margin-right: 2px;background: url("data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7")0 center no-repeat;
}
.vue-giant-tree .tmpTargetzTree {opacity: 0.8;background-color: #2ea9df;filter: alpha(opacity=80);
}
.vue-giant-tree .tmpzTreeMove_arrow {position: absolute;width: 18px;height: 18px;color: #4fcbf0;
}
</style>
<style>
ul.ztree.zTreeDragUL {margin: 0;padding: 0;position: absolute;overflow: hidden;background-color: #dedede;border: 1px #4fcbf0 dotted;border-radius: 4px;opacity: 0.7;
}.zTreeMask {position: absolute;z-index: 10000;opacity: 0;background-color: #cfcfcf;
}
</style>

在使用的页面中引入

注意:从接口获取到的树形数据中的 pId 字段名 中间的 ‘I’ 是大写,支持非树形结构数据,只需 pId 和 id 都有,ztree根据id及pId层级关系构建树结构

<template><div style="position: relative; margin: 15px"><el-buttontype="primary"icon="el-icon-document-copy"size="small"@click="openZtree">保存</el-button><el-dialogtitle="通过组织机构选择":visible.sync="dialogZTreeVisible"top="1%"width="40%"><!-- 操作 --><div class="box"><div v-if="loading"><zTreeLoadings></zTreeLoadings></div><div v-else><ZTree:setting="setting":nodes="nodes"@onClick="onClick"@onCheck="onCheck"@onCreated="handleCreated"@pushHandleData="pushHandleData"/></div></div></el-dialog><wp-messagev-if="message":message="message"@close="closeMessage"@isOk="closeMessage"></wp-message></div>
</template><script>
import * as Api from "@/api/wp-questionnaire";// 接口文件
import WpMessage from "@/components/wp-message"; // 弹窗组件
import ZTree from "@/components/wp-common/zTree";
import zTreeLoadings from "@/components/wp-common/loading";
export default {components: {WpMessage,ZTree,zTreeLoadings},data() {return {dialogZTreeVisible: false,nodes: [],showIndex: 0,ztreeObj: null,setting: {check: {enable: true,//这里设置是否显示复选框chkStyle: "checkbox",chkboxType: {Y: "s",N: "ps",}, //设置复选框是否与 父/子 级相关联},data: {simpleData: {enable: true, //设置是否启用简单数据格式(zTree支持标准数据格式跟简单数据格式)idKey: "id", //设置启用简单数据格式时id对应的属性名称pidKey: "pId", //设置启用简单数据格式时parentId对应的属性名称,ztree根据id及pid层级关系构建树结构rootPId: null, // 根节点的parentId设置为null},key: {name: "name",},},view: {selectedMulti: true, //设置是否能够同时选中多个节点showIcon: false, //设置是否显示节点图标showLine: true, //设置是否显示节点与节点之间的连线},callback: {onClick: function (e, treeId, treeNode) {checkNode_user = treeNode;},},},loading: false};},methods: {// 推送数据pushHandleData(val) {let param = {Id: id, //推送的数据条IduserIds: val, //推送用户列表,多个用户以逗号分隔};let peosonNum = val.split(",");// 调用推送的接口Api.questionUserAdd(param).then((res) => {if (res.data.code == 200) {this.toMessage("推送成功!共推送" + peosonNum.length + "人");this.dialogZTreeVisible = false;// this.$eventBus.$emit("getTableDataList");// 其他页面刷新页面,如果不需要可不加} else if (res.data.code == 504) {this.$notify({title: "提示",message: "当前推送数据量过大,请稍后刷新查看!",type: "warning",duration: 2000,});this.dialogZTreeVisible = false;} else {this.$message({type: "error",message: res.msg,});}});},// 获取组织树数据getZtreeData() {this.dialogZTreeVisible = truethis.loading = truelet param = {type: 3,id: String(this.currentQuertionId),};Api.searchUserTreeList(param).then((res) => {if (res.data.code == 200) {this.nodes = res.data.data;this.loading = false}});},// 打开树形结构弹窗openZtree() {this.getZtreeData();this.dialogZTreeVisible = true;},clickRemove(treeNode) {console.log("remove", treeNode);this.ztreeObj && this.ztreeObj.removeNode(treeNode);},onClick(evt, treeId, treeNode) {// 点击事件console.log(evt.type, treeNode);},onCheck(evt, treeId, treeNode) {// 选中事件console.log(evt.type, treeNode);},handleCreated(ztreeObj) {this.ztreeObj = ztreeObj;ztreeObj.expandNode(ztreeObj.getNodes()[0], true);}},
};
</script>

创建弹窗组件 index.vue:

其中 xhnrtp.png 就是个关闭图片

<template><div class="wp-message"><div class="message-container"><h4 class="message-header">信息<img src="@/assets/login/xhnrtp.png" alt="" @click="close" /></h4><div class="message-main">{{ message }}</div><div style="text-align: center; margin-bottom: 10px"><el-buttontype="primary"icon="el-icon-document-copy"size="small"@click="handelOk">确定</el-button></div></div></div>
</template><script>
export default {props: {message: {type: String,default: "",},},methods: {close() {this.$emit("close");},handelOk() {this.$emit("isOk");},},
};
</script><style lang="scss" scoped>
.wp-message {position: fixed;left: 0;right: 0;top: 0;bottom: 0;z-index: 9999;background-color: #00000060;.message-container {width: 300px;border-radius: 4px;background-color: #fff;position: absolute;left: 50%;top: 300px;transform: translateX(-50%);padding-bottom: 10px;.message-header {background-color: #eee;font-weight: normal;padding: 0px 20px;border-radius: 4px 4px 0px 0px;margin: 0px;height: 40px;line-height: 40px;color: #333;position: relative;img {position: absolute;right: 20px;top: 11px;cursor: pointer;}}.message-main {height: 100px;text-align: center;color: #333;font-size: 14px;display: flex;align-items: center;justify-content: center;margin: 0 20px;}}
}
</style>

由于数据量大加载比较慢,可创建一个加载组件 loading.vue 

<template><div class="box"><img class="imgs" src="@/assets/loading.gif" /></div>
</template><script>
export default {methods: {}
}
</script>
<style scoped>
.box {display: flex;justify-content: center;align-items: center;
}
.imgs {width: 50px;height: 50px;
}
</style>

其中的 loading.gif 就是个动态图。

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

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

相关文章

Termius安装docker

安装Termius 直接上官网 新建主机 更新一下yum 更新完成 安装docker的包 直接用命令安装 设置一下开机启动&#xff0c;可以查看docker的版本

Ui学习--UITableView

UI学习 UITableView基础UITableView协议UITableView高级协议与单元格总结 UITableView基础 UITableView作为iOS中的一个控件&#xff0c;用于以表格形式展示数据。例如通讯录好友&#xff0c;朋友圈信息等&#xff0c;都是UITableView的实际运用场景。 首先我们先要加入两个协…

K210使用雷龙NAND完成火灾检测

NAND 文章目录 NAND前言一、NAND是什么&#xff1f;二、来看一看NAND三、部署火灾检测 前言 前几天收到了雷龙NAND的芯片&#xff0c;一共两个芯片和一个转接板&#xff0c;我之前也没有使用过这款芯片&#xff0c;比较好奇&#xff0c;体验了一下&#xff0c;个人认为&#x…

嵌入式微处理器重点学习(三)

堆栈操作 R1=0x005 R3=0x004 SP=0x80014 STMFD sp!, {r1, r3} 指令STMFD sp!, {r1, r3}是一条ARM架构中的存储多个寄存器到内存的指令,这里用于将r1和r3寄存器的内容存储到栈上。STMFD(Store Multiple Full Descending)是一种全递减模式的多寄存器存储指令,它会先将栈指针…

three.js 基础01

1.场景创建 Scene() 2.常用形状集几何体「Geometry」[可设置长宽高等内容,如:new THREE.BoxGeometry(...)] 长方体 BoxGeometry圆柱体CylinderGeometry 球体SphereGeometry圆锥体ConeGeometry矩形平面 PlaneGeometry 圆面体CircleGeometry 3.常用材质「Materi…

linux 部署瑞数6实战(维普,药监局)sign第二部分

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx …

C/C++李峋同款跳动的爱心代码

一、写在前面 在编程的世界里&#xff0c;代码不仅仅是冷冰冰的命令&#xff0c;它也可以成为表达情感、传递浪漫的工具。今天&#xff0c;就让小编带着大家用C语言打造出李峋同款跳动的爱心吧&#xff01; 首先&#xff0c;我们需要知道C作为一种高级编程语言&#xff0c;拥…

宠物健康顾问系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾问管理&#xff0c;用户管理&#xff0c;健康知识管理&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;公告管理 顾问账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾…

头歌资源库(7)汉诺塔(循环)

一、 问题描述 二、算法思想 初始化三个柱子A、B、C&#xff0c;初始时所有的盘子都在柱子A上。对于从1到N&#xff08;N表示盘子的数量&#xff09;的每一个数字i&#xff0c;执行以下循环&#xff1a; a. 如果i是偶数&#xff0c;则将柱子B视为目标柱子&#xff0c;柱子C视为…

Python时间序列分析库

Sktime Welcome to sktime — sktime documentation 用于ML/AI和时间序列的统一API,用于模型构建、拟合、应用和验证支持各种学习任务,包括预测、时间序列分类、回归、聚类。复合模型构建,包括具有转换、集成、调整和精简功能的管道scikit学习式界面约定的交互式用户体验Pro…

【原创】springboot+mysql小区用水监控管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

AI 定位!GeoSpyAI上传一张图片分析具体位置 不可思议! ! !

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;常见AI大模型部署&#xff1a;点击&#xff01; &#x1f916;Ollama部署LLM专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月16日12点23分 &#x1f004;️文章质量&#xff1a;94分…

动态规划日常刷题

力扣70.爬楼梯 class Solution {public int climbStairs(int n) {return dfs(n);}//递归 //注意每次你可以爬 1 或 2 个台阶//如果最后一步是1 就先爬到n-1 把它缩小成0-n-1的范围//如果最后一步是2 就先爬到n-2 把它缩小成0-n-2的范围 private int dfs(int i){if(i < 1){r…

代码随想录算法训练营第五十九天|115.不同的子序列、 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

代码随想录算法训练营第五十九天 115.不同的子序列 题目链接&#xff1a;115.不同的子序列 确定dp数组以及下标的含义&#xff1a;dp[i][j] &#xff1a;以下标i - 1为结尾的s&#xff0c;和以下标j - 1为结尾的t&#xff0c;s中t的个数dp[i][j]确定递推公式&#xff1a; s[…

Intel HDSLB 高性能四层负载均衡器 — 代码剖析和高级特性

目录 文章目录 目录前言代码剖析软件架构目录结构配置解析启动流程分析数据面 jobs 注册数据面 jobs 执行 转发流程分析收包阶段L2 处理阶段L3 处理阶段L4 处理阶段 高级特性大象流转发优化快慢路径分离转发优化报文基础转发优化 最后参考文档 前言 在前 2 篇文章中&#xff0…

Qt第三方库QHotKey设置小键盘数字快捷键

一、看了一圈没有找到可以设置小键盘的情况。 这两天在研究快捷键的使用。发现qt的里的快捷键不是全局的。找了两个第三方快捷键QHotKey&#xff0c;还有一个QxtGlobalShortcut。但是这两个都不能设置小键盘的数字。 比如QKeySequenceEdit &#xff08;Ctrl1&#xff09; 这个…

【SpringBoot】SpringBoot:构建实时聊天应用

文章目录 引言项目初始化添加依赖 配置WebSocket创建WebSocket配置类创建WebSocket处理器 创建前端页面创建聊天页面 测试与部署示例&#xff1a;编写单元测试 部署扩展功能用户身份验证消息持久化群组聊天 结论 引言 随着实时通信技术的快速发展&#xff0c;聊天应用在现代We…

Luma AI如何注册:文生视频领域的新星

文章目录 Luma AI如何注册&#xff1a;文生视频领域的新星一、Luma 注册方式二、Luma 的效果三、Luma 的优势四、Luma 的功能总结 Luma AI如何注册&#xff1a;文生视频领域的新星 近年来&#xff0c;Luma AI 凭借其在文生视频领域的创新技术&#xff0c;逐渐成为行业的新星。…

MySQL基础——多表查询和事务

目录 1多表关系 2多表查询概述 3连接查询 3.1内连接 3.2左外连接 3.3右外连接 3.4自连接 4联合查询 5子查询 5.1标量子查询(子查询结果为单个值) 5.2列子查询(子查询结果为一列) 5.3行子查询(子查询结果为一行) 5.4表子查询(子查询结果为多行多列) 6事务简介和操…

vulnhub靶场-xxe打靶教程

目录 靶机导入 信息收集 发现IP 端口扫描 目录扫描 漏洞利用 靶机下载地址&#xff1a;XXE Lab: 1 ~ VulnHub 靶机导入 导入虚拟机 开启虚拟机 信息收集 发现IP arp-scan -l 发现靶机IP是192.168.202.150 端口扫描 使用nmap进行扫描 nmap -sS -A 192.168.202.150 …