feat: 打卡接口调整
parent
34805d76d6
commit
d102eb2844
|
@ -3,9 +3,13 @@
|
|||
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;
|
||||
|
@ -17,6 +21,7 @@ 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;
|
||||
|
||||
|
@ -390,10 +395,10 @@ class User extends Base
|
|||
try {
|
||||
$openid = input('openid/s');
|
||||
if (empty($openid)) {
|
||||
return $this->json(0,'success', ['status' => 0]);
|
||||
return $this->json(0, 'success', ['status' => 0]);
|
||||
}
|
||||
|
||||
$isActive = (int)Account::where('openid', $openid)->value('is_active');
|
||||
$isActive = (int) Account::where('openid', $openid)->value('is_active');
|
||||
|
||||
return $this->json(0, 'success', ['status' => $isActive]);
|
||||
} catch (Exception $e) {
|
||||
|
@ -442,4 +447,119 @@ class User extends Base
|
|||
|
||||
return $this->json(0, 'success', ['list' => $list]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打卡
|
||||
* 普通用户打卡不需要任何参数
|
||||
* 员工和负责人打卡 参数相同
|
||||
*/
|
||||
public function sign(): Json
|
||||
{
|
||||
try {
|
||||
$accountId = $this->request->user['user_id'] ?? 0;
|
||||
|
||||
if (!$customer = Account::findById($accountId)) {
|
||||
return $this->json(6001, '请先登录');
|
||||
}
|
||||
|
||||
// 工人打卡
|
||||
if ($customer['role'] == Account::ROLE_NORMAL && $this->normalSign($accountId)) {
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$input = input('post.');
|
||||
|
||||
$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,
|
||||
'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
|
||||
* @return bool
|
||||
* @throws \app\exception\ApiException
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
private function normalSign(int $accountId): bool
|
||||
{
|
||||
$time = time();
|
||||
// $time = $time - 86401 * 3;
|
||||
$now = date('Y-m-d H:i:s', $time);
|
||||
$day = date('Ymd', $time);
|
||||
|
||||
if (ClockLog::checkRate($accountId)) {
|
||||
throw new ApiException('打卡频率过快!');
|
||||
}
|
||||
|
||||
ClockLog::create([
|
||||
'account_id' => $accountId,
|
||||
'type' => ClockLog::TYPE_NORMAL,
|
||||
'created_at' => $now,
|
||||
'create_time' => $time,
|
||||
'day' => $day,
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,10 +188,20 @@ class Worker extends Base
|
|||
public function sign(): Json
|
||||
{
|
||||
try {
|
||||
$accountId = $this->request->user['user_id'] ?? 0;
|
||||
|
||||
if (!$customer = Account::findById($accountId)) {
|
||||
return $this->json(6001, '请先登录');
|
||||
}
|
||||
|
||||
if ($customer['role'] == Account::ROLE_NORMAL) {
|
||||
return $this->normalSign();
|
||||
}
|
||||
|
||||
$input = input('post.');
|
||||
|
||||
$rules = [
|
||||
'type|打卡类型' => 'require|in:in,out',
|
||||
'type|打卡类型' => 'require|in:morning_on,morning_off,afternoon_on,afternoon_off',
|
||||
'lat|维度' => 'require',
|
||||
'lng|经度' => 'require',
|
||||
'worksite_id|工地' => 'require|number',
|
||||
|
@ -203,12 +213,6 @@ class Worker extends Base
|
|||
return $validate;
|
||||
}
|
||||
|
||||
$accountId = $this->request->user['user_id'] ?? 0;
|
||||
|
||||
if (!$customer = Account::findById($accountId)) {
|
||||
return $this->json(6001, '请先登录');
|
||||
}
|
||||
|
||||
if ($customer['role'] != Account::ROLE_WORKER) {
|
||||
return $this->json(4003, '完成审核后方可打卡');
|
||||
}
|
||||
|
@ -250,6 +254,47 @@ class Worker extends Base
|
|||
return $this->json();
|
||||
}
|
||||
|
||||
private function normalSign($customer)
|
||||
{
|
||||
try {
|
||||
|
||||
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::where('account_id', $accountId)->where('type', $input['type'])->where('create_time', '>', time() - 60)->count()) {
|
||||
return $this->json(4001, '打卡频率过快!');
|
||||
}
|
||||
|
||||
ClockLog::create([
|
||||
'account_id' => $accountId,
|
||||
'type' => $input['type'],
|
||||
'worksite_id' => $input['worksite_id'],
|
||||
'created_at' => $now,
|
||||
'create_time' => $time,
|
||||
'day' => $day,
|
||||
'indexs' => $accountId.'-'.$input['worksite_id'].'-'.$day,
|
||||
]);
|
||||
|
||||
// 创建当日工资初始记录
|
||||
PayLog::createWhenNotExists($accountId, $input['worksite_id'], $day);
|
||||
} catch (Exception $e) {
|
||||
Log::error('工人打卡失败'.$e->getMessage());
|
||||
return $this->json(5000, '打卡失败!');
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
// 我的打卡
|
||||
public function clockList(): Json
|
||||
{
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace app\exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ApiException extends Exception
|
||||
{
|
||||
|
||||
}
|
|
@ -10,8 +10,13 @@ namespace app\model;
|
|||
*/
|
||||
class ClockLog extends Base
|
||||
{
|
||||
public const TYPE_IN = 'in';//上班
|
||||
public const TYPE_OUT = 'out';//下班
|
||||
public const TYPE_NORMAL = 'normal';//普通打卡 适用于普通用户打卡 不区分上下班 场地 位置等等
|
||||
|
||||
public const TYPE_MORNING_ON = 'morning_on';//上午上班
|
||||
public const TYPE_MORNING_OFF = 'morning_off';//上午下班
|
||||
|
||||
public const TYPE_AFTERNOON_ON = 'afternoon_on';//下午上班
|
||||
public const TYPE_AFTERNOON_OFF = 'afternoon_off';//下午下班
|
||||
|
||||
public const STATUS_TODO = 0;//待审核
|
||||
public const STATUS_YES = 1;//通过
|
||||
|
@ -25,8 +30,11 @@ class ClockLog extends Base
|
|||
public static function typeText(): array
|
||||
{
|
||||
return [
|
||||
self::TYPE_IN => '上班',
|
||||
self::TYPE_OUT => '下班',
|
||||
self::TYPE_NORMAL => '普通打卡',
|
||||
self::TYPE_MORNING_ON => '上午上班',
|
||||
self::TYPE_MORNING_OFF => '上午下班',
|
||||
self::TYPE_AFTERNOON_ON => '下午上班',
|
||||
self::TYPE_AFTERNOON_OFF => '下午下班',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -38,4 +46,44 @@ class ClockLog extends Base
|
|||
self::STATUS_NO => '审核拒绝',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查打卡频率
|
||||
* 目前针对普通用户
|
||||
*
|
||||
* @param int $accountId 用户ID
|
||||
* @param string $type 打卡类型
|
||||
* @param int $worksiteId 工地ID 默认0
|
||||
* @param int $seconds 时间限制,秒 即多少秒内只能打一次 默认60
|
||||
* @return bool true=单位时间有打卡 false=单位时间未打卡
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public static function checkRate(int $accountId, string $type = self::TYPE_NORMAL, int $worksiteId = 0, int $seconds = 60): bool
|
||||
{
|
||||
return self::where('account_id', $accountId)
|
||||
->where('type', $type)
|
||||
->where('worksite_id', $worksiteId)
|
||||
->where('create_time', '>', time() - $seconds)
|
||||
->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当天是否已打卡
|
||||
* 目前针对工人和负责人
|
||||
*
|
||||
* @param int $accountId 用户ID
|
||||
* @param string $type 打卡类型
|
||||
* @param int $worksiteId 工地ID 默认0
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public static function hasSign(int $accountId, string $type, int $worksiteId): bool
|
||||
{
|
||||
return self::where('account_id', $accountId)
|
||||
->where('type', $type)
|
||||
->where('worksite_id', $worksiteId)
|
||||
->where('create_time', '>=', strtotime(date('Y-m-d')))
|
||||
->where('create_time', '<=', strtotime(date('Y-m-d 23:59:59')))
|
||||
->count() > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,4 +86,67 @@ class Worksite extends Base
|
|||
{
|
||||
return self::order('sort', 'desc')->order('id', 'desc')->column('name', 'id');
|
||||
}
|
||||
|
||||
// 验证是否在打卡时间
|
||||
public static function checkSignTime(int $worksiteId, string $type): bool
|
||||
{
|
||||
if (!$item = self::find($worksiteId)) {
|
||||
return false;
|
||||
}
|
||||
$morningBegin = $item['old_morning_begin'];
|
||||
$morningEnd = $item['old_morning_end'];
|
||||
$afternoonBegin = $item['old_afternoon_begin'];
|
||||
$afternoonEnd = $item['old_afternoon_end'];
|
||||
|
||||
$now = time();
|
||||
|
||||
if ($now > $item['start_at']) {
|
||||
$morningBegin = $item['morning_begin'];
|
||||
$morningEnd = $item['morning_end'];
|
||||
$afternoonBegin = $item['afternoon_begin'];
|
||||
$afternoonEnd = $item['afternoon_end'];
|
||||
}
|
||||
|
||||
// 时间戳
|
||||
$morningBeginTs = strtotime($morningBegin);
|
||||
$morningEndTs = strtotime($morningEnd);
|
||||
$afternoonBeginTs = strtotime($afternoonBegin);
|
||||
$afternoonEndTs = strtotime($afternoonEnd);
|
||||
|
||||
$result = false;
|
||||
switch ($type) {
|
||||
// 普通用户打卡 不限制时间
|
||||
case ClockLog::TYPE_NORMAL:
|
||||
$result = true;
|
||||
break;
|
||||
// 上午上班时间 打卡时间在上班前的10分钟
|
||||
case ClockLog::TYPE_MORNING_ON:
|
||||
if (($morningBeginTs - 10 * 60) <= $now && $now <= $morningBeginTs) {
|
||||
$result = true;
|
||||
}
|
||||
break;
|
||||
// 上午下班时间 打卡时间在下班时间后 下次上班时间以前
|
||||
case ClockLog::TYPE_MORNING_OFF:
|
||||
if (($morningEndTs) <= $now && $now < $afternoonBeginTs) {
|
||||
$result = true;
|
||||
}
|
||||
break;
|
||||
|
||||
// 下午上班时间 打卡时间在上班前的10分钟
|
||||
case ClockLog::TYPE_AFTERNOON_ON:
|
||||
if (($afternoonBeginTs - 10 * 60) <= $now && $now <= $afternoonBeginTs) {
|
||||
$result = true;
|
||||
}
|
||||
break;
|
||||
|
||||
// 下午下班时间 打卡时间在下班时间后 当天23:59:59以前
|
||||
case ClockLog::TYPE_AFTERNOON_OFF:
|
||||
if (($afternoonEndTs) <= $now && $now < strtotime('23:59:59')) {
|
||||
$result = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue