帖子
帖子
用户
博客
课程
显示全部楼层
143
帖子
2
勋章
4万+
Y币

案例-模仿授权菜单(穿梭框、模态框、page等)

[复制链接]
发表于 2023-6-7 11:22:26
本帖最后由 yonyouhmm 于 2023-6-7 11:31 编辑

一、案例说明


此案例模仿“授权”功能菜单,给用户分配角色。使用应用构建完成此功能。主要涵盖常问的知识点:模态框、page组件、穿梭框的使用。授权页面如下:



二、对象建模

两个业务对象:用户、角色。


1、角色为单实体

角色(roleDefine)(创建角色参照)
roleName 角色名 文本
roleCode 角色编码 文本


2、用户为主子结构(子表保存所选角色)
用户(主表:userDefine
userName 用户名 文本
password 密码 文本
regDate 注册时间 日期

所选角色(用户子表:choosedRole
new2 角色编码 文本
roleDefine 角色名称 单选引用(上面的角色)


三、页面建模


1、角色  
构建单卡页面  维护几条数据。
穿梭框页面后续创建

创建角色参照

2、用户
构建主子页面  维护几条用户数据  只维护主表就行   
依据子表:所选角色 构建单卡带列表页面


四、授权页面开发
1、创建授权页面
依据用户构建列表页面,作为授权页面


2、调整授权页面
增加网格布局(两个单元格)每个单元格中增加多页签-一个子页签
第一个子页签将用户列表table拖入 原来的行内按钮删除  增加“已选角色”按钮
第二个子页签下增加page组件  关联构建的  已选角色 列表



3、前端脚本
授权页面中选择左侧用户列表中的数据   右侧展示用户的已选角色
  1. //有page组件的页面  需要使用此钩子函数  将page组件中的vm绑定到当前vm中
  2. viewModel.on('beforeSubPageRender', ({ vm, viewmeta }) => {
  3.   //将page组件对应的 已选角色列表 的vm  放到当前vm
  4.   if (viewmeta.cBillNo == 'userDefine2List') {
  5.     viewModel.roleViewModel = vm;
  6.     //已选角色列表 展示左侧点击选中的用户对应的子表 已选角色数据
  7.     viewModel.roleViewModel.on('beforeSearch', function (args) {
  8.       let userId = viewModel.getCache('userdefine_userId');
  9.       args.isExtend = true;
  10.       args.params.condition.simpleVOs = [
  11.         {
  12.           field: 'userDefine_id',
  13.           op: 'eq',
  14.           value1: userId
  15.         }
  16.       ];
  17.     });
  18.   }
  19. });

  20. //左侧用户列表选中后 将选中的用户id放入缓存
  21. viewModel.getGridModel().on('afterSelect', (args) => {
  22.   debugger;
  23.   let userId = viewModel.getGridModel().getRow(viewModel.getGridModel().getFocusedRowIndex()).id;
  24.   viewModel.setCache('userdefine_userId', userId);
  25.   //触发 右侧已选角色列表的查询
  26.   viewModel.roleViewModel.getCache('FilterViewModel').get('search').fireEvent('click');
  27. });

  28. //分配角色
  29. viewModel.get('button3vh').on('click', function (args) {
  30.   debugger;
  31.   let userId = viewModel.getGridModel().getRow(args.index).id;
  32.   // 打开模态框
  33.   let data = {
  34.     billtype: 'VoucherList', // 单据类型
  35.     billno: 'roleDefine2', // 单据号
  36.     params: {
  37.       mode: 'edit',
  38.       //传参
  39.       userId: userId
  40.     }
  41.   };
  42.   //打开一个单据,并在当前页面显示
  43.   cb.loader.runCommandLine('bill', data, viewModel);
  44. });
复制代码



4、页面效果


五、模态框、穿梭框页面开发
1、创建页面
业务对象角色中构建单列表页面


2、页面设计
  • 列表中原来的table删除
  • 增加穿梭框组件 打开备选区编辑器  修改cDataSourceName:"角色元数据uri"

  • 选中备选区 右侧属性 点字段设置  拖入字段  点同步设置 然后确定


  • 增加底部栏-按钮栏-取消、确认两个按钮  取消按钮绑定取消动作
  • 左侧层级选择第二层页面模板  打开编辑器 增加"templateType": "modal"属性。保存后,右侧属性设置宽度为800
  • 最终设计如下




3、前端脚本
  1. //页面加载后 根据params中的userId查询已分配的角色
  2. let hasRoles = [];
  3. let userId = viewModel.getParams().userId;
  4. viewModel.on('afterMount', (args) => {
  5.   if (userId) {
  6.     let result = cb.rest.invokeFunction(
  7.       'AT166892061D00000A.backApi.getHasRoles',
  8.       { userId: userId },
  9.       function (err, res) {},
  10.       viewModel,
  11.       { async: false }
  12.     );
  13.     hasRoles = result.result.res;
  14.    
  15.     //右侧已选区的数据 查询后setDataSource
  16.     //roledefine_1742294964902035463_table10ib_rightContainer   F12从yya中获取
  17.     viewModel.get('roledefine_1742294964902035463_table10ib_rightContainer').on('afterSetDataSource', function (data) {
  18.         debugger;
  19.         let gridModel = viewModel.get('roledefine_1742294964902035463_table10ib_rightContainer');
  20.         let b = viewModel.getCache('remark');
  21.         if (!b) {
  22.           let rightDataSource = [];
  23.           hasRoles.forEach((item) => {
  24.             rightDataSource.push({
  25.               id: item.roleDefine,//角色id
  26.               roleCode: item.roleDefine_roleCode,//角色编码
  27.               roleName: item.roleDefine_roleName,//角色名称
  28.               hasUserId: item.userDefine_id,//用户主表id
  29.               hasUserRoleId: item.id //用户的子表的id
  30.             });
  31.           });
  32.           viewModel.setCache('remark', 1);
  33.           gridModel.setState('dataSourceMode', 'local');
  34.           gridModel.setDataSource(rightDataSource);
  35.         } else {
  36.           viewModel.clearCache('remark');
  37.         }
  38.       });
  39.   }
  40.   
  41.   
  42. });

  43. //左侧备选区的数据 去除已经分配的数据
  44. viewModel.on('beforeSearch', (args) => {
  45.   if (hasRoles.length > 0) {
  46.     let hasRoleIds = hasRoles.map((item) => {
  47.       return item.roleDefine;
  48.     });
  49.     args.isExtend = true;
  50.     args.params.condition.simpleVOs = [
  51.       {
  52.         field: 'id',
  53.         op: 'nin',
  54.         value1: hasRoleIds
  55.       }
  56.     ];
  57.   }
  58. });

  59. //点确认将已选的角色保存到对应用户的角色子表中
  60. //这里保存的逻辑  是将原来用户的已选角色子表清空  然后从新插入?  
  61. //还是精准判断 进行增加和删除? 上面清空再新增  子表的id会变化  根据情况考虑
  62. //这里直接全部删除 然后从新增加
  63. //yya看下 左右穿梭时 gridModel中dataSource和rows中数据的区别
  64. viewModel.get('button47ac').on('click', function (args) {
  65.   let rows = viewModel.get('roledefine_1742294964902035463_table10ib_rightContainer').getRows();
  66.   //拼凑新增的数据
  67.   let insertData = [];
  68.   rows.forEach((item)=>{
  69.     insertData.push({
  70.       userDefine_id: userId,
  71.       roleDefine: item.id,
  72.       new2:item.roleCode
  73.     });
  74.   })
  75.   let result = cb.rest.invokeFunction("AT166892061D00000A.backApi.updateUserRoles", {insertData:insertData,userId:userId},
  76.   function(err, res){} ,viewModel,{async:false});
  77.   
  78.   //刷新父页面  关闭模态框
  79.   //viewModel.getCache('parentViewModel').execute('refresh');
  80.   //只触发右侧角色的从新查询
  81.   viewModel.getCache('parentViewModel').roleViewModel.getCache('FilterViewModel').get('search').fireEvent('click');
  82.   //关闭模态框
  83. **.**munication({type:'modal',payload:{data:false}});
  84. });
复制代码


4、后端脚本
  1. //getHasRoles
  2. let AbstractAPIHandler = require('AbstractAPIHandler');
  3.   class MyAPIHandler extends AbstractAPIHandler {
  4.    execute(request){
  5.      let userId = request.userId;
  6.      let sql = "select *, roleDefine.* from AT166892061D00000A.AT166892061D00000A.choosedRole where userDefine_id='"+userId+"'";
  7.      var res = ObjectStore.queryByYonQL(sql);
  8.      
  9.    return {res};
  10. }
  11. }
  12. exports({"entryPoint":MyAPIHandler});
复制代码
  1. //updateUserRoles
  2. let AbstractAPIHandler = require('AbstractAPIHandler');
  3.   class MyAPIHandler extends AbstractAPIHandler {
  4.    execute(request){
  5.      let insertData = request.insertData;
  6.      let userId = request.userId;
  7.      //清空子表
  8.      var object = {userDefine_id:userId};
  9.      var delRes = ObjectStore.deleteByMap("AT166892061D00000A.AT166892061D00000A.choosedRole",object,"userDefine2");
  10.      //新增子表
  11.      var insertRes = ObjectStore.insertBatch("AT166892061D00000A.AT166892061D00000A.choosedRole",insertData,"userDefine2");
  12.      
  13.    return {delRes:delRes,insertRes:insertRes};
  14. }
  15. }
  16. exports({"entryPoint":MyAPIHandler});
复制代码


五、演示界面
点击分配角色 弹出模态框 穿梭框左侧的数据去除已选角色   穿梭框右侧的数据显示已选角色




穿梭框中数据修改后  点击确定   授权页面右侧page数据更新

本帖子中包含更多资源,您需要 登录 才可以下载或查看,没有帐号?立即注册

X
赞一个
0
帖子
0
勋章
62
Y币
       老师您好,这个案例,查询死循环了。【//右侧已选区的数据 查询后setDataSource】,这一块的处理,在afterSetDataSource里面,处理setDataSource,页面死循环。请问这块如何处理的呢?
143
帖子
2
勋章
4万+
Y币
BIP138725 · 2023-12-8 17:20
老师您好,这个案例,查询死循环了。【//右侧已选区的数据 查询后setDataSource】,这一块的处理,在afterSetDataSource里面,处理setDataSource,页面死循环。请问这块如何处理的呢? ...

aftersetdatasource方法会死循环  代码中是通过setCache解决的 你可以调试一下
0
帖子
0
勋章
62
Y币
yonyouhmm · 2023-12-8 20:53aftersetdatasource方法会死循环  代码中是通过setCache解决的 你可以调试一下

多谢老师。我之前调试了,不知道为啥还是死循环,今天又调了一下,莫名就好了。
0
帖子
0
勋章
145
Y币
感谢分享
您需要登录后才可以回帖 登录

本版积分规则