Web开发学习7按钮级别权限控制

本文介绍了一种原创的权限控制思路,结合后台SpringSecurity拦截判断和前台ExtJS4动态渲染按钮。详细讲解了数据库表设计、角色与权限配置,以及如何在用户权限基础上实现前端按钮的加载和控制。通过角色和权限的多对多关系,实现不同用户对不同功能的访问控制。
摘要由CSDN通过智能技术生成
[size=large]这个功能的思路是自己原创的,没看过其他例子,其实是在做之前网上搜了很多也没个可以参考的例子.主要技术是后台springsecurity做拦截判断,前台Extjs4做按钮动态渲染.如果你不了解springsecrity,那你可以先看下我的另一篇相关博客

[b]创建数据库表(liqiubase方式创建看上一篇)[/b] [/size]


<createTable tableName="permissions">
<column name="id" type="bigint">
<constraints nullable="false" primaryKey="true" />
</column>
<!-- 权限名称 -->
<column name="name" type="varchar(32)" />
<!-- 该权限需要访问的链接 -->
<column name="actionurl" type="varchar(256)" />
<!-- 该权限需要用到的js -->
<column name="jsurl" type="varchar(256)" />
<!-- 权限等级 1主菜单 2子菜单 3及以下按钮 -->
<column name="level" type="int" />
<!-- 菜单父级id -->
<column name="parentid" type="bigint"/>
<!-- 排序编号 -->
<column name="ordernum" type="int" defaultValue="0"/>
</createTable>

[size=large]这张是权限表,也是菜单(按钮)表,每个菜单都有他自己需要访问链接的权限,当菜单类型为子菜单或按钮时还需要配置该按钮对应的js文件,对没错,每个按钮都有自己独立的js文件,在用户没有按钮权限的时候,前端是js都不需要加载的

[b]添加菜单初始数据[/b]
[/size]


<insert tableName="permissions">
<column name="id" value="1"/>
<column name="name" value="用户管理" />
<column name="level" value="1" />
<column name="parentid" value="-1"/>
<column name="ordernum" value="1"/>
</insert>
<insert tableName="permissions">
<column name="id" value="101"/>
<column name="name" value="账号管理" />
<column name="actionurl" value="account!query.action" />
<column name="jsurl" value="user/account/searchGrid" />
<column name="level" value="2" />
<column name="parentid" value="1"/>
<column name="ordernum" value="1"/>
</insert>
<insert tableName="permissions">
<column name="id" value="102"/>
<column name="name" value="角色管理" />
<column name="actionurl" value="" />
<column name="jsurl" value="user/role/mainPanel" />
<column name="level" value="2" />
<column name="parentid" value="1"/>
<column name="ordernum" value="2"/>
</insert>
<insert tableName="permissions">
<column name="id" value="1001"/>
<column name="name" value="新增" />
<column name="actionurl" value="account!save.action" />
<column name="jsurl" value="user/account/searchGridAddBtn" />
<column name="level" value="3" />
<column name="parentid" value="101"/>
<column name="ordernum" value="1"/>
</insert>
<insert tableName="permissions">
<column name="id" value="1004"/>
<column name="name" value="修改" />
<column name="actionurl" value="account!save.action,account!find.action" />
<column name="jsurl" value="user/account/searchGridUpdBtn" />
<column name="level" value="3" />
<column name="parentid" value="101"/>
<column name="ordernum" value="1"/>
</insert>


[size=large]添加了一个父级菜单用户管理,两个子集菜单账号管理和角色管理,同时在账号管理下添加两个按钮新增和修改,需要注意的是新增的授权链接是account!save.action而修改的授权链接是account!save.action,account!find.action,因为修改需要先查再能改,当用户被授予新增和修改两个权限的时候,访问account!save.action,account!find.action也就不会受阻了

[b]创建角色表和角色权限关联表[/b]
[/size]

<createTable tableName="roles">
<column name="id" type="bigint">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="rolename" type="varchar(32)" />
</createTable>

<insert tableName="roles">
<column name="id" value="1" />
<column name="rolename" value="超级管理员" />
</insert>
<createTable tableName="role_permission">
<column name="id" type="bigint">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="perid" type="bigint" />
<column name="roleid" type="bigint" />
</createTable>


