自定义多级联动选择器指南(uni-app)

  • 多端支持:可以运行在H5、APP、微信小程序还是支付宝小程序,都可以轻松使用改组件。
  • 自定义配置:您可以根据需要配置选择器的级数,使其适应不同的数据结构和用例。
  • 无限级联:此组件支持无限级联选择,使您能够创建具有复杂数据结构的选择器。
参数类型描述默认值必选
titlestring标题‘’
layernumber控制几级联动1
dataarray数据:[{name: ‘’, id: ‘’, children: [{name: ‘’, id: ‘’}]}][]

在这里插入图片描述

接口返回数据结构:

[
    {id: 47, name: "工厂1", parentId: 0, type: 0},
    {id: 48, name: "区域1", parentId: 47, type: 0},
    {id: 19, name: "设备1", parentId: 48, type: 1}
]

处理后数据结构:

[{ 
    id: 47, name: "工厂1", parentId: 0, type: 0,
    children: [{ 
        id: 48, name: "区域1", parentId: 47, type: 0,
        children: [
            { id: 19, name: "设备1", parentId: 48, type: 1 }
        ] 
    }] 
}]

引用示例:

<template>
	<view class="container">
		<view @click="bindDevice">选择设备</view>
        <cascade-picker ref="picker" :title="cascadePicker.title" :layer="cascadePicker.layer" :data="cascadePicker.data" @callback="pickerCallback"></cascade-picker>
    </view>
</template>
<script>
import cascadePicker from '@/components/cascade-picker/cascade-picker.vue';
import {handleTree} from "@/utils/tree";
export default {
	components: {
    	cascadePicker
	},
    data() {
        return {
			deviceArr: [],
			deviceId: '',
            cascadePicker: {
                title: 'picker标题',
                layer: null,
                data: []
          }
		}
	},
	onLoad() {
        this.getDeviceSimpleList()
      },
	methods: {
		// 获取设备列表
        getDeviceSimpleList() {
          getDeviceSimpleList().then(res => {
            this.deviceArr = handleTree(res.data)
          })
        },
		// 打开设备选择器
        bindDevice() {
          const _this = this;
          _this.cascadePicker.data = _this.deviceArr;
          _this.$refs.picker.open().then(function() {
            console.log('打开成功');
          });
        },
        // picker多级联动回调
        pickerCallback(e) {
          const {data} = e;
          const lastItem = data[data.length - 1];
          this.deviceId = lastItem.id;
        }
    }
}
</script>

@/utils/tree文件中的handleTree方法

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 * @param {*} rootId 根Id 默认 0
 */
export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children', rootId = 0) {
  rootId = rootId || Math.min.apply(Math, data.map(item => {
    return item[parentId]
  })) || 0
  //对源数据深度克隆
  const cloneData = JSON.parse(JSON.stringify(data))
  //循环所有项
  const treeData = cloneData.filter(father => {
    let branchArr = cloneData.filter(child => {
      //返回每一项的子级数组
      return father[id] === child[parentId]
    });
    branchArr.length > 0 ? father.children = branchArr : '';
    //返回第一层
    return father[parentId] === rootId;
  });
  return treeData !== '' ? treeData : data;
}

cascade-picker组件完整代码:

components文件夹下创建cascade-picker文件夹,然后在此文件夹下创建cascade-picker.vue - 多级联动组件

