routeId(); if ($id <= 0) { $id = (int)$this->input('id', 0) ?: (int)$this->input('userId', 0); } if ($id <= 0) { $this->fail('缺少商家参数', 400); } // 优先按 merchant.id 查,若未命中再按 user_id 查 $m = Db::name('fc_merchant')->where('id', $id)->find(); if (!$m) { $m = Db::name('fc_merchant')->where('user_id', $id)->find(); } if (!$m) { $this->fail('商家门店不存在', 404); } // 关联发布者基础信息 $user = Db::name('user')->where('id', $m['user_id'])->find(); $userNickname = $user ? (string)$user['nickname'] : ''; $userAvatar = $user ? (string)$user['avatar'] : ''; // 统计真实有效发布数量 $postCount = (int)Db::name('fc_post') ->where('user_id', $m['user_id']) ->where('status', 1) ->where('audit_status', 1) ->whereNull('deletetime') ->count(); // 计算用户与门店之间的物理距离(km) $clientLat = $this->coord('lat', 90); $clientLng = $this->coord('lng', 180); $distance = null; if ($clientLat !== null && $clientLng !== null && !empty($m['lat']) && !empty($m['lng'])) { $distance = $this->calcDistance($clientLat, $clientLng, (float)$m['lat'], (float)$m['lng']); } // 首屏拉取前 6 条该商家的有效发帖 $posts = $this->fetchMerchantPosts($m['user_id'], 1, 6); // 严格保护商家联系电话:未付费解锁或非会员状态下脱敏,杜绝从信息详情页跳转商家主页白嫖绕过 $rawContact = (string)(isset($m['contact']) ? $m['contact'] : ''); $unlocked = false; $me = $this->user(); if ($me) { $now = time(); $ext = $this->ext($me['id']); $isMember = (int)$ext['is_member'] === 1 && !empty($ext['member_expiretime']) && (int)$ext['member_expiretime'] > $now; $isOwner = (int)$m['user_id'] === (int)$me['id']; if ($isOwner || $isMember) { $unlocked = true; } else { // 检查是否从已解锁的关联信息跳转而来 $postId = (int)$this->input('postId', 0); if ($postId > 0) { $paidView = Db::name('fc_pay_view') ->where('user_id', $me['id']) ->where('post_id', $postId) ->find(); if ($paidView) { $unlocked = true; } } } } $displayContact = $unlocked ? $rawContact : $this->maskPhone($rawContact); $data = [ 'id' => (int)$m['id'], 'userId' => (int)$m['user_id'], 'name' => (string)$m['name'], 'logo' => (string)(isset($m['logo']) ? $m['logo'] : ''), 'banner' => (string)(isset($m['banner']) ? $m['banner'] : ''), 'address' => (string)(isset($m['address']) ? $m['address'] : ''), 'lat' => (isset($m['lat']) && $m['lat'] !== null && $m['lat'] !== '') ? (float)$m['lat'] : null, 'lng' => (isset($m['lng']) && $m['lng'] !== null && $m['lng'] !== '') ? (float)$m['lng'] : null, 'contact' => $displayContact, 'unlocked' => $unlocked, 'category' => (string)(isset($m['category']) ? $m['category'] : ''), 'notice' => (string)(isset($m['notice']) ? $m['notice'] : ''), 'auditStatus' => (int)$m['audit_status'], 'verified' => (int)$m['audit_status'] === 1, 'licenseVerified' => !empty($m['license']) && (int)$m['audit_status'] === 1, 'postCount' => $postCount, 'distance' => $distance, 'userNickname' => $userNickname, 'userAvatar' => $userAvatar, 'createdAt' => isset($m['createtime']) ? $this->iso($m['createtime']) : '', 'posts' => $posts['list'], 'hasMorePosts' => $posts['hasMore'], ]; $this->ok($data); } /** * M2 获取商家名下的信息列表(支持分页) * GET /api/v1/merchant/:id/posts * * @return void */ public function posts() { $id = (int)$this->routeId(); if ($id <= 0) { $id = (int)$this->input('id', 0) ?: (int)$this->input('userId', 0); } if ($id <= 0) { $this->fail('缺少商家参数', 400); } $userId = $id; $m = Db::name('fc_merchant')->where('id', $id)->find(); if ($m) { $userId = (int)$m['user_id']; } list($page, $size) = $this->pager(10, 30); $res = $this->fetchMerchantPosts($userId, $page, $size); $this->ok($res); } /** * 查询指定商家的发帖列表统一组装 * * @param int $userId 发布者用户ID * @param int $page 页码 * @param int $size 每页数量 * @return array */ protected function fetchMerchantPosts($userId, $page, $size) { $q = Db::name('fc_post') ->where('user_id', $userId) ->where('status', 1) ->where('audit_status', 1) ->whereNull('deletetime'); $total = (int)$q->count(); $rows = Db::name('fc_post') ->where('user_id', $userId) ->where('status', 1) ->where('audit_status', 1) ->whereNull('deletetime') ->order('is_top desc, id desc') ->page($page, $size) ->select(); $list = []; foreach ($rows as $r) { $catName = ''; if (!empty($r['category_id'])) { $cat = Db::name('fc_category')->where('id', $r['category_id'])->value('name'); $catName = $cat ? (string)$cat : ''; } $cover = (string)$r['cover']; $mediaArr = $this->jsonArr($r['media']); if ($cover === '' && !empty($mediaArr)) { $cover = $mediaArr[0]; } $tags = []; if (!empty($r['tags'])) { foreach (explode(',', (string)$r['tags']) as $t) { $t = trim($t); if ($t !== '') { $tags[] = $t; } } } $list[] = [ 'id' => (int)$r['id'], 'title' => (string)$r['title'], 'content' => (string)$r['content'], 'price' => (float)$r['price'], 'priceUnit' => (string)$r['price_unit'], 'cover' => $cover, 'media' => $mediaArr, 'area' => (string)$r['area'], 'address' => (string)$r['address'], 'categoryId' => (int)$r['category_id'], 'categoryName' => $catName, 'isTop' => (int)$r['is_top'] === 1, 'views' => (int)$r['views'], 'commentCount' => (int)$r['comment_count'], 'createdAt' => $this->iso($r['createtime']), 'tags' => $tags, ]; } return [ 'list' => $list, 'total' => $total, 'page' => $page, 'size' => $size, 'hasMore' => ($page * $size) < $total, ]; } /** * 计算两点大地距离(单位 km,保留 1 位小数) * * @param float $lat1 纬度1 * @param float $lng1 经度1 * @param float $lat2 纬度2 * @param float $lng2 经度2 * @return float */ protected function calcDistance($lat1, $lng1, $lat2, $lng2) { $earthRadius = 6378.137; $radLat1 = deg2rad($lat1); $radLat2 = deg2rad($lat2); $a = $radLat1 - $radLat2; $b = deg2rad($lng1) - deg2rad($lng2); $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))); $s = $s * $earthRadius; return round($s, 1); } }