【JSON2WEB】 12基于Amis-admin的动态导航菜单树

【JSON2WEB】01 WEB管理信息系统架构设计

【JSON2WEB】02 JSON2WEB初步UI设计

【JSON2WEB】03 go的模板包html/template的使用

【JSON2WEB】04 amis低代码前端框架介绍

【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成

【JSON2WEB】06 JSON2WEB前端框架搭建

【JSON2WEB】07 Amis可视化设计器CRUD增删改查

【JSON2WEB】08 Amis的事件和校验

【JSON2WEB】09 Amis-editor的代码移植到json2web

【JSON2WEB】10 基于 Amis 做个登录页面login.html

【JSON2WEB】11 基于 Amis 角色功能权限设置页面


管理信息系统一般注册用户较多,功能页面也很多,不同用户有不同的功能页面的操作权限,根据用户角色功能权限,生成动态的页面导航功能树是我采用的常规操作。

1 动态菜单的设计

关于数据库的表设计参阅 【REST2SQL】13 用户角色功能权限设计。

1.1 创建几个相关视图

  • 角色-页面权限视图
create or replace view role_menu_v as
select m.p_id as m_id,m.s_name ,s.pf_role,r.p_id as r_id,
  decode(length(s.pf_role),4,1,0) as b_yn,m.f_mod
 from s_menu m
cross join s_role r --先做一个角色与功能的笛卡尔交叉,再连接角色功能表
left join s_role_menu s on s.pf_menu = m.p_id and s.pf_role = r.p_id
order by r.p_id,m.p_id
;

在这里插入图片描述

  • 用户-角色视图
create or replace view user_role_v as
select r.p_id as r_id,r.s_name ,s.pf_user,u.p_id as u_id,
  decode(length(s.pf_role),4,1,0) as b_yn
 from s_role r
cross join s_user u --先做一个用户与角色的笛卡尔交叉,再连接用户角色表
left join s_user_role s on s.pf_user = u.p_id and s.pf_role = r.p_id
order by u.p_id,r.p_id
;

在这里插入图片描述

  • 用户-角色-页面视图
create or replace view user_role_menu_v as
select distinct
       m.p_id || m.s_name || nvl(m.s_note,'') as s_name,
        m.s_WINp,
         m.s_PARM,
         m.p_id as pf_menu,
         m.s_note,
         --u.pf_role,
         u.pf_user,
         m.f_mod
from s_user_role u -- 用户 - 角色 = 功能视图
left join s_role_menu r on r.pf_role = u.pf_role
left join s_menu m on m.p_id = r.pf_menu
order by u.pf_user, m.p_id
;

在这里插入图片描述

  • 用户-页面视图
create or replace view user_page_v as
select s_name as label,
       pf_menu as url,
       s_winp as schemaApi,
       pf_user as userid,
       decode(substr(pf_menu,2,3),'000',1,2) as layer
from USER_ROLE_MENU_V -- 用户功能页面
where f_mod = 'BS'
;

在这里插入图片描述
这个视图就是最后动态菜单树要呈现的内容,label,url,schemaapi是amin-admin矿建的要求,userid为用户Id,layer为导航菜单的层级,我一般只用2级。

2 后端实现

前端登录时发送过来用户ID,根据用户id获得页面权限列表和token。后端我还是用REST2SQL来实现。

2.1 创建获取用户页面的函数

代码如下:

/ 获取用户页面
func getUserPages(userId string) map[string]interface{} {
	selectSQL := "select label,url,schemaApi,layer from user_page_v where userid = '" + userId + "'"

	//执行 sql并返回 json 结果
	logger.Alog(true, fmt.Sprint("getUserPage:", selectSQL))

	result := Icrud.SelectData(selectSQL)

	// json串反序列化
	var dataset []map[string]interface{}
	err := json.Unmarshal([]byte(result), &dataset)
	if err != nil {
		fmt.Println("Error:", err)
		return nil
	}

	rows := make(map[string]interface{})
	rows["rows"] = dataset
	return rows
}

输入参数用户ID,返回一个map。

2.2 doToken()函数的修改

用户验证成功后,获取用户页面功能列表。