<template name="cascade-picker">
  <view class="aui-picker" v-if="SHOW" :class="{'aui-picker-in': FADE==1,'aui-picker-out': FADE==0}">
    <view class="aui-mask" @click.stop="close"></view>
    <view class="aui-picker-main">
      <view class="aui-picker-header">
        <view class="aui-picker-header-icon" @click.stop="close">取消</view>
        <view class="aui-picker-title" v-if="title">{{ title }}</view>
        <view class="aui-picker-header-icon aui-picker-confirm" @click.stop="_confirm">确认</view>
      </view>
      <view class="aui-picker-nav">
        <view class="aui-picker-navitem"
              v-if="nav.length>0"
              v-for="(item, index) in nav"
              :key="index"
              :data-index="index"
              :class="[index==navCurrentIndex ? 'active' : '', 'aui-picker-navitem-'+index]"
              :style="{margin: nav.length>2 ? '0 10px 0 0' : '0 30px 0 0'}"
              @click.stop="_changeNav($event)"
        >{{ item.name }}
        </view>
        <view class="aui-picker-navitem"
              :key="nav.length"
              :data-index="nav.length"
              :class="[nav.length==navCurrentIndex ? 'active' : '', 'aui-picker-navitem-'+nav.length]"
              :style="{margin: nav.length>2 ? '0 10px 0 0' : '0 30px 0 0'}"
              @click.stop="_changeNav($event)">请选择
        </view>
        <view class="aui-picker-navborder" :style="{left: navBorderLeft+'px'}"></view>
      </view>
      <view class="aui-picker-content">
        <view class="aui-picker-lists">
          <view class="aui-picker-list"
                v-for="(list, index) in queryItems.length + 1"
                :key="index"
                :data-index="index"
                :class="[index==navCurrentIndex ? 'active' : '']"
          >
            <view class="aui-picker-list-warp" v-if="index == 0">
              <view class="aui-picker-item"
                    v-for="(item, key) in items"
                    v-if="item.pid=='0'"
                    :key="key"
                    :data-pindex="index"
                    :data-index="key"
                    :data-id="item.id"
                    :data-pid="item.pid"
                    :data-name="item.name"
                    :data-type="item.type"
                    :class="{'active': result.length>index && result[index].id==item.id}"
                    :style="{'background': touchConfig.index==key && touchConfig.pindex==index ? touchConfig.style.background : ''}"
                    @click.stop="_chooseItem($event)"
                    @touchstart="_btnTouchStart($event)"
                    @touchmove="_btnTouchEnd($event)"
                    @touchend="_btnTouchEnd($event)"
              >{{ item.name }}
              </view>
            </view>
            <view class="aui-picker-list-warp" v-else>
              <view class="aui-picker-item"
                    v-for="(item, key) in queryItems[index-1]"
                    :key="key"
                    :data-pindex="index"
                    :data-index="key"
                    :data-id="item.id"
                    :data-pid="item.pid"
                    :data-name="item.name"
                    :data-type="item.type"
                    :class="{'active': result.length>index && result[index].id==item.id}"
                    :style="{'background': touchConfig.index==key && touchConfig.pindex==index ? touchConfig.style.background : ''}"
                    @click.stop="_chooseItem($event)"
                    @touchstart="_btnTouchStart($event)"
                    @touchmove="_btnTouchEnd($event)"
                    @touchend="_btnTouchEnd($event)"
              >{{ item.name }}
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'cascade-picker',
  props: {
    title: { //标题
      type: String,
      default: ''
    },
    layer: { //控制几级联动,默认无限级(跟随数据有无下级)
      type: Number,
      default: null
    },
    data: { //数据 如:[{id: '', name: '', children: [{id: '', name: ''}]}]
      type: Array,
      default() {
        return [
          // [{id: '', name: '', children: [{id: '', name: ''}]}]
        ]
      }
    }
  },
  data() {
    return {
      SHOW: false,
      FADE: -1,
      nav: [],
      items: [], // 第一级数据列表
      queryItems: [], // 各级数据列表
      navCurrentIndex: 0, // 当前选中的导航项索引
      navBorderLeft: 35, // 导航栏的边框左侧位置
      result: [],
      touchConfig: {
        index: -1,
        pindex: -1,
        style: {
          color: '#214579',
          background: '#EFEFEF'
        }
      },
      selectedData: [] // 用于回显数据的属性
    }
  },
  watch: {
    data() {
      const _this = this;
      const data = _this.data;
      _this.items = _this._flatten(data, '0')
    }
  },
  methods: {
    // 打开
    open() {
      const _this = this;
      _this.reset(); //打开时重置picker
      return new Promise(function (resolve, reject) {
        _this.SHOW = true;
        _this.FADE = 1;
        resolve();
      });
    },
    // 关闭
    close() {
      const _this = this;
      return new Promise(function (resolve, reject) {
        _this.FADE = 0;
        const _hidetimer = setTimeout(() => {
          _this.SHOW = false;
          _this.FADE = -1;
          clearTimeout(_hidetimer);
          resolve();
        }, 100)
      });
    },
    //重置
    reset() {
      const _this = this;
      _this.queryItems = [];
      _this.nav = [];
      _this.navBorderLeft = 35;
      _this.navCurrentIndex = 0;
      _this.result = [];
    },
    //导航栏切换
    _changeNav(e) {
      const _this = this;
      const index = Number(e.currentTarget.dataset.index);
      _this.navCurrentIndex = index;
      const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-" + index);
      _el.boundingClientRect(data => {
        _this.navBorderLeft = data.left + 20;
      }).exec();
    },
    //数据选择
    _chooseItem(e) {
      const _this = this;
      const id = e.currentTarget.dataset.id;
      const name = e.currentTarget.dataset.name;
      const pid = e.currentTarget.dataset.pid;
      const type = e.currentTarget.dataset.type;
      const _arr = [];
      _this.result[_this.navCurrentIndex] = {id: id, name: name, pid: pid, type: type};
      if (
        (!_this._isDefine(_this.layer) && _this._isDefine(_this._deepQuery(_this.data, id).children))
        ||
        (_this.navCurrentIndex < (Number(_this.layer) - 1) && _this._isDefine(_this._deepQuery(_this.data, id).children))
      ) { //有下级数据
        _this._deepQuery(_this.data, id).children.forEach(function (item, index) {
          _arr.push({id: item.id, name: item.name, pid: id, type: item.type});
        });
        if (_this.navCurrentIndex == _this.queryItems.length) { //选择数据
          _this.queryItems.push(_arr);
          _this.nav.push({name: name});
        } else { //重新选择数据
          _this.queryItems.splice(_this.navCurrentIndex + 1, 1);
          _this.nav.splice(_this.navCurrentIndex + 1, 1);
          _this.queryItems.splice(_this.navCurrentIndex, 1, _arr);
          _this.nav.splice(_this.navCurrentIndex, 1, {name: name});
        }
        _this.navCurrentIndex = _this.navCurrentIndex + 1;
        const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-" + _this.navCurrentIndex);
        setTimeout(() => {
          _el.boundingClientRect(data => {
            _this.navBorderLeft = data.left + 20;
          }).exec();
        }, 100)
      } else { //无下级数据且最后一级数据的type为1时,则可以确认关闭
        _this._confirm();
      }
    },
    _confirm() {
      const _this = this;
      const lastItem = _this.result[_this.result.length - 1];
      if (lastItem && lastItem.type === 1) {
        _this.close().then(() => {
          _this.$emit("callback", {status: 0, data: _this.result});
        });
      } else {
        uni.$u.toast('请选择设备')
      }
    },
    //递归遍历——将树形结构数据转化为数组格式
    _flatten(tree, pid) {
      return tree.reduce((arr, {id, name, type, children = []}) =>
        arr.concat([{id, name, pid, type}], this._flatten(children, id)), [])
    },
    //根据id查询对应的数据(如查询id=10100对应的对象)
    _deepQuery(tree, id) {
      let isGet = false;
      let retNode = null;

      function deepSearch(tree, id) {
        for (let i = 0; i < tree.length; i++) {
          if (tree[i].children && tree[i].children.length > 0) {
            deepSearch(tree[i].children, id);
          }
          if (id === tree[i].id || isGet) {
            isGet || (retNode = tree[i]);
            isGet = true;
            break;
          }
        }
      }

      deepSearch(tree, id);
      return retNode;
    },
    /***判断字符串是否为空
     @param {string} str 变量
     @example: aui.isDefine("变量");
     */
    _isDefine(str) {
      if (str == null || str == "" || str == "undefined" || str == undefined || str == "null" || str == "(null)" || str == 'NULL' || typeof (str) == 'undefined') {
        return false;
      } else {
        str = str + "";
        str = str.replace(/\s/g, "");
        if (str == "") {
          return false;
        }
        return true;
      }
    },
    _btnTouchStart(e) {
      const _this = this,
        index = Number(e.currentTarget.dataset.index),
        pindex = Number(e.currentTarget.dataset.pindex);
      _this.touchConfig.index = index;
      _this.touchConfig.pindex = pindex;
    },
    _btnTouchEnd(e) {
      const _this = this,
        index = Number(e.currentTarget.dataset.index),
        pindex = Number(e.currentTarget.dataset.pindex);
      _this.touchConfig.index = -1;
      _this.touchConfig.pindex = -1;
    },
  }
}
</script>

