AddController.class.php 12.7 KB
<?php
/**
 * Created by PhpStorm.
 * User: liyifei2012it
 * Date: 16/10/21
 * Time: 16:44
 */
namespace Apicp\Controller\User;

use VcySDK\Member;
use VcySDK\Service;
use VcySDK\Department;
use Common\Model\AttrModel;
use Common\Service\AttrService;

class AddController extends AbstractController
{

    /**
     * 【通讯录】人员批量导入-新增员工接口(遇到必填却不支持导入的属性时,忽略验证)
     * @author liyifei
     */
    public function Index_post()
    {
        $list = I('post.list');
        if (empty($list)) {
            E('_ERR_PARAM_UNDEFINED');
        }

        // 所有开启的属性
        $attrServ = new AttrService();
        $attrs = $attrServ->getAttrList(true, array(), true);

        // 将属性信息数组有索引数组转为以属性字段为键的关联数组
        $newAttrs = array();
        foreach ($attrs as $key => $v) {
            $newAttrs[$v['field_name']] = $v;
        }

        // 错误人员信息
        $errTag = false;
        $errData = [];
        // 格式化人员属性值并添加为内部人员
        $data = [];
        // 在职状态
        $memActive = null;
        // 离职日期
        $leaveDate = null;

        foreach ($list as $k => $v) {
            // 属性值
            $value = $v['attr_value'];
            // 属性详情信息
            $attr = $newAttrs[$v['field_name']];
            // 存储错误人员信息(用户原始数据)
            $errData[$k] = $v;
            $errData[$k]['type'] = intval($attr['type']);
            $errData[$k]['attr_name'] = $attr['attr_name'];
            $errData[$k]['is_required'] = $attr['is_required'];
            // 重置错误信息(前端再次提交时使用)
            unset($errData[$k]['error_msg']);

            // 图片、地址、直属上级等不保存
            $types = [
                AttrModel::ATTR_TYPE_ADDRESS,
                AttrModel::ATTR_TYPE_PICTURE,
                AttrModel::ATTR_TYPE_LEADER,
            ];
            if (in_array($attr['type'], $types)) {
                continue;
            }

            // 在职状态赋值
            if ($v['field_name'] == 'memActive') {
                $memActive = $value;
            }
            // 离职日期赋值
            if ($v['field_name'] == 'leaveDate') {
                $leaveDate = $value;
            }

            // 必填属性(必填属性、非特殊属性、未填写属性值时,报错)
            if ($attr['is_required'] == AttrModel::ATTR_IS_REQUIRED_TRUE && $value === '') {
                // 单选、下拉框单选、多选为必填,且用户未填写时,将所有选项option写入返回值
                if ($attr['type'] == AttrModel::ATTR_TYPE_RADIO || $attr['type'] == AttrModel::ATTR_TYPE_DROPBOX || $attr['type'] == AttrModel::ATTR_TYPE_CHECKBOX) {
                    $errData[$k]['option'] = $attr['option'];
                }
                $errTag = true;
                $errData[$k]['error_msg'] = "必填项不可为空";
                continue;
            }

            // 验证姓名
            if ($v['field_name'] == 'memUsername' && (mb_strlen($v['attr_value'], 'utf8') < 2 || mb_strlen($v['attr_value'], 'utf8') > 32)) {
                $errTag = true;
                $errData[$k]['error_msg'] = "姓名长度不正确";
                continue;
            }

            // 验证手机号
            if ($v['field_name'] == 'memMobile' && strlen($v['attr_value']) != 11) {
                $errTag = true;
                $errData[$k]['error_msg'] = "手机号格式不正确";
                continue;
            }

            // 验证邮箱
            if ($v['memEmail'] && $v['field_name'] == 'memEmail' && !preg_match('/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/', $value)) {
                $errTag = true;
                $errData[$k]['error_msg'] = "邮箱格式不正确";
                continue;
            }

            // 验证账号(规则:1~32位字符、仅可用大小写字母、数字、下划线)
            if ($v['attr_value'] !== '' && $v['field_name'] == 'memUserid' && !preg_match('/^[a-zA-Z0-9_]{1,32}$/', $value)) {
                $errTag = true;
                $errData[$k]['error_msg'] = "账号格式不正确";
                continue;
            }

            // 根据部门属性,取出部门信息
            if ($v['field_name'] == 'dpName') {
                // 以";"号为分隔符,根据分级部门名称查询部门ID
                $dpDir = explode(';', $v['attr_value']);
                foreach ($dpDir as $dir) {
                    $nameList = explode('/', $dir);
                    $dpId = $this->eachDept($nameList);
                    if (!$dpId) {
                        $errTag = true;
                        $errData[$k]['error_msg'] = "未找到组织信息";
                        break;
                    }
                    $data['dpIdList'][] = $dpId;
                }
                // 跳出当前循环,不可将部门dbName属性放入请求架构接口的参数中!!!
                continue;
            }

            // 根据属性类型,验证和格式化属性值
            if ($value !== '') {
                switch ($attr['type']) {
                    // 日期类型(标准格式: 2016-09-09 或 2016/09/09)
                    case AttrModel::ATTR_TYPE_DATE:
                        $resDate = $attrServ->checkDate($value);
                        if (!$resDate) {
                            $errTag = true;
                            $errData[$k]['error_msg'] = $attr['attr_name'] . "-格式不正确";
                            break;
                        }
                        // 属性值转为毫秒级时间戳
                        $value = strtotime($value) * 1000;
                        break;

                    // 日期时间类型(标准格式: 2016-09-09 09:09:09 或 2016/09/09 09:09:09)
                    case AttrModel::ATTR_TYPE_DATE_TIME:
                        $res = $attrServ->checkDateTime($value);
                        if (!$res) {
                            $errTag = true;
                            $errData[$k]['error_msg'] = $attr['attr_name'] . "-格式不正确";
                            break;
                        }
                        // 属性值转为毫秒级时间戳
                        $value = strtotime($value) * 1000;
                        break;

                    // 时间类型,格式是否正确(标准格式: 09:30:21)
                    case AttrModel::ATTR_TYPE_TIME:
                        $resTime = $attrServ->checkTime($value);
                        if (!$resTime) {
                            $errTag = true;
                            $errData[$k]['error_msg'] = $attr['attr_name'] . "-格式不正确";
                        }
                        break;

                    // 单选类型
                    case AttrModel::ATTR_TYPE_RADIO:
                        $nameArr = array_column($attr['option'], 'name');
                        if (!in_array($value, $nameArr)) {
                            $errTag = true;
                            $errData[$k]['error_msg'] = "选项错误";
                            $errData[$k]['option'] = $attr['option'];
                            break;
                        }
                        // 将选项option的name转为value(写入架构数据库)
                        foreach ($attr['option'] as $option) {
                            if ($option['name'] == $value) {
                                $value = $option['value'];
                            }
                        }
                        break;

                    // 下拉框单选类型
                    case AttrModel::ATTR_TYPE_DROPBOX:
                        $nameArr = array_column($attr['option'], 'name');
                        if (!in_array($value, $nameArr)) {
                            $errTag = true;
                            $errData[$k]['error_msg'] = "选项错误";
                            $errData[$k]['option'] = $attr['option'];
                            break;
                        }
                        // 将选项option的name转为value(写入架构数据库)
                        foreach ($attr['option'] as $option) {
                            if ($option['name'] == $value) {
                                $value = $option['value'];
                            }
                        }
                        break;

                    // 多选类型
                    case AttrModel::ATTR_TYPE_CHECKBOX:
                        $nameArr = array_column($attr['option'], 'name');
                        // 用户填写的数据必须以";"号为分隔符
                        $valueArr = explode(';', $value);
                        $valueTemp = [];
                        foreach ($valueArr as $name) {
                            if (!in_array($name, $nameArr)) {
                                $errTag = true;
                                $errData[$k]['error_msg'] = "选项错误";
                                $errData[$k]['option'] = $attr['option'];
                                break;
                            }
                            foreach ($attr['option'] as $option) {
                                if ($name == $option['name']) {
                                    $valueTemp[] = $option;
                                }
                            }
                        }
                        // 将选项option的value转为name-value的多维数组,并序列化(写入架构数据库)
                        if (!empty($valueTemp)) {
                            $value = serialize($valueTemp);
                        }
                        break;
                }
            }

            // 格式化人员信息,请求架构接口,添加为内部人员
            $data[$v['field_name']] = $value;
        }

        $result = [];
        if ($errTag) {
            // 人员信息有错误
            $result = [
                'message' => '',
                'list' => $errData,
            ];

        } else {
            // 在职状态为离职时,离职日期不可为空
            if ($memActive == "离职" && strlen($leaveDate) == 0) {
                $result = [
                    'message' => '在职状态为离职时,离职日期不可为空',
                    'list' => $errData,
                ];

            } else {
                try {
                    // 请求架构接口,添加人员
                    $newMember = new Member(Service::instance());
                    $newMember->add($data);

                } catch (\VcySDK\Exception $e) {
                    // 接收架构抛错,接收架构错误,并返回错误和人员信息
                    if ($e->getCode() != 0 || ($e->getCode() == 0 && strpos($e->getMessage(), '系统异常') !== false)) {
                        $result = [
                            'message' => $e->getMessage(),
                            'list' => $errData,
                        ];
                    }
                }
                clear_cache();
            }
        }

        $this->_result = $result;
    }