// 根据请求参数执行不同的TOKEN操作 ///
func doTOKEN(w http.ResponseWriter, req map[string]interface{}) {
	// 返回数据
	rw := returnMap()

	rowsMap := make(map[string]interface{})

	tokenMap := make(map[string]interface{})
	// token操作, generate or validate
	resToken := strings.ToLower(req["ResName"].(string))
	switch resToken {
	case "generate-token":
		// w.Write([]byte("generate-token"))
		var uid_pwd map[string]string = make(map[string]string)
		uid_pwd["Userid"] = req["Userid"].(string)
		uid_pwd["Passwd"] = req["Passwd"].(string)
		// 用户名及密码验证
		ret1 := uidPwdIsValid(uid_pwd)

		if ret1 == 1 {
			//fmt.Println(ret1)
			tokenMap = token.GenerateTokenHandler(w, uid_pwd)
			rw["msg"] = "恭喜您登录成功!"
			// 获取功能页面列表
			rowsMap = getUserPages(uid_pwd["Userid"])
			//fmt.Println(rowsMap)

		} else {
			tokenMap["token"] = "无效用户Id:" + uid_pwd["Userid"] + "或密码" + uid_pwd["Passwd"]
			rw["status"] = 401
			rw["msg"] = "用户ID或密码无效!"
		}

		// http://127.0.0.1:5217/TOKEN/generate-token?userid=9998&passwd=8999

		// curl "http://127.0.0.1:5217/TOKEN/generate-token?userid=9998&passwd=8999"

	case "validate-token":
		//w.Write([]byte("validate-token"))
		var tokenString string = req["Authorization"].(string)
		fmt.Println(tokenString)
		tokenMap = token.ValidateTokenHandler(w, tokenString)

		// curl http://localhost:5217/token/validate-token -H "Authorization:token"
	}

	// 返回数据
	if tokenMap == nil {
		rw["status"] = 401
		rw["msg"] = "无效token"
	}
	dataMap := make(map[string]interface{})
	dataMap["rows"] = rowsMap["rows"]
	dataMap["token"] = tokenMap["token"]
	rw["data"] = dataMap

	// 输出到 http.ResponseWriter
	httpResWriter(w, rw)
}

就是返回token和用户页面列表,Json内容如下:


{
  "data": {
    "rows": [
      {
        "LABEL": "Z000系统管理",
        "LAYER": 1,
        "SCHEMAAPI": null,
        "URL": "Z000"
      },
      {
        "LABEL": "Z010页面管理",
        "LAYER": 2,
        "SCHEMAAPI": "page.json",
        "URL": "Z010"
      },
      {
        "LABEL": "Z020角色管理",
        "LAYER": 2,
        "SCHEMAAPI": "role.json",
        "URL": "Z020"
      },
      {
        "LABEL": "Z030角色功能权限设置",
        "LAYER": 2,
        "SCHEMAAPI": "role_menu.json",
        "URL": "Z030"
      },
      {
        "LABEL": "Z040用户管理",
        "LAYER": 2,
        "SCHEMAAPI": "user.json",
        "URL": "Z040"
      },
      {
        "LABEL": "Z050用户角色设置",
        "LAYER": 2,
        "SCHEMAAPI": "user_role.json",
        "URL": "Z050"
      }
    ],
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiI1NDQ0IiwicGFzc3dkIjoiNDQ0NSIsImV4cCI6MTcxMjE1MjE4NiwiaXNzIjoiNTIxN-iCoeWKoemZoiJ9.H13dcOP6I4LV-KbCKsr8kYmtO3_jwf3QJ3uvk7Goy2k"
  },
  "msg": "恭喜您登录成功!",
  "status": 0
}

用户页面是要按层级排序的。

3 前端实现

登录成功后,保存用户页面列表,主页获取导航site.json时加入,用户功能页面。

3.1 site.json页面

{
  "status": 0,
  "msg": "",
  "data": {
    "pages": [
      {
        "label": "Home",
        "url": "/",
        "redirect": "welcome"
      },
      {
        "label": "导航树",
        "children": [
          {
            "label": "Welcome to Json2Web",
            "url": "welcome",
            "schemaApi": "get:/pages/hello.json"
          }          
        ]
      },
      {
        "label": "示例",
        "children": [
          {
            "label": "REST2SQL",
            "link": "https://blog.csdn.net/html5builder/article/details/135544119"
          },
          {
            "label": "JSON2WEB",
            "link": "https://blog.csdn.net/html5builder/article/details/135698948"
          },
          {
            "label": "AMIS文档",
            "link": "https://aisuda.bce.baidu.com/amis/zh-CN/docs/index"
          }
        ]
      }
    ]
  }
}

动态页面菜单就加在【导航树】的节点下面。

3.2 login.html登录页面

只需要成功后,保存下来用户功能页面即可。api代码如下:

