Zhiqim Manager(知启蒙管理台)是知启蒙框架中最核心的基础组件,大部分后台组件和产品都依赖该组件。因为管理台提供了核心的系统配置、菜单、操作员、部门、角色等权限功能,以及6种皮肤样式可供选择

森中灵 最后提交于4月前 修复切换frame模式时未情况includeUrl
ZmrSessionUser.java17KB
/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_manager.htm
 *
 * Zhiqim Manager is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager;

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

import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpSessionUser;
import org.zhiqim.httpd.context.ZmlContexts;
import org.zhiqim.httpd.context.annotation.AnLogNot;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.annotation.AnGenerics;
import org.zhiqim.kernel.json.Jsons;
import org.zhiqim.kernel.model.lists.HashSetS;
import org.zhiqim.kernel.util.Arrays;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.dbo.ZmrMenu;
import org.zhiqim.manager.dbo.ZmrOperator;
import org.zhiqim.manager.rule.ZmrMenuRule;

/**
 * 操作员会话用户信息
 *
 * @version v1.0.0 @author zouzhigang 2015-5-28 新建与整理
 */
@AnAlias("ZmrSessionUser")
@AnLogNot
public class ZmrSessionUser extends HttpSessionUser implements ZmrConstants
{
    private ZmrOperator operator;
    
    @AnGenerics(ZmrMenu.class)
    private List<ZmrMenu> menuList;
    private String topFirstMenuCode;
    
    private HashSetS menuUrlRules = new HashSetS();
    private HashSetS menuAllRules = new HashSetS();
    
    private String includeUrl;
    private String welcomeUrl;
    private boolean sidebar = true;
    private long selectedDeptId;
    
    public ZmrSessionUser()
    {
        this.menuList = new ArrayList<ZmrMenu>();
    }
    
    public String getSessionName()
    {
        return operator.getOperatorCode();
    }
    
    public String getRootPath(String path)
    {
        return getContext().getRootPath(path);
    }
    
    public String getPathInContext(String path)
    {
        int ind = path.indexOf("?");
        if (ind != -1)
            path = path.substring(0, ind);
        
        String contextPath = getContext().getContextPath();
        if (!"/".equals(contextPath) && path.startsWith(contextPath))
            path = Strings.trimLeft(path, contextPath);
        
        return path;
    }
    
    /**********************************************************************************************/
    //初始创建,用于登录绑定前操作,使用init开头的方法,无需刷新到可能的共享会话
    /**********************************************************************************************/
    
    public ZmrSessionUser initOperator(ZmrOperator operator)
    {
        this.operator = operator;
        return this;
    }
    
    public ZmrSessionUser initMenuAll(HttpContext context, List<ZmrMenu> menuList) throws Exception
    {
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuUrl() == null)
            {//根菜单没有URL,不处理
                continue;
            }
            