<style lang="scss" scoped>
/* ====================
  多级联动弹窗
 =====================*/
.aui-picker {
  width: 100vw;
  height: 100vh;
  //opacity: 0;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  /* display: none; */
}

// 遮罩层
.aui-mask {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, .3);
  position: absolute;
  left: 0;
  top: 0;
  z-index: 999;
}

.aui-picker.aui-picker-in {
  -moz-animation: aui-fade-in .1s ease-out forwards;
  -ms-animation: aui-fade-in .1s ease-out forwards;
  -webkit-animation: aui-fade-in .1s ease-out forwards;
  animation: aui-fade-in .1s ease-out forwards;
}

.aui-picker.aui-picker-out {
  -moz-animation: aui-fade-out .1s ease-out forwards;
  -ms-animation: aui-fade-out .1s ease-out forwards;
  -webkit-animation: aui-fade-out .1s ease-out forwards;
  animation: aui-fade-out .1s ease-out forwards;
}

.aui-picker-main {
  width: 100vw;
  height: 50vh;
  background: #FFF;
  //border-radius: 15px 15px 0 0;
  position: absolute;
  left: 0px;
  bottom: 0;
  z-index: 999;
}

.aui-picker.aui-picker-in .aui-picker-main {
  -moz-animation: aui-slide-up-screen .2s ease-out forwards;
  -ms-animation: aui-slide-up-screen .2s ease-out forwards;
  -webkit-animation: aui-slide-up-screen .2s ease-out forwards;
  animation: aui-slide-up-screen .2s ease-out forwards;
}

