文件
fenleixinxi/application/api/controller/Merchant.php

219 行
7.6 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace app\api\controller;
use think\Db;
/**
* 用户端 · 商家门店与主页(Module-MERCHANT)
* 路由:
* GET /api/v1/merchant/:id M1 商家公开主页/门店详情
* GET /api/v1/merchant/:id/posts M2 商家名下发布的信息流(分页)
*/
class Merchant extends V1
{
/**
* M1 获取商家门店详情及公开档案
* GET /api/v1/merchant/:id
* 规则:允许游客;支持通过 merchant.id 或 user_id 查询;若提供客户端坐标则计算到店距离
*
* @return void
*/
public function detail()
{
$id = (int)$this->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);
$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' => (string)(isset($m['contact']) ? $m['contact'] : ''),
'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);
}
}