<?php
namespace model;

use model\wdzy\user as WdzyUser;

/**
 * Class user
 * @package model
 */
class user extends \model\element
{
	public $realm = 'YIPARTS CATALOG SYSTEM';
	/**
	 * @param array|string $elecfg 配置数据或者配置element名称
	 */
	public function __construct($elecfg='user')
    {
		parent::__construct($elecfg);
	}
	
    /**
     * 工作台信息
     */
	function getWorkData($uid){
	    $sample = new \model\sample\sample();
        return [
            //子状态文本对照
            'stateText'=>$sample->plmstateText,
            
            //样品流程状态统计
            'processCount'=>$sample->getStateCount(), 
            
            //等待初审-所有&用户
            'allWaitCheck1'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_apply_comp'=>1,'s_check1'=>0,'s_check1_no_reason'=>'']),
            'userWaitCheck1'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_apply_comp'=>1,'s_check1'=>0,'s_check1_no_reason'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //等待复审-所有&用户
            'allWaitCheck2'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check1'=>1,'s_check2'=>0,'s_check2_no_reason'=>'']),
            'userWaitCheck2'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check1'=>1,'s_check2'=>0,'s_check2_no_reason'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //等待终审-所有&用户
            'allWaitCheck3'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check2'=>1,'s_check3'=>0,'s_check3_no_reason'=>'']),
            'userWaitCheck3'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check2'=>1,'s_check3'=>0,'s_check3_no_reason'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //等待采购-所有&用户
            'allWaitPurc'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3'=>1,'s_has_comein'=>0]),
            'userWaitPurc'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3'=>1,'s_has_comein'=>0,
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            
            //等待目录组审核-所有&用户
            'allWaitCheckSales'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_has_comein'=>1,'s_check_sales'=>0]),
            'userWaitCheckSales'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_has_comein'=>1,'s_check_sales'=>0,
                'OR'=>[
                    's_apply_user'=>$uid,
                    's_sign_opuser'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //等待技术部审核-所有&用户
            'allWaitCheckTech'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_sales'=>1,'s_check_tech'=>0,'s_check_tech_reason'=>'']),
            'userWaitCheckTech'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_sales'=>1,'s_check_tech'=>0,
                'OR'=>[
                    's_apply_user'=>$uid,
                    's_sign_opuser'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            
            //初审驳回-所有&用户
            'allNotCheck1'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check1_no_reason[!]'=>'']),
            'userNotCheck1'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check1_no_reason[!]'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //复审驳回-所有&用户
            'allNotCheck2'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check2_no_reason[!]'=>'']),
            'userNotCheck2'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check2_no_reason[!]'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //终审驳回-所有&用户
            'allNotCheck3'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3_no_reason[!]'=>'']),
            'userNotCheck3'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3_no_reason[!]'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            
            //目录组驳回-所有&用户
            'allNotCheckSales'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_sales_reason[!]'=>'']),
            'userNotCheckSales'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_sales_reason[!]'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    's_sign_opuser'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            //待技术部驳回-所有&用户
            'allNotCheckTech'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_tech_reason[!]'=>'']),
            'userNotCheckTech'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_check_tech_reason[!]'=>'',
                'OR'=>[
                    's_apply_user'=>$uid,
                    's_sign_opuser'=>$uid,
                    'RAW1'=> raw(" exists (select 1 from sample_follow where sf_s_id = s_id and sf_au_id='".getOpuser()."' limit 1)"),
                ]
            ]),
            
            //样品子状态统计-技术部审核过的-未编码的-所有
            'allSubStateCount'=>$this->db->select('sample'
                ,['s_state_sub'=>["total" => raw("COUNT(DISTINCT s_id)")]]
                ,[
                    'GROUP'=>['s_state_sub']
                    ,'s_stop'=>0,'s_check_tech'=>'1','s_outnum'=>''
                ]), 
            //样品子状态统计-技术部审核过的-未编码的-用户
            'userSubStateCount'=>$this->db->select('sample'
                ,['s_state_sub'=>["total" => raw("COUNT(DISTINCT s_id)")]]
                ,[
                    'GROUP'=>['s_state_sub']
                    ,'s_stop'=>0,'s_check_tech'=>'1','s_outnum'=>'','s_apply_user'=>$uid
                ]), 
                
            //采购人未采购的&用户
            'allNotPurc'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3'=>1,'s_has_purc'=>0]),
            'userNotPurc'=> $this->db->count('sample','s_id',['s_stop'=>0,'s_form'=>0,'s_check3'=>1,'s_has_purc'=>0,'s_purc_user'=>$uid]),
            
            //待进入交叉索引
            'allNumidxTemp'=> $this->db->count('pro_numidx_temp','pnt_id',['pnt_status'=>1]),
            //待进入交叉索引-等待初审
            'allNumidxTempWaitCheck1'=> $this->db->count('pro_numidx_temp','pnt_id',['pnt_status'=>1,'ck1'=>0]),
            //待进入交叉索引-等待复审
            'allNumidxTempWaitCheck2'=> $this->db->count('pro_numidx_temp','pnt_id',['pnt_status'=>1,'ck1'=>1,'ck2'=>0]),
            //待进入车型
            'allModelTemp'=> $this->db->count('pro_model_link_temp','pmlt_id',['pmlt_status'=>1]),
            //待进入车型-等待初审
            'allModelTempWaitCheck1'=> $this->db->count('pro_model_link_temp','pmlt_id',['pmlt_status'=>1,'ck1'=>0]),
            //待进入车型-等待复审
            'allModelTempWaitCheck2'=> $this->db->count('pro_model_link_temp','pmlt_id',['pmlt_status'=>1,'ck1'=>1,'ck2'=>0]),
        ];
	}
	