.aui-picker.aui-picker-out .aui-picker-main {
  -moz-animation: aui-slide-down-screen .2s ease-out forwards;
  -ms-animation: aui-slide-down-screen .2s ease-out forwards;
  -webkit-animation: aui-slide-down-screen .2s ease-out forwards;
  animation: aui-slide-down-screen .2s ease-out forwards;
}

.aui-picker-header {
  width: 100%;
  min-height: 50px;
  position: relative;
  z-index: 999;
  display: flex;
  justify-content: space-between;
  align-items: center;

  &-icon {
    font-size: 15px;
    color: #aaa;
    padding: 0 15px;
  }

  .aui-picker-confirm {
    height: 50px;
    line-height: 50px;
    text-align: center;
    font-size: 15px;
    color: $custom-content-color;
    padding: 0 15px;
  }
}

.aui-picker-header::after {
  content: '';
  width: 100%;
  height: 1px;
  background: rgba(100, 100, 100, .3);
  -moz-transform: scaleY(.3);
  -ms-transform: scaleY(.3);
  -webkit-transform: scaleY(.3);
  transform: scaleY(.3);
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 999;
}

.aui-picker-title {
  line-height: 20px;
  text-align: center;
  font-size: 17px;
  color: #333;
  padding: 15px;
  box-sizing: border-box;
  position: absolute;
  left: 50px;
  right: 50px;
  top: 0;
}

.aui-picker-content {
  width: 100%;
  height: -webkit-calc(100% - 100px);
  height: calc(100% - 100px);
}

.aui-picker-nav {
  width: 100%;
  height: 50px;
  text-align: left;
  padding: 0 15px;
  margin: 0 0 1px 0;
  justify-content: flex-start;
  white-space: nowrap;
  box-sizing: border-box;
  position: relative;
  overflow-x: scroll;
  overflow-y: hidden;
}

.aui-picker-nav::after {
  content: '';
  width: 100%;
  height: 1px;
  background: rgba(100, 100, 100, .3);
  -moz-transform: scaleY(.3);
  -ms-transform: scaleY(.3);
  -webkit-transform: scaleY(.3);
  transform: scaleY(.3);
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 999;
}

