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

vue实现动态路由菜单!!!

目录

  • 总结
  • 一、步骤
    • 1.编写静态路由
      • 编写router.js
      • main.js注册
    • 2.编写permisstions.js权限文件
      • 编写permisstions.js
      • axios封装的API
        • store.js状态库
        • system.js Axios-API
        • request.js axios请求实例封装
    • 3.编写菜单树组件
      • MenuTree.vue
    • 4.主页中使用菜单树组件


总结

递归处理后端响应的菜单树,后依次通过addRoute方法往静态父路由,添加动态子路由,添加完使用el-menu渲染并添加router属性实现路由菜单模式
addRoute:https://router.vuejs.org/zh/api/interfaces/Router.html#Methods-addRoute

后端数据库树菜单:
在这里插入图片描述

一、步骤

1.编写静态路由

  • 创建router.js文件默认导出静态路由,后在main.js加载注册

编写router.js

//静态路由配置文件
// eslint-disable-next-line no-unused-vars
import Router from "vue-router"
// eslint-disable-next-line no-unused-vars
import Vue from "vue"
//在Vue中加载路由模块
Vue.use(Router)//写路由表
// eslint-disable-next-line no-unused-vars
// const Foo = { template: '<div>foo</div>' }
const routes = [// 进入vue项目默认进入登录页面{path: "/",redirect: "/Login"},{path: "/Login",component: () => import("../view/Login"),meta: {skipAuthCheck: true // 添加一个标记,表示不需要进行身份验证检查}},{path: "/index",name: 'index',component: () => import("../components/index"),children: [// 默认显示hello页面{path: "/",redirect: "/hello"},{path: "/hello",meta: { requiresAuth: true },component: () => import("../components/hello"),},],},
]export default new Router({routes
});// 防止连续点击多次路由报错
let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace;
// push
Router.prototype.push = function push(location) {return routerPush.call(this, location).catch(err => err)
}
// replace
Router.prototype.replace = function push(location) {return routerReplace.call(this, location).catch(err => err)
}

main.js注册

import Vue from 'vue'
import App from './App.vue'
//引入一个router模块
import router from "@/router/router"
import routers from "@/router/permissions"
import element from 'element-ui';
import axiosInstance from '@/request/request'
import { createPinia } from 'pinia';
import 'element-ui/lib/theme-chalk/index.css';
// 在生产环境中禁用警告信息和启用构建优化
Vue.config.productionTip = false// 将 Axios 实例添加到 Vue 原型中,以便在组件中使用
// Vue.prototype.axios axios便在组件中使用如:this.$axios
Vue.prototype.axios = axiosInstanceconst pinia = createPinia();
Vue.use(pinia)Vue.use(element)
new Vue({router,routers,render: h => h(App),
}).$mount('#app')

2.编写permisstions.js权限文件

  • 结合axios封装API于permisstions中配置的全局前置守卫中获取菜单树存入sessionStorage缓存

编写permisstions.js