    /**
     * 得到记录全量信息
     * @param id|row $var id或者行记录
     * @return array
     * @return string
     */
	function getRowInfo($var){
        $row = $var;
		if(!is_array($var)){
            $row = $this->getRowByKey($var);
        }
        $row['captions']['au_id'] = $row['au_name'];
        $row['captions']['au_depa'] = $this->db->get('object','cn_name',['o_id'=>$row['au_depa']]);
        $row['captions']['au_area'] = $this->db->get('object','cn_name',['o_id'=>$row['au_area']]);
        return $row;
	}


    //批量设置所有非admin用户的密码为 123456
    public function updateAllPassTo123456NoExitsAdmin(){
        /*
        $rows = $this->db->select($this->table,'*',['au_id[!]'=>'admin']);
		foreach($rows as $row){
			if($row['au_id']!='admin'){
				$password = $this->pass2($row['au_id'],'123456');
				$this->db->update($this->table,['au_pass'=>$password],['au_id'=>$row['au_id']]);
			}
		}
		*/
    }

    public function getAdminAuid($value){
        $value = trim($value);
        $where = ['OR'=>[
                    'au_id'=>$value,
                    'au_name'=>$value
                    ]
                 ];
        return $this->db->get('adm_user',"au_id",$where);
    }

	/**
	 * 取用户的权限
	 * @param string $uid
	 * @param string $user_link_role //用户与角色关联表
	 * @return bool
	 */
	function getPowersByUid($uid,$user_link_role='adm_user_link_role'){
        if(empty($uid)){
            return [];
        }
        if($user_link_role=='adm_user_link_role'){
            $urfield = [
                'ar_id'=>'ault_ar_id',
                'au_id'=>'ault_au_id',
            ];
        }elseif($user_link_role=='frey_user_link_role'){
            $urfield = [
                'ar_id'=>'ult_ur_id',
                'au_id'=>'ult_u_id',
            ];
        }else{
            return [];
        }
        //用户所有角色
        $rows = $this->db->select('power_role_link'
            ,[
                '[>]'.$user_link_role=>['prl_ar_id'=>$urfield['ar_id']],
                '[>]power'=>['prl_power_code'=>'power_code']
             ]
            ,'power_name,power_role_link.*'
            ,[$urfield['au_id']=>$uid,'prl_value[>]'=>0,'power_enable'=>1]
        );
        $data = [];
        if($uid==='admin' || $uid==='frey.admin' || $uid==='test.admin' || $uid==='grid' || $uid=='daiff'||$uid==='admin888'){
            $data['isAdmin'] = true;
            return $data;
        }
        //合并权限
        foreach($rows as $row){
            //取产品参数  
            $row['params'] = [];
            if($prplRows = $this->db->select('power_role_param_link',
                ['prpl_cate','prpl_params'],
                [
                    'prpl_ar_id'=>$row['prl_ar_id'],
                    'prpl_power_code'=>$row['prl_power_code'],
                ]))
            {
                foreach($prplRows as $v){
                    if($v['prpl_params']!='')
                        $row['params'][$v['prpl_cate']] = $v['prpl_params'];
                }
            }
            //合并
            $code = $row['prl_power_code'];
            if(isset($data[$code])){
                $data[$code]['prl_code']            = $code;
                $data[$code]['prl_ar_id']           .= ','.$row['prl_ar_id'];
                $data[$code]['prl_value']           = mergeXor($data[$code]['prl_value'],$row['prl_value']);
                //$data[$code]['prl_cates']           = mergeIds($data[$code]['prl_cates'],$row['prl_cates']);
                $data[$code]['prl_makes']           = mergeIds($data[$code]['prl_makes'],$row['prl_makes']);
                $data[$code]['prl_factorys']        = mergeIds($data[$code]['prl_factorys'],$row['prl_factorys']);
                $data[$code]['prl_vers']            = mergeIds($data[$code]['prl_vers'],$row['prl_vers']);
                $data[$code]['prl_areas']           = mergeIds($data[$code]['prl_areas'],$row['prl_areas']);
                $data[$code]['prl_companys']        = mergeIds($data[$code]['prl_companys'],$row['prl_companys']);
                $data[$code]['prl_users']           = mergeIds($data[$code]['prl_users'],$row['prl_users']);
                $data[$code]['prl_fields']          = mergeIds($data[$code]['prl_fields'],$row['prl_fields']);
                $data[$code]['prl_masters']          = mergeIds($data[$code]['prl_masters'],$row['prl_masters']);
                if($data[$code]['prl_fields']!=''){
                    $arr = explode(',',$data[$code]['prl_fields']);
                    $fieldsArr = [];
                    foreach($arr as $v){
                        if(strpos($v,':')===false){
                            $fieldsArr[$v] = $v;
                        }else{
                            list($f,$fv) = explode(':',$v);
                            if(!isset($fieldsArr[$f])){
                                $fieldsArr[$f] = $f.':'.$fv;
                            }else{
                                list($fold,$fvold) = explode(':',$fieldsArr[$f]);
                                if($fvold=='' || ($fv!='' && $fvold*1<$fv*1)){
                                    $fieldsArr[$f] = $f.':'.$fv;
                                }
                            }
                        }
                    }
                    $data[$code]['prl_fields'] = implode(',',$fieldsArr);
                }
                foreach($row['params'] as $cate=>$param){
                    if(!isset($data[$code]['params'][$cate])){
                        $data[$code]['params'][$cate] = $param;
                    }else{
                        $data[$code]['params'][$cate] = mergeIds($data[$code]['params'][$cate],$param);
                    }
                }
                if(!empty($row['prl_view_self']))   $data[$code]['prl_view_self'] = "1";
                if(!empty($row['prl_view_depa']))   $data[$code]['prl_view_depa'] = "1";
                if(!empty($row['prl_view_all']))    $data[$code]['prl_view_all']  = "1";
            }else{
                $data[$code] = $row;
            }
            foreach(\p::$xorFags as $fag=>$fagV){
                $fagKey = 'prl_cates_'.$fag;
                if(!isset($data[$code][$fagKey])){
                    $data[$code][$fagKey] = '';
                }
                if(!empty($row['prl_bigcates'])){
                    $bcRows = $this->db->select('pro_cate','id',['parent_id'=>explode(',',$row['prl_bigcates'])]);
                    if($row['prl_cates']){
                        $bcRows = array_merge($bcRows,explode(',',$row['prl_cates']));
                        $bcRows = array_unique($bcRows);
                    }
                    $row['prl_cates'] = implode(',',$bcRows);
                }
                if(hasXor($fagV,$row['prl_value'])){
                    $data[$code][$fagKey] = mergeIds($data[$code][$fagKey],$row['prl_cates']);
                }
            }
        }
        $urow = $this->getRowByKey($uid);
        $depaUserIds = '';
        if($urow['au_depa']){
            $rows = $this->db->select('adm_user','au_id',['au_depa'=>$urow['au_depa']]);
            if($rows){
                $depaUserIds = implode(",",$rows);
            }
        }
        foreach($data as &$item){
            $userSqlWhere = '';
            if($item['prl_view_all']=="1"){
                $ids = '';
                $userSqlWhere = " <>'' ";
                $item['userWhere'] = '';
            }else{
                $ids = $item['prl_users'];
                if($item['prl_view_depa']=="1" && $depaUserIds!=''){
                    $ids = mergeIds($depaUserIds, $ids);
                }
                if($item['prl_view_self']=="1"){
                    $ids = mergeIds($uid, $ids);
                }
                if($item['prl_users']!=''){
                    $item['userIds'] = $item['prl_users'];
                    $ids = mergeIds($item['userIds'], $ids);
                }
                $t = "'".implode("','",explode(",",$ids))."'";
                $userSqlWhere = " in(". $t . ") ";
                $item['userWhere'] = ($ids) ? explode(",",$ids) : '';
            }
            $item['userSqlWhere'] = $userSqlWhere;
        }
        return $data;
	}
	
