From 9878dcc914931cdeb6213c1c840546d21cc0581b Mon Sep 17 00:00:00 2001 From: chengxl0318 <1172937051@qq.com> Date: Thu, 27 Mar 2025 11:22:57 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=96=87=E7=AB=A0=E5=AE=A1=E6=A0=B8?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5OPENAI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/api/controller/Aireview.php | 207 ++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 application/api/controller/Aireview.php diff --git a/application/api/controller/Aireview.php b/application/api/controller/Aireview.php new file mode 100644 index 0000000..f147d3b --- /dev/null +++ b/application/api/controller/Aireview.php @@ -0,0 +1,207 @@ +sApiKey = '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'; + $this->proxy = ''; + $this->sUrl = 'https://api.openai.com/v1/chat/completions'; + + parent::__construct($request); + } + + /** + * CURL 发送请求到 OpenAI + * @param $messages 内容 + * @param $model 模型类型 + */ + protected function curlOpenAI($messages, $model = 'gpt-4o'){ + + $sUrl = $this->sUrl; + + $data = [ + 'model' => $model, + 'messages' => $messages, + 'temperature' => 0.7 + ]; + + $this->curl = curl_init(); + + + // 通用配置 + curl_setopt($this->curl, CURLOPT_URL, $sUrl); + // 设置头信息 + curl_setopt($this->curl, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'Authorization: Bearer ' . $this->sApiKey + ]); + curl_setopt($this->curl, CURLOPT_PROXY,$this->proxy); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,true); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,2); + curl_setopt($this->curl, CURLOPT_POST, true); //设置为POST方式 + curl_setopt($this->curl, CURLOPT_POSTFIELDS,json_encode($data)); + curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE) ; // 获取数据返回 + // curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout); + + $result = curl_exec($this->curl); + + //请求失败 + if (curl_errno($this->curl)){ + $this->sError = curl_errno($this->curl); + curl_close($this->curl); + return FALSE; + } + $this->sResponesData = json_decode($result); + curl_close($this->curl); + return TRUE; + } + + /** + * @title AI审核文章 + * @param article_id 文章ID + * @param abstrart 摘要 + * @param keywords 关键词 + * @param model 接口模型 + * @param stream 是否流式输出 true是false否 + */ + public function review(){ + + + //获取参数 + $aParam = $this->request->post(); + if(empty($aParam['article_id'])){ + exit(json_encode(array('status' => 2,'msg' => 'Please select an article' ))); + } + if(empty($aParam['abstrart'])){ + exit(json_encode(array('status' => 2,'msg' => 'abstrart cannot be empty' ))); + } + if(empty($aParam['keywords'])){ + exit(json_encode(array('status' => 2,'msg' => 'keywords cannot be empty' ))); + } + + //查询文章 + $aArticle = Db::table('t_article')->field('article_id,abstrart,keywords,journal_id')->where('article_id',$aParam['article_id'])->find(); + if(empty($aArticle)){ + exit(json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ))); + } + + //根据期刊ID查询期刊信息 + $aJournal = Db::table('t_journal')->field('zname')->where('journal_id',$aArticle['journal_id'])->find(); + if(empty($aJournal)){ + exit(json_encode(array('status' => 4,'msg' => 'This article is not associated with a journal' ))); + } + //组织参数 + $sContent = ''; + $sContent .= '摘要:'.$aParam['abstrart']; + $sContent .= '关键词:'.$aParam['keywords']; + $sContent .= '以上这篇文章是否符合'.$aJournal['zname'].'?是否具有科学前沿性和创新性?'; + $messages = [ + [ + 'role' => 'user', //角色:platform:平台;developer:开发者;user:用户;guideline:模型规范“指南”部分:连接:https://model-spec.openai.com/2025-02-12.html#chain_of_command + 'content' => $sContent + ] + ]; + //请求接口 + $sModel = $aParam['api_model'] ?? 'gpt-4o'; + $result = $this->curlOpenAI($messages,$sModel); + if($result == FALSE){ + exit(json_encode(array('status' => 4,'msg' => 'Interface request failed'.$this->sError))); + } + + //处理返回信息 + $data = $this->sResponesData; + if(!is_object($data)){ + exit(json_encode(array('status' => 5,'msg' => 'There is a misunderstanding in the data returned by the interface'))); + } + $data = object_to_array($data); + $aChoices = $data['choices'] ?? []; + if(empty($aChoices)){ + exit(json_encode(array('status' => 6,'msg' => 'OPENAI did not return data'))); + } + $aChoicesInfo = $aChoices[0] ?? []; + $aMessage = $aChoicesInfo['message'] ?? []; + if(empty($aMessage['content'])){ + exit(json_encode(array('status' => 7,'msg' => 'OPENAI returns empty data'))); + } + + //执行数据入库 + $param = []; + $param['content'] = addslashes($aMessage['content']); + $param['article_id'] = $aParam['article_id']; + $aResult = $this->addAiReview($param); + exit(json_encode($aResult)); + + + } + + /** + * @title AI审核内容入库 + * @param article_id 文章ID + * @param content 内容 + */ + protected function addAiReview($aParam = array()){ + + //返回数组 + $aResult = ['status' => 1,'msg' => 'AI review successful']; + //必填参数验证 + $aFields = ['article_id','content']; + $bStatus = true; + foreach($aFields as $val){ + if(empty($aParam[$val])){ + $aResult = ['status' => 2,'msg' => $val.'cannot be empty']; + $bStatus = false; + break; + } + } + if($bStatus == false){ + return $aResult; + } + //执行入库 + $aParam['create_time'] = date('Y-m-d H:i:s'); + if(!Db::name('article_ai_review')->insert($aParam)){ + $aResult = ['status' => 2,'msg' => 'Failed to add AI audit content']; + } + return $aResult; + } + + /** + * @title 文章AI审核内容查询 + * @param article_id 文章ID + */ + public function get(){ + + //获取参数 + $aParam = $this->request->post(); + if(empty($aParam['article_id'])){ + exit(json_encode(array('status' => 2,'msg' => 'Please select an article' ))); + } + + //查询文章 + $aArticle = Db::table('t_article')->field('article_id')->where('article_id',$aParam['article_id'])->find(); + if(empty($aArticle)){ + exit(json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ))); + } + //查询文章审核内容 + $aAiReview = Db::table('t_article_ai_review')->field('content')->where('article_id',$aParam['article_id'])->find(); + exit(json_encode(array('status' => 1,'msg' => 'Successfully obtained article review content','data' => $aAiReview))); + } +} From 0aa18858c8d83cd6117b903e4877b1b32dcb2f59 Mon Sep 17 00:00:00 2001 From: chengxl0318 <1172937051@qq.com> Date: Fri, 28 Mar 2025 14:59:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=91=98=E8=A6=81=E5=8A=A0=E5=AD=97=E6=95=B0=E6=9C=80=E4=BD=8E?= =?UTF-8?q?=E9=99=90=E5=88=B6200=EF=BC=8C=E6=96=87=E7=AB=A0=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=96=B0=E5=A2=9E=E5=AD=97=E6=AE=B5ai=E5=AE=A1?= =?UTF-8?q?=E6=A0=B8=E5=86=85=E5=AE=B9=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/api/controller/Article.php | 40 +++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/application/api/controller/Article.php b/application/api/controller/Article.php index b125bfa..140715d 100644 --- a/application/api/controller/Article.php +++ b/application/api/controller/Article.php @@ -106,6 +106,13 @@ class Article extends Base ->limit($limit_start, $data['pageSize'])->select(); $count = $this->article_obj->where($where)->count(); + //查询AI审核内容 chengxiaoling 20250328 start + $aAiReview = array(); + if(!empty($res)){ + $aArticleId = array_column($res, 'article_id'); + $aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->whereIn('article_id',$aArticleId)->column('article_id,content'); + } + //查询AI审核内容 chengxiaoling 20250328 end foreach ($res as $key => $val) { //查询建议转投详情 @@ -131,6 +138,10 @@ class Article extends Base } } $res[$key]['proof'] = $proof_state; + + //返回AI审核内容 chengxiaoling 20250328 start + $res[$key]['ai_review'] = empty($aAiReview[$val['article_id']]) ? '' : $aAiReview[$val['article_id']]; + //返回AI审核内容 chengxiaoling 20250328 end } //返回数据 @@ -613,6 +624,13 @@ class Article extends Base $user_res = $this->user_obj->where(['account' => $username])->find(); $article_old_info = $this->article_obj->where('article_id', $data['articleId'])->find(); + + //判断简介字符串长度是否不低于200 chengxiaoling 20250327 start + if(!$this->checkMinChars($data['abstrart'],200)){ + return jsonError("The abstract should not be less than 200 Chinese characters or English words!"); + } + //判断简介字符串长度是否不低于200 chengxiaoling 20250327 end + Db::startTrans(); //更新文章信息 @@ -2482,7 +2500,6 @@ class Article extends Base //接受参数,查询信息 $data = $this->request->post(); - $user_res = $this->user_obj->where('account', $data['username'])->find(); //确定用户是否属于黑名单 @@ -2916,6 +2933,12 @@ class Article extends Base if (!$rule->check($data)) { return jsonError($rule->getError()); } + //判断简介字符串长度是否不低于200 chengxiaoling 20250327 start + if(!$this->checkMinChars($data['abstrart'],200)){ + return jsonError("The abstract should not be less than 200 Chinese characters or English words!"); + } + //判断简介字符串长度是否不低于200 chengxiaoling 20250327 end + $user_info = $this->user_obj->where('user_id', $data['user_id'])->find(); $journal_info = $this->journal_obj->where('journal_id', $data['journal'])->find(); @@ -4254,4 +4277,19 @@ class Article extends Base $this->user_msg_obj->where("user_id", $data['editor_id'])->update(["state" => 1]); return jsonSuccess([]); } + + /** + * 验证字符长度 + * @param $str 字符串 + * @param $num 字符长度 + * @return void + */ + private function checkMinChars($str = '',$num = 200) { + // 过滤非汉字和英文的字符(保留汉字、大小写字母) + $filteredStr = preg_replace('/[^\x{4e00}-\x{9fa5}a-zA-Z0-9]/u', '', $str); + + // 计算有效字符总数(汉字按1个字符计,英文和数字同理) + $total = mb_strlen($filteredStr, 'UTF-8'); + return $total >= $num; + } } From 797d8fc5c43add015ed20cdbdda2bc7441a0c2c6 Mon Sep 17 00:00:00 2001 From: chengxl0318 <1172937051@qq.com> Date: Fri, 28 Mar 2025 15:30:26 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E7=BC=96=E8=BE=91=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E7=AB=A0=E5=88=97=E8=A1=A8=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AD=97=E6=AE=B5ai=E5=AE=A1=E6=A0=B8=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/api/controller/Article.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/application/api/controller/Article.php b/application/api/controller/Article.php index 140715d..2785191 100644 --- a/application/api/controller/Article.php +++ b/application/api/controller/Article.php @@ -106,14 +106,6 @@ class Article extends Base ->limit($limit_start, $data['pageSize'])->select(); $count = $this->article_obj->where($where)->count(); - //查询AI审核内容 chengxiaoling 20250328 start - $aAiReview = array(); - if(!empty($res)){ - $aArticleId = array_column($res, 'article_id'); - $aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->whereIn('article_id',$aArticleId)->column('article_id,content'); - } - //查询AI审核内容 chengxiaoling 20250328 end - foreach ($res as $key => $val) { //查询建议转投详情 $transfer_info = $this->article_transfer_obj @@ -138,10 +130,6 @@ class Article extends Base } } $res[$key]['proof'] = $proof_state; - - //返回AI审核内容 chengxiaoling 20250328 start - $res[$key]['ai_review'] = empty($aAiReview[$val['article_id']]) ? '' : $aAiReview[$val['article_id']]; - //返回AI审核内容 chengxiaoling 20250328 end } //返回数据 @@ -354,6 +342,15 @@ class Article extends Base ->order('t_article.article_id desc') ->limit($limit_start, $data['pageSize']) ->select(); + + //查询AI审核内容 chengxiaoling 20250328 start + $aAiReview = array(); + if(!empty($res)){ + $aArticleId = array_column($res, 'article_id'); + $aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->whereIn('article_id',$aArticleId)->column('article_id,content'); + } + //查询AI审核内容 chengxiaoling 20250328 end + //增加审稿意见信息 foreach ($res as $key => $val) { $cache_review = $this->article_reviewer_obj @@ -391,6 +388,10 @@ class Article extends Base $file_frag[$v['type_name']][] = $v; } $res[$key]['file'] = $file_frag; + + //返回AI审核内容 chengxiaoling 20250328 start + $res[$key]['ai_review'] = empty($aAiReview[$val['article_id']]) ? '' : $aAiReview[$val['article_id']]; + //返回AI审核内容 chengxiaoling 20250328 end } //添加国家信息 From 319c545ae686fefa31582371f9d25c58f84e08fe Mon Sep 17 00:00:00 2001 From: chengxl0318 <1172937051@qq.com> Date: Fri, 28 Mar 2025 16:15:11 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=AF=B7=E6=B1=82AI=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E6=9C=89=E5=B0=B1=E8=BF=94=E5=9B=9E=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/api/controller/Aireview.php | 50 +++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/application/api/controller/Aireview.php b/application/api/controller/Aireview.php index f147d3b..4ff963e 100644 --- a/application/api/controller/Aireview.php +++ b/application/api/controller/Aireview.php @@ -91,12 +91,12 @@ class Aireview extends Base if(empty($aParam['article_id'])){ exit(json_encode(array('status' => 2,'msg' => 'Please select an article' ))); } - if(empty($aParam['abstrart'])){ - exit(json_encode(array('status' => 2,'msg' => 'abstrart cannot be empty' ))); - } - if(empty($aParam['keywords'])){ - exit(json_encode(array('status' => 2,'msg' => 'keywords cannot be empty' ))); - } + // if(empty($aParam['abstrart'])){ + // exit(json_encode(array('status' => 2,'msg' => 'abstrart cannot be empty' ))); + // } + // if(empty($aParam['keywords'])){ + // exit(json_encode(array('status' => 2,'msg' => 'keywords cannot be empty' ))); + // } //查询文章 $aArticle = Db::table('t_article')->field('article_id,abstrart,keywords,journal_id')->where('article_id',$aParam['article_id'])->find(); @@ -104,6 +104,16 @@ class Aireview extends Base exit(json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ))); } + //获取文章评测内容 + $aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->where('article_id',$aParam['article_id'])->find(); + if(!empty($aAiReview)){ + exit(json_encode(array('status' => 1,'msg' => 'AI has been reviewed','data' => $aAiReview))); + } + + $aParam['abstrart'] = empty($aParam['abstrart']) ? $aArticle['abstrart'] : $aParam['abstrart'];//简介 + $aParam['keywords'] = empty($aParam['keywords']) ? $aArticle['keywords'] : $aParam['keywords'];//关键词 + + //根据期刊ID查询期刊信息 $aJournal = Db::table('t_journal')->field('zname')->where('journal_id',$aArticle['journal_id'])->find(); if(empty($aJournal)){ @@ -161,7 +171,7 @@ class Aireview extends Base protected function addAiReview($aParam = array()){ //返回数组 - $aResult = ['status' => 1,'msg' => 'AI review successful']; + $aResult = ['status' => 1,'msg' => 'AI review successful','data' => $aParam]; //必填参数验证 $aFields = ['article_id','content']; $bStatus = true; @@ -204,4 +214,30 @@ class Aireview extends Base $aAiReview = Db::table('t_article_ai_review')->field('content')->where('article_id',$aParam['article_id'])->find(); exit(json_encode(array('status' => 1,'msg' => 'Successfully obtained article review content','data' => $aAiReview))); } + + public function test(){ + //获取参数 + $aParam = $this->request->post(); + if(empty($aParam['content'])){ + exit(json_encode(array('status' => 2,'msg' => '请输入需要验证的字符串' ))); + } + if(!$this->checkMinChars($aParam['content'],200)){ + exit(json_encode(array('status' => 3,'msg' => '字符串长度未满足配置' ))); + } + exit(json_encode(array('status' => 1,'msg' => '验证成功' ))); + } + /** + * 验证字符长度 + * @param $str 字符串 + * @param $num 字符长度 + * @return void + */ + private function checkMinChars($str = '',$num = 200) { + // 过滤非汉字和英文的字符(保留汉字、大小写字母) + $filteredStr = preg_replace('/[^\x{4e00}-\x{9fa5}a-zA-Z0-9]/u', '', $str); + + // 计算有效字符总数(汉字按1个字符计,英文和数字同理) + $total = mb_strlen($filteredStr, 'UTF-8'); + return $total >= $num; + } }