    /**
     * 轮询查找最底层部门ID
     * @author zhonglei
     * @param array $nameList 部门层级关系(如: ['畅移', '产品部', '产品'])
     * @param array $deptIdList 部门层级关系对应的部门ID
     * @return bool|mixed
     */
    private function eachDept($nameList, $deptIdList = [])
    {
        $newDept = new Department(Service::instance());

        $index = count($deptIdList);
        $name = $nameList[$index];

        if ($index == 0) {
            // 调用UC部门列表接口,获取顶级部门列表数据
            $topDpId = '';
            $dpList = $newDept->listAll([], 1, 99999);
            foreach ($dpList['list'] as $v) {
                if (empty($v['dpParentid'])) {
                    $topDpId = $v['dpId'];
                }
            }
            if (!$topDpId) {
                return false;
            }
            $deptList[] = $newDept->detail(['dpId' => $topDpId]);

        } else {
            $parentId = $deptIdList[$index - 1];
            // 根据parentId取子部门列表数据
            $dpList = $newDept->listAll(['dpId' => $parentId, 1, 99999]);
            $deptList = $dpList['list'];
        }

        foreach ($deptList as $v) {
            if ($v['dpName'] == $name) {
                $deptIdList[$index] = $v['dpId'];
                break;
            }
        }

        if (!isset($deptIdList[$index])) {
            return false;
        }

        if (count($deptIdList) == count($nameList)) {
            return $deptIdList[$index];
        } else {
            return $this->eachDept($nameList, $deptIdList);
        }
    }

}