[size=large]角色和权限是多对多的关系,一个角色可以有多个权限,一个权限也可以属于多个角色,
配完初始数据以后前台展示大致是这样的(图片太大请在新窗口打开)[/size]
[img]http://dl2.iteye.com/upload/attachment/0110/3935/d7e898bc-1efd-34b3-ab94-8f6a3f974b0d.jpg[/img]

[size=large]
拥有角色管理的的用户可以添加删除角色,同时可以为没每个角色分配权限
[b]创建用户角色关联表[/b]
[/size]

<createTable tableName="account_role">
<column name="accountid" type="bigint" />
<column name="roleid" type="bigint" />
</createTable>
<insert tableName="account_role">
<column name="accountid" value="1" />
<column name="roleid" value="1" />
</insert>

[size=large]
这里给admin初始化了id为1的角色,也就是超级管理员,同样
拥有账号管理里的用户可以为账号添加角色
[/size]
[img]http://dl2.iteye.com/upload/attachment/0110/3944/6dfbee3e-fa7b-38f8-a9d9-4957e702118b.jpg[/img]
[size=large]到这里数据的配置基本讲完了,再展示下初始数据的liqiubase文件,大致就是那几张表,
最后我再给游客2分配了几个权限,新增一个角色为游客2的账号[/size]
[img]http://dl2.iteye.com/upload/attachment/0110/3948/d595180d-68b6-3a56-ab41-b109ec4ec99e.jpg[/img]


[img]http://dl2.iteye.com/upload/attachment/0110/4029/66a7093a-30df-3742-bd72-6053889ceabc.jpg[/img]


[img]http://dl2.iteye.com/upload/attachment/0110/3956/f9e4412e-70e6-386c-9b56-0adbf4eeedc5.jpg[/img]

[size=large]以上展示的只是数据配置的过程,通俗的讲就是想法,
现在想法已经出来了,权限也分配好了真正的权限控制核心代码就开始了,首先展示下我的hibernate entity
[/size]

package cn.sdh.entity;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.struts2.json.annotations.JSON;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;

import cn.sdh.common.base.AuditEntity;

@SuppressWarnings("serial")
@Entity
@Table(name="accounts")
public class Account extends AuditEntity implements UserDetails {


public Account(){
}

public Account(Long id, String username, String password, String email,Date lastLoginTime, int userType){
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.lastLoginTime = lastLoginTime;
this.userType = userType;
}

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACCOUNT")
@SequenceGenerator(name = "SEQ_ACCOUNT", sequenceName = "SEQ_ACCOUNT", initialValue = 2, allocationSize = 1)
@Column(name="id")
private Long id;

@Column(name="username")
private String username;

@Column(name="password")
private String password;

@Column(name="email")
private String email;

//@Type(type="cn.sdh.common.userType.dateToInt")
@Column(name="lastlogintime")
private Date lastLoginTime;

private int userType;//用户类型-1:超级管理员 0普通用户 1+级用户

//是否在线
@Transient
private int isOnLine;

//搜索时间 起止
@Transient
private Date lastLoginTime1;

@Transient
private Date lastLoginTime2;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="account_role",joinColumns={@JoinColumn(name="accountid")},inverseJoinColumns={@JoinColumn(name="roleid")})
private List<Role> roles = new ArrayList<Role>();

@Transient
private File photo;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public List<Role> getRoles() {
return roles;
}

public void setRoles(List<Role> roles) {
this.roles = roles;
}

public Date getLastLoginTime() {
return lastLoginTime;
}

public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}

/**
* 告诉spring当前用户的角色
*/
@Override
@JSON(serialize=false)
public Collection<GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
for (Role role : this.getRoles()) {
authSet.add(new GrantedAuthorityImpl(role.getId().toString()));
}
return authSet;
}

@Override
@JSON(serialize=false)
public boolean isAccountNonExpired() {
return true;
}

@Override
@JSON(serialize=false)
public boolean isAccountNonLocked() {
return true;
}

@Override
@JSON(serialize=false)
public boolean isCredentialsNonExpired() {
return true;
}

