【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.hqwc.cn/news/591981.html

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

相关文章

非写代码无以致远

标题党一下&#xff0c;本篇文章主要汇总了一些代码题&#xff0c;让大家写一些代码练习一下吧&#xff01; 变种水仙花_牛客题霸_牛客网 (nowcoder.com) #include<stdio.h> int main() {for (int i 10000; i < 99999; i) {int sum 0;for (int j 10; j < 1000…

多IP数字证书450元一年送一月

IP数字证书是一种特殊的数字证书。因为互联网的发展和普及&#xff0c;现在大多数网站都是进行了域名解析的域名网站&#xff0c;使用的也是由正规证书颁发机构(CA)颁发的域名数字证书。而IP数字证书则是由证书颁发机构(CA)为只有公网IP地址的网站颁发的数字证书。今天就随SSL盾…

无法打开pycharm虚拟环境

问题&#xff1a;在pycharm的terminal中执行pip命令&#xff0c;但是下载的包没有安装到该项目的虚拟环境中。 激活虚拟环境&#xff0c;打开terminal&#xff0c;执行myenv\Scripts\activate&#xff0c;显示执行出错 无法加载文件 D:\Project\RF_Project\venv\Scripts\acti…

c++的学习之路:10、string(2)

本章主要说一下模拟实现string类的部分功能&#xff0c;文章末附上所有代码。 目录 一、构造函数与析构函数 二、拷贝构造 三、c_str 四、【】和迭代器的遍历与访问 五、size 六、判断 七、reserve 八、push_back 九、resize 十、append 十一、 十二、insert 十…

JS详解-函数柯里化

简介&#xff1a; 柯里化&#xff08;Currying&#xff09;是一种关于函数的高阶技术。柯里化是一种函数的转换&#xff0c;它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。柯里化不会调用函数。它只是对函数进行转换。 举个例子&#xff1a; 已最简单的…

789. 数的范围 (二分学习)左端大右,右端小左

题目链接https://www.acwing.com/file_system/file/content/whole/index/content/4317/ 当求左端点时&#xff0c;条件是a【mid】大于等于x&#xff0c;并把右端点缩小。 当求右端点时&#xff0c;条件是a【mid】小于等于x&#xff0c;并把左端点扩大。 1.确定一个区间&…

Linux--进程(2)

目录 前言 1. 进程的状态 1.1 进程排队 1.2 运行&#xff0c;阻塞&#xff0c;挂起 2.Linux下具体的进程状态 2.1僵尸和孤儿 3.进程的优先级 4.Linux的调度与切换 前言 这篇继续来学习进程的其它知识 上篇文章&#xff1a;Linux--进程&#xff08;1&#xff09;-CS…

数据库管理工具 DBeaverUE for Mac激活版

DBeaverUE for Mac是一款功能强大且易于使用的数据库管理工具&#xff0c;专为Mac用户设计。它支持多种数据库类型&#xff0c;如MySQL、PostgreSQL、Oracle等&#xff0c;使得用户可以轻松管理和操作各种数据库。 软件下载&#xff1a;DBeaverUE for Mac激活版下载 DBeaverUE …

Prometheus+grafana环境搭建方法及流程两种方式(docker和源码包)(一)

1.选型对比 最近项目上有对项目服务及中间件的监控需求&#xff0c;要做实现方案调研&#xff0c;总结一下自己的成果&#xff0c;目前业界主流可选的方案有&#xff1a; 国外开源&#xff1a; Prometheus&#xff1a;Prometheus - Monitoring system & time series dat…

gpt国内怎么用?最新版本来了

claude 3 opus面世后&#xff0c;这几天已经有许多应用&#xff0c;而其精确以及从不偷懒&#xff08;截止到2024年3月11日还没有偷懒&#xff09;的个性&#xff0c;也使得我们可以用它来首次完成各种需要多轮对话的尝试。 今天我们想要进行的一项尝试就是—— 如何从一个不知…

『VUE』11. 操作数组的方法(详细图文注释)

目录 vue中操作数组的方法会修改原数组的 会进行渲染更新不修改原数组的 不会进行渲染更新 push自动渲染concat 赋值渲染总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 vue中操作数组的方法 vue中数组数据呈现在网页,只检测…

基于卷积神经网络的鸟类识别系统(pytorch框架)【python源码+UI界面+前端界面+功能源码详解】

功能演示&#xff1a; 鸟类识别系统&#xff0c;基于vgg16&#xff0c;resnet50卷积神经网络&#xff08;pytorch框架&#xff09;_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积神经网络的鸟类识别系统是在pytorch框架下实现的&#xff0c;系统中有两个模型可…