作者 邓超

es

@@ -46,7 +46,7 @@ class HotMail { @@ -46,7 +46,7 @@ class HotMail {
46 } 46 }
47 $id = end($ids); 47 $id = end($ids);
48 48
49 - if($id<($maxId-100000)){ 49 + if($id<($maxId-200000)){
50 continue; 50 continue;
51 } 51 }
52 52
@@ -44,7 +44,7 @@ class SyncToEsCmd { @@ -44,7 +44,7 @@ class SyncToEsCmd {
44 $data = $db->first(\Model\listsSql::first('`id` = '.$id)); 44 $data = $db->first(\Model\listsSql::first('`id` = '.$id));
45 if($data){ 45 if($data){
46 // 设置 进程 是否在运行 46 // 设置 进程 是否在运行
47 - redis()->set('sync_my_pid:'.getmypid(),time(),86400); 47 +// redis()->set('sync_my_pid:'.getmypid(),time(),86400);
48 48
49 $data['is_auto']=$db->count('select count(*) from `lists_auto` where `list_id` = '.$data['id']) ? 1 : 0; 49 $data['is_auto']=$db->count('select count(*) from `lists_auto` where `list_id` = '.$data['id']) ? 1 : 0;
50 50
@@ -79,8 +79,13 @@ class SyncToEsCmd { @@ -79,8 +79,13 @@ class SyncToEsCmd {
79 'email' => $data['from'], 79 'email' => $data['from'],
80 'name' => $data['from_name']??'' 80 'name' => $data['from_name']??''
81 ]; 81 ];
82 - unset($data['from_name']); 82 + }else{
  83 + $data['from'] = [
  84 + 'email' => '',
  85 + 'name' => ''
  86 + ];
83 } 87 }
  88 + unset($data['from_name']);
84 unset($data['date']); 89 unset($data['date']);
85 if(!empty($data['created_at'])){ 90 if(!empty($data['created_at'])){
86 $data['created_at'] = date('Y-m-d\TH:i:s',strtotime($data['created_at'])); 91 $data['created_at'] = date('Y-m-d\TH:i:s',strtotime($data['created_at']));
  1 +<?php
  2 +
  3 +namespace Controller\fob_ai;
  4 +
  5 +
  6 +
  7 +use Controller\Base;
  8 +use Lib\Es\Es;
  9 +use Lib\Mail\MailFun;
  10 +use Lib\Verify;
  11 +use Model\folderSql;
  12 +use function Swoole\Coroutine\Http\request;
  13 +
  14 +/**
  15 + * 黑格 fob 那边专用 业务
  16 + * 为定制逻辑
  17 + * @author:dc
  18 + * @time 2024/7/18 11:40
  19 + * Class MailList
  20 + * @package Controller\fob_ai
  21 + */
  22 +class MailListV2Es extends Base {
  23 +
  24 + /**
  25 + * @var Es
  26 + */
  27 + public $es;
  28 +
  29 + public function __construct()
  30 + {
  31 + $this->es = new Es('hg_ai_emails');
  32 + }
  33 +
  34 + /**
  35 + * 当前邮箱下指定的文件夹
  36 + * @param string $folder
  37 + * @return array
  38 + * @throws \Lib\Err
  39 + * @author:dc
  40 + * @time 2024/7/19 11:37
  41 + */
  42 + private function getFolderId(string $folder,$emails=[]){
  43 + if(!$emails){
  44 + $emails = $this->getEmails('id');
  45 + }
  46 + $k = md5(json_encode($emails));
  47 + // 查询 文件夹
  48 + static $folderList;
  49 + if(empty($folderList[$k])){
  50 + $folderList[$k] = db()->all(folderSql::all($emails));
  51 + }
  52 + $folder_id = [];
  53 + // 文件夹id
  54 + if($folderList[$k]){
  55 + foreach ($folderList[$k] as $item){
  56 + if(folderAlias($item['folder']) == $folder){
  57 + $folder_id[] = $item['id'];
  58 + }
  59 + }
  60 + }
  61 + if(!$folder_id){
  62 + app()->e('folder_not_fount');
  63 + }
  64 +
  65 + return $folder_id;
  66 + }
  67 +
  68 +
  69 + /**
  70 + * 处理like条件
  71 + * @param $str
  72 + * @return string
  73 + * @author:dc
  74 + * @time 2024/9/4 11:14
  75 + */
  76 + private function getLikeStr($str){
  77 + if(str_starts_with($str, '^')){
  78 + return addslashes(mb_substr($str,1,99)).'%%';
  79 + }
  80 + return '%%'.addslashes($str).'%%';
  81 + }
  82 +
  83 + /**
  84 + * 邮件列表
  85 + * 接收参数
  86 + * page 分页
  87 + * limit 每页数量
  88 + * mail_id 指定邮件id
  89 + * attachment 是否附件
  90 + * emails 邮箱
  91 + * folder 文件夹
  92 + * from_not_in 不在这些发件箱的邮件
  93 + * @throws \Lib\Err
  94 + * @author:dc
  95 + * @time 2024/7/18 11:40
  96 + */
  97 + public function lists(){
  98 +
  99 + // 分页 页数
  100 + $page = app()->request('page',1,'intval') ? : 1;
  101 + $limit = app()->request('limit',20,'intval') ? : 1;
  102 +
  103 + // 指定id
  104 + $ids = app()->requestArr('mail_id');
  105 + foreach ($ids as $i=>$d){
  106 + if(!is_numeric($d)){
  107 + unset($ids[$i]);
  108 + }
  109 + }
  110 +
  111 + // 目录
  112 + $folder = app()->request('folder','收件箱');
  113 + // 只允许查询这里文件夹
  114 + if(!in_array($folder,['收件箱','发件箱','垃圾箱','星标邮件','预热收件箱','预热发件箱','自动回复收件箱','Starred','草稿箱'])){
  115 + app()->e('folder_not_fount');
  116 + }
  117 +
  118 + $where['is_hots'] = 0;
  119 +
  120 + if($folder=='星标邮件'||$folder=='Starred'){
  121 + $folder = '收件箱';
  122 + $where['flagged'] = 1; // 星标
  123 + unset($where['is_hots']);
  124 + }elseif ($folder=='预热收件箱'){
  125 + $folder = '收件箱';
  126 + $where['is_hots'] = 1;
  127 + }elseif ($folder=='预热发件箱'){
  128 + $folder = '发件箱';
  129 + $where['is_hots'] = 1;
  130 + } elseif ($folder=='自动回复收件箱'){
  131 + $is_auto_inbox = 1;
  132 + $folder = '收件箱';
  133 + $where['is_hots'] = 0;
  134 + }elseif ($folder=='草稿箱'){
  135 + $folder = '草稿箱';
  136 + $where['is_hots'] = 0;
  137 + }
  138 +
  139 + $seen = app()->request('seen',-1,'intval');
  140 + // 已读/未读
  141 + if(paramHas('seen')){
  142 + if(in_array($seen,[0,1])){
  143 + $where['seen'] = $seen;
  144 + }
  145 + }
  146 + // 搜索标题
  147 + $where['subject'] = [];
  148 + $keyword = app()->request('keyword');
  149 + if($keyword){
  150 + $where['subject'] = $keyword;
  151 + }
  152 + // 联系人
  153 + $address = app()->request('address');
  154 + if($address){
  155 + if(is_array($address)){
  156 + // 发贱人
  157 + if(Verify::sEmail($address['from']??'')){
  158 + if($folder=='发件箱'){
  159 + $where['to'] = $address['from'];
  160 + }else{
  161 + $where['from'] = $address['from'];
  162 + }
  163 + }
  164 + }
  165 + }
  166 +
  167 + if($ids) $where['uuid'] = $ids;
  168 +
  169 + if(app()->request('attachment',0,'bool_Val')){
  170 + // 附件
  171 + $where['is_file'] = 1; //附件
  172 + }
  173 +
  174 + // 软删
  175 + $where['deleted'] = 0;
  176 +
  177 +
  178 + /************ 2024-09-02 *************/
  179 + if($folder=='收件箱' && empty($where['flagged']) && !$ids) {
  180 + if(!empty($is_auto_inbox)){
  181 + // 是否是自动收件箱
  182 + $where['is_auto'] = 1;
  183 + }else{
  184 + $where['is_auto'] = 0;
  185 + }
  186 + }
  187 + /************ 2024-09-02 *************/
  188 +
  189 + $query = [
  190 + 'bool'=>[
  191 + 'must' => []
  192 + ]
  193 + ];
  194 + foreach ($where as $k=>$v){
  195 + if($k=='subject'){
  196 + $query['bool']['must'][] = [
  197 + 'query_string' => [
  198 + 'query'=>'"'.addcslashes($keyword,'"').'"',
  199 + "default_field"=> "subject"
  200 + ]
  201 + ];
  202 + }else{
  203 + $query['bool']['must'][] = [
  204 + 'term' => [
  205 + $k=>$v
  206 + ]
  207 + ];
  208 + }
  209 +
  210 + }
  211 +
  212 + // 星标就不加文件夹赛选
  213 + if(empty($where['flagged'])){
  214 + $query['bool']['must'][] = $this->assignSql($folder);
  215 + }else{
  216 + $query['bool']['must'][] = $this->assignSql2();
  217 + }
  218 +
  219 +
  220 + $result = $this->es->search(['query'=>$query],($page-1) * $limit,$limit,['udate'=>"desc"]);
  221 + app()->_json($result);
  222 +
  223 + // map
  224 +// $lists = array_map(function ($v){
  225 +// $v['uuid'] = md5($v['email_id'].'-'.$v['folder_id'].'-'.$v['uid']);
  226 +// if(!empty($v['description'])){
  227 +// $v['description'] = @html_entity_decode($v['description'], ENT_COMPAT, 'UTF-8');
  228 +// }
  229 +// $v['to_name'] = @json_decode($v['to_name'],true);
  230 +// $v['to_name'] = $v['to_name']?:[];
  231 +// if($v['to_name']){
  232 +// if(!empty($v['to_name'][0]['email'])){
  233 +// $v['to'] = $v['to_name'][0]['email'];
  234 +// }
  235 +// $v['to_name'] = MailFun::mb_coding($v['to_name'][0]['name']??'');
  236 +// }
  237 +// if(is_array($v['to_name'])){
  238 +// $v['to_name'] = '';
  239 +// }
  240 +// return $v;
  241 +// },$lists?:[]);
  242 +
  243 +
  244 +
  245 +// app()->_json(listsPage($lists,$total,$page,$limit));
  246 +
  247 + }
  248 +
  249 +
  250 +
  251 + private function assignSql($folder){
  252 + // 被分配的
  253 + $assign = app()->request('assign');
  254 + $query = [];
  255 + $fids = [];
  256 + if(!empty($assign['email_id'])){
  257 + // 此处请求中的
  258 + $email = array_values(array_intersect($assign['email_id'],$this->getEmails('id')));
  259 + if($email){
  260 + $fids = $this->getFolderId($folder,$email);
  261 + // 有目录id和from
  262 + if($fids && !empty($assign['from'])){
  263 + if($folder=='发件箱'){
  264 + $query = [
  265 + 'query' =>[
  266 + 'bool' => [
  267 + 'must' => [
  268 + ['terms'=>['folder_id'=>$fids]],
  269 + ['query_string'=>[
  270 + 'query'=> implode(' ',$assign['from']),
  271 + 'default_field'=>'to'
  272 + ]]
  273 + ]
  274 + ]
  275 + ]
  276 + ];
  277 + }else{
  278 + $query = [
  279 + 'query' =>[
  280 + 'bool' => [
  281 + 'must' => [
  282 + ['terms'=>['folder_id'=>$fids]],
  283 + ['terms'=>['from.email'=>$assign['from']]],
  284 + ]
  285 + ]
  286 + ]
  287 + ];
  288 + }
  289 + }
  290 + }
  291 +
  292 + // 返回 不在assign中的目录
  293 + $afids = array_values(array_diff($this->getFolderId($folder),$fids));
  294 +
  295 + if($query && $afids){
  296 + $query = [
  297 + 'query' =>[
  298 + 'bool' => [
  299 + 'must' => [
  300 + $query
  301 + ],
  302 + 'should' =>[
  303 + ['terms'=>['folder_id'=>$afids]]
  304 + ]
  305 + ]
  306 + ]
  307 + ];
  308 + }else if($afids){
  309 + return [
  310 + 'query' =>[
  311 + 'bool' => [
  312 + 'must' =>[
  313 + ['terms'=>['folder_id'=>$afids]]
  314 + ]
  315 + ]
  316 + ]
  317 + ];
  318 + }else if($query&&!$afids){
  319 + return $query;
  320 + }
  321 + return ['term'=>['folder_id'=> -1]];
  322 +
  323 + }
  324 +
  325 + return ['terms'=>['folder_id'=> $this->getFolderId($folder)]];
  326 +
  327 + }
  328 + private function assignSql2(){
  329 + // 被分配的
  330 + $assign = app()->request('assign');
  331 + $sql = '';
  332 + $query = [];
  333 + if(!empty($assign['email_id'])){
  334 + // 分配的联系人
  335 + $email = array_values(array_intersect($assign['email_id'],$this->getEmails('id')));
  336 + if($email&&!empty($assign['from'])){
  337 + $query['must'] = [
  338 + ['terms'=>['email_id'=>$email]]
  339 + ];
  340 + $query['must'][] = [
  341 + 'query'=>[
  342 + 'bool'=>[
  343 + 'must'=>[
  344 + ['terms'=>['from.email'=>$assign['from']]]
  345 + ],
  346 + 'should'=>[
  347 + "query_string" =>[
  348 + "query" => implode(' ',$assign['from']),
  349 + 'default_field' => 'to'
  350 + ]
  351 + ]
  352 + ]
  353 + ]
  354 + ];
  355 + }
  356 +
  357 + // 分配的邮箱
  358 + $email2 = array_diff($this->getEmails('id'),$assign['email_id']);
  359 + if($email2){
  360 + if($query){
  361 + $query['must'][] = [
  362 + 'query'=>[
  363 + 'bool'=>[
  364 + 'must'=>[
  365 + $query
  366 + ],
  367 + 'should'=>[
  368 + ['terms'=>['email_id'=>$email2]]
  369 + ]
  370 + ]
  371 + ]
  372 + ];
  373 + return ['query'=>[
  374 + 'bool'=> $query
  375 + ]];
  376 + }
  377 +
  378 + return ['query'=>[
  379 + 'bool'=> [
  380 + 'must'=>[
  381 + ['terms'=>['email_id'=>$email2]]
  382 + ]
  383 + ]
  384 + ]];
  385 + }
  386 +
  387 + if($sql){
  388 + return ['query'=>[
  389 + 'bool'=> $query
  390 + ]];
  391 + }
  392 +
  393 +
  394 + return [
  395 + 'query'=>[
  396 + 'bool'=> [
  397 + 'must'=>[['term'=>['email_id'=>-1]]]
  398 + ]
  399 + ]
  400 + ];
  401 + }
  402 +
  403 + // 默认
  404 + return dbWhere(['email_id'=>$this->getEmails('id')]).' and ';
  405 +
  406 + }
  407 + private function assignSql3($folder){
  408 + // 被分配的
  409 + $assign = app()->request('assign');
  410 + $sql = '';
  411 + $fids = [];
  412 + if(!empty($assign['email_id'])){
  413 + // 此处请求中的
  414 + $email = array_diff($this->getEmails('id'),$assign['email_id']);
  415 + if($email){
  416 + $fids = $this->getFolderId($folder,$email);
  417 + // 有目录id和from
  418 + if($fids){
  419 + return dbWhere(['folder_id'=>$fids]).' and ';
  420 + }
  421 + }
  422 +
  423 +
  424 + return '`folder_id` = -1 and ';
  425 +
  426 + }
  427 +
  428 + return dbWhere(['folder_id'=>$this->getFolderId($folder)]).' and ';
  429 +
  430 + }
  431 +
  432 +
  433 +
  434 + public function count(){
  435 + return [];
  436 + }
  437 +
  438 +
  439 +}
  440 +
  441 +
  442 +
  443 +
  444 +
  445 +
  446 +
  447 +
  448 +
  449 +
  450 +
  451 +
  452 +
  453 +
@@ -55,7 +55,7 @@ class Es { @@ -55,7 +55,7 @@ class Es {
55 * @param array $body 55 * @param array $body
56 * @param int $from 56 * @param int $from
57 * @param int $size 57 * @param int $size
58 - * @param array $sort 58 + * @param array $sort [key=>val,...]
59 * @return array 59 * @return array
60 * @author:dc 60 * @author:dc
61 * @time 2023/6/5 14:35 61 * @time 2023/6/5 14:35
@@ -66,14 +66,17 @@ class Es { @@ -66,14 +66,17 @@ class Es {
66 'index' => $this->getIndex(), 66 'index' => $this->getIndex(),
67 'body' => $body, 67 'body' => $body,
68 'from' => $from, 68 'from' => $from,
69 - 'size' => $size 69 + 'size' => $size,
  70 + "track_total_hits"=> true // 确保返回总匹配文档数量
70 ]; 71 ];
71 // 排序 72 // 排序
72 if($sort){ 73 if($sort){
73 - $params['sort'] = $sort; 74 + if(empty($params['body']['sort'])) $params['body']['sort'] = [];
  75 + foreach ($sort as $k=>$s){
  76 + $params['body']['sort'][] = [ $k => [ 'order' => $s ] ];
  77 + }
74 } 78 }
75 79
76 -  
77 try { 80 try {
78 $response = $this->client->search($params); 81 $response = $this->client->search($params);
79 }catch (\Throwable $e) { 82 }catch (\Throwable $e) {
@@ -85,6 +88,16 @@ class Es { @@ -85,6 +88,16 @@ class Es {
85 88
86 } 89 }
87 90
  91 + /**
  92 + * 统计数量
  93 + * @param array $param
  94 + * @author:dc
  95 + * @time 2025/3/4 9:47
  96 + */
  97 + public function count(array $param){
  98 +
  99 + }
  100 +
88 101
89 /** 102 /**
90 * @param array $param 103 * @param array $param
@@ -219,7 +232,7 @@ class Es { @@ -219,7 +232,7 @@ class Es {
219 } 232 }
220 233
221 234
222 - return $response; 235 + return $response->asArray();
223 236
224 237
225 } 238 }
@@ -281,18 +294,6 @@ class Es { @@ -281,18 +294,6 @@ class Es {
281 return $response[$this->getIndex()]['mappings']['properties']??[]; 294 return $response[$this->getIndex()]['mappings']['properties']??[];
282 } 295 }
283 296
284 - /**  
285 - * 判断是否存在索引  
286 - * @return bool  
287 - * @author:dc  
288 - * @time 2023/6/29 12:37  
289 - */  
290 - public function hasIndex(){  
291 - $params['index'] = $this->getIndex();  
292 - $response = $this->client->indices()->exists($params);  
293 - return $response;  
294 - }  
295 -  
296 297
297 298
298 } 299 }
@@ -22,6 +22,12 @@ return [ @@ -22,6 +22,12 @@ return [
22 22
23 'fob/v2/lists' => [\Controller\fob_ai\MailListV2::class, 'lists'], 23 'fob/v2/lists' => [\Controller\fob_ai\MailListV2::class, 'lists'],
24 'fob/v2/count' => [\Controller\fob_ai\MailListV2::class, 'count'],// 统计数量 24 'fob/v2/count' => [\Controller\fob_ai\MailListV2::class, 'count'],// 统计数量
  25 + // 查询es的
  26 + 'fob/es/lists' => [\Controller\fob_ai\MailListV2Es::class, 'lists'],
  27 + 'fob/es/count' => [\Controller\fob_ai\MailListV2Es::class, 'count'],// 统计数量
  28 +
  29 +
  30 +
25 31
26 // 邮件详情 32 // 邮件详情
27 'info' => [\Controller\Home::class, 'info'], 33 'info' => [\Controller\Home::class, 'info'],