@Override
@JSON(serialize=false)
public boolean isEnabled() {
return true;
}

public Date getLastLoginTime1() {
return lastLoginTime1;
}

public void setLastLoginTime1(Date lastLoginTime1) {
this.lastLoginTime1 = lastLoginTime1;
}

public Date getLastLoginTime2() {
return lastLoginTime2;
}

public void setLastLoginTime2(Date lastLoginTime2) {
this.lastLoginTime2 = lastLoginTime2;
}

public int getUserType() {
return userType;
}

public void setUserType(int userType) {
this.userType = userType;
}

public int getIsOnLine() {
return isOnLine;
}

public void setIsOnLine(int isOnLine) {
this.isOnLine = isOnLine;
}

@JSON(serialize=false)
public List<Permission> getSignPer(){

List<Permission> perList = new ArrayList<Permission>();

for(Role role : this.getRoles()){
List<Permission> sublist = role.getPermissionList();

for(int h = 0; h<sublist.size(); h++){
boolean continueFlag = false;

for(int j = 0;j<perList.size();j++){
if(role.getPermissionList().get(h).getId()==perList.get(j).getId()){
continueFlag = true;

break;
}

}

if(continueFlag){
continue;
}
if(role.getPermissionList().get(h).getLevel()==2){
role.getPermissionList().get(h).setLeaf(1);
}
role.getPermissionList().get(h).setChildren(null);
//role.getPermissionList().get(h).setControlType(role.getPermissionList().get(h).getControlType());
perList.add(role.getPermissionList().get(h));
}

}

return perList;
}

public File getPhoto() {
return photo;
}

public void setPhoto(File photo) {
this.photo = photo;
}

}



package cn.sdh.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.struts2.json.annotations.JSON;

import cn.sdh.common.base.AuditEntity;

/**
* 权限类(菜单,按钮,功能)
* @author 孙东辉
*/
@Entity
@Table(name="permissions")
public class Permission extends AuditEntity{

/**
*
*/
private static final long serialVersionUID = 7930766554705439940L;


@Id
@Column(name="id")
private Long id;


@Column(name="name")
private String name;

/**
* 访问地址
*/
@Column(name="actionurl")
private String actionUrl;

/**
* js文件地址
*/
@Column(name="jsurl")
private String jsUrl;

/**
* 等级 1-N
*/
@Column(name="level")
private int level;

/**
* 父级编号
*/
@Column(name="parentid")
private Long parentid;

/**
* 弹出的控件类
*/
@Transient
private String controlType;

@Transient
private int leaf;

@Transient
private boolean checked;

@Transient
private boolean expanded = true;

@OneToMany(fetch=FetchType.EAGER)
@JoinColumn(name = "parentid", referencedColumnName="id",insertable=false,updatable=false)
private List<Permission> children;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getActionUrl() {
return actionUrl;
}

public void setActionUrl(String actionUrl) {
this.actionUrl = actionUrl;
}

public String getJsUrl() {
return jsUrl;
}

public void setJsUrl(String jsUrl) {
this.jsUrl = jsUrl;
}

public int getLevel() {
return level;
}

public void setLevel(int level) {
this.level = level;
}

public Long getParentid() {
return parentid;
}

public void setParentid(Long parentid) {
this.parentid = parentid;
}

@JSON(name="text")
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getControlType() {
if(this.jsUrl!=null)
return getControlTypeByDg(this.jsUrl);
else
return this.controlType;
}

public void setControlType(String controlType) {
this.controlType = controlType;
}

public int getLeaf() {
if(this.level==3){
return 1;
}
return this.leaf;
}

public void setLeaf(int leaf) {
this.leaf = leaf;
}

public boolean isChecked() {
return checked;
}

public void setChecked(boolean checked) {
this.checked = checked;
}

public List<Permission> getChildren() {
return children;
}

public void setChildren(List<Permission> children) {
this.children = children;
}

public boolean isExpanded() {
return expanded;
}

public void setExpanded(boolean expanded) {
this.expanded = expanded;
}

/**
* 通过路径获得组件名称
* @param path
* @return
*/
public String getControlTypeByDg(String path){
if(path.indexOf("/")>=0){
path = path.replaceFirst(path.substring(path.indexOf("/"),path.indexOf("/")+2), path.substring(path.indexOf("/")+1,path.indexOf("/")+2).toUpperCase());

return getControlTypeByDg(path);
}else{
return path;
}

}

}