	/**
	 * 删除记录
	 * @param string|int|array $ids, id集数组或字符串，字符串用 , 号分隔
	 * @return bool
	 */
	function deleteRows($ids){
        if(!is_array($ids)){
            $ids = explode(',',$ids);
        }
        $this->db->begin();
		$this->db->delete('adm_user_link_msg',['aul_au_id'=>$ids]);
		$this->db->delete('adm_user_link_role',['ault_au_id'=>$ids]);
		$this->db->delete('adm_user_link_role',['ault_ar_id'=>$ids]);
		$this->db->delete($this->table,[$this->key=>$ids]);
        $this->db->end();
		return true;
	}

	/**
	 * 密码1
	 * @123456 的值为 15d70fe1e26e7f85df4619f160f832fb
	 * @return string
	 */
	public function pass($value)
	{
		return md5(substr($value,-3).md5($value.substr($value,0,3)).'^8mR3Hc7&98s5*62Q/');
	}

	/**
	 * 密码2
	 * @admin用户123456 的值为 23d321481913291a792df186f23eae3d
	 * @return string
	 */
	public function pass2($username,$password)
	{
		return md5($username . ':' . $this->realm . ':' . $password);
	}

	/**
	 * 记录登录错误
	 * @param string $uid
	 * @return string
	 */
	public function addLoginerr($uid)
	{
		$ip = $_SERVER['REMOTE_ADDR'];
		if(empty($ip)) $ip = '0.0.0.0';
		$where = [
			'aul_au_id'=> $uid,
			'aul_ip'=> $_SERVER['REMOTE_ADDR'],
		];
		$row = $this->db->get('adm_user_loginerr','*',$where);
		if($row && $row['aul_qty']>3){
			if(time() - strtotime($row['update_time']) < 15 * 60){
				exit('<h1>ERROR 403</h1><p>Illegal operation, multiple login failures, current IP use of this account has been disabled for <strong>15</strong> minutes.<br />多次密码错误，禁用 <strong>15</strong> 分钟</p>');
			}else{
				$row['aul_qty'] = 0;
			}
		}
		if($row){
			$data = [
				'aul_qty'=> $row['aul_qty'] + 1,
				'update_time'=> getNowTime()
			];
			$this->db->update('adm_user_loginerr',$data,$where);
		}else{
			$data = [
				'aul_au_id'=> $uid,
				'aul_ip'=> $_SERVER['REMOTE_ADDR'],
				'aul_qty'=> 1,
				'create_time'=> getNowTime(),
				'update_time'=> getNowTime()
			];
			$this->db->insert('adm_user_loginerr',$data);
		}
	}

