mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-23 10:28:13 +00:00
refactor: 提取搜索逻辑到 Model Scope
- User: 新增 scopeSearchByKeyword - Project: 新增 scopeSearchByKeyword - ProjectTask: 新增 scopeSearchByKeyword - File: 新增 scopeSearchByKeyword, scopeSharedToUser - WebSocketDialogMsg: 新增 scopeSearchByKeyword, scopeAccessibleByUser - SearchController: 使用新的 Model Scope 简化 MySQL 回退逻辑
This commit is contained in:
parent
67fc0781e5
commit
ec0db3a76c
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use DB;
|
|
||||||
use Request;
|
use Request;
|
||||||
use App\Models\File;
|
use App\Models\File;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
@ -10,7 +9,6 @@ use App\Models\ProjectTask;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\WebSocketDialog;
|
use App\Models\WebSocketDialog;
|
||||||
use App\Models\WebSocketDialogMsg;
|
use App\Models\WebSocketDialogMsg;
|
||||||
use App\Models\WebSocketDialogUser;
|
|
||||||
use App\Module\Base;
|
use App\Module\Base;
|
||||||
use App\Module\Apps;
|
use App\Module\Apps;
|
||||||
use App\Module\Manticore\ManticoreFile;
|
use App\Module\Manticore\ManticoreFile;
|
||||||
@ -93,28 +91,13 @@ class SearchController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
private function searchContactByMysql(string $key, int $take): array
|
private function searchContactByMysql(string $key, int $take): array
|
||||||
{
|
{
|
||||||
$builder = User::select(User::$basicField)
|
$users = User::select(User::$basicField)
|
||||||
->where('bot', 0)
|
->where('bot', 0)
|
||||||
->whereNull('disable_at');
|
->whereNull('disable_at')
|
||||||
|
->searchByKeyword($key)
|
||||||
if (str_contains($key, "@")) {
|
->orderByDesc('line_at')
|
||||||
$builder->where("email", "like", "%{$key}%");
|
->take($take)
|
||||||
} elseif (Base::isNumber($key)) {
|
->get();
|
||||||
$builder->where(function ($query) use ($key) {
|
|
||||||
$query->where("userid", intval($key))
|
|
||||||
->orWhere("nickname", "like", "%{$key}%")
|
|
||||||
->orWhere("pinyin", "like", "%{$key}%")
|
|
||||||
->orWhere("profession", "like", "%{$key}%");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$builder->where(function ($query) use ($key) {
|
|
||||||
$query->where("nickname", "like", "%{$key}%")
|
|
||||||
->orWhere("pinyin", "like", "%{$key}%")
|
|
||||||
->orWhere("profession", "like", "%{$key}%");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$users = $builder->orderByDesc('line_at')->take($take)->get();
|
|
||||||
|
|
||||||
return $users->map(function ($user) {
|
return $users->map(function ($user) {
|
||||||
return array_merge($user->toArray(), [
|
return array_merge($user->toArray(), [
|
||||||
@ -193,12 +176,12 @@ class SearchController extends AbstractController
|
|||||||
{
|
{
|
||||||
$projects = Project::authData()
|
$projects = Project::authData()
|
||||||
->whereNull('projects.archived_at')
|
->whereNull('projects.archived_at')
|
||||||
->where("projects.name", "like", "%{$key}%")
|
->searchByKeyword($key)
|
||||||
->orderByDesc('projects.id')
|
->orderByDesc('projects.id')
|
||||||
->take($take)
|
->take($take)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return $projects->map(function ($project) use ($userid) {
|
return $projects->map(function ($project) {
|
||||||
$array = $project->toArray();
|
$array = $project->toArray();
|
||||||
$array['relevance'] = 0;
|
$array['relevance'] = 0;
|
||||||
$array['desc_preview'] = null;
|
$array['desc_preview'] = null;
|
||||||
@ -275,29 +258,18 @@ class SearchController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
private function searchTaskByMysql(int $userid, string $key, int $take): array
|
private function searchTaskByMysql(int $userid, string $key, int $take): array
|
||||||
{
|
{
|
||||||
$builder = ProjectTask::with(['taskUser', 'taskTag'])
|
$tasks = ProjectTask::with(['taskUser', 'taskTag'])
|
||||||
->whereIn('project_tasks.project_id', function ($query) use ($userid) {
|
->whereIn('project_tasks.project_id', function ($query) use ($userid) {
|
||||||
$query->select('project_id')
|
$query->select('project_id')
|
||||||
->from('project_users')
|
->from('project_users')
|
||||||
->where('userid', $userid);
|
->where('userid', $userid);
|
||||||
})
|
})
|
||||||
->whereNull('project_tasks.archived_at')
|
->whereNull('project_tasks.archived_at')
|
||||||
->whereNull('project_tasks.deleted_at');
|
->whereNull('project_tasks.deleted_at')
|
||||||
|
->searchByKeyword($key)
|
||||||
if (Base::isNumber($key)) {
|
->orderByDesc('project_tasks.id')
|
||||||
$builder->where(function ($query) use ($key) {
|
->take($take)
|
||||||
$query->where("project_tasks.id", intval($key))
|
->get();
|
||||||
->orWhere("project_tasks.name", "like", "%{$key}%")
|
|
||||||
->orWhere("project_tasks.desc", "like", "%{$key}%");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$builder->where(function ($query) use ($key) {
|
|
||||||
$query->where("project_tasks.name", "like", "%{$key}%")
|
|
||||||
->orWhere("project_tasks.desc", "like", "%{$key}%");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$tasks = $builder->orderByDesc('project_tasks.id')->take($take)->get();
|
|
||||||
|
|
||||||
return $tasks->map(function ($task) {
|
return $tasks->map(function ($task) {
|
||||||
$array = $task->toArray();
|
$array = $task->toArray();
|
||||||
@ -381,15 +353,10 @@ class SearchController extends AbstractController
|
|||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
// 搜索用户自己的文件
|
// 搜索用户自己的文件
|
||||||
$builder = File::where('userid', $userid);
|
$ownFiles = File::where('userid', $userid)
|
||||||
if (Base::isNumber($key)) {
|
->searchByKeyword($key)
|
||||||
$builder->where(function ($query) use ($key) {
|
->take($take)
|
||||||
$query->where("id", $key)->orWhere("name", "like", "%{$key}%");
|
->get();
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$builder->where("name", "like", "%{$key}%");
|
|
||||||
}
|
|
||||||
$ownFiles = $builder->take($take)->get();
|
|
||||||
|
|
||||||
foreach ($ownFiles as $file) {
|
foreach ($ownFiles as $file) {
|
||||||
$results[] = array_merge($file->toArray(), [
|
$results[] = array_merge($file->toArray(), [
|
||||||
@ -401,24 +368,11 @@ class SearchController extends AbstractController
|
|||||||
// 搜索共享给用户的文件
|
// 搜索共享给用户的文件
|
||||||
$remaining = $take - count($results);
|
$remaining = $take - count($results);
|
||||||
if ($remaining > 0) {
|
if ($remaining > 0) {
|
||||||
$builder = File::whereIn('pshare', function ($queryA) use ($userid) {
|
$sharedFiles = File::sharedToUser($userid)
|
||||||
$queryA->select('files.id')
|
->searchByKeyword($key)
|
||||||
->from('files')
|
->take($remaining)
|
||||||
->join('file_users', 'files.id', '=', 'file_users.file_id')
|
->get();
|
||||||
->where('files.userid', '!=', $userid)
|
|
||||||
->where(function ($queryB) use ($userid) {
|
|
||||||
$queryB->whereIn('file_users.userid', [0, $userid]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (Base::isNumber($key)) {
|
|
||||||
$builder->where(function ($query) use ($key) {
|
|
||||||
$query->where("id", $key)->orWhere("name", "like", "%{$key}%");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$builder->where("name", "like", "%{$key}%");
|
|
||||||
}
|
|
||||||
|
|
||||||
$sharedFiles = $builder->take($remaining)->get();
|
|
||||||
foreach ($sharedFiles as $file) {
|
foreach ($sharedFiles as $file) {
|
||||||
$temp = $file->toArray();
|
$temp = $file->toArray();
|
||||||
if ($file->pshare === $file->id) {
|
if ($file->pshare === $file->id) {
|
||||||
@ -501,32 +455,28 @@ class SearchController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
private function searchMessageByMysql(int $userid, string $key, int $take, int $dialogId = 0): array
|
private function searchMessageByMysql(int $userid, string $key, int $take, int $dialogId = 0): array
|
||||||
{
|
{
|
||||||
$builder = DB::table('web_socket_dialog_msgs as m')
|
$builder = WebSocketDialogMsg::select([
|
||||||
->select([
|
'id as msg_id',
|
||||||
'm.id as msg_id',
|
'dialog_id',
|
||||||
'm.dialog_id',
|
'userid',
|
||||||
'm.userid',
|
'type',
|
||||||
'm.type',
|
'msg',
|
||||||
'm.msg',
|
'created_at',
|
||||||
'm.created_at',
|
|
||||||
])
|
])
|
||||||
->join('web_socket_dialog_users as u', 'm.dialog_id', '=', 'u.dialog_id')
|
->accessibleByUser($userid)
|
||||||
->where('u.userid', $userid)
|
->where('bot', 0)
|
||||||
->where('m.bot', 0)
|
->searchByKeyword($key);
|
||||||
->where('m.key', 'like', "%{$key}%");
|
|
||||||
|
|
||||||
if ($dialogId > 0) {
|
if ($dialogId > 0) {
|
||||||
$builder->where('m.dialog_id', $dialogId);
|
$builder->where('dialog_id', $dialogId);
|
||||||
}
|
}
|
||||||
|
|
||||||
$items = $builder->orderByDesc('m.id')
|
$items = $builder->orderByDesc('id')
|
||||||
->limit($take)
|
->limit($take)
|
||||||
->get()
|
->get();
|
||||||
->all();
|
|
||||||
|
|
||||||
$results = [];
|
return $items->map(function ($item) {
|
||||||
foreach ($items as $item) {
|
return [
|
||||||
$results[] = [
|
|
||||||
'msg_id' => $item->msg_id,
|
'msg_id' => $item->msg_id,
|
||||||
'dialog_id' => $item->dialog_id,
|
'dialog_id' => $item->dialog_id,
|
||||||
'userid' => $item->userid,
|
'userid' => $item->userid,
|
||||||
@ -536,9 +486,7 @@ class SearchController extends AbstractController
|
|||||||
'relevance' => 0,
|
'relevance' => 0,
|
||||||
'content_preview' => null,
|
'content_preview' => null,
|
||||||
];
|
];
|
||||||
}
|
})->toArray();
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -128,6 +128,45 @@ class File extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
const zipMaxSize = 1024 * 1024 * 1024; // 1G
|
const zipMaxSize = 1024 * 1024 * 1024; // 1G
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按关键词搜索文件(Scope)
|
||||||
|
* 支持:文件ID(纯数字)、文件名
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param string $keyword 搜索关键词
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSearchByKeyword($query, string $keyword)
|
||||||
|
{
|
||||||
|
if (is_numeric($keyword)) {
|
||||||
|
return $query->where(function ($q) use ($keyword) {
|
||||||
|
$q->where("id", intval($keyword))
|
||||||
|
->orWhere("name", "like", "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $query->where("name", "like", "%{$keyword}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 筛选用户可访问的共享文件(Scope)
|
||||||
|
* 不包括用户自己的文件,仅返回他人共享给该用户的文件
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param int $userid 用户ID
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSharedToUser($query, int $userid)
|
||||||
|
{
|
||||||
|
return $query->whereIn('pshare', function ($subQuery) use ($userid) {
|
||||||
|
$subQuery->select('files.id')
|
||||||
|
->from('files')
|
||||||
|
->join('file_users', 'files.id', '=', 'file_users.file_id')
|
||||||
|
->where('files.userid', '!=', $userid)
|
||||||
|
->where(function ($q) use ($userid) {
|
||||||
|
$q->whereIn('file_users.userid', [0, $userid]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件列表
|
* 获取文件列表
|
||||||
|
|||||||
@ -164,6 +164,18 @@ class Project extends AbstractModel
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按关键词搜索项目(Scope)
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param string $keyword 搜索关键词
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSearchByKeyword($query, string $keyword)
|
||||||
|
{
|
||||||
|
return $query->where("projects.name", "like", "%{$keyword}%");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取任务统计数据
|
* 获取任务统计数据
|
||||||
* @param $userid
|
* @param $userid
|
||||||
|
|||||||
@ -353,6 +353,32 @@ class ProjectTask extends AbstractModel
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按关键词搜索任务(Scope)
|
||||||
|
* 支持:任务ID(纯数字)、任务名称、描述
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param string $keyword 搜索关键词
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSearchByKeyword($query, string $keyword)
|
||||||
|
{
|
||||||
|
if (is_numeric($keyword)) {
|
||||||
|
// 纯数字:匹配任务ID 或 名称/描述
|
||||||
|
return $query->where(function ($q) use ($keyword) {
|
||||||
|
$q->where("project_tasks.id", intval($keyword))
|
||||||
|
->orWhere("project_tasks.name", "like", "%{$keyword}%")
|
||||||
|
->orWhere("project_tasks.desc", "like", "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 普通文本:搜索名称/描述
|
||||||
|
return $query->where(function ($q) use ($keyword) {
|
||||||
|
$q->where("project_tasks.name", "like", "%{$keyword}%")
|
||||||
|
->orWhere("project_tasks.desc", "like", "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成描述
|
* 生成描述
|
||||||
* @param $content
|
* @param $content
|
||||||
|
|||||||
@ -773,24 +773,51 @@ class User extends AbstractModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按关键词搜索用户(Scope)
|
||||||
|
* 支持:邮箱(含@)、用户ID(纯数字)、昵称/拼音/职业
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param string $keyword 搜索关键词
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSearchByKeyword($query, string $keyword)
|
||||||
|
{
|
||||||
|
if (str_contains($keyword, "@")) {
|
||||||
|
// 包含 @ 按邮箱搜索
|
||||||
|
return $query->where("email", "like", "%{$keyword}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_numeric($keyword)) {
|
||||||
|
// 纯数字:匹配用户ID 或 昵称/拼音/职业
|
||||||
|
return $query->where(function ($q) use ($keyword) {
|
||||||
|
$q->where("userid", intval($keyword))
|
||||||
|
->orWhere("nickname", "like", "%{$keyword}%")
|
||||||
|
->orWhere("pinyin", "like", "%{$keyword}%")
|
||||||
|
->orWhere("profession", "like", "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 普通文本:搜索昵称/拼音/职业
|
||||||
|
return $query->where(function ($q) use ($keyword) {
|
||||||
|
$q->where("nickname", "like", "%{$keyword}%")
|
||||||
|
->orWhere("pinyin", "like", "%{$keyword}%")
|
||||||
|
->orWhere("profession", "like", "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索用户
|
* 搜索用户
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param $take
|
* @param $take
|
||||||
* @return User[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection
|
* @return User[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection
|
||||||
|
* @deprecated 建议使用 scopeSearchByKeyword
|
||||||
*/
|
*/
|
||||||
public static function searchUser($key, $take = 20)
|
public static function searchUser($key, $take = 20)
|
||||||
{
|
{
|
||||||
return User::select(User::$basicField)
|
return User::select(User::$basicField)
|
||||||
->where(function ($query) use ($key) {
|
->searchByKeyword($key)
|
||||||
if (str_contains($key, "@")) {
|
->orderBy('userid')
|
||||||
$query->where("email", "like", "%{$key}%");
|
|
||||||
} else {
|
|
||||||
$query->where("nickname", "like", "%{$key}%")
|
|
||||||
->orWhere("pinyin", "like", "%{$key}%")
|
|
||||||
->orWhere("profession", "like", "%{$key}%");
|
|
||||||
}
|
|
||||||
})->orderBy('userid')
|
|
||||||
->take($take)
|
->take($take)
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,6 +111,36 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
return $this->hasOne(User::class, 'userid', 'userid');
|
return $this->hasOne(User::class, 'userid', 'userid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按关键词搜索消息(Scope)
|
||||||
|
* 搜索 key 字段(消息的可搜索内容)
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param string $keyword 搜索关键词
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeSearchByKeyword($query, string $keyword)
|
||||||
|
{
|
||||||
|
return $query->where('key', 'like', "%{$keyword}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 筛选用户可访问的对话消息(Scope)
|
||||||
|
* 通过 web_socket_dialog_users 表验证用户对对话的访问权限
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param int $userid 用户ID
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeAccessibleByUser($query, int $userid)
|
||||||
|
{
|
||||||
|
return $query->whereIn('dialog_id', function ($subQuery) use ($userid) {
|
||||||
|
$subQuery->select('dialog_id')
|
||||||
|
->from('web_socket_dialog_users')
|
||||||
|
->where('userid', $userid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 阅读占比
|
* 阅读占比
|
||||||
* @return int|mixed
|
* @return int|mixed
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user