package cn.sdh.entity;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import cn.sdh.common.base.AuditEntity;

/**
* 角色类
* @author 孙东辉
*/
@Entity
@Table(name="roles")
public class Role extends AuditEntity{

/**
*
*/
private static final long serialVersionUID = 5459879676154477558L;

@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ROLE")
@SequenceGenerator(name = "SEQ_ROLE", sequenceName = "SEQ_ROLE", initialValue = 100, allocationSize = 1)
private Long id;

/**
* 角色名称
*/
@Column(name="rolename")
private String roleName;

/**
* 拥有的权限集合
*/
@ManyToMany(fetch = FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
@OrderBy("level")
@JoinTable(name="role_permission",joinColumns={@JoinColumn(name="roleid")},inverseJoinColumns={@JoinColumn(name="perid")})
private List<Permission> permissionList = new ArrayList<Permission>();


public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public List<Permission> getPermissionList() {
return permissionList;
}

public void setPermissionList(List<Permission> permissionList) {
this.permissionList = permissionList;
}

}



[size=large]Account作为springsecrity的账户类必须实现UserDetails接口,实现的getAuthorities方法是告诉spring当前用户的角色,还有个自定义方法getSignPer用于获取当前用户的权限列表,Permission类有个方法getControlTypeByDg通过配置的jsUrl链接获取Extjs的组件类名,他们的用处后面就能看到,这里补充下我用的是Hibernate的注解方式,严格来讲项目中除了公共配置部分,其他包括Struts Spring等需要xml配置的我全用了注解,如果你对注解不是很了解用xml配置的形式也是可以的

用户通过springsecrity登录成功的时候,会把Account对象保存它的上下文,然后访问这个跳转到主页的action方法,action方法中从springsecrity上下文中获取到Account后通过getSignPer方法获取当前用户的权限(也就是菜单),下面就是用户cccq3y的菜单了
[/size]

/**
* 跳转到主页
*
* @throws JSONException
*/
public String index() throws JSONException {

entity = SpringSecurityUtils.getCurrentUser();

List<Permission> perList = entity.getSignPer();

HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("perList", perList);
request.setAttribute("perListJson", JSONUtil.serialize(perList));

return "index";
}



[img]http://dl2.iteye.com/upload/attachment/0110/4020/9f8e88f9-fd69-3a63-a9ec-34ac79a172d8.jpg[/img]
[size=large]当用户点击新增确认按钮时,浏览器会向后台提交一个表单,url为account!save.action,首先会被springsecrity的MyFilterInvocationSecurityMetadataSource拦截到[/size]

package cn.sdh.audit;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

import cn.sdh.common.exception.ServiceException;
import cn.sdh.entity.Permission;
import cn.sdh.entity.Role;
import cn.sdh.service.RoleService;
import cn.sdh.utils.MyCacheUtil;

/**
* 告诉spring当前访问链接 需要什么权限 在这边定义
* @author 孙东辉
*
*/
@Service
public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

@Autowired
private RoleService roleService;

public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {

//这个是当前访问的链接
String requestUrl = ((FilterInvocation) object).getRequestUrl();

//设置哪些页面不需要权限就可访问
if(requestUrl.indexOf("account!index.action") >= 0
|| requestUrl.indexOf("index.jsp") >= 0
|| requestUrl.indexOf("permission!queryBtnListByControlType.action") >= 0
|| requestUrl.indexOf("account!searchOnlineList.action")>=0
|| requestUrl.indexOf("queryDicDataByKey.action")>=0){
return null;
}

// 对于带参数的请求,截取?前面的uri
int urlIndex = requestUrl.indexOf("?");

if (urlIndex != -1) {
requestUrl = requestUrl.substring(0, urlIndex);
}

//如果第一位是/ 去掉
if(requestUrl.startsWith("/")){
requestUrl = requestUrl.substring(1);
}

//从缓存中取当前系统的所有角色
List<Role> roles = (List<Role>) MyCacheUtil.getRolesList();


if(roles == null || roles.size()==0){//如果缓存中没有

try {
roles = roleService.query();

//把角色放入缓存
MyCacheUtil.setRolesList(roles);
} catch (ServiceException e) {
throw new IllegalArgumentException(e.getMsg());
}
}

Collection<ConfigAttribute> c = new HashSet<ConfigAttribute>();
//遍历所有角色
List<Permission> permissionList = null;
if(roles.size()>0){
for(int i = 0;i<roles.size();i++){
permissionList = roles.get(i).getPermissionList();

for(int j = 0;j<permissionList.size();j++){
//如果权限中的actionUrl包含当前访问的链接,当说明现在这个角色是可以访问该链接的
if(permissionList.get(j)!=null&&permissionList.get(j).getActionUrl()!=null&&permissionList.get(j).getActionUrl().indexOf(requestUrl)>=0){
ConfigAttribute configAttribute = new SecurityConfig(roles.get(i).getId()+"");
c.add(configAttribute);
break;
}
}

}
}else{
return null;
}

//最后返回的是一个角色的集合,并且这些角色都是可以访问该链接的
return c;
}

public Collection<ConfigAttribute> getAllConfigAttributes() {

return null;
}

public boolean supports(Class<?> clazz) {

return true;
}

}