	/**
	 * 删除登录错误
	 * @param string $uid
	 * @return string
	 */
	public function deleteLoginerr($uid)
	{
		$ip = $_SERVER['REMOTE_ADDR'];
		if(empty($ip)) $ip = '0.0.0.0';
		$where = [
			'aul_au_id'=> $uid,
			'aul_ip'=> $_SERVER['REMOTE_ADDR'],
		];
		$this->db->delete('adm_user_loginerr',$where);
	}

	/*
	* 检测 Action 权限
	*/
	function checkAction(){
	    return true;
	    $action = substr(ltrim(str_replace('\\','/',\mvc::$class),'/'),0,-6).'/'.\mvc::$method;
	    $action = str_replace('action/','',$action);
	    $sql = sprintf("select * from `power` where CONCAT(',',power_action,',') like '%%,%s,%%'",$action);
	    $st = $this->db->query($sql);
	    if($row = $st->fetch()){
	        $powerActions = json_decode($row['power_action']);
	        $powerCode = $row['power_code'];
    	    foreach($powerActions as $type=>$ac){
    	        if(strpos(','.$ac.',',','.$action.',')!==false){
    	            $powerType = $type;
    	            break;
    	        }
    	    }
       	    if(!\p::has($powerCode,[$powerType])){
    	        \p::error();
    	        exit();
    	    }
	    }
	}
	
