651 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			651 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			PHP
		
	
	
<?php
 | 
						||
 | 
						||
namespace app\controller\api\v1;
 | 
						||
 | 
						||
use app\controller\api\Base;
 | 
						||
use app\exception\ApiException;
 | 
						||
use app\exception\RepositoryException;
 | 
						||
use app\model\Account;
 | 
						||
use app\model\AccountRecord;
 | 
						||
use app\model\ClockLog;
 | 
						||
use app\model\PayLog;
 | 
						||
use app\model\Worksite;
 | 
						||
use app\repository\AccountRepository;
 | 
						||
use app\service\File;
 | 
						||
use app\service\Jwt;
 | 
						||
use app\service\wx\WechatApplets;
 | 
						||
use app\validate\User as UserValidate;
 | 
						||
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
 | 
						||
use Exception;
 | 
						||
use think\Collection;
 | 
						||
use think\db\exception\DataNotFoundException;
 | 
						||
use think\db\exception\DbException;
 | 
						||
use think\db\exception\ModelNotFoundException;
 | 
						||
use think\facade\Config;
 | 
						||
use think\facade\Log;
 | 
						||
use think\response\Json;
 | 
						||
 | 
						||
class User extends Base
 | 
						||
{
 | 
						||
    protected $noNeedLogin = [
 | 
						||
        'login',
 | 
						||
        'tempLogin',
 | 
						||
        'signInfo',
 | 
						||
        'signToday',
 | 
						||
        'checkActive'
 | 
						||
    ];
 | 
						||
 | 
						||
    /**
 | 
						||
     * 登录  成功返回token及用户信息
 | 
						||
     *
 | 
						||
     * @return Json
 | 
						||
     * @throws InvalidConfigException
 | 
						||
     */
 | 
						||
    public function login(): Json
 | 
						||
    {
 | 
						||
        $params = input();
 | 
						||
 | 
						||
        Log::error('进入参数');
 | 
						||
        Log::error($params);
 | 
						||
        Log::error('参数结束');
 | 
						||
        $validate = new UserValidate();
 | 
						||
        if (!$validate->scene('wx_applets')->check($params)) {
 | 
						||
            return $this->json(4000, $validate->getError());
 | 
						||
        }
 | 
						||
        $minApp = WechatApplets::getInstance();
 | 
						||
        $jsCode = $params['code'];
 | 
						||
        $wxUser = $minApp->auth->session($jsCode);
 | 
						||
 | 
						||
        if (isset($wxUser['errcode']) && $wxUser['errcode'] != 0) {
 | 
						||
            return $this->json(4001, $wxUser['errcode'].';'.$wxUser['errmsg'] ?? '登录失败');
 | 
						||
        }
 | 
						||
        // $wxUser success has [session_key, openid, unionid]
 | 
						||
        // 有效期2小时
 | 
						||
        $wxUser['expire_time'] = time() + 7200;
 | 
						||
        $wxUser['session_key'] = $wxUser['session_key'] ?? '';
 | 
						||
        $openID                = $wxUser['openid'];
 | 
						||
        $unionid               = $wxUser['unionid'] ?? '';
 | 
						||
 | 
						||
        if (empty($openID) && empty($unionid)) {
 | 
						||
            return $this->json(4002, '登录失败');
 | 
						||
        }
 | 
						||
        $isActive    = $params['is_active'] ?? 0;
 | 
						||
        $isActive    = (is_numeric($isActive) && $isActive > 0) ? AccountRepository::BOOL_TRUE : AccountRepository::BOOL_FALSE;
 | 
						||
        $phoneActive = $params['phone_active'] ?? 0;
 | 
						||
        $phoneActive = (is_numeric($phoneActive) && $phoneActive > 0) ? AccountRepository::BOOL_TRUE : AccountRepository::BOOL_FALSE;
 | 
						||
 | 
						||
        try {
 | 
						||
            $repo    = AccountRepository::getInstance();
 | 
						||
            $account = $repo->findByOpenID($openID);
 | 
						||
            if (!$account && !empty($unionid)) {
 | 
						||
                $account = $repo->findByUnionId($unionid);
 | 
						||
            }
 | 
						||
 | 
						||
            $now = date('Y-m-d H:i:s');
 | 
						||
            if (!$account) {
 | 
						||
                // 自动注册
 | 
						||
                $account = $repo->create([
 | 
						||
                    'unionid'      => $unionid ?? '',
 | 
						||
                    'openid'       => $openID,
 | 
						||
                    'last_login'   => $now,
 | 
						||
                    'login_ip'     => $this->request->ip(),
 | 
						||
                    'created_at'   => $now,
 | 
						||
                    'nickname'     => $params['nickname'] ?? '',
 | 
						||
                    'headimgurl'   => $params['headimgurl'] ?? '',
 | 
						||
                    'mobile'       => $params['mobile'] ?? '',
 | 
						||
                    'status'       => AccountRepository::STATUS_NORMAL,
 | 
						||
                    'is_active'    => $isActive,
 | 
						||
                    'phone_active' => $phoneActive,
 | 
						||
                    'session_key'  => $wxUser['session_key'] ?? '',
 | 
						||
                ]);
 | 
						||
            } else {
 | 
						||
                $updateData = [
 | 
						||
                    'last_login'  => date('Y-m-d H:i:s'),
 | 
						||
                    'login_ip'    => $this->request->ip(),
 | 
						||
                    'session_key' => $wxUser['session_key'] ?? '',
 | 
						||
                ];
 | 
						||
 | 
						||
                // 更新资料
 | 
						||
                $modifyStringList = ['headimgurl', 'nickname', 'mobile'];
 | 
						||
                foreach ($modifyStringList as $modifyKey) {
 | 
						||
                    if (isset($account[$modifyKey]) && empty($account[$modifyKey])) {
 | 
						||
                        $updateData[$modifyKey] = $params[$modifyKey] ?? '';
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                if (empty($account['gender'])) {
 | 
						||
                    $updateData['gender'] = $params['gender'] ?? 0;
 | 
						||
                }
 | 
						||
                if (isset($account['is_active']) && $account['is_active'] == AccountRepository::BOOL_FALSE) {
 | 
						||
                    $updateData['is_active'] = $isActive;
 | 
						||
                }
 | 
						||
                if (isset($account['phone_active']) && $account['phone_active'] == AccountRepository::BOOL_FALSE) {
 | 
						||
                    $updateData['phone_active'] = $phoneActive;
 | 
						||
                }
 | 
						||
 | 
						||
                $repo->update($updateData, ['id' => $account['id']]);
 | 
						||
 | 
						||
                $account = $repo->findById($account['id']);
 | 
						||
            }
 | 
						||
        } catch (RepositoryException | Exception $e) {
 | 
						||
            return $this->json(4003, '登录失败!'.$e->getMessage());
 | 
						||
        }
 | 
						||
 | 
						||
        $account = $account->toArray();
 | 
						||
        $jwtData = [
 | 
						||
            'user_id'     => $account['id'],
 | 
						||
            'open_id'     => $openID,
 | 
						||
            'session_key' => $wxUser['session_key'],
 | 
						||
            'expire_time' => $wxUser['expire_time'],
 | 
						||
        ];
 | 
						||
 | 
						||
        $account['headimgurl'] = File::convertCompleteFileUrl($account['headimgurl']);
 | 
						||
        $fields                = [
 | 
						||
            'coding', 'real_name', 'nickname', 'headimgurl', 'gender', 'mobile',
 | 
						||
            'status', 'is_active', 'phone_active'
 | 
						||
        ];
 | 
						||
 | 
						||
        $accountData = arrayKeysFilter($account, $fields);
 | 
						||
        $data        = [
 | 
						||
            'account_id' => $account['id'],
 | 
						||
            'token'      => Jwt::generate($jwtData),
 | 
						||
            'expire'     => $wxUser['expire_time'],
 | 
						||
            'openid'     => $openID,
 | 
						||
        ];
 | 
						||
        $data        = array_merge($data, $accountData);
 | 
						||
 | 
						||
        return $this->json(0, 'success', $data);
 | 
						||
    }
 | 
						||
 | 
						||
 | 
						||
    /**
 | 
						||
     * 获取用户信息
 | 
						||
     *
 | 
						||
     * @return Json
 | 
						||
     */
 | 
						||
    public function info(): Json
 | 
						||
    {
 | 
						||
        try {
 | 
						||
            $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
 | 
						||
            $user = Account::getUser($accountId);
 | 
						||
 | 
						||
            return $this->json(0, 'success', $user);
 | 
						||
        } catch (Exception $e) {
 | 
						||
            return $this->json(4000, '没有相关的用户记录'.$e->getMessage());
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 修改用户信息
 | 
						||
     */
 | 
						||
    public function updateInfo(): Json
 | 
						||
    {
 | 
						||
        try {
 | 
						||
            $params = input('post.');
 | 
						||
 | 
						||
            $rules = [
 | 
						||
                'field|修改项'  => 'require|in:nickname',
 | 
						||
                'value|修改内容' => 'require',
 | 
						||
            ];
 | 
						||
 | 
						||
            $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
 | 
						||
            $validate = $this->validateByApi($params, $rules, ['field.in' => '参数错误']);
 | 
						||
 | 
						||
            if ($validate !== true) {
 | 
						||
                return $validate;
 | 
						||
            }
 | 
						||
 | 
						||
            if (!$customer = Account::findById($accountId)) {
 | 
						||
                return $this->json(4004, '用户不存在');
 | 
						||
            }
 | 
						||
 | 
						||
            $customer->save([
 | 
						||
                $params['field'] => $params['value']
 | 
						||
            ]);
 | 
						||
        } catch (Exception $e) {
 | 
						||
            Log::error('修改用户信息失败'.$e->getMessage());
 | 
						||
            return $this->json(5000, '修改失败!'.$e->getMessage());
 | 
						||
        }
 | 
						||
 | 
						||
        return $this->json();
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 临时登录  通过openid登录 仅用于接口测试阶段
 | 
						||
     *
 | 
						||
     * @return Json
 | 
						||
     * @throws DataNotFoundException
 | 
						||
     * @throws DbException
 | 
						||
     * @throws ModelNotFoundException
 | 
						||
     */
 | 
						||
    public function tempLogin(): Json
 | 
						||
    {
 | 
						||
        $params = $this->request->param();
 | 
						||
 | 
						||
        if (!isset($params['openid'])) {
 | 
						||
            return $this->json(4001, '参数错误');
 | 
						||
        }
 | 
						||
 | 
						||
        if (!$user = AccountRepository::getInstance()->findByOpenID($params['openid'])) {
 | 
						||
            return $this->json(4004, '账号不存在');
 | 
						||
        }
 | 
						||
 | 
						||
        $data = [
 | 
						||
            'token'  => Jwt::generate(['user_id' => $user['id'], 'nickname' => $user['nickname']]),
 | 
						||
            'expire' => Jwt::expire()
 | 
						||
        ];
 | 
						||
 | 
						||
        return $this->json(0, 'success', $data);
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 用户操作记录 分享、咨询
 | 
						||
     *
 | 
						||
     * @return Json
 | 
						||
     * @throws Exception
 | 
						||
     */
 | 
						||
    public function record(): Json
 | 
						||
    {
 | 
						||
        if (!$this->request->isPost()) {
 | 
						||
            return $this->json(4000, '无效请求');
 | 
						||
        }
 | 
						||
 | 
						||
        $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
        $params    = input('post.');
 | 
						||
 | 
						||
        $rules = [
 | 
						||
            'type|操作类型' => 'require|in:content,other,spu,activity',
 | 
						||
            'action|操作' => 'require',
 | 
						||
        ];
 | 
						||
 | 
						||
        if (isset($params['type']) && $params['type'] == AccountRecord::TYPE_CONTENT) {
 | 
						||
            $rules['id|ID'] = 'require';
 | 
						||
        }
 | 
						||
 | 
						||
        $validate = $this->validateByApi($params, $rules, ['type.in' => '类型错误', 'id.require' => '此类型 ID必传']);
 | 
						||
 | 
						||
        if ($validate !== true) {
 | 
						||
            return $validate;
 | 
						||
        }
 | 
						||
 | 
						||
        try {
 | 
						||
            $relationId = $params['id'] ?? 0;
 | 
						||
            $relationId = is_numeric($relationId) ? $relationId : 0;
 | 
						||
            AccountRecord::record($accountId, $params['type'], $params['action'], $relationId);
 | 
						||
        } catch (Exception $e) {
 | 
						||
            AccountRepository::log('记录用户操作失败', $e);
 | 
						||
            return $this->json(5001, '操作失败');
 | 
						||
        }
 | 
						||
 | 
						||
        return $this->json();
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 绑定手机
 | 
						||
     *
 | 
						||
     * @return bool|Json
 | 
						||
     * @throws Exception
 | 
						||
     */
 | 
						||
    public function bindPhone()
 | 
						||
    {
 | 
						||
        if (!$this->request->isPost()) {
 | 
						||
            return $this->json(4000, '无效请求');
 | 
						||
        }
 | 
						||
 | 
						||
        $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
        $params    = input('post.');
 | 
						||
 | 
						||
        $rules = [
 | 
						||
            'encryptedData|加密数据' => 'require',
 | 
						||
            'iv|IV'              => 'require',
 | 
						||
        ];
 | 
						||
 | 
						||
        $validate = $this->validateByApi($params, $rules);
 | 
						||
 | 
						||
        if ($validate !== true) {
 | 
						||
            return $validate;
 | 
						||
        }
 | 
						||
 | 
						||
        try {
 | 
						||
            if (!$account = Account::findById($accountId)) {
 | 
						||
                return $this->json(4000, '用户不存在');
 | 
						||
            }
 | 
						||
 | 
						||
            // 解密手机相关数据  若存在手机则覆盖
 | 
						||
            $minApp      = WechatApplets::getInstance();
 | 
						||
            $sessionKey  = $this->request->user['session_key'] ?? '';
 | 
						||
            $decryptData = $minApp->encryptor->decryptData($sessionKey, $params['iv'], $params['encryptedData']);
 | 
						||
            $phone       = $decryptData['phoneNumber'] ?? ''; // 通过iv和加密数据 解密出手机号
 | 
						||
 | 
						||
            if (Account::where('id', '<>', $accountId)->where('mobile', $phone)->count() > 0) {
 | 
						||
                return $this->json(4000, '该手机已被绑定,若有绑定错误,请联系客服');
 | 
						||
            }
 | 
						||
 | 
						||
            if ($phone) {
 | 
						||
                $account->save(['mobile' => $phone, 'phone_active' => Account::COMMON_ON]);
 | 
						||
            }
 | 
						||
 | 
						||
            return $this->json(0, 'success', ['phone' => $phone]);
 | 
						||
        } catch (Exception $e) {
 | 
						||
            AccountRepository::log('手机绑定失败', $e);
 | 
						||
            return $this->json(5001, '手机绑定失败');
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    // 打卡页面信息
 | 
						||
    public function signInfo(): Json
 | 
						||
    {
 | 
						||
        $list = [];
 | 
						||
 | 
						||
        $week = ['日', '一', '二', '三', '四', '五', '六'];
 | 
						||
 | 
						||
        $info = [
 | 
						||
            'today'   => date('Y年m月d日'),
 | 
						||
            'week'    => '星期'.$week[date('w')],
 | 
						||
            'now'     => date('H:i:s'),
 | 
						||
            'is_sign' => (int) !empty($list),
 | 
						||
        ];
 | 
						||
 | 
						||
        return $this->json(0, 'success', ['info' => $info]);
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 今日打卡记录
 | 
						||
     *
 | 
						||
     * @return \think\response\Json
 | 
						||
     * @throws \think\db\exception\DataNotFoundException
 | 
						||
     * @throws \think\db\exception\DbException
 | 
						||
     * @throws \think\db\exception\ModelNotFoundException
 | 
						||
     */
 | 
						||
    public function signToday(): Json
 | 
						||
    {
 | 
						||
        $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
 | 
						||
        $list = [];
 | 
						||
 | 
						||
        $buttonColor = 'gray';
 | 
						||
 | 
						||
        if ($accountId > 0) {
 | 
						||
            if (!$account = Account::findById($accountId)) {
 | 
						||
                return $this->json(6001, '请先登录');
 | 
						||
            }
 | 
						||
 | 
						||
            $where   = [];
 | 
						||
            $where[] = ['cl.created_at', '>', date('Y-m-d 00:00:00')];
 | 
						||
            $where[] = ['cl.created_at', '<', date('Y-m-d 23:59:59')];
 | 
						||
            $where[] = ['cl.account_id', '=', $accountId];
 | 
						||
 | 
						||
            $where[] = ['cl.role', '=', $account['role']];
 | 
						||
            $limit   = $account['role'] == Account::ROLE_NORMAL ? 4 : 0;//普通用户只展示最新4条 其他不限制
 | 
						||
            $list    = \app\model\ClockLog::alias('cl')
 | 
						||
                ->leftJoin('worksite w', 'w.id = cl.worksite_id')
 | 
						||
                ->field('cl.*,w.name as worksite_name')
 | 
						||
                ->where($where)
 | 
						||
                ->limit($limit)
 | 
						||
                ->order('cl.id', 'desc')
 | 
						||
                ->select();
 | 
						||
 | 
						||
 | 
						||
            /**
 | 
						||
             *  打卡按钮颜色 gray=灰色 orange=橙色 绿色=green
 | 
						||
             * 普通人 只有灰色 和 绿色 未打卡灰色 打卡>0为绿色
 | 
						||
             * 工人和负责人
 | 
						||
             * 灰色: 未打卡、(中途休息期间如12~14 未判断此条件)
 | 
						||
             * 橙色:上班卡数量>下班卡数量且>0
 | 
						||
             * 绿色:1. 下班卡数量>= 上班卡数量 且下班卡数量>=1 或 2.下午下班卡打了后
 | 
						||
             */
 | 
						||
            if ($account['role'] == Account::ROLE_NORMAL) {
 | 
						||
                $buttonColor = $list->count() > 0 ? 'green' : 'gray';
 | 
						||
            } else {
 | 
						||
                $array    = $list->whereIn('status', [0, 1])->column('type');
 | 
						||
                $onCount  = 0;//上班卡数量
 | 
						||
                $offCount = 0;//下班卡数量
 | 
						||
                foreach ($array as $sign) {
 | 
						||
                    if (strpos($sign, '_on')) {
 | 
						||
                        $onCount++;
 | 
						||
                    }
 | 
						||
 | 
						||
                    if (strpos($sign, '_off')) {
 | 
						||
                        $offCount++;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
                if (in_array('afternoon_off', $array) || ($offCount >= $onCount && $offCount >= 1)) {
 | 
						||
                    $buttonColor = 'green';
 | 
						||
                }
 | 
						||
 | 
						||
                if (($offCount >= $onCount && $offCount >= 1) || $onCount > 0) {
 | 
						||
                    $buttonColor = 'orange';
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            $list->each(function ($item) {
 | 
						||
                $item->type_text = ClockLog::typeText()[$item->type];
 | 
						||
                switch ($item->status) {
 | 
						||
                    case 0:
 | 
						||
                        $item->status_text = '待确认';
 | 
						||
                        break;
 | 
						||
                    case 1:
 | 
						||
                        $item->status_text = '已确认';
 | 
						||
                        break;
 | 
						||
                    case -1:
 | 
						||
                        $item->status_text = '不通过';
 | 
						||
                        break;
 | 
						||
                }
 | 
						||
                $item->time = date('H:i', $item->create_time);
 | 
						||
            });
 | 
						||
            $list = $list->toArray();
 | 
						||
        }
 | 
						||
 | 
						||
        return $this->json(0, 'success', ['buttonColor' => $buttonColor, 'list' => $list]);
 | 
						||
    }
 | 
						||
 | 
						||
    public function checkActive(): Json
 | 
						||
    {
 | 
						||
        try {
 | 
						||
            $openid = input('openid/s');
 | 
						||
            if (empty($openid)) {
 | 
						||
                return $this->json(0, 'success', ['status' => 0]);
 | 
						||
            }
 | 
						||
 | 
						||
            $isActive = (int) Account::where('openid', $openid)->value('is_active');
 | 
						||
 | 
						||
            return $this->json(0, 'success', ['status' => $isActive]);
 | 
						||
        } catch (Exception $e) {
 | 
						||
            return $this->json(4000, '检查账号是否微信授权是不'.$e->getMessage());
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     *  月度打卡记录
 | 
						||
     * {
 | 
						||
     * 'ok':[2,5,6,8,12],
 | 
						||
     * 'add':[4,7,11,22],
 | 
						||
     * 'no':[19,28]
 | 
						||
     * }
 | 
						||
     *
 | 
						||
     * @return \think\response\Json
 | 
						||
     * @throws \think\db\exception\DataNotFoundException
 | 
						||
     * @throws \think\db\exception\DbException
 | 
						||
     * @throws \think\db\exception\ModelNotFoundException
 | 
						||
     */
 | 
						||
    public function monthSignLog(): Json
 | 
						||
    {
 | 
						||
        $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
        $date      = input('date/s', '');
 | 
						||
        $date      = $date ?: date('Y-m');
 | 
						||
        $ym        = str_replace('-', '', $date);
 | 
						||
 | 
						||
        $res = [
 | 
						||
            'ok'  => [], //正常打卡:普通用户当天有打卡=正常 工人和负责人:打满4次=正常
 | 
						||
            'add' => [],// 补打卡:仅限工人和负责人 当天存在补卡
 | 
						||
            'no'  => [],// 非正常打卡:仅限工人和负责人 4>打卡次数>0
 | 
						||
        ];
 | 
						||
 | 
						||
        if ($accountId > 0) {
 | 
						||
            if (!$account = Account::findById($accountId)) {
 | 
						||
                return $this->json(6001, '请先登录');
 | 
						||
            }
 | 
						||
 | 
						||
            $where   = [];
 | 
						||
            $where[] = ['cl.day', 'like', $ym.'%'];
 | 
						||
            $where[] = ['cl.account_id', '=', $accountId];
 | 
						||
            $where[] = ['cl.role', '=', $account['role']];
 | 
						||
            $list    = \app\model\ClockLog::alias('cl')
 | 
						||
                ->where($where)
 | 
						||
                ->select();
 | 
						||
 | 
						||
            $signNum = [];//每日打卡次数
 | 
						||
            foreach ($list as $item) {
 | 
						||
                $day = (int) substr($item['day'], -2);
 | 
						||
                if (!isset($signNum[$day])) {
 | 
						||
                    $signNum[$day] = 0;
 | 
						||
                }
 | 
						||
                $signNum[$day]++;
 | 
						||
                if ($item['is_replenish'] == ClockLog::COMMON_ON) {
 | 
						||
                    $res['add'][] = $day;
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            foreach ($signNum as $day => $count) {
 | 
						||
                if ($account['role'] == Account::ROLE_NORMAL) {
 | 
						||
                    if ($count >= 1) {
 | 
						||
                        $res['ok'][] = $day;
 | 
						||
                    }
 | 
						||
                } else {
 | 
						||
                    if ($count == 4) {
 | 
						||
                        $res['ok'][] = $day;
 | 
						||
                    } else {
 | 
						||
                        $res['no'][] = $day;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            $res['ok']  = array_unique($res['ok']);
 | 
						||
            $res['add'] = array_unique($res['add']);
 | 
						||
            $res['no']  = array_unique($res['no']);
 | 
						||
        }
 | 
						||
 | 
						||
        return $this->json(0, 'success', $res);
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 打卡
 | 
						||
     * 普通用户打卡不需要任何参数
 | 
						||
     * 员工和负责人打卡 参数相同
 | 
						||
     */
 | 
						||
    public function sign(): Json
 | 
						||
    {
 | 
						||
        try {
 | 
						||
            $accountId = $this->request->user['user_id'] ?? 0;
 | 
						||
 | 
						||
            if (!$customer = Account::findById($accountId)) {
 | 
						||
                return $this->json(6001, '请先登录');
 | 
						||
            }
 | 
						||
 | 
						||
            $input = input('post.');
 | 
						||
 | 
						||
            // 工人打卡
 | 
						||
            if ($customer['role'] == Account::ROLE_NORMAL && $this->normalSign($accountId, $input['type'])) {
 | 
						||
                return $this->json();
 | 
						||
            }
 | 
						||
 | 
						||
            $rules = [
 | 
						||
                'type|打卡类型'      => 'require|in:morning_on,morning_off,afternoon_on,afternoon_off',
 | 
						||
                'lat|维度'         => 'require',
 | 
						||
                'lng|经度'         => 'require',
 | 
						||
                'worksite_id|工地' => 'require|number',
 | 
						||
            ];
 | 
						||
 | 
						||
            $validate = $this->validateByApi($input, $rules, ['type.in' => '打卡类型错误']);
 | 
						||
 | 
						||
            if ($validate !== true) {
 | 
						||
                return $validate;
 | 
						||
            }
 | 
						||
 | 
						||
            Config::load('extra/base', 'base');
 | 
						||
            $baseConfig = config('base');
 | 
						||
            $signArea   = $baseConfig['sign_area'] ?? 200;
 | 
						||
            $worksite   = Worksite::getNearest($input['lng'], $input['lat'], $signArea);
 | 
						||
            if (empty($worksite) || $worksite['id'] != $input['worksite_id']) {
 | 
						||
                return $this->json(4004, '不在打卡范围!');
 | 
						||
            }
 | 
						||
 | 
						||
            $time = time();
 | 
						||
            //            $time = $time - 86401 * 3;
 | 
						||
            $now = date('Y-m-d H:i:s', $time);
 | 
						||
            $day = date('Ymd', $time);
 | 
						||
 | 
						||
            if (ClockLog::hasSign($accountId, $input['type'], $input['worksite_id'])) {
 | 
						||
                return $this->json(4001, '今日已打过此卡');
 | 
						||
            }
 | 
						||
 | 
						||
            $data = [
 | 
						||
                'account_id'  => $accountId,
 | 
						||
                'type'        => $input['type'],
 | 
						||
                'worksite_id' => $input['worksite_id'],
 | 
						||
                'created_at'  => $now,
 | 
						||
                'create_time' => $time,
 | 
						||
                'day'         => $day,
 | 
						||
                'role'        => $customer['role'],
 | 
						||
                'indexs'      => $accountId.'-'.$input['worksite_id'].'-'.$day,
 | 
						||
            ];
 | 
						||
 | 
						||
            // 工人
 | 
						||
            if ($customer['role'] == Account::ROLE_WORKER) {
 | 
						||
                $data['need_statistic'] = Account::COMMON_ON;
 | 
						||
            }
 | 
						||
 | 
						||
            // 负责人
 | 
						||
            if ($customer['role'] == Account::ROLE_MANAGER) {
 | 
						||
                $data['status']         = Account::COMMON_ON;
 | 
						||
                $data['need_statistic'] = Account::COMMON_OFF;
 | 
						||
            }
 | 
						||
            ClockLog::create($data);
 | 
						||
 | 
						||
            // 创建当日工资初始记录
 | 
						||
            PayLog::createWhenNotExists($accountId, $input['worksite_id'], $day);
 | 
						||
        } catch (ApiException $e) {
 | 
						||
            return $this->json(4000, $e->getMessage());
 | 
						||
        } catch (Exception $e) {
 | 
						||
            Log::error('打卡失败'.$e->getMessage());
 | 
						||
            return $this->json(5000, '打卡失败!');
 | 
						||
        }
 | 
						||
 | 
						||
        return $this->json();
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * 普通用户打卡
 | 
						||
     *
 | 
						||
     * @param  int  $accountId
 | 
						||
     * @param  string  $type
 | 
						||
     * @return bool
 | 
						||
     * @throws \app\exception\ApiException
 | 
						||
     * @throws \think\db\exception\DbException
 | 
						||
     */
 | 
						||
    private function normalSign(int $accountId, string $type): bool
 | 
						||
    {
 | 
						||
        $time = time();
 | 
						||
        //            $time = $time - 86401 * 3;
 | 
						||
        $now = date('Y-m-d H:i:s', $time);
 | 
						||
        $day = date('Ymd', $time);
 | 
						||
 | 
						||
        if (ClockLog::checkRate($accountId, $type)) {
 | 
						||
            throw new ApiException('打卡频率过快!');
 | 
						||
        }
 | 
						||
 | 
						||
        ClockLog::create([
 | 
						||
            'account_id'  => $accountId,
 | 
						||
            'type'        => $type,
 | 
						||
            'created_at'  => $now,
 | 
						||
            'create_time' => $time,
 | 
						||
            'day'         => $day,
 | 
						||
            'status'      => ClockLog::COMMON_ON,
 | 
						||
        ]);
 | 
						||
 | 
						||
        return true;
 | 
						||
    }
 | 
						||
}
 |