dootask/app/Models/UserFavorite.php
kuaifan 73ca4b1ea5 feat: 扩展收藏功能,支持消息类型的收藏
- 在 UserFavorite 模型中添加消息类型常量
- 更新 UsersController,支持消息的收藏、切换和状态检查
- 修改前端 Vue 组件以实现消息的收藏操作和状态显示
- 优化收藏管理界面,支持消息类型的展示与处理
2025-09-23 09:48:06 +08:00

297 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Models;
use Carbon\Carbon;
use App\Models\File;
/**
* App\Models\UserFavorite
*
* @property int $id
* @property int $userid 用户ID
* @property string $favoritable_type 收藏类型
* @property int $favoritable_id 收藏对象ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $favoritable
* @property-read \App\Models\User|null $user
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereFavoritableId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereFavoritableType($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserFavorite whereUserid($value)
* @mixin \Eloquent
*/
class UserFavorite extends AbstractModel
{
const TYPE_TASK = 'task';
const TYPE_PROJECT = 'project';
const TYPE_FILE = 'file';
const TYPE_MESSAGE = 'message';
protected $fillable = [
'userid',
'favoritable_type',
'favoritable_id',
];
/**
* 关联用户
*/
public function user()
{
return $this->belongsTo(User::class, 'userid', 'userid');
}
/**
* 多态关联
*/
public function favoritable()
{
return $this->morphTo();
}
/**
* 切换收藏状态
* @param int $userid 用户ID
* @param string $type 收藏类型
* @param int $id 收藏对象ID
* @return array ['favorited' => bool, 'action' => 'added'|'removed']
*/
public static function toggleFavorite($userid, $type, $id)
{
$favorite = self::whereUserid($userid)
->whereFavoritableType($type)
->whereFavoritableId($id)
->first();
if ($favorite) {
// 取消收藏
$favorite->delete();
return ['favorited' => false, 'action' => 'removed'];
} else {
// 添加收藏
self::create([
'userid' => $userid,
'favoritable_type' => $type,
'favoritable_id' => $id,
]);
return ['favorited' => true, 'action' => 'added'];
}
}
/**
* 检查是否已收藏
* @param int $userid 用户ID
* @param string $type 收藏类型
* @param int $id 收藏对象ID
* @return bool
*/
public static function isFavorited($userid, $type, $id)
{
return self::whereUserid($userid)
->whereFavoritableType($type)
->whereFavoritableId($id)
->exists();
}
/**
* 获取用户收藏列表
* @param int $userid 用户ID
* @param string|null $type 收藏类型过滤
* @param int $page 页码
* @param int $pageSize 每页数量
* @return array
*/
public static function getUserFavorites($userid, $type = null, $page = 1, $pageSize = 20)
{
$query = self::whereUserid($userid)->orderByDesc('created_at');
if ($type) {
$query->whereFavoritableType($type);
}
$favorites = $query->paginate($pageSize, ['*'], 'page', $page);
$data = [
'tasks' => [],
'projects' => [],
'files' => [],
'messages' => []
];
// 分组收集ID
$taskIds = [];
$projectIds = [];
$fileIds = [];
$messageIds = [];
foreach ($favorites->items() as $favorite) {
switch ($favorite->favoritable_type) {
case self::TYPE_TASK:
$taskIds[] = $favorite->favoritable_id;
break;
case self::TYPE_PROJECT:
$projectIds[] = $favorite->favoritable_id;
break;
case self::TYPE_FILE:
$fileIds[] = $favorite->favoritable_id;
break;
case self::TYPE_MESSAGE:
$messageIds[] = $favorite->favoritable_id;
break;
}
}
// 批量查询具体数据
if (!empty($taskIds)) {
$tasks = ProjectTask::select([
'project_tasks.id',
'project_tasks.name',
'project_tasks.project_id',
'project_tasks.complete_at',
'project_tasks.created_at',
'project_tasks.flow_item_id',
'project_tasks.flow_item_name',
'projects.name as project_name'
])
->leftJoin('projects', 'project_tasks.project_id', '=', 'projects.id')
->whereIn('project_tasks.id', $taskIds)
->get()
->keyBy('id');
foreach ($favorites->items() as $favorite) {
if ($favorite->favoritable_type === self::TYPE_TASK && isset($tasks[$favorite->favoritable_id])) {
$task = $tasks[$favorite->favoritable_id];
// 解析 flow_item_name 字段格式status|name|color
$flowItemParts = explode('|', $task->flow_item_name ?: '');
$flowItemStatus = $flowItemParts[0] ?? '';
$flowItemName = $flowItemParts[1] ?? $task->flow_item_name;
$flowItemColor = $flowItemParts[2] ?? '';
$data['tasks'][] = [
'id' => $task->id,
'name' => $task->name,
'project_id' => $task->project_id,
'project_name' => $task->project_name,
'complete_at' => $task->complete_at,
'flow_item_id' => $task->flow_item_id,
'flow_item_name' => $flowItemName,
'flow_item_status' => $flowItemStatus,
'flow_item_color' => $flowItemColor,
'favorited_at' => Carbon::parse($favorite->created_at)->format('Y-m-d H:i:s'),
];
}
}
}
if (!empty($projectIds)) {
$projects = Project::select([
'id', 'name', 'desc', 'archived_at', 'created_at'
])->whereIn('id', $projectIds)->get()->keyBy('id');
foreach ($favorites->items() as $favorite) {
if ($favorite->favoritable_type === self::TYPE_PROJECT && isset($projects[$favorite->favoritable_id])) {
$project = $projects[$favorite->favoritable_id];
$data['projects'][] = [
'id' => $project->id,
'name' => $project->name,
'desc' => $project->desc,
'archived_at' => $project->archived_at,
'favorited_at' => Carbon::parse($favorite->created_at)->format('Y-m-d H:i:s'),
];
}
}
}
if (!empty($fileIds)) {
$files = File::select([
'id', 'name', 'ext', 'size', 'pid', 'created_at'
])->whereIn('id', $fileIds)->get()->keyBy('id');
foreach ($favorites->items() as $favorite) {
if ($favorite->favoritable_type === self::TYPE_FILE && isset($files[$favorite->favoritable_id])) {
$file = $files[$favorite->favoritable_id];
$data['files'][] = [
'id' => $file->id,
'name' => $file->name,
'ext' => $file->ext,
'size' => $file->size,
'pid' => $file->pid,
'favorited_at' => Carbon::parse($favorite->created_at)->format('Y-m-d H:i:s'),
];
}
}
}
if (!empty($messageIds)) {
$messages = WebSocketDialogMsg::select([
'id', 'dialog_id', 'userid', 'type', 'msg', 'created_at'
])->whereIn('id', $messageIds)->get()->keyBy('id');
foreach ($favorites->items() as $favorite) {
if ($favorite->favoritable_type === self::TYPE_MESSAGE && isset($messages[$favorite->favoritable_id])) {
$message = $messages[$favorite->favoritable_id];
// 使用 previewTextMsg 获取消息预览文本
$previewText = '';
if ($message->msg && is_array($message->msg)) {
$previewText = WebSocketDialogMsg::previewTextMsg($message->msg);
}
// 如果没有预览文本,使用消息类型作为标题
if (empty($previewText)) {
$previewText = '[' . ucfirst($message->type) . ']';
}
$data['messages'][] = [
'id' => $message->id,
'name' => $previewText,
'dialog_id' => $message->dialog_id,
'userid' => $message->userid,
'type' => $message->type,
'favorited_at' => Carbon::parse($favorite->created_at)->format('Y-m-d H:i:s'),
];
}
}
}
return [
'data' => $data,
'total' => $favorites->total(),
'current_page' => $favorites->currentPage(),
'per_page' => $favorites->perPage(),
'last_page' => $favorites->lastPage(),
];
}
/**
* 清理用户收藏
* @param int $userid 用户ID
* @param string|null $type 收藏类型null表示全部类型
* @return int 删除的记录数
*/
public static function cleanUserFavorites($userid, $type = null)
{
$query = self::whereUserid($userid);
if ($type) {
$query->whereFavoritableType($type);
}
return $query->delete();
}
}