store_id)) { if (IS_POST) { $res = array( 'status' => 0, 'msg' => '您无权访问该接口', ); $this->ajaxReturn($res); } else { session(null); echo ''; exit; } } } /** * 围栏管理页面 */ public function index() { $this->display(); } /** * 获取围栏列表 */ public function getFenceList() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $store_id = I('post.store_id', $this->store_id); $page = I('post.page', 1); $size = I('post.size', 10); // 验证参数 if (!$store_id) { $this->ajaxReturn(['code' => 400, 'msg' => '门店ID不能为空']); } $where = [ 'store_id' => $store_id, 'is_deleted' => 0 ]; // 计算总数 $total = M('ls_store_delivery_fence')->where($where)->count(); // 获取列表数据 $list = M('ls_store_delivery_fence') ->where($where) ->order('create_time DESC') ->page($page, $size) ->select(); $this->ajaxReturn([ 'code' => 200, 'msg' => '获取成功', 'data' => [ 'list' => $list ?: [], 'total' => $total, 'page' => $page, 'size' => $size ] ]); } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 新增围栏 */ public function addFence() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $fence_name = I('post.fence_name'); $fence_type = I('post.fence_type'); $fence_data = I('post.fence_data'); $is_active = I('post.is_active', 1); $store_id = I('post.store_id', $this->store_id); $merchant_id = I('post.merchant_id', $this->merchant_id); // 验证必填参数 if (!$fence_name) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏名称不能为空']); } if (!in_array($fence_type, [1, 2])) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏类型错误']); } if (!$fence_data) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏数据不能为空']); } // 验证围栏数据格式 $fence_data_array = json_decode($fence_data, true); if (!$fence_data_array) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏数据格式错误']); } // 验证围栏数据内容 if ($fence_type == 1) { // 多边形 if (!isset($fence_data_array['type']) || $fence_data_array['type'] !== 'polygon' || !isset($fence_data_array['coordinates']) || !is_array($fence_data_array['coordinates'])) { $this->ajaxReturn(['code' => 400, 'msg' => '多边形围栏数据格式错误']); } } else if ($fence_type == 2) { // 圆形 if (!isset($fence_data_array['type']) || $fence_data_array['type'] !== 'circle' || !isset($fence_data_array['center']) || !isset($fence_data_array['radius'])) { $this->ajaxReturn(['code' => 400, 'msg' => '圆形围栏数据格式错误']); } } // 检查围栏名称是否重复 $exists = M('ls_store_delivery_fence')->where([ 'store_id' => $store_id, 'fence_name' => $fence_name, 'is_deleted' => 0 ])->find(); if ($exists) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏名称已存在']); } // 插入数据 $data = [ 'store_id' => $store_id, 'merchant_id' => $merchant_id, 'fence_name' => $fence_name, 'fence_type' => $fence_type, 'fence_data' => $fence_data, 'is_active' => $is_active, 'create_time' => time(), 'update_time' => time(), 'is_deleted' => 0 ]; $result = M('ls_store_delivery_fence')->add($data); if ($result) { $this->ajaxReturn(['code' => 200, 'msg' => '添加成功', 'data' => ['id' => $result]]); } else { $this->ajaxReturn(['code' => 500, 'msg' => '添加失败']); } } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 更新围栏 */ public function updateFence() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $id = I('post.id'); $fence_name = I('post.fence_name'); $fence_type = I('post.fence_type'); $fence_data = I('post.fence_data'); $is_active = I('post.is_active', 1); $store_id = I('post.store_id', $this->store_id); // 验证必填参数 if (!$id) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏ID不能为空']); } if (!$fence_name) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏名称不能为空']); } if (!in_array($fence_type, [1, 2])) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏类型错误']); } if (!$fence_data) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏数据不能为空']); } // 验证围栏是否存在 $fence = M('ls_store_delivery_fence')->where([ 'id' => $id, 'store_id' => $store_id, 'is_deleted' => 0 ])->find(); if (!$fence) { $this->ajaxReturn(['code' => 404, 'msg' => '围栏不存在']); } // 验证围栏数据格式 $fence_data_array = json_decode($fence_data, true); if (!$fence_data_array) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏数据格式错误']); } // 检查围栏名称是否重复(排除当前记录) $exists = M('ls_store_delivery_fence')->where([ 'store_id' => $store_id, 'fence_name' => $fence_name, 'is_deleted' => 0, 'id' => ['neq', $id] ])->find(); if ($exists) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏名称已存在']); } // 更新数据 $data = [ 'fence_name' => $fence_name, 'fence_type' => $fence_type, 'fence_data' => $fence_data, 'is_active' => $is_active, 'update_time' => time() ]; $result = M('ls_store_delivery_fence')->where(['id' => $id])->save($data); if ($result !== false) { $this->ajaxReturn(['code' => 200, 'msg' => '更新成功']); } else { $this->ajaxReturn(['code' => 500, 'msg' => '更新失败']); } } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 更新围栏状态 */ public function updateFenceStatus() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $id = I('post.id'); $is_active = I('post.is_active'); $store_id = $this->store_id; // 验证参数 if (!$id) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏ID不能为空']); } if (!in_array($is_active, [0, 1])) { $this->ajaxReturn(['code' => 400, 'msg' => '状态参数错误']); } // 验证围栏是否存在 $fence = M('ls_store_delivery_fence')->where([ 'id' => $id, 'store_id' => $store_id, 'is_deleted' => 0 ])->find(); if (!$fence) { $this->ajaxReturn(['code' => 404, 'msg' => '围栏不存在']); } // 更新状态 $result = M('ls_store_delivery_fence')->where(['id' => $id])->save([ 'is_active' => $is_active, 'update_time' => time() ]); if ($result !== false) { $this->ajaxReturn(['code' => 200, 'msg' => '状态更新成功']); } else { $this->ajaxReturn(['code' => 500, 'msg' => '状态更新失败']); } } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 删除围栏 */ public function deleteFence() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $id = I('post.id'); $store_id = $this->store_id; // 验证参数 if (!$id) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏ID不能为空']); } // 验证围栏是否存在 $fence = M('ls_store_delivery_fence')->where([ 'id' => $id, 'store_id' => $store_id, 'is_deleted' => 0 ])->find(); if (!$fence) { $this->ajaxReturn(['code' => 404, 'msg' => '围栏不存在']); } // 软删除 $result = M('ls_store_delivery_fence')->where(['id' => $id])->save([ 'is_deleted' => 1, 'update_time' => time() ]); if ($result !== false) { $this->ajaxReturn(['code' => 200, 'msg' => '删除成功']); } else { $this->ajaxReturn(['code' => 500, 'msg' => '删除失败']); } } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 获取围栏详情 */ public function getFenceDetail() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $id = I('post.id'); $store_id = $this->store_id; // 验证参数 if (!$id) { $this->ajaxReturn(['code' => 400, 'msg' => '围栏ID不能为空']); } // 获取围栏详情 $fence = M('ls_store_delivery_fence')->where([ 'id' => $id, 'store_id' => $store_id, 'is_deleted' => 0 ])->find(); if (!$fence) { $this->ajaxReturn(['code' => 404, 'msg' => '围栏不存在']); } $this->ajaxReturn(['code' => 200, 'msg' => '获取成功', 'data' => $fence]); } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 检查坐标是否在围栏内 */ public function checkPointInFence() { if (!IS_POST) { $this->ajaxReturn(['code' => 400, 'msg' => '请求方式错误']); } try { $lng = I('post.lng'); $lat = I('post.lat'); $store_id = I('post.store_id', $this->store_id); // 验证参数 if (!$lng || !$lat) { $this->ajaxReturn(['code' => 400, 'msg' => '经纬度不能为空']); } // 获取该门店所有启用的围栏 $fences = M('ls_store_delivery_fence')->where([ 'store_id' => $store_id, 'is_active' => 1, 'is_deleted' => 0 ])->select(); $inFence = false; $fenceInfo = null; foreach ($fences as $fence) { $fence_data = json_decode($fence['fence_data'], true); if ($fence['fence_type'] == 1) { // 多边形 if ($this->pointInPolygon($lng, $lat, $fence_data['coordinates'][0])) { $inFence = true; $fenceInfo = $fence; break; } } else if ($fence['fence_type'] == 2) { // 圆形 if ($this->pointInCircle($lng, $lat, $fence_data['center'], $fence_data['radius'])) { $inFence = true; $fenceInfo = $fence; break; } } } $this->ajaxReturn([ 'code' => 200, 'msg' => '检查完成', 'data' => [ 'in_fence' => $inFence, 'fence_info' => $fenceInfo ] ]); } catch (Exception $e) { $this->ajaxReturn(['code' => 500, 'msg' => '系统错误:' . $e->getMessage()]); } } /** * 判断点是否在多边形内(射线法) */ private function pointInPolygon($lng, $lat, $polygon) { $count = count($polygon); $inside = false; for ($i = 0, $j = $count - 1; $i < $count; $j = $i++) { $xi = $polygon[$i][0]; $yi = $polygon[$i][1]; $xj = $polygon[$j][0]; $yj = $polygon[$j][1]; if ((($yi > $lat) != ($yj > $lat)) && ($lng < ($xj - $xi) * ($lat - $yi) / ($yj - $yi) + $xi)) { $inside = !$inside; } } return $inside; } /** * 判断点是否在圆形内 */ private function pointInCircle($lng, $lat, $center, $radius) { $distance = $this->calculateDistance($lat, $lng, $center[1], $center[0]); return $distance <= $radius; } /** * 计算两点间距离(米) */ private function calculateDistance($lat1, $lng1, $lat2, $lng2) { $R = 6371000; // 地球半径(米) $dLat = deg2rad($lat2 - $lat1); $dLng = deg2rad($lng2 - $lng1); $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLng/2) * sin($dLng/2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); return $R * $c; } }