chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | YwxApp [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace addon\forum\controller;
|
||||
|
||||
use addon\forum\model\ForumBoard;
|
||||
use addon\forum\model\ForumTopic;
|
||||
use addon\forum\model\ForumReply;
|
||||
use addon\forum\model\ForumMessage;
|
||||
use ywxapp\model\BaseModel;
|
||||
use think\facade\Db;
|
||||
|
||||
class Index extends ForumFrontend
|
||||
{
|
||||
protected $noNeedLogin = [];
|
||||
protected $noNeedVerify = ['*'];
|
||||
|
||||
/**
|
||||
* 社区首页:版块 + 帖子流
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$boards = ForumBoard::enabledList();
|
||||
$topics = ForumTopic::listFront(0, '', 'new', 1, 20);
|
||||
$hot = ForumTopic::listFront(0, '', 'hot', 1, 10);
|
||||
$this->attachAuthors($topics);
|
||||
$this->attachAuthors($hot);
|
||||
|
||||
// 当前会员未读消息
|
||||
$unread = 0;
|
||||
if ($member = $this->member()) {
|
||||
$unread = ForumMessage::unreadCount((int) $member['uid']);
|
||||
}
|
||||
|
||||
$this->assign([
|
||||
'boards' => $boards,
|
||||
'topics' => $topics,
|
||||
'hot' => $hot,
|
||||
'unread' => $unread,
|
||||
'typeMap'=> ForumTopic::$typeMap,
|
||||
]);
|
||||
return $this->fetch('index/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 版块帖子列表
|
||||
*/
|
||||
public function board($slug = '')
|
||||
{
|
||||
$board = ForumBoard::findBySlug($slug);
|
||||
if (!$board) {
|
||||
$this->assign('msg', '版块不存在');
|
||||
return $this->fetch('index/notfound');
|
||||
}
|
||||
$type = $this->request->param('type', '');
|
||||
$order = $this->request->param('order', 'new');
|
||||
$page = (int) $this->request->param('page', 1);
|
||||
$topics = ForumTopic::listFront((int) $board->id, $type, $order, $page, 20);
|
||||
$this->attachAuthors($topics);
|
||||
|
||||
$this->assign([
|
||||
'board' => $board,
|
||||
'topics' => $topics,
|
||||
'type' => $type,
|
||||
'order' => $order,
|
||||
'typeMap'=> ForumTopic::$typeMap,
|
||||
]);
|
||||
return $this->fetch('index/board');
|
||||
}
|
||||
|
||||
/**
|
||||
* 帖子详情 + 回复列表
|
||||
*/
|
||||
public function topic($id = 0)
|
||||
{
|
||||
$topic = ForumTopic::findById((int) $id);
|
||||
if (!$topic || (int) $topic->status !== 1) {
|
||||
$this->assign('msg', '帖子不存在、待审核或已下架');
|
||||
return $this->fetch('index/notfound');
|
||||
}
|
||||
ForumTopic::addViews((int) $topic->id);
|
||||
|
||||
$replies = ForumReply::listByTopic((int) $topic->id);
|
||||
$board = ForumBoard::find((int) $topic->board_id);
|
||||
|
||||
// 作者信息(复用会员表),带默认值避免模板内联查库
|
||||
$author = Db::name('member')->where('id', $topic->user_id)
|
||||
->field('id,nickname,avatar,intro')->find();
|
||||
if (!$author) {
|
||||
$author = ['id' => $topic->user_id, 'nickname' => '匿名', 'avatar' => '', 'intro' => ''];
|
||||
}
|
||||
|
||||
// 每条回复附带用户信息
|
||||
$uids = array_column($replies->toArray(), 'user_id');
|
||||
$users = [];
|
||||
if (!empty($uids)) {
|
||||
$users = Db::name('member')->where('id', 'in', array_unique($uids))
|
||||
->column('nickname,avatar', 'id');
|
||||
}
|
||||
$replyList = [];
|
||||
foreach ($replies as $rp) {
|
||||
$u = $users[$rp['user_id']] ?? ['nickname' => '匿名', 'avatar' => ''];
|
||||
$replyList[] = [
|
||||
'id' => $rp['id'],
|
||||
'user_id' => $rp['user_id'],
|
||||
'floor' => $rp['floor'],
|
||||
'content' => $rp['content'],
|
||||
'create_at' => $rp['create_at'],
|
||||
'nickname' => $u['nickname'] ?: '匿名',
|
||||
'avatar' => $u['avatar'] ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
$this->assign([
|
||||
'topic' => $topic,
|
||||
'author' => $author,
|
||||
'replyList' => $replyList,
|
||||
'board' => $board,
|
||||
'related' => \addon\forum\service\ForumSearchService::related((int) $topic->id, 6),
|
||||
'typeName' => ForumTopic::$typeMap[$topic->type] ?? '',
|
||||
]);
|
||||
return $this->fetch('index/topic');
|
||||
}
|
||||
|
||||
/**
|
||||
* 发帖页
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
if (!$this->requireLogin()) {
|
||||
return redirect('/user/login');
|
||||
}
|
||||
$boards = ForumBoard::enabledList();
|
||||
$this->assign('boards', $boards);
|
||||
$this->assign('typeMap', ForumTopic::$typeMap);
|
||||
$cfg = \ywxapp\service\AddonService::config('forum');
|
||||
$this->assign('editorHeight', (int) ($cfg['editor_height'] ?? 360));
|
||||
return $this->fetch('index/post');
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交发帖
|
||||
*/
|
||||
public function doPost()
|
||||
{
|
||||
if (!$this->requireLogin()) {
|
||||
return $this->error('请先登录');
|
||||
}
|
||||
$member = $this->member();
|
||||
$data = $this->request->post();
|
||||
|
||||
$title = trim((string) ($data['title'] ?? ''));
|
||||
$content = trim((string) ($data['content'] ?? ''));
|
||||
$boardId = (int) ($data['board_id'] ?? 0);
|
||||
$type = (int) ($data['type'] ?? 0);
|
||||
$lat = (float) ($data['lat'] ?? 0);
|
||||
$lng = (float) ($data['lng'] ?? 0);
|
||||
|
||||
if ($title === '' || $content === '' || $boardId < 1) {
|
||||
return $this->error('请填写完整信息');
|
||||
}
|
||||
if (!isset(ForumTopic::$typeMap[$type])) {
|
||||
$type = ForumTopic::TYPE_ASK;
|
||||
}
|
||||
|
||||
$needAudit = (int) config('forum.need_audit');
|
||||
$status = $needAudit ? 0 : 1; // 0待审 1正常
|
||||
$auditReason = '';
|
||||
|
||||
// 机审(云审):开启 need_audit 且无 AI 审核服务时,按策略直接通过/转人工
|
||||
if ($needAudit) {
|
||||
$ai = new \addon\wxchat\service\AiAuditService();
|
||||
$res = $ai->audit($title . "\n" . $content);
|
||||
if ($res['code'] === 0) {
|
||||
if (!empty($res['data']['blocked'])) {
|
||||
// 机审命中违规:直接驳回,不进入人工队列
|
||||
$status = -1;
|
||||
$auditReason = '机审不通过:' . ($res['data']['reason'] ?? '内容违规');
|
||||
}
|
||||
// 机审通过:保持待审(status=0),等待人工复核
|
||||
}
|
||||
// AI 服务不可用(code!=0 且非 blocked):维持待审,转人工队列
|
||||
}
|
||||
|
||||
\addon\forum\library\ForumSchema::ensure();
|
||||
$topicId = ForumTopic::insertGetId([
|
||||
'board_id' => $boardId,
|
||||
'user_id' => $member['id'],
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'type' => $type,
|
||||
'status' => $status,
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'audit_reason' => $auditReason,
|
||||
'create_at' => time(),
|
||||
'update_at' => time(),
|
||||
]);
|
||||
|
||||
ForumBoard::incr($boardId, 'topic_count', 1);
|
||||
\addon\forum\service\ForumSearchService::sync($topicId);
|
||||
|
||||
if ($status === -1) {
|
||||
return $this->success(['id' => $topicId], $auditReason);
|
||||
}
|
||||
return $this->success(['id' => $topicId], $needAudit ? '发布成功,等待审核' : '发布成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交回复
|
||||
*/
|
||||
public function doReply()
|
||||
{
|
||||
if (!$this->requireLogin()) {
|
||||
return $this->error('请先登录');
|
||||
}
|
||||
$member = $this->member();
|
||||
$data = $this->request->post();
|
||||
$topicId = (int) ($data['topic_id'] ?? 0);
|
||||
$content = trim((string) ($data['content'] ?? ''));
|
||||
|
||||
if ($topicId < 1 || $content === '') {
|
||||
return $this->error('回复内容不能为空');
|
||||
}
|
||||
$topic = ForumTopic::findById($topicId);
|
||||
if (!$topic) {
|
||||
return $this->error('帖子不存在');
|
||||
}
|
||||
|
||||
$floor = ForumReply::countByTopic($topicId) + 1;
|
||||
$replyId = ForumReply::insertGetId([
|
||||
'topic_id' => $topicId,
|
||||
'user_id' => $member['id'],
|
||||
'content' => $content,
|
||||
'floor' => $floor,
|
||||
'status' => 1,
|
||||
'create_at' => time(),
|
||||
'update_at' => time(),
|
||||
]);
|
||||
|
||||
// 更新帖子回复计数 + 最后回复
|
||||
ForumTopic::where('id', $topicId)->inc('reply_count', 1)->update([
|
||||
'last_reply_id' => $replyId,
|
||||
'last_reply_uid' => $member['id'],
|
||||
'last_reply_time' => time(),
|
||||
]);
|
||||
ForumBoard::incr((int) $topic->board_id, 'reply_count', 1);
|
||||
|
||||
// 给帖子作者发消息(非自己)
|
||||
if ($topic->user_id != $member['id']) {
|
||||
ForumMessage::insert([
|
||||
'user_id' => $topic->user_id,
|
||||
'from_uid' => $member['id'],
|
||||
'type' => 'reply',
|
||||
'topic_id' => $topicId,
|
||||
'reply_id' => $replyId,
|
||||
'content' => mb_substr(strip_tags($content), 0, 120),
|
||||
'is_read' => 0,
|
||||
'create_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success(['floor' => $floor], '回复成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
public function search()
|
||||
{
|
||||
$kw = trim((string) $this->request->param('q', ''));
|
||||
$list = [];
|
||||
if ($kw !== '') {
|
||||
$list = \addon\forum\service\ForumSearchService::search($kw, (int) $this->request->param('page', 1), 20);
|
||||
}
|
||||
$this->assign('kw', $kw);
|
||||
$this->assign('list', $list);
|
||||
return $this->fetch('index/search');
|
||||
}
|
||||
|
||||
/**
|
||||
* 附近帖子(GEO/LBS):由前端定位传入 lat/lng,展示半径内帖子
|
||||
*/
|
||||
public function nearby()
|
||||
{
|
||||
$lat = (float) $this->request->param('lat', 0);
|
||||
$lng = (float) $this->request->param('lng', 0);
|
||||
$radius = (float) $this->request->param('radius', 10);
|
||||
$list = \addon\forum\service\ForumSearchService::nearby($lat, $lng, $radius, 30);
|
||||
$this->assign('list', $list);
|
||||
$this->assign('lat', $lat);
|
||||
$this->assign('lng', $lng);
|
||||
$this->assign('radius', $radius);
|
||||
return $this->fetch('index/nearby');
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量给帖子列表(Paginator)注入 author 字段,避免模板读取不存在的关联属性
|
||||
* @param \think\Paginator $paginator
|
||||
*/
|
||||
private function attachAuthors($collection)
|
||||
{
|
||||
if (!is_iterable($collection)) {
|
||||
return;
|
||||
}
|
||||
$uids = [];
|
||||
foreach ($collection as $t) {
|
||||
$uids[] = $t['user_id'] ?? ($t->user_id ?? 0);
|
||||
}
|
||||
$uids = array_filter(array_unique($uids));
|
||||
$users = [];
|
||||
if (!empty($uids)) {
|
||||
$users = Db::name('member')->where('id', 'in', $uids)
|
||||
->column('nickname,avatar', 'id');
|
||||
}
|
||||
foreach ($collection as $t) {
|
||||
$uid = $t['user_id'] ?? ($t->user_id ?? 0);
|
||||
$u = $users[$uid] ?? ['nickname' => '匿名', 'avatar' => ''];
|
||||
$t->author = [
|
||||
'nickname' => $u['nickname'] ?: '匿名',
|
||||
'avatar' => $u['avatar'] ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户主页(展示其论坛数据)
|
||||
*/
|
||||
public function user($id = 0)
|
||||
{
|
||||
$user = Db::name('member')->where('id', (int) $id)->field('id,nickname,avatar,intro')->find();
|
||||
if (!$user) {
|
||||
$this->assign('msg', '用户不存在');
|
||||
return $this->fetch('index/notfound');
|
||||
}
|
||||
$topics = ForumTopic::where('user_id', (int) $id)
|
||||
->where('status', 1)
|
||||
->order('id desc')
|
||||
->limit(20)->select();
|
||||
$this->assign('member', $user);
|
||||
$this->assign('topics', $topics);
|
||||
return $this->fetch('index/user');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user