feat: 扩展 SeekDB 支持联系人、项目、任务的 AI 搜索
- 合并 SeekDBFileSyncTask 到 SeekDBSyncTask - 统一 AI 搜索 API 入口
This commit is contained in:
@@ -12,7 +12,6 @@ use App\Models\FileLink;
|
||||
use App\Models\FileUser;
|
||||
use App\Models\User;
|
||||
use App\Models\UserRecentItem;
|
||||
use App\Module\Apps;
|
||||
use App\Module\Base;
|
||||
use App\Module\Down;
|
||||
use App\Module\Timer;
|
||||
@@ -118,7 +117,7 @@ class FileController extends AbstractController
|
||||
/**
|
||||
* @api {get} api/file/search 搜索文件列表
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiDescription 需要token身份(仅搜索文件名,AI 内容搜索请使用 api/search/file)
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup file
|
||||
* @apiName search
|
||||
@@ -126,8 +125,6 @@ class FileController extends AbstractController
|
||||
* @apiParam {String} [link] 通过分享地址搜索(如:https://t.hitosea.com/single/file/ODcwOCwzOSxpa0JBS2lmVQ==)
|
||||
* @apiParam {String} [key] 关键词
|
||||
* @apiParam {Number} [take] 获取数量(默认:50,最大:100)
|
||||
* @apiParam {String} [search_content] 是否搜索文件内容(yes/no,默认:no)
|
||||
* @apiParam {String} [search_type] 搜索类型(text/vector/hybrid,默认:hybrid,仅 search_content=yes 时有效)
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
@@ -139,8 +136,6 @@ class FileController extends AbstractController
|
||||
//
|
||||
$link = trim(Request::input('link'));
|
||||
$key = trim(Request::input('key'));
|
||||
$searchContent = Request::input('search_content', 'no') === 'yes';
|
||||
$searchType = Request::input('search_type', 'hybrid');
|
||||
$id = 0;
|
||||
$take = Base::getPaginate(100, 50, 'take');
|
||||
if (preg_match("/\/single\/file\/(.*?)$/i", $link, $match)) {
|
||||
@@ -151,34 +146,6 @@ class FileController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
// 如果需要搜索文件内容且有关键词
|
||||
if ($searchContent && $key && !$id && Apps::isInstalled('seekdb')) {
|
||||
$results = \App\Module\SeekDB\SeekDBFile::search(
|
||||
$user->userid,
|
||||
$key,
|
||||
$searchType,
|
||||
0,
|
||||
$take
|
||||
);
|
||||
// 获取完整的文件信息
|
||||
if (!empty($results)) {
|
||||
$fileIds = array_column($results, 'file_id');
|
||||
$files = File::whereIn('id', $fileIds)->get()->keyBy('id');
|
||||
$array = [];
|
||||
foreach ($results as $result) {
|
||||
$file = $files->get($result['file_id']);
|
||||
if ($file) {
|
||||
$temp = $file->toArray();
|
||||
$temp['content_preview'] = $result['content_preview'] ?? null;
|
||||
$temp['relevance'] = $result['relevance'] ?? 0;
|
||||
$array[] = $temp;
|
||||
}
|
||||
}
|
||||
return Base::retSuccess('success', $array);
|
||||
}
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
|
||||
// 搜索自己的
|
||||
$builder = File::whereUserid($user->userid);
|
||||
if ($id) {
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Request;
|
||||
use App\Models\File;
|
||||
use App\Models\User;
|
||||
use App\Module\Base;
|
||||
use App\Module\Apps;
|
||||
use App\Module\SeekDB\SeekDBFile;
|
||||
use App\Module\SeekDB\SeekDBUser;
|
||||
use App\Module\SeekDB\SeekDBProject;
|
||||
use App\Module\SeekDB\SeekDBTask;
|
||||
|
||||
/**
|
||||
* @apiDefine search
|
||||
*
|
||||
* 智能搜索
|
||||
*/
|
||||
class SearchController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @api {get} api/search/contact AI 搜索联系人
|
||||
*
|
||||
* @apiDescription 需要token身份,需要安装 SeekDB 应用
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup search
|
||||
* @apiName contact
|
||||
*
|
||||
* @apiParam {String} key 搜索关键词
|
||||
* @apiParam {String} [search_type] 搜索类型(text/vector/hybrid,默认:hybrid)
|
||||
* @apiParam {Number} [take] 获取数量(默认:20,最大:50)
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function contact()
|
||||
{
|
||||
User::auth();
|
||||
|
||||
if (!Apps::isInstalled('seekdb')) {
|
||||
return Base::retError('SeekDB 应用未安装');
|
||||
}
|
||||
|
||||
$key = trim(Request::input('key'));
|
||||
$searchType = Request::input('search_type', 'hybrid');
|
||||
$take = min(50, max(1, intval(Request::input('take', 20))));
|
||||
|
||||
if (empty($key)) {
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
|
||||
$results = SeekDBUser::search($key, $searchType, $take);
|
||||
|
||||
// 补充用户完整信息
|
||||
$userids = array_column($results, 'userid');
|
||||
if (!empty($userids)) {
|
||||
$users = User::whereIn('userid', $userids)
|
||||
->select(User::$basicField)
|
||||
->get()
|
||||
->keyBy('userid');
|
||||
|
||||
foreach ($results as &$item) {
|
||||
$userData = $users->get($item['userid']);
|
||||
if ($userData) {
|
||||
$item = array_merge($userData->toArray(), [
|
||||
'relevance' => $item['relevance'] ?? 0,
|
||||
'introduction_preview' => $item['introduction_preview'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Base::retSuccess('success', $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/search/project AI 搜索项目
|
||||
*
|
||||
* @apiDescription 需要token身份,需要安装 SeekDB 应用
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup search
|
||||
* @apiName project
|
||||
*
|
||||
* @apiParam {String} key 搜索关键词
|
||||
* @apiParam {String} [search_type] 搜索类型(text/vector/hybrid,默认:hybrid)
|
||||
* @apiParam {Number} [take] 获取数量(默认:20,最大:50)
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function project()
|
||||
{
|
||||
$user = User::auth();
|
||||
|
||||
if (!Apps::isInstalled('seekdb')) {
|
||||
return Base::retError('SeekDB 应用未安装');
|
||||
}
|
||||
|
||||
$key = trim(Request::input('key'));
|
||||
$searchType = Request::input('search_type', 'hybrid');
|
||||
$take = min(50, max(1, intval(Request::input('take', 20))));
|
||||
|
||||
if (empty($key)) {
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
|
||||
$results = SeekDBProject::search($user->userid, $key, $searchType, $take);
|
||||
|
||||
// 补充项目完整信息
|
||||
$projectIds = array_column($results, 'project_id');
|
||||
if (!empty($projectIds)) {
|
||||
$projects = \App\Models\Project::whereIn('id', $projectIds)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
foreach ($results as &$item) {
|
||||
$projectData = $projects->get($item['project_id']);
|
||||
if ($projectData) {
|
||||
$item = array_merge($projectData->toArray(), [
|
||||
'relevance' => $item['relevance'] ?? 0,
|
||||
'desc_preview' => $item['desc_preview'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Base::retSuccess('success', $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/search/task AI 搜索任务
|
||||
*
|
||||
* @apiDescription 需要token身份,需要安装 SeekDB 应用
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup search
|
||||
* @apiName task
|
||||
*
|
||||
* @apiParam {String} key 搜索关键词
|
||||
* @apiParam {String} [search_type] 搜索类型(text/vector/hybrid,默认:hybrid)
|
||||
* @apiParam {Number} [take] 获取数量(默认:20,最大:50)
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function task()
|
||||
{
|
||||
$user = User::auth();
|
||||
|
||||
if (!Apps::isInstalled('seekdb')) {
|
||||
return Base::retError('SeekDB 应用未安装');
|
||||
}
|
||||
|
||||
$key = trim(Request::input('key'));
|
||||
$searchType = Request::input('search_type', 'hybrid');
|
||||
$take = min(50, max(1, intval(Request::input('take', 20))));
|
||||
|
||||
if (empty($key)) {
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
|
||||
$results = SeekDBTask::search($user->userid, $key, $searchType, $take);
|
||||
|
||||
// 补充任务完整信息
|
||||
$taskIds = array_column($results, 'task_id');
|
||||
if (!empty($taskIds)) {
|
||||
$tasks = \App\Models\ProjectTask::whereIn('id', $taskIds)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
foreach ($results as &$item) {
|
||||
$taskData = $tasks->get($item['task_id']);
|
||||
if ($taskData) {
|
||||
$item = array_merge($taskData->toArray(), [
|
||||
'relevance' => $item['relevance'] ?? 0,
|
||||
'desc_preview' => $item['desc_preview'] ?? null,
|
||||
'content_preview' => $item['content_preview'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Base::retSuccess('success', $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/search/file AI 搜索文件
|
||||
*
|
||||
* @apiDescription 需要token身份,需要安装 SeekDB 应用
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup search
|
||||
* @apiName file
|
||||
*
|
||||
* @apiParam {String} key 搜索关键词
|
||||
* @apiParam {String} [search_type] 搜索类型(text/vector/hybrid,默认:hybrid)
|
||||
* @apiParam {Number} [take] 获取数量(默认:20,最大:50)
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function file()
|
||||
{
|
||||
$user = User::auth();
|
||||
|
||||
if (!Apps::isInstalled('seekdb')) {
|
||||
return Base::retError('SeekDB 应用未安装');
|
||||
}
|
||||
|
||||
$key = trim(Request::input('key'));
|
||||
$searchType = Request::input('search_type', 'hybrid');
|
||||
$take = min(50, max(1, intval(Request::input('take', 20))));
|
||||
|
||||
if (empty($key)) {
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
|
||||
$results = SeekDBFile::search($user->userid, $key, $searchType, 0, $take);
|
||||
|
||||
// 补充文件完整信息
|
||||
$fileIds = array_column($results, 'file_id');
|
||||
if (!empty($fileIds)) {
|
||||
$files = File::whereIn('id', $fileIds)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
$formattedResults = [];
|
||||
foreach ($results as $item) {
|
||||
$fileData = $files->get($item['file_id']);
|
||||
if ($fileData) {
|
||||
$formattedResults[] = array_merge($fileData->toArray(), [
|
||||
'relevance' => $item['relevance'] ?? 0,
|
||||
'content_preview' => $item['content_preview'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
return Base::retSuccess('success', $formattedResults);
|
||||
}
|
||||
|
||||
return Base::retSuccess('success', []);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use App\Tasks\DeleteBotMsgTask;
|
||||
use App\Tasks\CheckinRemindTask;
|
||||
use App\Tasks\CloseMeetingRoomTask;
|
||||
use App\Tasks\ZincSearchSyncTask;
|
||||
use App\Tasks\SeekDBFileSyncTask;
|
||||
use App\Tasks\SeekDBSyncTask;
|
||||
use App\Tasks\UnclaimedTaskRemindTask;
|
||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||
use Laravolt\Avatar\Avatar;
|
||||
@@ -274,8 +274,8 @@ class IndexController extends InvokeController
|
||||
Task::deliver(new CloseMeetingRoomTask());
|
||||
// ZincSearch 同步
|
||||
Task::deliver(new ZincSearchSyncTask());
|
||||
// SeekDB 文件同步
|
||||
Task::deliver(new SeekDBFileSyncTask());
|
||||
// SeekDB 同步(文件/用户/项目/任务)
|
||||
Task::deliver(new SeekDBSyncTask());
|
||||
|
||||
return "success";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user