api: {
            url: 'http://127.0.0.1:5217/token/generate-token?userid=$userId&passwd=$passWd',
            method: 'get',
            adaptor: function (payload) {
              console.log(payload);
              if (payload.status === 0) {
                localStorage.setItem('token', payload.data.token);
                let rows = JSON.stringify(payload.data.rows)
                // console.log('rows',rows);
                localStorage.setItem('rows', rows);
                // localStorage.clear(); location.href = '/login.html';
                return payload;
              }
            }
          },

关键代码就两行:

	let rows = JSON.stringify(payload.data.rows)
	// console.log('rows',rows);
	localStorage.setItem('rows', rows);

先把json对象转为json字符串,在保存到loacaStorage中。

3.2 index.html主页

原来页面导航的api如下:

api:'/pages/site.json'

增加接收适配器代码如下:

api: {
          url: '/pages/site.json',
          adaptor: function (payload) {
            console.log('Payload', payload);
            // 页面权限字符串
            let rows = localStorage.getItem("rows");
            // 字符串转json
            let pageJson = JSON.parse(rows);
            console.log('pageJson:', pageJson);
            // 要插入菜单的节点
            let pages = payload.data.pages[1];
            console.log('pages:', pages);
            // 创建动态菜单

            pageJson.map(function (page) {
              let layers = page.LAYER;
              let labels = page.LABEL;
              let schemaApis = 'get:/pages/' + page.SCHEMAAPI;
              let urls = page.URL;
              let l1 = pages.children.length;
              
              if (layers == 1) {
                // 插入一级菜单               
                pages.children[l1] = {label:labels,"children":[]};
              } else {    
                // 插入二级菜单
                let l2 =  pages.children[l1 - 1].children.length;       
                pages.children[l1 - 1].children[l2] = {label:labels,url:urls,schemaApi:schemaApis};  
              };
            });
            // 返回
            return payload;
          }
        }

注:先取出保存的用户页面列表Json字符串并转为json对象方便操作,再定位要插入导航节点,三采用map循环创建动态菜单(根据层级构建,一级只有label,和children[];二级还有url和schemaapi)。

4 实操演练

4.1 登录

在这里插入图片描述
输入用户名和密码点【提交】即可。

4.2 欢迎页面

登录成功切换到主页的欢迎页面:

在这里插入图片描述

4.3 动态导航菜单加载成功

动态导航菜单加载成功,测试各页面操作正常。
在这里插入图片描述


本文完。

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

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

相关文章

Firefox 关键词高亮插件的简单实现