[size=large]返回的角色中应该有一个是游客2的id,然后再被MyAccessDecisionManager拦截到[/size]
package cn.sdh.audit;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

/**
* 自定义访问决定器 控制用户能否访问该链接
* @author sun
*
*/
public class MyAccessDecisionManager implements AccessDecisionManager {


public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {

//如果访问的页面没有权限限制 那么不做拦截继续访问 如果未空说明该页面不需要任何角色
// 注意这里的configAttributes 其实就是MyFilterInvocationSecurityMetadataSource返回的
if (configAttributes == null) {
return;
}

//如果有权限限制 那么需要迭代权限 验证用户所拥有的权限是否包含 当前页面的访问权限
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while (ite.hasNext()) {

//获取访问页面需要的权限
ConfigAttribute ca = ite.next();

//获取访问页面需要的权限的权限名称
String needRole = ((SecurityConfig) ca).getAttribute();

//迭代用户所拥有的权限
for (GrantedAuthority ga : authentication.getAuthorities()) {
//如果用户的其中一个权限满足 访问链接需要的其中一个权限,那么访问将继续
if (needRole.equals(ga.getAuthority())) {
return;
}
}
}
//否则 访问将被终止
throw new AccessDeniedException("没有权限访问");
}

public boolean supports(ConfigAttribute attribute) {
// TODO Auto-generated method stub
return true;
}

public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}



}

[size=large]注释写个很清楚了,把当前用户所拥有的角色和MyFilterInvocationSecurityMetadataSource返回的访问当前链接需要哪些角色,如果包含说明当前用户能访问该链接了,再没抛AccessDeniedException错误的情况下验证都通过

最后再说下前端代码,首先主页的jsp要根据权限加载js文件
[/size]

<!-- 根据权限加载js文件 -->
<s:iterator value="#request.perList" var="bean">
<s:if test="#bean.jsUrl!=null">
<script type="text/javascript" src="common/jscode/<s:property value="#bean.jsUrl"/>.js"></script>
</s:if>
</s:iterator>


[size=large]然后来感受下extjs4的强大之处了,首先我封装一个公共的权限工具条[/size]
/**
* 权限按钮工具条
*/
Ext.define("app.base.auditbar", {
extend : "Ext.toolbar.Toolbar",
alias : 'widget.auditbar',
initComponent : function() {
var me = this;

var call = function(){
var sme = me;

// 根据组件类型 获取它所有的按钮
Ext.Ajax.request({
url : 'permission!queryBtnListByControlType.action',
params : {
'entity.controlType' : me.compont
},
success : new app.ajaxHand({
success : function(result,scope) {
var btns = result.searchList;

for ( var i = 0; i < btns.length; i++) {
if(scope){
sme = scope;
}
sme.insert(i, [ {
xtype : btns[i].controlType,
text : btns[i].text
} ]);
}
}
},sme)

});
};

if(me.remote){
call();
}


if(me.searchItems){
if(!me.items){
me.items = [];
}
me.items =me.items.concat(['->', {
xtype : "searchItems",
items : me.searchItems
} ]);
}

me.callParent(me);
}
});

