SaveController.class.php 10.5 KB
<?php

namespace Api\Controller\User;

use Com\Rpc;
use Common\Common\User;
use Common\Common\StudyMapRight;
use Common\Model\AttrModel;
use Common\Service\AttrService;
use Common\Service\UserRecordService;
use Common\Service\UserService;
use Common\Common\Cache;

class SaveController extends AbstractController
{
    /**
     * 权限标识列表
     */
    const RIGHT_TYPE_LIST = [
        1 => 'dp_ids',
        5 => 'job_ids',
        6 => 'role_ids'
    ];

    /**
     * 权限标识:人员
     */
    const RIGHT_TYPE_IS_USER = 3;

    /**
     * Save
     * @author tangxingguo
     * @desc 【通讯录】人员保存
     * @param Array dp_ids:true 部门ID
     * @param String uid:true 人员ID
     * @param Int list[].type:true 字段类型(1=单行文本;2=多行文本;3=数字;4=日期;5=时间;6=日期时间;7=单选;8=多选;9=地址;10=图片;999=选人组件,前端不可选择)
     * @param String list[].field_name:true 属性对应的UC字段名称
     * @param String list[].attr_name:true 属性名称
     * @param String|Array list [].attr_value:true 属性的值(属性类型为图片、多选时,该值为数组类型;单选时,值为单选项Option中的value)
     * @param String|Array list [].option:true 单选选项(属性类型为单选时,必须以数组形式请求)
     * @param String|Array list [].is_required:true 是否必填(0=非必填;1=必填)
     * @param String|Array list [].is_system:true 是否为系统字段(0=自定义字段;1=系统字段)
     * @param String|Array list [].postion:true 前端布局
     * @return bool
     */
    public function Index_post()
    {

        $uid = I('post.uid', '', 'trim');
        $list = I('post.list');
        $dpIds = I('post.dp_ids');

        // 权限检查
        if (!$this->_checkRight()) {
            E('_ERR_NO_EDIT_USER_RIGHT');
        }

        if (empty($uid)) {
            E('_ERR_UID_IS_NULL');
        }

        if (empty($list) || empty($dpIds)) {
            E('_ERR_PARAM_IS_NULL');
        }

        // 以架构接口参数字段为键,拼接用户信息
        $attrServ = new AttrService();
        $attrs = $attrServ->getAttrList(true, array(), true);
        $data = [
            'dpIdList' => $dpIds
        ];

        $list = array_combine(array_column($list, 'field_name'), $list);

        foreach ($attrs as $attr) {
            $fieldName = $attr['field_name'];
            // 日期类型 为空时 跳过
            if (($attr['type'] == AttrModel::ATTR_TYPE_DATE) &&
                empty($list[$fieldName]['attr_value'])
            ) {
                continue;
            }
            // 防止前端未传参时,赋值为null,UC在保存自定义属性的值时,null会导致保存失败!
            $data[$fieldName] = $list[$fieldName]['attr_value'] !== null ? $list[$fieldName]['attr_value'] : '';

            // 图片、多选项,序列化存储在架构
            $serializeAttr = [
                AttrModel::ATTR_TYPE_CHECKBOX,
                AttrModel::ATTR_TYPE_PICTURE,
            ];
            if (in_array($list[$fieldName]['type'], $serializeAttr) && !empty($data[$fieldName])) {
                $data[$fieldName] = serialize($data[$fieldName]);
            }
        }

        // 调用验证接口,验证参数传值是否符合规范
        $errors = $attrServ->checkValue($data);
        if (!empty($errors)) {
            E($errors[0]);
        }

        // 编辑前获取用户完整数据,用于编辑后对比组织、岗位、角色变化($userOld非地图逻辑)
        $userSdk = &User::instance();
        $userOld = $user_old = $userSdk->getByUid($uid);

        // =========学习地图业务逻辑 Start=========

        // 未关注的用户不进行对比
        if (isset($user_old['memSubscribeStatus']) &&
            $user_old['memSubscribeStatus'] != User::SUBSCRIBE_STATUS_SUBSCRIBED) {
            $user_old = [];
        }

        // =========学习地图业务逻辑 End=========

        $userServ = new UserService();
        $result = $userServ->saveUser($uid, $data);

        // 新增、修改用户成功时,UC返回该用户的完整信息
        if (isset($result['memUid'])) {
            $uid = $result['memUid'];
        }

        // 保存后新的用户数据($userNew非地图逻辑)
        $userNew = $user_new = $userSdk->getByUid($uid);

        // =========学习地图业务逻辑 Start=========
        if (!empty($user_old)) {
            // 用户部门、岗位和角色数据有差异
            if ($this->_contrastRight($user_old, $user_new)) {
                // 获取新的可参与学习的地图ID
                $studyMapRight = &StudyMapRight::instance();
                $map_ids_old = $studyMapRight->listMapId($user_old);
                $map_ids_new = $studyMapRight->listMapId($user_new);
                $diff_ids = array_diff($map_ids_new, $map_ids_old);

                if (!empty($diff_ids)) {
                    $url = rpcUrl('/Map/Rpc/User/SendNotice');
                    $parmas = ['uid' => $uid, 'map_ids' => array_values($diff_ids)];
                    Rpc::phprpc($url)->invoke('index', $parmas);
                }
            }
        }
        // =========学习地图业务逻辑 End=========

        // 人员信息被修改,保存变更记录
        if ($this->_diffData($userOld, $userNew)) {
            $recordServ = new UserRecordService();
            $recordServ->insert([
                'uid' => $this->uid,
                'username' => $this->_login->user['memUsername'],
                'edit_uid' => $userNew['memUid'],
                'edit_username' => $userNew['memUsername'],
                'old_form' => serialize($userOld),
                'new_form' => serialize($userNew),
            ]);
        }

        $this->_result = [
            'uid' => $uid
        ];
    }