            //解析变量,如${zhiqim_manager}
            String urls = ZmlContexts.parseZmlContent(context, menu.getMenuUrl());
            String[] urlArr = Arrays.toStringArray(urls);
            for (String url : urlArr)
            {//URL支持用逗号配置多个
                menuAllRules.add(url);
            }
        }
        
        return this;
    }
    
    public ZmrSessionUser initMenuList(HttpContext context, List<ZmrMenu> menuList) throws Exception
    {
        if (menuList == null || menuList.isEmpty())
            return this;

        this.menuList = menuList;
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuUrl() == null)
            {//根菜单没有URL,不处理
                continue;
            }
            
            //解析变量,如${zhiqim_manager}
            String urls = ZmlContexts.parseZmlContent(context, menu.getMenuUrl());
            menu.setMenuUrl(urls);
            
            String[] urlArr = Arrays.toStringArray(urls);
            for (String url : urlArr)
            {//URL支持用逗号配置多个
                menuUrlRules.add(url);
            }
        }
        
        //取顶级第一个栏目
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuType() == 1 && menu.getMenuLevel() == 1)
            {
                topFirstMenuCode = menu.getMenuCode();
                break;
            }
        }
        
        return this;
    }
    
    public ZmrSessionUser initWelcomeUrl(String welcomeUrl)
    {
        this.welcomeUrl = welcomeUrl;
        return this;
    }
    
    public ZmrSessionUser initIncludeUrl(String includeUrl)
    {
        this.includeUrl = includeUrl;
        return this;
    }
    
    /**********************************************************************************************/
    //中途设置,setOperator/setMenuList/setIncludeUrl/setSidebar,需要flush
    /**********************************************************************************************/
    
    /** 修改个人信息变化 */
    public void setOperator(ZmrOperator operator)
    {
        initOperator(operator).flush();
    }
    
    /** 修改菜单时权限变化 */
    public void setMenuList(List<ZmrMenu> menuList) throws Exception
    {
        initMenuList(getContext(), menuList).flush();
    }
    
    /** 由页面AJAX设置 */
    public void setIncludeUrl(String includeUrl)
    {
        initIncludeUrl(includeUrl).flush();
    }
    
    /** 由页面AJAX设置 */
    public void setSidebar(boolean sidebar)
    {
        this.sidebar = sidebar;
        this.flush();
    }
    
    /***************************************************************************************/
    //操作员相关信息
    /***************************************************************************************/
    
    public ZmrOperator getOperator()
    {
        return operator;
    }

    public String getOperatorCode()
    {
        return operator.getOperatorCode();
    }

    public String getOperatorName()
    {
        return operator.getOperatorName();
    }
    
    public String getOperatorPassSalt()
    {
        return operator.getOperatorPassSalt();
    }

    public int getOperatorType()
    {
        return operator.getOperatorType();
    }
    
    public int getOperatorTypeThenG()
    {
        return isSuperAdmin()?0:1;
    }
    
    public boolean isSuperAdmin()
    {
        return getOperatorType() == 0;
    }
    
    public boolean isAdmin()
    {
        return isSuperAdmin() || operator.getOperatorType() == 1;
    }
    
    public String getOperatorMobile()
    {
        return operator.getOperatorMobile();
    }

    public String getOperatorEmail()
    {
        return operator.getOperatorEmail();
    }

    /***************************************************************************************/
    //操作员参数相关信息
    /***************************************************************************************/
    
    public boolean hasOperatorParam(String key)
    {
        if (Validates.isEmptyBlank(operator.getOperatorParam()))
            return false;
        
        return Jsons.getString(operator.getOperatorParam(), key) != null;
    }
    
    public String getOperatorParam(String key)
    {
        if (Validates.isEmptyBlank(operator.getOperatorParam()))
            return null;
        
        return Jsons.getString(operator.getOperatorParam(), key);
    }
    
    public int getOperatorParamInt(String key)
    {
        if (Validates.isEmptyBlank(operator.getOperatorParam()))
            return -1;
        
        return Jsons.getInt(operator.getOperatorParam(), key);
    }
    
    public long getOperatorParamLong(String key)
    {
        if (Validates.isEmptyBlank(operator.getOperatorParam()))
            return -1;
        
        return Jsons.getLong(operator.getOperatorParam(), key);
    }
    
    /***************************************************************************************/
    //操作员权限相关信息
    /***************************************************************************************/
    
    public List<ZmrMenu> getMenuList()
    {
        return menuList;
    }

    public boolean hasAllRule(String path)
    {
        if (path == null)
            return false;

        return menuAllRules.contains(path);
    }
    
    public boolean hasMenuRule(String path)
    {
        if (path == null)
            return false;

        return menuUrlRules.contains(path);
    }
    
    /** 获取顶级栏目 */
    public List<ZmrMenu> getTopMenuList()
    {
        List<ZmrMenu> list = new ArrayList<>();
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuLevel() == 1 && menu.getMenuType() == 1)
                list.add(menu);
        }
        
        return list;
    }
    
    /** 获取顶级栏目 */
    public ZmrMenu getTopMenuFirst()
    {
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuLevel() == 1 && menu.getMenuType() == 1)
                return menu;
        }
        
        return null;
    }
    
    /** 判断存在子菜单 */
    public boolean hasChildMenu(String menuCode)
    {
        for (ZmrMenu menu : menuList)
        {
            if (menu.getParentCode().equals(menuCode) && menu.getMenuType() == 1)
                return true;
        }
        
        return false;
    }
    
    /** 获取第一个子菜单 */
    public ZmrMenu getChildMenuFirst(String menuCode)
    {
        for (ZmrMenu menu : menuList)
        {
            if (menu.getParentCode().equals(menuCode) && menu.getMenuType() == 1)
                return menu;
        }
        
        return null;
    }
    
    /** 获取子菜单列表 */
    public List<ZmrMenu> getChildMenuList(String menuCode)
    {
        List<ZmrMenu> list = new ArrayList<>();
        for (ZmrMenu menu : menuList)
        {
            if (menu.getParentCode().equals(menuCode) && menu.getMenuType() == 1)
                list.add(menu);
        }
        
        return list;
    }
    
    /** 通过子菜单获取顶级菜单 */
    public ZmrMenu getTopMenuByChild(String childMenuCode)
    {
        if (childMenuCode == null)
            return null;
        
        ZmrMenu child = null;
        for (ZmrMenu menu : menuList)
        {
            if (menu.getMenuCode().equals(childMenuCode))
            {
                if (menu.getMenuType() != 1 && menu.getMenuLevel() != 1)
                    return null;//不是二级菜单,暂时不支持
                
                child = menu;
                break;
            }
        }
        
        return (child == null)?null:getMenu(child.getParentCode());
    }
    
    /**
     * 获取选中的顶级菜单,和includeUrl比较,如果未找到则取第一个顶级菜单(除了02)
     * 
     * @param request           请求
     * @return                  选中的菜单
     */
    public String getSelectedTopMenuCodeOrFirstMenuCode(HttpRequest request)
    {
        return getSelectedTopMenuCode(request, topFirstMenuCode);
    }
    
    /**
     * 获取选中的顶级菜单,和includeUrl比较,如果未找到返回null(02_concise用到)
     * 
     * @param request           请求
     * @return                  选中的菜单
     */
    public String getSelectedTopMenuCode(HttpRequest request)
    {
        return getSelectedTopMenuCode(request, null);
    }
    
    /**
     * 获取选中的顶级菜单,和includeUrl比较,如果未找到取缺省值
     * 
     * @param request           请求
     * @param defaultMenuCode   缺省菜单
     * @return                  选中的顶级菜单
     */
    public String getSelectedTopMenuCode(HttpRequest request, String defaultMenuCode)
    {
        ZmrMenu menu = getMenu(request);
        if (menu == null || menu.getMenuLevel() == 0)
            return defaultMenuCode;
        
        if (menu.getMenuLevel() == 1)
        {//顶级
            return menu.getMenuType() == 1?menu.getMenuCode():defaultMenuCode;
        }
     
        while(true)
        {//大于顶级循环找到顶级为止
            menu = getMenu(menu.getParentCode());
            if (menu == null)
                return null;
            
            if (menu.getMenuLevel() > 1)
                continue;
            
            return menu.getMenuType() == 1?menu.getMenuCode():defaultMenuCode;
        }
    }
    
    /**
     * 获取选中的二级菜单,和includeUrl比较,如果未找到返回null
     * 
     * @param request           请求
     * @return                  对应的二级菜单
     */
    public String getSelectedSecondMenuCode(HttpRequest request)
    {
        ZmrMenu menu = getMenu(request);
        if (menu == null || menu.getMenuLevel() <= 1)
            return null;
        
        if (menu.getMenuLevel() == 2)
        {//二级
            return menu.getMenuType() == 1?menu.getMenuCode():null;
        }
     
        while(true)
        {//大于二级循环找到二级为止
            menu = getMenu(menu.getParentCode());
            if (menu == null)
                return null;
            
            if (menu.getMenuLevel() > 2)
                continue;
            
            return menu.getMenuType() == 1?menu.getMenuCode():null;
        }
    }
    
    public ZmrMenu getMenu(String menuCode)
    {
        for (ZmrMenu menu : menuList)
        {
            if (menuCode.equals(menu.getMenuCode()))
                return menu;
        }
        
        return null;
    }
    
    public ZmrMenu getMenu(HttpRequest request)
    {
        if (includeUrl == null)
        {//没有指定内部页
            return getMenuByPath(request.getPathInContext());
        }
        
        String path = getPathInContext(includeUrl);
        ZmrMenu menu = getMenuByPath(includeUrl);
        if (menu != null)
        {//本身是菜单页
            return menu;
        }
        
        //再检查是否菜单属性页
        path = ZmrMenuRule.getMenuUrl(path);
        if (path == null)
            return getMenuByPath(request.getPathInContext());
        else
            return getMenuByPath(path);
    }
    
    /** 通过路径找到菜单,级别大的优先 */
    public ZmrMenu getMenuByPath(String pathInContext)
    {
        ZmrMenu selected = null;
        for (ZmrMenu menu : menuList)
        {
            if (Validates.isNotEmpty(menu.getMenuUrl()) && menu.getMenuUrl().contains(pathInContext))
            {
                if (selected == null || selected.getMenuLevel() < menu.getMenuLevel())
                    selected = menu;
            }
        }
        
        return selected;
    }
    
    /**************************************************************************************/
    //框架时左右相关信息
    /**************************************************************************************/
    
    public String getIncludeUrl()
    {
        return includeUrl;
    }
    
    public boolean isWelcomeUrl()
    {
        return Validates.isEqual(welcomeUrl, includeUrl);
    }

    public boolean hasSidebar()
    {
        return sidebar;
    }

    public String getSidebarClass()
    {
        return sidebar?"":"z-hide";
    }

    /**************************************************************************************/
    //头像相关信息
    /**************************************************************************************/
    
    public long getOperatorAvatar()
    {
        return operator.getOperatorAvatar();
    }
    
    public String getAvatar50()
    {
        return operator.getOperatorAvatar()==0?getRootPath(_PATH_SERVICE_RES_AVATAR_):getAvatarUrl(getOperatorAvatar(), 50);
    }

    public String getAvatar100()
    {
        return operator.getOperatorAvatar()==0?getRootPath(_PATH_SERVICE_RES_AVATAR_):getAvatarUrl(getOperatorAvatar(), 100);
    }
    
    public String getAvatar150()
    {
        return operator.getOperatorAvatar()==0?getRootPath(_PATH_SERVICE_RES_AVATAR_):getAvatarUrl(getOperatorAvatar(), 150);
    }
    
    public String getAvatarUrl(long avatarId, int avatarSize)
    {
        return getRootPath(new StringBuffer("/").append(getContext().getAttribute(ZMR_PATH)).append("/avatar/").append(avatarId).append("/").append(avatarSize).append(".png").toString());
    }
    
    /**************************************************************************************/
    //部门默认选中,用于数据权限时在各页面切换默认选中
    /**************************************************************************************/
    
    public void setSelectedDeptId(long deptId)
    {
        this.selectedDeptId = deptId;
        this.flush();
    }
    
    public long getSelectedDeptId()
    {
        return selectedDeptId;
    }
    
    public long getSelectedDeptId(long defaultValue)
    {
        return selectedDeptId == 0?defaultValue:selectedDeptId;
    }
}