目录 1、配置 manifest.json 文件 2、编写侧边栏结构 3、查找关键词并高亮的方法 3-1) 如果直接使用 innerHTML 进行替换 4、清除关键词高亮 5、页面脚本代码 6、参考 1、配置 manifest.json 文件 {"manifest_version": 2,"name": &quo…

配置zookeeper的时候三个节点都启动了但是查询zookeeper的角色的时候显示没启动成功

场景 搭建了一个音乐平台数仓,一共有五个节点,其中三个节点配置zookeeper,我的操作是先把这三个节点的zookeeper全部启动,然后再分别查询各自zookeeper的角色。出现了一下问题: Error contacting service. It is proba…

网络层

网络层主要负责两方面的事情 1.地址管理:制定一系列的规则,通过地址,描述出网络中的设备的位置 2.路由选择:网络环境是非常复杂的。从一个节点到另外一个节点之间,存在很多条不同的路径,通过路由选择来筛…

【nc工具信息传输】

nc,全名叫 netcat,它可以用来完成很多的网络功能,譬如端口扫描、建立TCP/UDP连接,数据传输、网络调试等等,因此,它也常被称为网络工具的 瑞士军刀 。 nc [-46DdhklnrStUuvzC] [-i interval] [-p source_po…

3.恒定乘积自动做市商算法及代码

中心化交易所的安全风险 在中心化交易所中注册账户时,是由交易所生成一个地址,用户可以向地址充币,充到地址之后交易所就会根据用户充币的数量显示在管理界面中。但是充币的地址是掌管在交易所之中的,资产的控制权还是在交易所。…

【Java多线程(4)】案例:设计模式

目录 一、什么是设计模式? 二、单例模式 1. 饿汉模式 2. 懒汉模式 懒汉模式-第一次改进 懒汉模式-第二次改进 懒汉模式-第三次改进 一、什么是设计模式? 设计模式是针对软件设计中常见问题的通用解决方案。它们提供了一种被广泛接受的方法来解决…

【2024系统架构设计】案例分析- 5 Web应用

目录 一 基础知识 二 真题 一 基础知识 1 Web应用技术分类 大型网站系统架构的演化:高性能、高可用、可维护、应变、安全。 从架构来看:MVC,MVP,MVVM,REST,Webservice,微服务。

从头开发一个RISC-V的操作系统(一)计算机系统漫游

文章目录 前提计算机的硬件组成程序的存储与执行操作系统 目标:通过这一个系列课程的学习,开发出一个简易的在RISC-V指令集架构上运行的操作系统。 前提 这个系列的大部分文章和知识来自于:[完结] 循序渐进,学习开发一个RISC-V上…

element-ui divider 组件源码分享

今日简单分享 divider 组件,主要有以下两个方面: 1、divider 组件页面结构 2、divider 组件属性 一、组件页面结构 二、组件属性 2.1 direction 属性,设置分割线方向,类型 string,horizontal / vertical&#xff0…

AtCoder Beginner Contest 347 A~F

AtCoder Beginner Contest 347 A~F - 知乎 (zhihu.com) Tasks - AtCoder Beginner Contest 347 A.Divisible(循环) 代码 #include<bits/stdc.h> using namespace std;void solve() {int n, k;cin >> n >> k;for (int i 0; i < n; i) {int a;cin >…

如何申请Telegram机器人 | 推送通知

一、前言 利用Telegram机器人推送通知&#xff0c;需要在环境变量填入正确的TG_BOT_TOKEN以及TG_USER_ID&#xff0c;以下教程简明阐述如何获取Token以及UserID 二、获取步骤 1、首先在Telegram上搜索BotFather机器人。需要注意的是&#xff0c;搜索结果中选择ID为BotFather…

基于向量数据库搭建自己的搜索引擎

前言【基于chatbot】 厌倦了商业搜索引擎搜索引擎没完没了的广告&#xff0c;很多时候&#xff0c;只是需要精准高效地检索信息&#xff0c;而不是和商业广告“斗智斗勇”。以前主要是借助爬虫工具&#xff0c;而随着技术的进步&#xff0c;现在有了更多更方便的解决方案&…

Maven--lib分离的打包方式

就是把lib包和source源码分开打包。优势就是&#xff0c;面对频繁更新的应用场景时&#xff0c;可以只更新源码包&#xff08;当然&#xff0c;前提是你的依赖没有增减&#xff09;。尤其是使用jenkins更新项目时&#xff0c;会省去很多时间吧&#xff1f; 不同项目的 lib之间不…

【C++练级之路】【Lv.18】哈希表(哈希映射,光速查找的魔法)

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、哈希1.1 哈希概念1.2 哈希函数1.3 哈希冲突 二、闭散列2.1 数据类型2.2 成员变量2.3 默认成员函数2.…

保研线性代数复习3

一.基底&#xff08;Basis&#xff09; 1.什么是生成集&#xff08;Generating Set&#xff09;&#xff1f;什么是张成空间&#xff08;Span&#xff09;&#xff1f; 存在向量空间V(V&#xff0c;&#xff0c;*)&#xff0c;和向量集&#xff08;xi是所说的列向量&#xff…

【软件工程】概要设计

1. 导言 1.1 目的 该文档的目的是描述学生成绩管理系统的概要设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统结构简介 系统接口设计 数据设计 模块设计 界面设计 本文的预期读者是&#xff1a; 项目开发人员 项目管理人员 项目评测人员&#xff08;…

算法设计与分析实验报告python实现(串匹配问题、采用分治法求解最大连续子序列和问题、用分治策略求众数问题、最近点对问题)

一、 实验目的 1&#xff0e;加深学生对算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、串匹配问…

Docker安装mysql并且设置主从

Docker安装部署mysql 下载镜像 docker pull mysql:5.7.35查看镜像 docker images启动 直接启动不挂载文件 docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD123456 -d mysql:5.7.35挂载文件 docker run -p 3306:3306 --name mysql \ -v /usr/local/docker/m…

正则表达式与JSON序列化:去除JavaScript对象中的下划线键名

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

【Java EE】关于Maven

文章目录 &#x1f38d;什么是Maven&#x1f334;为什么要学Maven&#x1f332;创建⼀个Maven项目&#x1f333;Maven核心功能&#x1f338;项目构建&#x1f338;依赖管理 &#x1f340;Maven Help插件&#x1f384;Maven 仓库&#x1f338;本地仓库&#x1f338;私服 ⭕总结 …