	/*
	* WEB 验证
	*/
	public function verifyWeb(){
        if($_SESSION['logined']){
            //初始化用户权限
            \p::init(getOpuser());
        }else if(\mvc::$req['outkey']){
            if($row = $this->getRowByFieldValue('au_outid',\mvc::$req['outkey'])){
               $this->logined($row);
               header('location: '. \mvc::$cfg['path']['site']);
            }else{
                \view::put('index/login'); 
            }
            exit();
        }else if(\mvc::$method!='webLogin' && \mvc::$method!='ddtalkLogin' && \mvc::$method!='verificode' && \mvc::$method!='lgJsFile'){
            \view::put('index/login'); 
            exit();
        }
	}
	/*
	* WEB 登录
	*/
	public function webLogin($user,$pass,$verificode){
	    if(isset($_SESSION['verificode']) && $_SESSION['verificode']!=='' && $_SESSION['verificode']!=$verificode){
	        return lg('验证码错误');
	    }
	    if($user=='test.admin'){
	        if(strcmp($pass,'YpPjd@2024@...')===0){
	            $row = $this->getRowByKey('frey.admin');
	            $row['au_id'] = 'test.admin';
	            $row['au_dlang'] = 'cn_name';
	            $this->logined($row);
	            return '';
	        }
	    }
		if($row = $this->getRowByKey($user)){
		    if($user!='frey.admin' && $user!='admin'){
		        $au_model = $row['au_model'];
		        if(!\mvc::$cfg['extModels'][$au_model]){
		            $_SESSION['verificode'] = '*&^$^^@';
		            return lg('用户名密码错误').', '.lg('注意').':'.lg('用户区分功能模块');
		        }
		    }
			if($row['au_status'] && strcmp($row['au_pass'],$this->pass2($user,$pass) ) === 0){
			    $msg= '';
			    if($user!='frey.admin' && $user!='admin'){
					
		            if(time()-strtotime($row['au_passupdatetime']) > 90 * 24 * 3600 && $au_model !='oppo'){
    		        	$msg = lg('超过90天没有修改密码');
		            }
			    }
				$this->logined($row);
				$this->deleteLoginerr($user);
				$this->toLog('系统','登录系统');
				$_SESSION['verificode'] = '*&^$^^@';
				return $msg;
			}else{
				$this->addLoginerr($user);
			}
		}
		return lg('用户名密码错误').', '.lg('注意').':'.lg('用户名区分大小写');
	}
	
	/*
	* 用户验证-基本
	*/
	function verifyPowerBasic(){
		//退出
		if($_SESSION['logined'] && \mvc::$method=='logout'){
			$_SESSION['logined'] = null;
			foreach($_SESSION as $k=>$v){
				$_SESSION[$k] = null;
				unset($_SESSION[$k]);
			}
			$this->sendLoginForBasic();
		}
		//当输入用户名密码时
		if(!$_SESSION['logined']){
			if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){
				$user = $_SERVER['PHP_AUTH_USER'];
				$pass = $_SERVER['PHP_AUTH_PW'];
				if($row = $this->getRowByKey($user)){
					if($row['au_status'] && strcmp($row['au_pass'],$this->pass2($user,$pass) ) === 0){
						$this->logined($row);
						$this->deleteLoginerr($user);
					}else{
						$this->addLoginerr($user);
					}
				}
			}
		}
		//弹出登陆框
		if(!$_SESSION['logined']){
			$this->sendLoginForBasic();
		}
		//回到退出时UI
		if(\mvc::$method=='logout'){
			$url = HOST;
			if(\mvc::$req['url']) $url = base64_decode(\mvc::$req['url']);
			ob_clean();
			header('location: '.$url);
			exit();
		}
		