// 导入默认导出的路由对象用于跳转路由
// import router from '@/router/router';
//导入路由表
import routers from "@/router/router"
//路由配置文件
import { tokenStore } from "@/store/store"// 全局前置守卫
// to当前即将要进入的路由对象
routers.beforeEach((to, from, next) => {//如果当前的访问的请求是Login放行if (to.path === '/Login') {next();}else {//其余访问请求判断用户是否登录if (!isLoggedIn()) {console.log("抱歉你未登录");next('/Login'); // 如果用户未登录,则重定向到登录页面} else {// console.log(to);next();}}})
//登录验证函数
function isLoggedIn() {console.log("进入路由守卫");// 在这里实现检查用户是否已登录的逻辑,例如检查是否有有效的令牌或会话// 如果已登录,返回true,否则返回falseconst jwtToken = sessionStorage.getItem('jwtToken'); // 从本地缓存中获取会话信息// console.log(jwtToken);let userId = sessionStorage.getItem('user_name_id');//userId存在获取动态路由信息if (userId && jwtToken) {// if (tokenStore().flag) {tokenStore().getRouters(userId).then((res) => {if (res.status == 201) {// console.log(res.data);//动态路由源信息let r = res.data;// 过滤动态路由菜单let menu = fnAddDynamicMenuRoutes(r)console.log(menu);menu.forEach(element => {element.children.forEach(s => {// console.log(s);//index为父路由的name属性值  s是需添加的路由routers.addRoute('index', s);})});// console.log(routers);// 动态路由得到后修改标记为false表示已执行过无需在执行tokenStore().flag = false;// 保存路由到会话sessionStorage.setItem('menu', JSON.stringify(menu));}if (res.status == 501) {//未获取到动态路由重新登录routers.push("/Login");}})// }}return jwtToken && routers; // 如果登录令牌存在,则用户已登录
}// 用于处理动态菜单数据,将其转为 route 形式
function fnAddDynamicMenuRoutes(menuList = [], routes = []) {// 用于保存普通路由数据let temp = []// 用于保存存在子路由的路由数据let route = []// 遍历数据for (let i = 0; i < menuList.length; i++) {// 存在子路由,则递归遍历,并返回数据作为 children 保存if (menuList[i].childMenus && menuList[i].childMenus.length > 0) {// 获取路由的基本格式route = getRoute(menuList[i])// 递归处理子路由数据,并返回,将其作为路由的 childMenus 保存route.children = fnAddDynamicMenuRoutes(menuList[i].childMenus)// 保存存在子路由的路由routes.push(route)} else {// 保存普通路由temp.push(getRoute(menuList[i]))}}// 返回路由结果return routes.concat(temp)
}// 返回路由的基本格式
function getRoute(item) {// 路由基本格式let route = {// 路由的路径path: item.path,// 路由名name: item.menuName,// 路由所在组件  必须有一段已定义好的组件名字// component: (resolve) => require([`@/layout/Index`], resolve),component: (resolve) => require([`../components${item.menuUrl}.vue`], resolve),meta: {id: item.menuType,// icon: item.icon},// 路由的子路由children: []}// 返回 routereturn route
}export default routers

axios封装的API

store.js状态库
// 导入pinia库
import { defineStore } from 'pinia';
// 导入api
import { login, logOut, getRouters } from '@/request/api/system';
// 导入jwt解析器
import jwtDecode from "jwt-decode";
// 导入默认导出的路由对象用于跳转路由
import router from '@/router/router';export const tokenStore = defineStore({id: 'myStore',state: () => ({jwtToken: null,user_name: null,user_name_id: null,user_type: null,menu: null,}),actions: {getRouters(userId) {return new Promise((resolve) => {getRouters(userId).then(res => {console.log(res);resolve(res)})})},doLogin(params) {login(params).then((res) => {if (res.status == 200) {const jwtToken = res.data; // 从响应中获取JWTsessionStorage.setItem('jwtToken', jwtToken);this.jwtToken = jwtToken; // pinia存储JWT// 解码JWT令牌以获取载荷信息const decodedToken = jwtDecode(jwtToken);console.log(decodedToken);//访问包含在JWT令牌中的用户信息//保存用户类型的id便于门诊医生问诊var user_name_id = decodedToken.user_name_id;sessionStorage.setItem('user_name_id', user_name_id);this.user_name_id = user_name_id;//保存用户类型便于控制导航栏的显示与隐藏const userType = decodedToken.user_type;this.user_type =userType == 1? "系统管理员": userType == 2? "挂号员": "门诊医生";//跳转到主页router.push("/index");}});},LogOut() {return logOut();}},
});
system.js Axios-API
import axiosInstance from "@/request/request"export function login(data) {return axiosInstance({url : "/Login",method : "POST",data})
}export function logOut() {return axiosInstance({url : "/LogOut",method : "get",})
}export function getUserInfo(data) {return axiosInstance({url : "/User/select",method : "post",data})
}export function getRouters(userId) {return axiosInstance({url : `/UserTreeInfo${userId}`,method : "get",})
}
request.js axios请求实例封装
import axios from 'axios'
import { Message } from 'element-ui'
import {tokenStore} from "@/store/store";// 创建一个 Axios 实例
const axiosInstance = axios.create({baseURL: 'http://localhost:8080/qy', // 通用后端 Url 地址timeout: 5000, // 请求最大等待时间,headers: { 'Content-Type': 'application/json' },
})// 添加请求拦截器
axiosInstance.interceptors.request.use((config) => {// 获取请求的URLconst requestUrl = config.url;console.log(requestUrl);// console.log(config);// 提取URL路径部分/qy/Login// const urlPath = new URL(requestUrl).pathname;// 如果是post请求将参数data转成json字符串// 检查请求方法是否为 POSTif (config.method === 'post' || config.method === 'POST') {// 将请求数据转换为 JSON 字符串config.data = JSON.stringify(config.data);}if (config.method === 'get' || config.method === 'GET') {config.headers['Content-Type'] = 'x-www-form-urlencoded';}// 在请求头中获取令牌信息const jwtToken = tokenStore().jwtToken // 从pinia中获取令牌// 检查是否是登录请求,这里假设登录请求的URL是 '/Login'if (requestUrl !== '/Login' && requestUrl !== '/LogOut') {console.log(requestUrl);// 如果不是登录请求,添加令牌到请求头if (jwtToken) {config.headers.Authorization = `${jwtToken}`}}return config},(error) => {return Promise.reject(error)}
)//添加响应拦截器
axiosInstance.interceptors.response.use((response) => {var res = response.data// console.log(res);// 设置请求状态弹窗提示if (res.status == 200) {//请求成功提示Message.success(res.msg);}else if(res.msg === "菜单载入成功") {return res}else {Message.error(res.msg);}// 后端响应Resbody的data数据return res
},(error) => {return Promise.reject(error)}
)export default axiosInstance

3.编写菜单树组件

  • 接受父组件菜单树,递归遍历渲染树菜单

MenuTree.vue

<template><div><!-- :default-active 一进页面默认显示的页面unique-opened 保持一个子菜单的打开router 采用路由模式 菜单上的index就是点击跳转的页面text-color 菜单文字的颜色active-text-color 菜单激活后文字的颜色--><el-menudefault-activebackground-color="#2b333e"routertext-color="#fff"active-text-color="#ffd04b"><template v-for="item in menuData"><el-submenuv-if="item.children && item.children.length > 0":key="item.id":index="item.path"><template slot="title"><i class="el-icon-menu"></i><span>{{ item.name }}</span></template><!-- 若有子菜单递归渲染 --><menu-tree :menuData="item.children" /></el-submenu><el-menu-item v-else :key="item.id" :index="item.path">{{item.name}}</el-menu-item></template></el-menu></div>
</template><script>
export default {props: {menuData: {},},name: "MenuTree",
};
</script>

4.主页中使用菜单树组件

  • 导入组件并注册MenuTree.vue,通过JSON.parse()转换菜单树对象menuData,后父传子menuData渲染菜单树
<!-- eslint-disable vue/multi-word-component-names -->
<template><!-- 整个页面 --><div class="index"><!-- 左导航 --><divclass="leftNav":style="{width: leftNavWidth,visibility: show,transition: transitionParam,}"><!-- 标题 --><h2 style="color: #fff; margin: 20px 0">青芽在线医疗</h2><!-- 动态导航 --><!-- {{ menuData }} --><menu-tree :menuData="menuData"></menu-tree></div><!-- 主界面 --><divclass="mainSection":style="{ width: mainSectionWidth, transition: transitionParam }"><!-- 标题头部 --><div class="QYheader"><span class="el-icon-s-operation" @click="controlWidth"></span><span class="QYheaderFont"><el-button type="primary" @click="LogOut">退出登录</el-button></span><div class="QYheaderRight"><span class="el-icon-user-solid"></span><span class="QYheaderRightFont">{{ user_name }}</span></div></div><!-- 二级路由部分 --><div class="QYcontent"><router-view></router-view></div><!-- QYcontent --></div><!-- mainSection --></div><!-- index -->
</template><script>
import { tokenStore } from "@/store/store";
import MenuTree from "../components/MenuTree.vue";
export default {// eslint-disable-next-line vue/multi-word-component-namesname: "mainSection",components: {MenuTree,},data() {return {menuData: JSON.parse(sessionStorage.getItem("menu")),tokenStore: tokenStore(),//接收从Login页传来的登录用户名user_name: tokenStore().user_name,//接收从Login页传来的用户类型user_type: tokenStore().user_type,//设置导航和主界面默认宽高leftNavWidth: "16%",mainSectionWidth: "84%",show: "visible",transitionParam: "width 0.5s ease",};},methods: {//控制导航和主界面的宽和高controlWidth() {console.log("已进入控制宽度方法");this.leftNavWidth = this.leftNavWidth === "16%" ? "0%" : "16%";//控制左导航的显示与隐藏  同时设置mainSectionWidth的宽和高if (this.leftNavWidth === "16%") {this.show = "visible";this.mainSectionWidth = "84%";} else if (this.leftNavWidth === "0%") {this.show = "hidden";this.mainSectionWidth = "100%";}},LogOut() {// 删除所有本地缓存包括令牌信息// localStorage.clear();this.tokenStore.LogOut().then((res) => {if (res.status == 200) {// 删除所有本地缓存包括令牌信息sessionStorage.clear();// 重置获取路由的标记tokenStore.flag = false;// 跳转到登录页面this.$router.push({ path: "/Login" });}});// localStorage.removeItem("user_name");// localStorage.removeItem("user_type");},},
};
</script><style>
@import url(../css/index.css);
</style>

相关文章:

vue实现动态路由菜单!!!

目录 总结一、步骤1.编写静态路由编写router.jsmain.js注册 2.编写permisstions.js权限文件编写permisstions.jsaxios封装的APIstore.js状态库system.js Axios-APIrequest.js axios请求实例封装 3.编写菜单树组件MenuTree.vue 4.主页中使用菜单树组件 总结 递归处理后端响应的…...

企业如何选择安全又快速的大文件传输平台

在现代信息化社会&#xff0c;数据已经成为各个行业的重要资源&#xff0c;而数据的传输和交换则是数据价值的体现。在很多场合&#xff0c;企业需要传输或接收大文件&#xff0c;例如设计图纸、视频素材、软件开发包、数据库备份等。这些文件的大小通常在几百兆字节到几十个字…...

springboot 自定义starter逐级抽取

自定义starter 背景:各个组件需要引入starter 还有自己的配置风格 –基本配置原理 &#xff08;1&#xff09;自定义配置文件 导入配置可以在配置文件中自动识别&#xff0c;提示 导入依赖后可以发现提示 &#xff08;2&#xff09;配置文件实现 –让配置文件对其他模块生…...

GAN:ImprovedGAN-训练GAN的改进策略

论文&#xff1a;https://arxiv.org/abs/1606.03498 代码&#xff1a;https://github.com/openai/improved_gan 发表&#xff1a;NIPS 2016 一、文章创新 1&#xff1a;Feature matching&#xff1a;特征匹配通过为生成器指定新目标来解决GANs的不稳定性&#xff0c;从而防止…...

docker限制容器内存的方法

在服务器中使用 docker 时&#xff0c;如果不对 docker 的可调用内存进行限制&#xff0c;当 docker 内的程序出现不可预测的问题时&#xff0c;就很有可能因为内存爆炸导致服务器主机的瘫痪。而对 docker 进行限制后&#xff0c;可以将瘫痪范围控制在 docker 内。 因此&#…...

阿里达摩院裁撤量子实验室

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 马云的达摩院也不搞量子计算了&#xff0c;因为缺钱&#xff0c;整体裁掉了达摩院量子实验室&#xff0c;把所有的设备都赠送给了浙江大学。 达摩院量子实验室&#xff1a;总共30个研究员&#xf…...

mysql数据库基础知识,Mysql的索引和主键区别,数据库的事务的基本特性

文章目录 数据库基础知识Mysql的索引和主键的区别数据库的事务的基本特性 数据库基础知识 为什么要使用数据库 数据保存在内存 优点&#xff1a; 存取速度快 缺点&#xff1a; 数据不能永久保存 数据保存在文件 优点&#xff1a; 数据永久保存 缺点&#xff1a;1&#xf…...

解决Vscode使用git提交卡住的问题

使用Vscode的git提交代码经常会很慢/卡住。 先点击左下角&#xff0c;进入设置 找到git的配置(建议直接搜索)&#xff0c;把use Editor As commit input的勾选去掉即可解决。...

Linux C语言 32-网络编程之UDP例程

Linux C语言 32-网络编程之UDP例程 本节关键字&#xff1a;C语言 网络编程 UDP协议 套接字操作 服务端 客户端 相关C库函数&#xff1a;setsockopt, socket, bind, recvfrom, sendto, close 相关接口介绍 Linux C语言 30-套接字操作 例程执行任务说明 本例程中服务端的任务…...

ubuntu22.04系统下载程序和依赖,并拷贝到指定路径下

脚本1 apt install aptitude apt-get -d install xxx #xxx是待下载的安装包 mv /var/cache/apt/archives/* /home/tuners/1apt install aptitude apt-get -d install xxx mv /var/cache/apt/archives/*.deb /home/tuners/1 xxx 为程序包名称 /home/tuners/1为保存程序包的…...

Kafka KRaft 版本集群部署详细教程(附配置文件详细解释)

版本说明 Ubuntu 18.04.6Kafka 3.6.0JDK8 集群配置 操作系统ip域名Kafka Broker 端口Kafka Controller 端口Ubuntu 18.04.6192.168.50.131kafka1.com90929093Ubuntu 18.04.6192.168.50.132kafka2.com90929093Ubuntu 18.04.6192.168.50.133kafka3.com90929093 安装 vim, cur…...

在龙蜥 anolis os 23 上 源码安装 PostgreSQL 16.1

在龙蜥 OS 23上&#xff0c;本来想使用二进制安装&#xff0c;结果发现没有针对龙蜥的列表&#xff1a; 于是想到了源码安装&#xff0c;下面我们列出了PG源码安装的步骤&#xff1a; 1.安装准备 1.1.创建操作系统组及用户 groupadd postgres useradd -g postgres -m postgr…...

UDP的不可靠性可以用来做什么

User Datagram Protocol&#xff08;UDP&#xff0c;用户数据报协议&#xff09;是互联网协议套件中的一种传输层协议。与TCP不同&#xff0c;UDP是一种无连接的、不可靠的协议。 要知道UDP可以用来做什么&#xff0c;首先我们要知道它有何特点: 1,无连接&#xff1a; UDP是一…...

vue3还用this吗?getCurrentInstance获取当前组件实例

在 Vue 2 中&#xff0c;this 关键字代表当前组件实例。在组件的选项对象中&#xff0c;this 可以用于访问组件实例的属性、方法以及 Vue 实例的一些特定方法。 在Vue3中&#xff0c;我们发现this是undefined&#xff0c;那我们真的没法使用this了吗&#xff1f;vu3给我们提供…...

高校学生宿舍公寓报修维修生活管理系统 微信小程序b2529

本课题要求实现一套基于微信小程序宿舍生活管理系统&#xff0c;系统主要包括&#xff08;管理员&#xff0c;学生、维修员和卫检员&#xff09;四个模块等功能。 使用基于微信小程序宿舍生活管理系统相对传统宿舍生活管理系统信息管理方式具备很多优点&#xff1a;首先可以大幅…...

C++类与对象(7)—友元、内部类、匿名对象、拷贝对象时编译器优化

目录 一、友元 1、定义 2、友元函数 3、友元类 二、内部类 1、定义 2、特性&#xff1a; 三、匿名对象 四、拷贝对象时的一些编译器优化 1、传值&传引用返回优化对比 2、匿名对象作为函数返回对象 3、接收返回值方式对比 总结&#xff1a; 一、友元 1、定义…...

Django回顾2

目录 一.HTTP 1.URL介绍 2.格式&#xff1a; 3.补充&#xff1a; 二.web框架 1.什么是框架 2.什么是web框架 3.wsgi协议 基于wsgi协议的web服务器&#xff1a; 4.协议是怎么规定的 三.Django 1.MVC与MTV模型&#xff08;所有框架其实都遵循MVC架构&#xff09; 2.…...

<JavaDS> 二叉树遍历各种遍历方式的代码实现 -- 前序、中序、后序、层序遍历

目录 有以下二叉树&#xff1a; 一、递归 1.1 前序遍历-递归 1.2 中序遍历-递归 1.3 后序遍历-递归 二、递归--使用链表 2.1 前序遍历-递归-返回链表 2.2 中序遍历-递归-返回链表 2.3 后序遍历-递归-返回链表 三、迭代--使用栈 3.1 前序遍历-迭代-使用栈 3.2 中序遍…...

如何控制Spring工厂创建对象的次数?详解Spring对象的声明周期!

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…...

计算机杂谈系列精讲100篇-【计算机应用】PyTorch部署及分布式训练

目录 C平台PyTorch模型部署流程 1.模型转换 1. 不支持的操作 2. 指定数据类型 2.保存序列化模型 3.C load训练好的模型 4. 执行Script Module PyTorch分布式训练 分布式并行训练概述 Pytorch分布式数据并行 手把手渐进式实战 A. 单机单卡 B. 单机多卡DP C. 多机多卡DDP D. L…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...