    /**
     * 对比用户部门、岗位和角色数据,有差异则返回true
     * @param array $user_old 旧的用户数据
     * @param array $user_new 新的用户数据
     * @return bool
     */
    private function _contrastRight($user_old, $user_new)
    {
        // 获取旧数据中部门、岗位和角色ID
        $old_ids = array_column($user_old['dpName'], 'dpId');
        $old_ids[] = $user_old['job']['jobId'];
        $old_ids[] = $user_old['role']['roleId'];

        // 获取新数据中部门、岗位和角色ID
        $new_ids = array_column($user_new['dpName'], 'dpId');
        $new_ids[] = $user_new['job']['jobId'];
        $new_ids[] = $user_new['role']['roleId'];

        return !empty(array_diff($old_ids, $new_ids)) || !empty(array_diff($new_ids, $old_ids));
    }

    /**
     * 检查当前用户是否有人员编辑权限
     * @author tangxingguo
     * @return bool
     */
    private function _checkRight()
    {
        // 当前员工是否有编辑权限(flag:1=部门;3=人员;5=岗位;6=角色)
        clear_cache();
        // 权限类型
        $rightType = self::RIGHT_TYPE_LIST;
        // 权限数据
        $rights = [];
        // 权限内的人员
        $uids = [];
        $settings = Cache::instance()->get('Common.AppSetting');
        if (!empty($settings['manageAuths']['value']['selectedList'])) {
            foreach ($settings['manageAuths']['value']['selectedList'] as $v) {
                // 权限代表人员
                if ($v['flag'] == self::RIGHT_TYPE_IS_USER) {
                    $uids[] = $v['id'];
                    continue;
                }
                // 其他
                if (isset($rightType[$v['flag']])) {
                    $rights[$rightType[$v['flag']]][] = $v['id'];
                }
            }
        }

        $rightUids = $this->_getUids($rights);
        $uids = array_values(array_unique(array_merge($uids, $rightUids)));

        return in_array($this->uid, $uids) ? true : false;
    }

    /**
     * 通过组织、岗位、角色获取人员UID
     * @author tangxingguo
     * @param $data
     * @return array
     */
    private function _getUids($data)
    {
        $uids = [];
        $userServ = &User::instance();

        // 组织
        if (isset($data['dp_ids'])) {
            $conds = [
                'dpIdList' => $data['dp_ids'],
                'departmentChildrenFlag' => 1
            ];
            $list = $userServ->listAll($conds);
            if (!empty($list)) {
                $uids = array_column($list, 'memUid');
            }
        }

        // 岗位
        if (isset($data['job_ids'])) {
            $conds = [
                'jobIdList' => $data['job_ids']
            ];
            $list = $userServ->listAll($conds);
            if (!empty($list)) {
                $uids = array_merge($uids, array_column($list, 'memUid'));
            }
        }

        // 角色
        if (isset($data['role_ids'])) {
            $conds = ['roleIdList' => $data['role_ids']];
            $list = $userServ->listAll($conds);
            if (!empty($list)) {
                $uids = array_merge($uids, array_column($list, 'memUid'));
            }
        }

        return $uids;
    }

    /**
     * 对比数据
     * @author tangxingguo
     * @param $oldData
     * @param $newData
     * @return bool
     */
    private function _diffData($oldData, $newData)
    {
        // 对比用户部门、岗位和角色数据,有差异则返回true
        if ($this->_contrastRight($oldData, $newData)) {
            return true;
        }

        // 对比属性
        $keys = ['memEmail', 'memUsername', 'memGender', 'memTelephone', 'custom1', 'custom2',
            'custom3', 'custom4', 'custom5', 'custom6', 'custom7', 'custom8', 'custom9', 'custom10'];
        $oldData = array_intersect_key_reserved($oldData, $keys, true);
        $newData = array_intersect_key_reserved($newData, $keys, true);

        foreach ($newData as $k => $v) {
            if ($v == $oldData[$k]) {
                continue;
            }

            if ($v != $oldData[$k]) {
                // 非序列化数据
                if (!is_serialized($v)) {
                    return true;
                }

                // 序列化信息判断
                if (!is_serialized($oldData[$k])) {
                    // 老数据非序列化数据
                    return true;
                }
                $newAttr = unserialize($v);
                $oldAttr = unserialize($oldData[$k]);
                if ($newAttr[0]['name'] != $oldAttr[0]['name'] || $newAttr[0]['value'] != $oldAttr[0]['value']) {
                    return true;
                }
            }
        }

        return false;
    }


}