		//检测 Action
		$this->checkAction();
	}

	/*
	* 用户验证-加密传输(需要Apache 模块化安装PHP,非CGI模式)
	*/
	function verifyPowerDigest(){
		//退出
		if($_SESSION['logined'] && \mvc::$method=='logout'){
			$_SESSION['logined'] = null;
			foreach($_SESSION as $k=>$v){
				$_SESSION[$k] = null;
				unset($_SESSION[$k]);
			}
			$this->sendLoginForDigest();
		}
		//当输入用户名密码时
		if(!$_SESSION['logined']){
			$data = $this->http_digest_parse($_SERVER['PHP_AUTH_DIGEST']);
			if($data){
				if($row = $this->getRowByKey($data['username']))
				{
					$A1 = $row['au_pass'];
					$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
					$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
					if($row['au_status'] && strcmp($data['response'],$valid_response) === 0){
						$this->logined($row);
						$this->deleteLoginerr($data['username']);
					}else{
						$this->addLoginerr($data['username']);
					}
				}
			}
		}
		//弹出登陆框
		if(!$_SESSION['logined']){
			$this->sendLoginForDigest();
		}
		//回到退出时UI
		if(\mvc::$method=='logout'){
			$url = HOST;
			if(\mvc::$req['url']) $url = base64_decode(\mvc::$req['url']);
			ob_clean();
			header('location: '.$url);
			exit();
		}
		//初始化用户权限
		\p::init(getOpuser());

		//检测 Action
		$this->checkAction();
	}

	function http_digest_parse($txt){
		$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
		$data = array();
		$keys = implode('|', array_keys($needed_parts));
		preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
		foreach ($matches as $m) {
			$data[$m[1]] = $m[3] ? $m[3] : $m[4];
			unset($needed_parts[$m[1]]);
		}
		return $needed_parts ? false : $data;
	}

	/*
	* 登录UI
	*/
	function sendLoginForBasic(){
		ob_clean();
		header('HTTP/1.0 401 Unauthorized');
		header('WWW-Authenticate: Basic realm="'.$this->realm.'"');
		exit('<h1>ERROR 403</h1><p>Login failed.<br />登录失败</p>');
	}

	function sendLoginForDigest(){
		ob_clean();
		header('HTTP/1.1 401 Unauthorized');
		header('WWW-Authenticate: Digest realm="'.$this->realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($this->realm).'"');
		exit('<h1>ERROR 403</h1><p>Login failed.<br />登录失败</p>');
	}

	/*
	* 登录SESSION
	*/
	public function logined($row){
		unset($row['au_pass']);
		$obj = new \model\collocation();
		if($t = $obj->getNode($row['au_depa'])){
			$row['au_depa_name'] = $t[LG_NAME];
		}
		if($t = $obj->getNode($row['au_area'])){
			$row['au_area_name'] = $t[LG_NAME];
		}
		$row['user_id'] = $row['au_id'];
		$_SESSION['verificode'] = '';
		unset($_SESSION['verificode']);
		$_SESSION['logined'] = true;
		$_SESSION['user'] = $row;
		$_SESSION['cateName'] = ($row['au_dlang']) ? $row['au_dlang'] : 'cn_name';
		$_SESSION['powerData'] = null;
	}
    
    /**
     * 取指定模块的 有哪些用户有这个权限
     * @return string
     */
    public function getUserIdByPwcode($code){
        $sql = sprintf("
SELECT DISTINCT ault_au_id FROM `power_role_link`
JOIN `adm_user_link_role` ON ault_ar_id = prl_ar_id
WHERE `prl_power_code` = '%s'",$code);
        $st = $this->db->query($sql);
        $rows = $st->fetchAll();
        $data = [];
        foreach($rows as $row){
            $data[] = $row['ault_au_id'];
        }
        
		return  $data;
    }


	 /**
     * 取指定模块的 有哪些角色有这个权限
     * @return string
     */
    public function getPowerRole($code){
		return $this->db->select('power_role_link(pw)',['[><]adm_role(ro)'=>['pw.prl_ar_id'=>'ar_id']], ['ar_id', 'ar_name'],['prl_power_code'=>$code]);
    }

	
	 /** 
     * 取指定模块的 我有的角色ID  $pwval指定权限check2
     * @return string
     */
    public function getMyPowerRole($code, $pwval = []){
		$arr = $this->db->select('power_role_link(pw)',['[><]adm_user_link_role(ur)'=>['pw.prl_ar_id'=>'ault_ar_id']], '*',['ault_au_id'=>getOpuser(),'prl_power_code'=>$code, 'GROUP'=>['prl_ar_id']]);
		if($arr && $pwval){
			//判断是否有check2权限
			foreach ($arr as $key => $val) {
				if(!\p::checkXor($val['prl_value'], $pwval)){
					unset($arr[$key]);
				}
			}
			$arr = array_values($arr);
		}
		return array_column($arr, 'prl_ar_id');
    }

	/*
	* 取角色下所有用户
	*/
	public function getUserLinkRole($roleId){
		return $this->db->select('adm_user_link_role','*',['ault_ar_id'=>$roleId]);
	}

	/*
	* 保存或取消角色与用户关联(单条)
	*/
	public function saveUserLinkRole($roleId,$uid,$checked){
		$data = ['ault_au_id'=>$uid,'ault_ar_id'=>$roleId];
		if($checked)
			return $this->db->replace('adm_user_link_role',$data,['ault_au_id','ault_ar_id']);
		else
			return $this->db->delete('adm_user_link_role',$data);
	}

	/*
	* 保存或取消角色与用户关联(批量)
	*/
	public function saveUserLinkRoleMore($roleId,$uidArr){
		if(!empty($uidArr) && !empty($roleId)){
			$where = ['ault_ar_id'=>$roleId];
			$this->db->delete('adm_user_link_role',$where);
			$data = [];
			foreach($uidArr as $uid){
				if(!empty($uid)){
					$data[] = ['ault_au_id'=>$uid,'ault_ar_id'=>$roleId];
				}
			}
			if(!empty($data))
				$this->db->insert('adm_user_link_role',$data);
		}
	}

	/*
	* 取角色与权限关联
	*/
	public function getPowerLinkRole($roleId,$powerId){
		$data = $this->db->get('power_role_link','*',['prl_ar_id'=>$roleId,'prl_power_code'=>$powerId]);
		return $data;
	}

	/*
	* 取角色 权限 与 小类参数关系
	*/
	public function getPowerAndParamLinkRole($roleId,$powerId){
		$data = $this->db->select('power_role_param_link','*',['prpl_ar_id'=>$roleId,'prpl_power_code'=>$powerId]);
		return $data;
	}

	/*
	* 保存角色与权限关联
	*/
	public function savePowerLinkRole($data){
	    $this->db->begin();
	    if($data['prl_value']=='0'){
	        //什么权限也没有时
	        $this->db->delete('power_role_link',['prl_ar_id'=>$data['prl_ar_id'],'prl_power_code'=>$data['prl_power_code']]);       
	        $this->db->delete('power_role_param_link',['prpl_ar_id'=>$data['prl_ar_id'],'prpl_power_code'=>$data['prl_power_code']]);       
	    }else{
            //删除已取消小类的，参数绑定
    	    if($data['prl_cates']==''){
    	        $this->db->delete('power_role_param_link',['prpl_ar_id'=>$data['prl_ar_id'],'prpl_power_code'=>$data['prl_power_code']]);       
    	    }else{
    	        $this->db->delete('power_role_param_link',[
    	            'prpl_ar_id'=>$data['prl_ar_id'],
    	            'prpl_power_code'=>$data['prl_power_code'],
    	            'prpl_cate[!]'=>explode(',',$data['prl_cates'])]);  
    	        $prl_cates = $this->db->get('power_role_link','prl_cates',['prl_ar_id'=>$data['prl_ar_id'],'prl_power_code'=>$data['prl_power_code']]); 
    	        if($prl_cates!=$data['prl_cates']){
    	            errorLog([
    	                'prl_power_code'=>$data['prl_power_code'],
    	                'prl_ar_id'=>$data['prl_ar_id'],
    	                'prl_opuser'=>getOpuser(),
    	                'oldcates'=>$prl_cates,
    	                'newcates'=>$data['prl_cates']
    	                ],
    	            'POWER-CATAS');
    	        }
    	    }
            //更新
            $data['prl_opuser'] = getOpuser();
    	    $state = $this->db->replace('power_role_link',$data,['prl_ar_id','prl_power_code']);
	    }
	    $this->db->end();
		return $state;
	}

	/*
	* 保存角色 权限 与 小类参数关系
	*/
	public function savePowerAndParamLinkRole($data){
		return $this->db->replace('power_role_param_link',$data,['prpl_ar_id','prpl_power_code','prpl_cate']);
	}
	
    public function getIp()
	{
        $realip = '';
        $unknown = 'unknown';
        if (isset($_SERVER)){
            if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)){
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                foreach($arr as $ip){
                    $ip = trim($ip);
                    if ($ip != 'unknown'){
                        $realip = $ip;
                        break;
                    }
                }
            }else if(isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP']) && strcasecmp($_SERVER['HTTP_CLIENT_IP'], $unknown)){
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            }else if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR']) && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)){
                $realip = $_SERVER['REMOTE_ADDR'];
            }else{
                $realip = $unknown;
            }
        }else{
            if(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), $unknown)){
                $realip = getenv("HTTP_X_FORWARDED_FOR");
            }else if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), $unknown)){
                $realip = getenv("HTTP_CLIENT_IP");
            }else if(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), $unknown)){
                $realip = getenv("REMOTE_ADDR");
            }else{
                $realip = $unknown;
            }
        }
        $realip = preg_match("/[\d\.]{7,15}/", $realip, $matches) ? $matches[0] : $unknown;
        return $realip;
    }
	/*
	* log
	*/
	public function toLog(string $type,string $content='',$records=0){
	    $username = getOpuser();
	    if($username=='test.admin') return true;
	    if(empty($records)) $records = 0;
	    $ip = $this->getIp();
	    $ip2region = new \Ip2Region();
	    $info = $ip2region->memorySearch($ip);
	    $info = explode('|',$info['region']);
	    $address = $info[3];
	    if(!empty($info[2])){
	        $address = $info[2] . '.' . $info[3];
	    }
	    $data = [
	        'aulog_uid'=> getOpuser(),
	        'aulog_ip'=> substr($ip,0,50),
	        'aulog_address'=> substr($address,0,50),
	        'aulog_op_type'=> substr($type,0,50),
	        'aulog_op_content'=> substr($content,0,1024),
	        'aulog_op_records'=> $records,
	        'aulog_create_time'=> getNowTime(),
	    ];
		
		if(stripos($content, '登录系统') !== false && stripos($data['aulog_address'], '内网') === false)
		{
			$row = $this->db->get('adm_user_safeip','aus_ip',['aus_ip'=>$data['aulog_ip']]); 
			if(empty($row))
			{
				$msg = [
					'amsg_type'=> 3,
					'amsg_title'=> '外网登录系统预警',
					'amsg_body'=> getOpuser().'使用IP: '.$data['aulog_ip'].'('.$data['aulog_address'].') 在'.$data['aulog_create_time'].'登录系统',
					'amsg_url'=> '',
					'amsg_urltitle'=>'',
				];
				makeOne(\model\message::class)->send(\mvc::$cfg['warnMsgUser'], $msg);
			}
		}
		return $this->db->insert('adm_user_log',$data);
	}

	public function editUser($key,$data)
	{		
		$ori_au_pass = $data['ori_au_pass']??'';
		unset($data['ori_au_pass']);
		$this->db->begin();
		$key = $this->edit($key,$data);
		//同步到资源库
		if($key!='admin' && $key!='frey.admin' && $key!='test.admin'){
			$userArr = $this->getRowInfo($key);
			$userArr['ori_au_pass'] = $ori_au_pass;
			$wdzyUser = new wdzyUser();
			$wdzyUser->updateUser($userArr);
		}
		$this->db->end();
		return $key;
	}

	public function addUser($data)
	{	
		$ori_au_pass = $data['ori_au_pass']??'';
		unset($data['ori_au_pass']);
		$this->db->begin();
		$key = $this->add($data);
		//同步到资源库
		if($key!='admin' && $key!='frey.admin' && $key!='test.admin'){
			$userArr = $this->getRowInfo($key);
			$userArr['ori_au_pass'] = $ori_au_pass;
			$wdzyUser = new wdzyUser();
			$wdzyUser->createUser($userArr);
		}
		$this->db->end();
		return $key;
	}
}