1020 lines
33 KiB
PHP
1020 lines
33 KiB
PHP
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | YwxApp [ WE CAN DO IT JUST THINK ]
|
|
// +----------------------------------------------------------------------
|
|
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
|
|
// +----------------------------------------------------------------------
|
|
// | Author: ywxapp<admin@ywxapp.cn>
|
|
// +----------------------------------------------------------------------
|
|
declare (strict_types = 1);
|
|
|
|
namespace addon\wxchat\controller\api;
|
|
|
|
use addon\wxchat\model\WxchatMoment as MomentModel;
|
|
use think\facade\Log;
|
|
use think\Request;
|
|
use ywxapp\controller\FrontendBase;
|
|
|
|
header('Access-Control-Allow-Origin: *'); // 允许所有域
|
|
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
|
|
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
|
|
header('Access-Control-Allow-Credentials: true');
|
|
|
|
/**
|
|
* Moment 类
|
|
*
|
|
* @author ywxapp <admin@ywxapp.cn>
|
|
*/
|
|
class Moment extends FrontendBase
|
|
{
|
|
private $uid = 0;
|
|
|
|
/**
|
|
* Summary of noNeedLogin
|
|
* @var array
|
|
*/
|
|
protected $noNeedLogin = [];
|
|
|
|
/**
|
|
* Summary of noNeedVerify
|
|
* @var array
|
|
*/
|
|
protected $noNeedVerify = ['*'];
|
|
|
|
/**
|
|
* 控制器初始化 initialize
|
|
* @return void
|
|
*/
|
|
protected function initialize()
|
|
{
|
|
if ($this->auth->isLogin) {
|
|
$this->uid = $this->auth->model->uid;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取动态详情
|
|
* @param int $id
|
|
* @return Json
|
|
*/
|
|
public function red(int $id)
|
|
{
|
|
try {
|
|
// 查询动态详情
|
|
$info = MomentModel::with([
|
|
'member' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname,avatar,introduction,follower_count,following_count,dynamic_count');
|
|
},
|
|
'media' =>
|
|
function ($query) {
|
|
$query->field('id,mid,type,url,thumbnail_url,width,height,duration,sort_order')->order('sort_order', 'asc');
|
|
},
|
|
'hashtags' =>
|
|
function ($query) {
|
|
$query->field('hashtags.id,hashtags.name,hashtags.description');
|
|
},
|
|
])->where('id', $id)
|
|
->where('status', 1)
|
|
->find();
|
|
|
|
if (! $info) {
|
|
$this->error();
|
|
}
|
|
// 增加浏览量
|
|
$this->increaseViewCount($id, $this->uid);
|
|
// 获取当前用户与动态的交互状态
|
|
$interaction = $this->getUserInteraction($id, $this->uid);
|
|
// 获取评论列表(分页)
|
|
$page = Request::param('page', 1);
|
|
$limit = Request::param('limit', 20);
|
|
$comments = $this->getComments($id, $page, $limit, $this->uid);
|
|
// 构建响应数据
|
|
$response = [
|
|
'moment' => $this->formatDynamic($info, $interaction),
|
|
'comments' => $comments['list'],
|
|
'comment_total' => $comments['total'],
|
|
'comment_pages' => $comments['pages'],
|
|
];
|
|
$this->success($response, 'success');
|
|
|
|
} catch (\Exception $e) {
|
|
$this->error('服务器错误:' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 动态广场列表(推荐/关注/附近/热门)
|
|
*/
|
|
public function index()
|
|
{
|
|
$uid = $this->auth->model->uid;
|
|
$scope = Request::param('scope', 'recommend');
|
|
$page = max(1, (int) Request::param('page', 1));
|
|
$pageSize = max(1, min(50, (int) Request::param('page_size', 10)));
|
|
|
|
$query = MomentModel::with([
|
|
'member' =>
|
|
function ($q) {
|
|
$q->field('id,username,nickname,avatar,introduction');
|
|
},
|
|
'media' =>
|
|
function ($q) {
|
|
$q->field('id,mid,type,url,thumbnail_url,sort_order')->order('sort_order', 'asc');
|
|
},
|
|
'hashtags' =>
|
|
function ($q) {
|
|
$q->field('hashtags.id,hashtags.name');
|
|
},
|
|
])->where('status', 1);
|
|
|
|
if ($scope == 'follow') {
|
|
$ids = UserFollowModel::where('follower_id', $uid)->column('following_id');
|
|
if (empty($ids)) {
|
|
$this->success(['list' => [], 'total' => 0, 'page' => $page]);
|
|
return;
|
|
}
|
|
$query->where('uid', 'in', $ids)->order('create_at', 'desc');
|
|
} elseif ($scope == 'hot') {
|
|
$query->order('like_count', 'desc')->order('comment_count', 'desc');
|
|
} else {
|
|
if ($scope == 'nearby') {
|
|
$query->where('latitude', '>', 0)->where('longitude', '>', 0);
|
|
}
|
|
$query->order('create_at', 'desc');
|
|
}
|
|
|
|
$total = $query->count();
|
|
$list = $query->page($page, $pageSize)->select();
|
|
|
|
$result = [];
|
|
foreach ($list as $info) {
|
|
$result[] = $this->formatDynamic($info, $this->getUserInteraction($info->id, $uid));
|
|
}
|
|
|
|
$this->success(['list' => $result, 'total' => $total, 'page' => $page]);
|
|
}
|
|
|
|
/**
|
|
* 我的动态列表(获赞页复用)
|
|
*/
|
|
public function mine()
|
|
{
|
|
$uid = $this->uid;
|
|
$page = max(1, (int) Request::param('page', 1));
|
|
$pageSize = max(1, min(50, (int) Request::param('page_size', 10)));
|
|
|
|
$query = MomentModel::with([
|
|
'member' =>
|
|
function ($q) {
|
|
$q->field('id,username,nickname,avatar,introduction');
|
|
},
|
|
'media' =>
|
|
function ($q) {
|
|
$q->field('id,mid,type,url,thumbnail_url,sort_order')->order('sort_order', 'asc');
|
|
},
|
|
'hashtags' =>
|
|
function ($q) {
|
|
$q->field('hashtags.id,hashtags.name');
|
|
},
|
|
])->where('uid', $uid)->where('status', 1)->order('create_at', 'desc');
|
|
|
|
$total = $query->count();
|
|
$list = $query->page($page, $pageSize)->select();
|
|
|
|
$result = [];
|
|
foreach ($list as $info) {
|
|
$result[] = $this->formatDynamic($info, $this->getUserInteraction($info->id, $uid));
|
|
}
|
|
$this->success(['list' => $result, 'total' => $total, 'page' => $page]);
|
|
}
|
|
|
|
/**
|
|
* 我的收藏列表
|
|
*/
|
|
public function collectedList()
|
|
{
|
|
$uid = $this->uid;
|
|
$page = max(1, (int) Request::param('page', 1));
|
|
$pageSize = max(1, min(50, (int) Request::param('page_size', 10)));
|
|
|
|
$mids = Db::name('wxchat_moment_collects')
|
|
->where('uid', $uid)
|
|
->order('create_at', 'desc')
|
|
->column('mid');
|
|
if (empty($mids)) {
|
|
$this->success(['list' => [], 'total' => 0, 'page' => $page]);
|
|
return;
|
|
}
|
|
$total = count($mids);
|
|
$slice = array_slice($mids, ($page - 1) * $pageSize, $pageSize);
|
|
|
|
$list = MomentModel::with([
|
|
'member' =>
|
|
function ($q) {
|
|
$q->field('id,username,nickname,avatar,introduction');
|
|
},
|
|
'media' =>
|
|
function ($q) {
|
|
$q->field('id,mid,type,url,thumbnail_url,sort_order')->order('sort_order', 'asc');
|
|
},
|
|
'hashtags' =>
|
|
function ($q) {
|
|
$q->field('hashtags.id,hashtags.name');
|
|
},
|
|
])->where('id', 'in', $slice)->where('status', 1)->select();
|
|
|
|
$map = [];
|
|
foreach ($list as $info) {
|
|
$map[$info->id] = $info;
|
|
}
|
|
$result = [];
|
|
foreach ($slice as $mid) {
|
|
if (isset($map[$mid])) {
|
|
$result[] = $this->formatDynamic($map[$mid], $this->getUserInteraction($mid, $uid));
|
|
}
|
|
}
|
|
$this->success(['list' => $result, 'total' => $total, 'page' => $page]);
|
|
}
|
|
|
|
/**
|
|
* 我的浏览记录
|
|
*/
|
|
public function historyList()
|
|
{
|
|
$uid = $this->uid;
|
|
$page = max(1, (int) Request::param('page', 1));
|
|
$pageSize = max(1, min(50, (int) Request::param('page_size', 10)));
|
|
|
|
$mids = Db::name('wxchat_view_history')
|
|
->where('uid', $uid)
|
|
->order('create_at', 'desc')
|
|
->column('mid');
|
|
if (empty($mids)) {
|
|
$this->success(['list' => [], 'total' => 0, 'page' => $page]);
|
|
return;
|
|
}
|
|
$mids = array_values(array_unique($mids));
|
|
$total = count($mids);
|
|
$slice = array_slice($mids, ($page - 1) * $pageSize, $pageSize);
|
|
|
|
$list = MomentModel::with([
|
|
'member' =>
|
|
function ($q) {
|
|
$q->field('id,username,nickname,avatar,introduction');
|
|
},
|
|
'media' =>
|
|
function ($q) {
|
|
$q->field('id,mid,type,url,thumbnail_url,sort_order')->order('sort_order', 'asc');
|
|
},
|
|
'hashtags' =>
|
|
function ($q) {
|
|
$q->field('hashtags.id,hashtags.name');
|
|
},
|
|
])->where('id', 'in', $slice)->where('status', 1)->select();
|
|
|
|
$map = [];
|
|
foreach ($list as $info) {
|
|
$map[$info->id] = $info;
|
|
}
|
|
$result = [];
|
|
foreach ($slice as $mid) {
|
|
if (isset($map[$mid])) {
|
|
$result[] = $this->formatDynamic($map[$mid], $this->getUserInteraction($mid, $uid));
|
|
}
|
|
}
|
|
$this->success(['list' => $result, 'total' => $total, 'page' => $page]);
|
|
}
|
|
|
|
/**
|
|
* 发布动态
|
|
* @return Json
|
|
*/
|
|
public function create()
|
|
{
|
|
try {
|
|
$data = Request::post();
|
|
$validate = Validate::rule([
|
|
'content' => 'max:2000',
|
|
'type' => 'require|in:1,2,3',
|
|
'is_public' => 'in:0,1',
|
|
'media' => 'array',
|
|
'hashtags' => 'array',
|
|
]);
|
|
if (! $validate->check($data)) {
|
|
$this->error($validate->getError());
|
|
}
|
|
// 内容与媒体至少存在其一
|
|
if (empty($data['content']) && empty($data['media'])) {
|
|
$this->error('请填写内容或添加图片');
|
|
}
|
|
Db::startTrans();
|
|
try {
|
|
// 创建动态
|
|
$info = new MomentModel();
|
|
$info->uid = $this->uid;
|
|
$info->content = $data['content'] ?? '';
|
|
$info->type = $data['type'];
|
|
$info->location = $data['location'] ?? null;
|
|
$info->latitude = $data['latitude'] ?? null;
|
|
$info->longitude = $data['longitude'] ?? null;
|
|
$info->is_public = $data['is_public'] ?? 1;
|
|
$info->save();
|
|
|
|
$infoId = $info->id;
|
|
|
|
// 保存媒体文件
|
|
if (! empty($data['media'])) {
|
|
$mediaData = [];
|
|
foreach ($data['media'] as $index => $media) {
|
|
$mediaData[] = [
|
|
'dynamic_id' => $infoId,
|
|
'type' => $media['type'],
|
|
'url' => $media['url'],
|
|
'thumbnail_url' => $media['thumbnail_url'] ?? null,
|
|
'width' => $media['width'] ?? null,
|
|
'height' => $media['height'] ?? null,
|
|
'duration' => $media['duration'] ?? null,
|
|
'sort_order' => $index,
|
|
];
|
|
}
|
|
DynamicMediaModel::insertAll($mediaData);
|
|
}
|
|
|
|
// 处理话题标签
|
|
if (! empty($data['hashtags'])) {
|
|
$hashtagData = [];
|
|
foreach ($data['hashtags'] as $hashtagName) {
|
|
// 查找或创建标签
|
|
$hashtag = HashtagModel::where('name', $hashtagName)->find();
|
|
if (! $hashtag) {
|
|
$hashtag = new HashtagModel();
|
|
$hashtag->name = $hashtagName;
|
|
$hashtag->save();
|
|
}
|
|
|
|
// 关联动态和标签
|
|
$hashtagData[] = [
|
|
'dynamic_id' => $infoId,
|
|
'hashtag_id' => $hashtag->id,
|
|
];
|
|
|
|
// 更新标签计数
|
|
$hashtag->dynamic_count = Db::raw('dynamic_count + 1');
|
|
$hashtag->save();
|
|
}
|
|
|
|
if (! empty($hashtagData)) {
|
|
Db::name('dynamic_hashtags')->insertAll($hashtagData);
|
|
}
|
|
}
|
|
|
|
// 更新用户动态计数
|
|
UserModel::where('id', $this->uid)->inc('dynamic_count')->update();
|
|
|
|
Db::commit();
|
|
|
|
return json([
|
|
'code' => 200,
|
|
'message' => '动态发布成功',
|
|
'data' => [
|
|
'id' => $infoId,
|
|
],
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw $e;
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
return json([
|
|
'code' => 500,
|
|
'message' => '发布失败:' . $e->getMessage(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发布评论
|
|
* @return Json
|
|
*/
|
|
public function comment(): Json
|
|
{
|
|
try {
|
|
$data = Request::post();
|
|
|
|
// 验证数据
|
|
$validate = Validate::rule([
|
|
'dynamic_id' => 'require|integer|gt:0',
|
|
'content' => 'require|max:1000',
|
|
'parent_id' => 'integer|gt:0',
|
|
'reply_to_user_id' => 'integer|gt:0',
|
|
]);
|
|
|
|
if (! $validate->check($data)) {
|
|
return json([
|
|
'code' => 400,
|
|
'message' => $validate->getError(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查动态是否存在
|
|
$info = MomentModel::where('id', $data['dynamic_id'])
|
|
->where('status', 1)
|
|
->find();
|
|
|
|
if (! $info) {
|
|
return json([
|
|
'code' => 404,
|
|
'message' => '动态不存在',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 开始事务
|
|
Db::startTrans();
|
|
|
|
try {
|
|
// 创建评论
|
|
$comment = new CommentModel();
|
|
$comment->dynamic_id = $data['dynamic_id'];
|
|
$comment->user_id = $this->uid;
|
|
$comment->parent_id = $data['parent_id'] ?? 0;
|
|
$comment->reply_to_user_id = $data['reply_to_user_id'] ?? null;
|
|
$comment->content = $data['content'];
|
|
$comment->save();
|
|
|
|
$commentId = $comment->id;
|
|
|
|
// 更新动态评论数
|
|
$info->comment_count = Db::raw('comment_count + 1');
|
|
$info->save();
|
|
|
|
// 如果是回复评论,更新父评论的回复数
|
|
if (! empty($data['parent_id'])) {
|
|
CommentModel::where('id', $data['parent_id'])
|
|
->inc('reply_count')
|
|
->update();
|
|
}
|
|
|
|
Db::commit();
|
|
|
|
// 获取完整的评论信息
|
|
$comment = CommentModel::with(['member' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname,avatar');
|
|
}])->where('id', $commentId)->find();
|
|
|
|
return json([
|
|
'code' => 200,
|
|
'message' => '评论成功',
|
|
'data' => $this->formatComment($comment),
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw $e;
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
return json([
|
|
'code' => 500,
|
|
'message' => '评论失败:' . $e->getMessage(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 点赞动态
|
|
* @return Json
|
|
*/
|
|
public function like(): Json
|
|
{
|
|
try {
|
|
$infoId = Request::post('dynamic_id', 0);
|
|
|
|
if (! $infoId) {
|
|
return json([
|
|
'code' => 400,
|
|
'message' => '动态ID不能为空',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查动态是否存在
|
|
$info = MomentModel::where('id', $infoId)
|
|
->where('status', 1)
|
|
->find();
|
|
|
|
if (! $info) {
|
|
return json([
|
|
'code' => 404,
|
|
'message' => '动态不存在',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查是否已点赞
|
|
$like = DynamicLikeModel::where('dynamic_id', $infoId)
|
|
->where('user_id', $this->uid)
|
|
->find();
|
|
|
|
if ($like) {
|
|
// 取消点赞
|
|
$like->delete();
|
|
$info->like_count = Db::raw('like_count - 1');
|
|
$info->save();
|
|
|
|
$liked = false;
|
|
$message = '取消点赞成功';
|
|
} else {
|
|
// 点赞
|
|
$like = new DynamicLikeModel();
|
|
$like->dynamic_id = $infoId;
|
|
$like->user_id = $this->uid;
|
|
$like->save();
|
|
|
|
$info->like_count = Db::raw('like_count + 1');
|
|
$info->save();
|
|
|
|
$liked = true;
|
|
$message = '点赞成功';
|
|
}
|
|
|
|
return json([
|
|
'code' => 200,
|
|
'message' => $message,
|
|
'data' => [
|
|
'liked' => $liked,
|
|
'like_count' => $info->like_count,
|
|
],
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return json([
|
|
'code' => 500,
|
|
'message' => '操作失败:' . $e->getMessage(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 收藏动态
|
|
* @return Json
|
|
*/
|
|
public function collect(): Json
|
|
{
|
|
try {
|
|
$infoId = Request::post('dynamic_id', 0);
|
|
$folderId = Request::post('folder_id', 0);
|
|
|
|
if (! $infoId) {
|
|
return json([
|
|
'code' => 400,
|
|
'message' => '动态ID不能为空',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查动态是否存在
|
|
$info = MomentModel::where('id', $infoId)
|
|
->where('status', 1)
|
|
->find();
|
|
|
|
if (! $info) {
|
|
return json([
|
|
'code' => 404,
|
|
'message' => '动态不存在',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查是否已收藏
|
|
$collect = DynamicCollectModel::where('dynamic_id', $infoId)
|
|
->where('user_id', $this->uid)
|
|
->find();
|
|
|
|
if ($collect) {
|
|
// 取消收藏
|
|
$collect->delete();
|
|
$info->collect_count = Db::raw('collect_count - 1');
|
|
$info->save();
|
|
|
|
$collected = false;
|
|
$message = '取消收藏成功';
|
|
} else {
|
|
// 收藏
|
|
$collect = new DynamicCollectModel();
|
|
$collect->dynamic_id = $infoId;
|
|
$collect->user_id = $this->uid;
|
|
$collect->folder_id = $folderId;
|
|
$collect->save();
|
|
|
|
$info->collect_count = Db::raw('collect_count + 1');
|
|
$info->save();
|
|
|
|
$collected = true;
|
|
$message = '收藏成功';
|
|
}
|
|
|
|
return json([
|
|
'code' => 200,
|
|
'message' => $message,
|
|
'data' => [
|
|
'collected' => $collected,
|
|
'collect_count' => $info->collect_count,
|
|
],
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return json([
|
|
'code' => 500,
|
|
'message' => '操作失败:' . $e->getMessage(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 关注用户
|
|
* @return Json
|
|
*/
|
|
public function follow(): Json
|
|
{
|
|
try {
|
|
$followingId = Request::post('following_id', 0);
|
|
|
|
if (! $followingId) {
|
|
return json([
|
|
'code' => 400,
|
|
'message' => '用户ID不能为空',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
if ($this->uid == $followingId) {
|
|
return json([
|
|
'code' => 400,
|
|
'message' => '不能关注自己',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查用户是否存在
|
|
$user = UserModel::where('id', $followingId)
|
|
->where('status', 1)
|
|
->find();
|
|
|
|
if (! $user) {
|
|
return json([
|
|
'code' => 404,
|
|
'message' => '用户不存在',
|
|
'data' => null,
|
|
]);
|
|
}
|
|
|
|
// 检查是否已关注
|
|
$follow = UserFollowModel::where('follower_id', $this->uid)
|
|
->where('following_id', $followingId)
|
|
->find();
|
|
|
|
if ($follow) {
|
|
// 取消关注
|
|
$follow->delete();
|
|
|
|
// 更新用户关注数
|
|
UserModel::where('id', $this->uid)
|
|
->dec('following_count')
|
|
->update();
|
|
|
|
UserModel::where('id', $followingId)
|
|
->dec('follower_count')
|
|
->update();
|
|
|
|
$followed = false;
|
|
$message = '取消关注成功';
|
|
} else {
|
|
// 关注
|
|
$follow = new UserFollowModel();
|
|
$follow->follower_id = $this->uid;
|
|
$follow->following_id = $followingId;
|
|
$follow->save();
|
|
|
|
// 更新用户关注数
|
|
UserModel::where('id', $this->uid)
|
|
->inc('following_count')
|
|
->update();
|
|
|
|
UserModel::where('id', $followingId)
|
|
->inc('follower_count')
|
|
->update();
|
|
|
|
$followed = true;
|
|
$message = '关注成功';
|
|
}
|
|
|
|
return json([
|
|
'code' => 200,
|
|
'message' => $message,
|
|
'data' => [
|
|
'followed' => $followed,
|
|
],
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return json([
|
|
'code' => 500,
|
|
'message' => '操作失败:' . $e->getMessage(),
|
|
'data' => null,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取评论列表
|
|
* @param int $infoId
|
|
* @param int $page
|
|
* @param int $limit
|
|
* @param int $this->uid
|
|
* @return array
|
|
*/
|
|
private function getComments(int $infoId, int $page, int $limit, int $uid = 0)
|
|
{
|
|
// 查询顶级评论
|
|
$query = CommentModel::with([
|
|
'member' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname,avatar');
|
|
},
|
|
'replyToUser' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname');
|
|
},
|
|
])->where('dynamic_id', $infoId)
|
|
->where('parent_id', 0)
|
|
->where('status', 1)
|
|
->order('is_top', 'desc')
|
|
->order('create_at', 'desc');
|
|
|
|
$total = $query->count();
|
|
$pages = ceil($total / $limit);
|
|
|
|
$comments = $query->page($page, $limit)->select();
|
|
|
|
$formattedComments = [];
|
|
foreach ($comments as $comment) {
|
|
$formattedComment = $this->formatComment($comment);
|
|
|
|
// 获取评论的回复
|
|
$replies = CommentModel::with([
|
|
'member' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname,avatar');
|
|
},
|
|
'replyToUser' =>
|
|
function ($query) {
|
|
$query->field('id,username,nickname');
|
|
},
|
|
])->where('parent_id', $comment->id)
|
|
->where('status', 1)
|
|
->order('create_at', 'asc')
|
|
->limit(5) // 只获取前5条回复
|
|
->select();
|
|
|
|
$formattedComment['replies'] = [];
|
|
foreach ($replies as $reply) {
|
|
$formattedComment['replies'][] = $this->formatComment($reply);
|
|
}
|
|
|
|
$formattedComments[] = $formattedComment;
|
|
}
|
|
|
|
return [
|
|
'list' => $formattedComments,
|
|
'total' => $total,
|
|
'pages' => $pages,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 增加浏览量
|
|
* @param int $infoId
|
|
* @param int $userId
|
|
*/
|
|
private function increaseViewCount(int $infoId, int $userId = 0): void
|
|
{
|
|
try {
|
|
// 更新动态浏览量
|
|
MomentModel::where('id', $infoId)
|
|
->inc('view_count')
|
|
->update();
|
|
|
|
// 记录浏览历史
|
|
$viewHistory = new ViewHistoryModel();
|
|
$viewHistory->dynamic_id = $infoId;
|
|
$viewHistory->user_id = $userId ?: null;
|
|
$viewHistory->ip_address = Request::ip();
|
|
$viewHistory->user_agent = Request::header('user-agent');
|
|
$viewHistory->save();
|
|
|
|
} catch (\Exception $e) {
|
|
// 浏览记录失败不影响主流程
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取用户与动态的交互状态
|
|
* @param int $infoId
|
|
* @param int $userId
|
|
* @return array
|
|
*/
|
|
private function getUserInteraction(int $infoId, int $userId): array
|
|
{
|
|
if (! $userId) {
|
|
return [
|
|
'liked' => false,
|
|
'collected' => false,
|
|
'followed' => false,
|
|
];
|
|
}
|
|
|
|
$liked = DynamicLikeModel::where('dynamic_id', $infoId)
|
|
->where('user_id', $userId)
|
|
->find() ? true : false;
|
|
|
|
$collected = DynamicCollectModel::where('dynamic_id', $infoId)
|
|
->where('user_id', $userId)
|
|
->find() ? true : false;
|
|
|
|
// 获取动态作者ID
|
|
$info = MomentModel::where('id', $infoId)->find();
|
|
$followed = false;
|
|
|
|
if ($info && $info->user_id != $userId) {
|
|
$followed = UserFollowModel::where('follower_id', $userId)
|
|
->where('following_id', $info->user_id)
|
|
->find() ? true : false;
|
|
}
|
|
|
|
return [
|
|
'liked' => $liked,
|
|
'collected' => $collected,
|
|
'followed' => $followed,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 格式化动态数据
|
|
* @param MomentModel $info
|
|
* @param array $interaction
|
|
* @return array
|
|
*/
|
|
private function formatDynamic(MomentModel $info, array $interaction): array
|
|
{
|
|
$user = $info->user;
|
|
|
|
$media = [];
|
|
$images = [];
|
|
$videoUrl = '';
|
|
foreach ($info->media as $m) {
|
|
$mType = ($m->type == 2 || $m->type == 'video') ? 'video' : 'image';
|
|
$mItem = [
|
|
'type' => $mType,
|
|
'url' => $m->url,
|
|
'thumbnail' => $m->thumbnail_url,
|
|
];
|
|
$media[] = $mItem;
|
|
if ($mType == 'image') {
|
|
$images[] = $m->url;
|
|
} elseif ($videoUrl === '') {
|
|
$videoUrl = $m->url;
|
|
}
|
|
}
|
|
|
|
$type = 'text';
|
|
if ($videoUrl !== '') {
|
|
$type = 'video';
|
|
} elseif (count($images) > 0) {
|
|
$type = 'image';
|
|
}
|
|
|
|
$hashtags = [];
|
|
foreach ($info->hashtags as $h) {
|
|
$hashtags[] = ['id' => $h->id, 'name' => $h->name];
|
|
}
|
|
|
|
$isLiked = ! empty($interaction['liked']);
|
|
$isCollect = ! empty($interaction['collected']);
|
|
$isFollow = ! empty($interaction['followed']);
|
|
|
|
return [
|
|
'id' => $info->id,
|
|
'uid' => $info->uid,
|
|
'userId' => $user ? $user->id : 0,
|
|
'userName' => $user ? $user->nickname : '',
|
|
'userAvatar' => $user ? $user->avatar : '',
|
|
'userVip' => false,
|
|
'content' => $info->content,
|
|
'images' => $images,
|
|
'videoUrl' => $videoUrl,
|
|
'type' => $type,
|
|
'location' => $info->location ?: '',
|
|
'time' => (int) $info->create_at * 1000,
|
|
'likes' => (int) $info->like_count,
|
|
'comments' => (int) $info->comment_count,
|
|
'shares' => (int) $info->share_count,
|
|
'isLiked' => $isLiked,
|
|
'isPinned' => false,
|
|
'tags' => array_map(function ($h) { return $h['name']; }, $hashtags),
|
|
'hot' => (int) $info->like_count >= 50,
|
|
'distance' => 0,
|
|
// 详情页扩展字段
|
|
'media' => $media,
|
|
'hashtags' => $hashtags,
|
|
'stats' => [
|
|
'like_count' => (int) $info->like_count,
|
|
'comment_count' => (int) $info->comment_count,
|
|
'share_count' => (int) $info->share_count,
|
|
'collect_count' => (int) $info->collect_count,
|
|
'view_count' => (int) $info->view_count,
|
|
],
|
|
'interaction' => [
|
|
'liked' => $isLiked,
|
|
'collected' => $isCollect,
|
|
'followed' => $isFollow,
|
|
],
|
|
'view' => (int) $info->view_count,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 格式化评论数据
|
|
* @param CommentModel $comment
|
|
* @return array
|
|
*/
|
|
private function formatComment(CommentModel $comment): array
|
|
{
|
|
$replyTo = null;
|
|
if ($comment->reply_to_user_id && $comment->replyToUser) {
|
|
$replyTo = [
|
|
'id' => $comment->replyToUser->id,
|
|
'username' => $comment->replyToUser->username,
|
|
'nickname' => $comment->replyToUser->nickname,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'id' => $comment->id,
|
|
'member' => [
|
|
'id' => $comment->user->id,
|
|
'username' => $comment->user->username,
|
|
'nickname' => $comment->user->nickname,
|
|
'avatar' => $comment->user->avatar,
|
|
],
|
|
'reply_to' => $replyTo,
|
|
'content' => $comment->content,
|
|
'like_count' => $comment->like_count,
|
|
'reply_count' => $comment->reply_count,
|
|
'is_top' => $comment->is_top,
|
|
'create_time' => (int) $comment->create_at,
|
|
'create_time_formatted' => date('Y-m-d H:i:s', (int) $comment->create_at),
|
|
];
|
|
}
|
|
|
|
|
|
public function upload()
|
|
{
|
|
$request = $this->request;
|
|
|
|
// 记录请求的详细信息
|
|
Log::record('请求方法: ' . $request->method());
|
|
Log::record('请求URL: ' . $request->url());
|
|
Log::record('请求参数: ' . json_encode($request->param()));
|
|
Log::record('请求头信息: ' . json_encode($request->header()));
|
|
Log::record('请求头信息: ' . json_encode($request->file()));
|
|
Log::record('请求体信息: ' . json_encode($request->post())); // 对于POST请求
|
|
Log::record('请求IP: ' . $request->ip());
|
|
Log::record('请求时间: ' . date('Y-m-d H:i:s'));
|
|
// 获取表单上传文件
|
|
|
|
$files = request()->file('file');
|
|
// $savename = \think\facade\Filesystem::disk('local')->putFile( 'topic', $files);
|
|
|
|
$savename = \think\facade\Filesystem::putFile('topic', $files);
|
|
$disk =\think\facade\Filesystem::getDefaultDriver();
|
|
$disk = \think\facade\Filesystem::getDiskConfig($disk) ;
|
|
$this->success([
|
|
'fid' => 0,
|
|
'name' => $files->getOriginalName(),
|
|
'url' =>$disk['url'] . DIRECTORY_SEPARATOR . $savename,
|
|
], '上传成功');
|
|
|
|
|
|
}
|
|
}
|