.aui-picker-navitem {
  width: 80px;
  line-height: 50px;
  font-size: 16px;
  margin: 0 30px 0 0;
  text-align: center;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.aui-picker-navitem.active {
  color: $custom-content-color;
}

.aui-picker-navborder {
  width: 40px;
  height: 3px;
  background: $custom-content-color;
  border-radius: 5px;
  transition: left .15s;
  position: absolute;
  left: 40px;
  bottom: 0;
}

.aui-picker-lists {
  width: 100%;
  height: 100%;
  justify-content: space-around;
  white-space: nowrap;
}

.aui-picker-list {
  width: 100%;
  height: 100%;
  overflow: hidden;
  overflow-y: scroll;
  display: none;
  vertical-align: top;
}

.aui-picker-list.active {
  display: inline-block;
}

.aui-picker-list-warp {
  width: 100%;
  height: auto;
  box-sizing: border-box;
  padding: 15px 0;
  display: inline-block;
}

.aui-picker-item {
  width: 100%;
  height: 50px;
  line-height: 50px;
  padding: 0 15px;
  box-sizing: border-box;
  font-size: 15px;
  color: #333;
  position: relative;
}

.aui-picker-item.active {
  color: $custom-content-color;
}

.aui-picker-item.active::after {
  content: '✔';
  font-size: 15px;
  color: $custom-content-color;
  position: absolute;
  top: 0px;
  right: 10px;
}

</style>
总结

自定义多级联动选择器组件将有助于您在uni-app中创建灵活的选择器,以满足各种不同平台和级数的需求。如果有任何问题、反馈或需要进一步的帮助,请不要犹豫,在下面的评论中提出。期待听到您的声音,以便改进和完善这个组件。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL--基本介绍

一.数据库前言 1.数据库的相关介绍 关系数据库管理系统&#xff08;Relational Database Management System&#xff1a;RDBMS&#xff09;是指包括相互联系的逻辑组织和存取这些数据的一套程序 (数据库管理系统软件)。关系数据库管理系统就是管理关系数据库&#xff0c;并将数…

张雪峰:如果你现在是计算机专业,一定要优先报网络安全,它是未来国家发展的大方向

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 “计算机专业 一定要优先报 网络安全 它是未来国家发展的大方向” 为什么推荐学网络安全&#xff1f; “没有网络安全就没有国家安全。”当前&#xff…

Git Push(TODO)

最近经常碰到GIT push不上去的问题。到处求人解决也真是尴尬&#xff0c;想自己看看&#xff0c;所以刚刚在github上建了一个仓&#xff0c;试了下。结果如下&#xff1a; 暂时可能还不行&#xff0c;因为数据都是加密的&#xff0c;没法看到具体GIT的交互信息。。。 后面再想办…

12.个人博客系统(Java项目基于spring和vue)

目录 1.系统的受众说明 2.相关技术介绍 2.1 B/S 简介 2.2 JAVA 简介 2.3 vue简介 2.4 SSM和Springboot简介 3.可行性分析 3.1 技术可行性分析 3.2 经济可行性分析 3.3 操作可行性 4.系统设计 4.1 系统总流程 4.2 博主用例 4.3 游客用例 4.4 系统类 4.…

HarmonyOS 模块化设计

1.HarmonyOS 模块化设计 模块化设计文档   应用程序包开发与使用文档 1.1. 概述 组件化一直是移动端比较流行的开发方式&#xff0c;有着编译运行快&#xff0c;业务逻辑分明&#xff0c;任务划分清晰等优点&#xff0c;HarmonyOs组件化的使用&#xff0c;有利于模块之间的解…

算法笔记day05

目录 1.最小公倍数 2.最长连续的子序列 3.字母收集 1.最小公倍数 求最小公倍数_牛客题霸_牛客网 算法思路&#xff1a; 这就是一道数学题&#xff0c;a,b的最小公倍数 a * b / 最大公约数。 使用辗转相除法&#xff0c;求a&#xff0c;b的最大公约数。 #include <iostre…

Cadence元件A属性和B属性相互覆盖

最近在使用第三方插件集成到Cadence,协助导出BOM到平台上&#xff0c;方便对BOM进行管理和修改&#xff0c;结果因为属性A和属性B不相同&#xff0c;导致导出的BOM错误。如下图&#xff1a; ​​ 本来我们需要导出Q12&#xff0c;结果给我们导出了Q13&#xff0c;或者反之&…

UNIX网络编程-传输层

概述 传输层主要包括&#xff1a;TCP、UDP、SCTP&#xff08;流控制传输协议&#xff09;&#xff01; 绝大多数客户端/服务器网络应用都使用TCP/UDP。SCTP是一个较新的协议&#xff0c;最初设计用于跨因特网传输电话信令。 这些传输协议都转而使用网络协议IP&#xff1a;或是…

VScode分文件编写报错 | 如何进行VScode分文件编写 | 小白也能轻松解决版

分文件编写遇到的问题 分文件编写例子如下所示&#xff1a; 但是直接使用 Run Code 或者 调试C/C文件 会报错如下&#xff1a; 正在执行任务: C/C: g.exe 生成活动文件 正在启动生成… cmd /c chcp 65001>nul && D:\Librarys\mingw64\bin\g.exe -fdiagnostics-col…

计算机网络——传输层服务

传输层会给段加上目标ip和目标端口号 应用层去识别报文的开始和结束

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十五集:制作更多地图,更多敌人,更多可交互对象

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作更多敌人2.制作更多可交互对象二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象三、第三个代表性场景 1.制作更多敌人2.制…

MongoDB安装配置及配置和启动服务

MongoDB 安装配置 附&#xff1a;MongoDB官网下载地址&#xff1a; https://www.mongodb.com/download-center/community 注&#xff1a; 官网可以下载最新版的MongoDB安装包&#xff0c;有MSI安装版和ZIP安装版。我们课堂上使用4.4.4的ZIP安装版。安装版参考博客&#xff1…

【redis】基础指令|数据结构总览|单线程架构分析

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#xff1a;redis系类博客都是以redis5.0版本为基础&#xff01;&#xff01;&#xff01; 目录 Redis常见命令 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 数据结构和内部编码 单线程架构 Redis…

群控系统服务端开发模式-数据库设计图

根据整理的业务需求可以发现&#xff0c;本系统数据库针对1.0版本就分两种库。第一类是管理层的数据库&#xff0c;分别是管理员表、角色表、菜单表、部门表、级别表。分别对应控制权限及数据权限。 一、管理层数据库设计图 二、业务层数据库设计图

潜水定位通信系统的功能和使用方法_鼎跃安全

潜水定位通信系统是保障潜水安全与作业高效的关键设备。它利用先进的声呐、无线电等技术&#xff0c;可精准定位潜水员位置。在水下能实现潜水员之间以及与水面的双向通信&#xff0c;确保信息及时传递。具备高可靠性和稳定性&#xff0c;即使在复杂水环境中也能正常运行。 一、…

智能体能和人工智能有什么区别?

智能体与人工智能&#xff08;AI&#xff09;之间存在明显的区别&#xff0c;尽管两者在技术和应用上有一定的重叠。 一、定义与范畴 人工智能&#xff08;AI&#xff09; 人工智能是指通过模拟、延伸和扩展人的智能&#xff0c;使计算机或其他智能设备具有人类智能的一种技术…

Redis --- 第六讲 --- 关于持久化

前言 持久化&#xff1a;MySQL的事务&#xff0c;有四大比较核心的特性 1、原子性 2、一致性 3、持久性 》 把数据存储到硬盘上 》持久&#xff0c;把数据存储在内存上》持久化。重启进程/重启主机之后&#xff0c;数据是否存在。 4、隔离性 Redis是一个内存数据库&#…

如何在忘记密码的情况下解锁 iPhone? 6 种方法分享

您是否因为没有密码而无法解锁您的 iPhone&#xff1f; 别担心&#xff0c;这种情况比你想象的更常见&#xff01;忘记密码是 iPhone 用户面临的最常见问题之一&#xff0c;而且可能非常令人沮丧 - 但不要绝望。 在这篇文章中&#xff0c;我们将与您分享绕过 iPhone 屏幕密码…

No provider available from registry RegistryDirectory

【中】No provider available from registry RegistryDirectory Dubbo 3.2.9Nacos 2.1.0 最近在做配置文件升级&#xff0c;服务比较多&#xff0c;之前的Dubbo配置各个服务写的比较乱&#xff0c;有的用Nacos上的 data-id&#xff0c;有的又是在自己的服务引入配置 遂准备统一…

记录一次从nacos配置信息泄露到redis写计划任务接管主机

经典c段打点开局。使用dddd做快速的打点发现某系统存在nacos权限绕过 有点怀疑是蜜罐&#xff0c;毕竟nacos这实在是有点经典 nacos利用 老规矩见面先上nacos利用工具打一波看看什么情况 弱口令nacos以及未授权访问&#xff0c;看这记录估计被光顾挺多次了啊 手动利用Nacos-…