【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_modfrom 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_ynfrom 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 distinctm.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"] = datasetreturn 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 validateresToken := 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"] = 401rw["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"] = 401rw["msg"] = "无效token"}dataMap := make(map[string]interface{})dataMap["rows"] = rowsMap["rows"]dataMap["token"] = tokenMap["token"]rw["data"] = dataMap// 输出到 http.ResponseWriterhttpResWriter(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");// 字符串转jsonlet 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 动态导航菜单加载成功

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


本文完。

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

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

相关文章

Day:004(1) | Python爬虫:高效数据抓取的编程技术(数据解析)

数据解析-正则表达式 在前面我们已经搞定了怎样获取页面的内容,不过还差一步,这么多杂乱的代码夹杂文字我们怎样 把它提取出来整理呢?下面就开始介绍一个十分强大的工具,正则表达式! 正则表达式是对字符串操作的一种…

RabbitMQ3.13.x之七_RabbitMQ消息队列模型

RabbitMQ3.13.x之七_RabbitMQ消息队列模型 文章目录 RabbitMQ3.13.x之七_RabbitMQ消息队列模型1. RabbitMQ消息队列模型1. 简单队列2. Work Queues(工作队列)3. Publish/Subscribe(发布/订阅)4. Routing(路由)5. Topics(主题)6. RPC(远程过程调用)7. Publisher Confirms(发布者…

不同设备使用同一个Git账号

想要在公司和家里的电脑上用同一个git账号来pull, push代码 1. 查看原设备的用户名和邮箱 第1种方法, 依次输入 git config user.name git config user.email第2种方法, 输入 cat ~/.gitconfig2. 配置新设备的用户名和邮箱 用户名和邮箱与原设备保持…

vue结合Elempent-Plus/UI穿梭框更改宽度以及悬浮文本显示

由于分辨率不同会导致文本内容显示不全,如下所示: 因此需要 1、悬浮到对应行上出现悬浮信息 实现代码如下所示: 这里只演示Vue3版本代码,Vue2版本不再演示 区别就在插槽使用上Vue3使用:#default“”;Vu…

网络安全教学

如今,组织的信息系统和数据面临着许多威胁。而人们了解网络安全的所有基本要素是应对这些威胁的第一步。 网络安全是确保信息完整性、机密性和可用性(ICA)的做法。它代表了应对硬盘故障、断电事故,以及来自黑客或竞争对手攻击等防御和恢复能力。而后者包…

clickhouse MPPDB数据库--新特性使用示例

clickhouse 新特性: 从clickhouse 22.3至最新的版本24.3.2.23,clickhouse在快速发展中,每个版本都增加了一些新的特性,在数据写入、查询方面都有性能加速。 本文根据clickhouse blog中的clickhouse release blog中,学…

C++数据结构与算法——二叉树的修改与构造

C第二阶段——数据结构和算法,之前学过一点点数据结构,当时是基于Python来学习的,现在基于C查漏补缺,尤其是树的部分。这一部分计划一个月,主要利用代码随想录来学习,刷题使用力扣网站,不定时更…

Redis Desktop Manager可视化工具

可视化工具 Redis https://www.alipan.com/s/uHSbg14XmsL 提取码: 38cl 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。 官网下载(不推荐):http…

SALESFORCE MODEL 简单记录

SALESFORCE MODEL 简单记录,在以下地址可以看到一些salesforce的模型资料 https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_list.htmhttps://architect.salesforce.com/diagrams#framework

2024054期传足14场胜负前瞻

2024054期售止时间为4月7日(周日)20点30分,敬请留意: 本期深盘多,1.5以下赔率3场,1.5-2.0赔率6场,其他场次是平半盘、平盘。本期14场难度中等。以下为基础盘前瞻,大家可根据自身判断…

Spring Cloud介绍

一、SpringCloud总体概述 Cloud Foundry Service Broker:通用service集成进入Cloud Foundry Cluster:服务集群 Consul:注册中心 Security:安全认证 Stream:消息队列 Stream App Starters:Spring Cloud Stre…

记第一次eudsrc拿到RCE(下)

目录 前言 个人介绍 挖洞公式 漏洞介绍 信息泄露漏洞 任意文件读取漏洞 远程命令执行(RCE)漏洞 漏洞详情 漏洞点1 漏洞点2 漏洞点3 修复建议 总结 前言 免责声明 以下漏洞均已经上报漏洞平台。请勿利用文章内的相关技术从事非法测试。若因…

基于python爬虫与数据分析系统设计

**单片机设计介绍,基于python爬虫与数据分析系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于Python爬虫与数据分析系统的设计是一个结合了网络数据抓取、清洗、存储和数据分析的综合项目。这样的系统通常…

【javaWeb Maven高级】Maven高级学习

Maven高级学习 分模块设计继承与聚合继承版本锁定聚合 私服资源的上传与下载本地私服配置 分模块设计 为什么需要进行分模块设计? 将项目按照功能拆分成若干个子模块,方便项目的管理维护,扩展,也方便模块间的相互调用&#xff0c…

vue 打包 插槽 inject reactive draggable 动画 foreach pinia状态管理

在Vue项目中,当涉及到打包、插槽(Slots)、inject/reactive、draggable、transition、foreach以及pinia时,这些都是Vue框架的不同特性和库,它们各自在Vue应用中有不同的用途。下面我将逐一解释这些概念,并说…

vue2项目安装(使用vue-cli脚手架)

使用npm安装 安装镜像(使npm创建项目更快):镜像可更换 npm config set registry https://registry.npmmirror.com1.全局安装vue-cli(一次) npm install -g vue/cli 2. 查看vue-cli 版本 vue --version 3. 创建项目…

HTTP详解及代码实现

HTTP详解及代码实现 HTTP超文本传输协议 URL简述状态码常见的状态码 请求方法请求报文响应报文HTTP常见的HeaderHTTP服务器代码 HTTP HTTP的也称为超文本传输协议。解释HTTP我们可以将其分为三个部分来解释:超文本,传输,协议。 超文本 加粗样…

ObjectiveC-08-OOP面向对象程序设计-类的分离与组合

本节用一简短的文章来说下是ObjectiveC中的类。类其实是OOP中的一个概念,概念上简单来讲类是它是一组关系密切属性的集合,所谓的关系就是对现实事物的抽象。 上面提到的关系包括很多种,比如has a, is a,has some等&…

jenkins+docker实现可持续自动化部署springboot项目

目录 一、前言 二、微服务带来的挑战 2.1 微服务有哪些问题 2.2 微服务给运维带来的挑战 三、可持续集成与交付概述 3.1 可持续集成与交付概念 3.1.1 持续集成 3.1.2 持续交付 3.1.3 可持续集成与交付核心理念 3.2 可持续集成优点 3.3 微服务为什么需要可持续集成 四…

【JVM】如何定位、解决内存泄漏和溢出

目录 1.概述 2.堆溢出、内存泄定位及解决办法 2.1.示例代码 2.2.抓堆快照 2.3.分析堆快照 1.概述 常见的几种JVM内存溢出的场景如下: Java堆溢出: 错误信息: java.lang.OutOfMemoryError: Java heap space 原因:Java对象实例在运行时持…