[size=large]然后是grid基类[/size]
Ext.define("app.base.grid", {
extend : "Ext.grid.Panel",

//日期
dateRender : function(){return Ext.util.Format.dateRenderer(app.constant.date_render);},

//日期加时间
datetimeRender : function(){return Ext.util.Format.dateRenderer(app.constant.datetime_render);},

//单元格编辑插件
editingPlugin : function(){ return Ext.create('Ext.grid.plugin.CellEditing',{});},

//行编辑插件
rowEditingPlugin : function(){return Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
errorSummary : false,
autoCancel: true
});},

//行复选框
selModelPlugin : function(){return Ext.create("Ext.selection.CheckboxModel");},

initComponent : function(){
var me = this;
if(me.paging){
me.bbar = Ext.create('app.base.paging',{
store:me.store
});
}
me.tbar = Ext.create('app.base.auditbar',{
compont : me.xtype,
searchItems : me.searchItems,
remote:me.auditbarEnable,
items : me.btns
});

this.callParent();
},

//添加行
addRow : function(){
this.store.insert(0,new (Ext.ModelManager.getModel(this.model)));
this.editing.cancelEdit();
if(this.editing){
this.editing.startEdit(0,0);
}
},

//删除行
deleteRow : function(){

var recode = this.getSelectionModel().getSelection();

this.store.remove(recode);
},

//验证选中行
checkSelectRow : function(count,tip){
if(!count){
count = 1;
}
tip = tip || "请"+(count!=1?"至少":"")+"选择一行要删除的记录";

var recode = this.getSelectionModel().getSelection();

if(recode.length==0||(count==1&&recode.length>1)){
app.alert(tip);
return false;
}

var usedata = [];
var ids = "";
for(var i = 0;i<recode.length;i++){
usedata.push(recode[i].data);
ids += recode[i].data.id;
if(i!=recode.length-1){
ids += ",";
}
}
usedata.unshift(ids);

return usedata;
}

});

[size=large]把当前组件的xtype作为参数,到后台获取对应的父级菜单,再根据用户拥有的按钮权限获取这个用户在当前组件的按钮权限,那么问题来了,我是如果通过xtype定位到那条权限数据的呢,真相是我在配置账号管理这个权限的时候配置的jsUrl为user/account/searchGrid然后通过上面Permission类自定义的getControlTypeByDg方法转成xtype,再来看看我的grid子类就清楚了[/size]
Ext.define("app.user.account.searchGrid", {
extend : "app.user.account.grid",
alias: 'widget.userAccountSearchGrid',

initComponent : function(){
var me = this;
me.editing = me.rowEditingPlugin();
Ext.apply(this,{
plugins : [me.editing],
paging : true,
selModel : me.selModelPlugin(),
searchItems :[{
fieldLabel : '用户名',
xtype : 'textfield',
labelAlign : 'right',
name : 'entity.username',
labelWidth : 45
},{
fieldLabel : '邮箱',
xtype : 'textfield',
labelAlign : 'right',
name : 'entity.email',
labelWidth : 45
},{
fieldLabel : '上次登录起',
xtype : 'datefield',
labelAlign : 'right',
name : 'entity.lastLoginTime1',
labelWidth : 75
},{
fieldLabel : '上次登录止',
xtype : 'datefield',
labelAlign : 'right',
name : 'entity.lastLoginTime2',
labelWidth : 75
}]
});

me.callParent();
}
});

[size=large]alias:widget.userAccountSearchGrid,这样就能和后台的权限做对应了,而且在点击菜单树的时候同样用到这个功能,我会根据当前被点击菜单的jsUrl属性转义成xtype,然后很方便的加载对应的组件,就这么简单.最后展示下我的js文件目录


[img]http://dl2.iteye.com/upload/attachment/0110/4032/fa508ba8-ae76-36ea-bbce-faa413ed1be7.jpg[/img]

写到这里差不多就结束了,写的有点乱,看不懂的可以加我qq探讨一下;

[/size]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值