getHook();
parent::initialize();
}
public static function getHook()
{
//需要使用静态方法Facade 不然会报错
\think\Facade\Hook::listen('response_send');
}
/*
* 业务控制器
* 上传csv关键词数据
* https://console.zx2049.com/api/ai/uploadCsv?file=20240504/eebcb4ca6a8a69fdd9e0f60c16b55746.csv
*/
public function uploadCsv(){
//测试
$url = request()->get('file',0);
if($url !== 0){
$this->csvHandle('./uploads/'.$url);
return json([]);
}
$file = request()->file('file'); //$file = $_FILES['file'];
$info = $file->move( './uploads');
if($info){
// 成功上传后 获取上传信息
// 输出 jpg
//$url = $info->getExtension();
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
$url = $info->getSaveName();
// 输出 42a79759f284b767dfcb2a0197904287.jpg
//echo $info->getFilename();
$data = ['code' => 0, 'msg' => '文件上传成功', 'data' =>['src'=>$url]];
}else{
// 上传失败获取错误信息
$info = $file->getError();
$data = ['code' => 1, 'msg' => '文件上传失败', 'data' =>$info];
}
return json($data);
}
/*
* 业务控制器
* 处理表单
*/
public function uploadCsvFrom(){
$post = request()->post();
/*
* rule:
0
title:
建筑职称
file:
url:
20240505/2aff80b14c861480183278bbc9442f56.csv
*/
//判断关键词是否存在
$one = Db::name('options')->where('title','=',$post['title'])->where('status','=',1)->find();
if(empty($one)){
$data = ['code' => 1, 'msg' => '关键词不存在', 'data' => []];
return json($data);
}
if(!empty($post['url'])){
$this->csvHandle('./uploads/'.$post['url'],$post['rule'],$post['title']);
$data = ['code' => 0, 'msg' => '提交成功', 'data' =>$post];
}else{
$data = ['code' => 1, 'msg' => '提交失败', 'data' => []];
}
return json($data);
}
/*
* 逻辑控制器
* 规则的指令集和创意 如果为空 调用全局的即可 同样优先调用自身规则
*/
public function csvHandle($url,$rule,$title){
// 读取CSV文件
$filename = $url;
if (file_exists($filename)) {
$file = fopen($filename, 'r');
//任务批次
$task_no = date('YmdHis',time()).'-'.rand(1,10000);
$pid = time(); //不考虑并发提交多次间隔也是秒级
$num = 1;
$log_content = '';
$log_content_error = '';
$s_num = 0;
$f_num = 0;
while (($line = fgetcsv($file)) !== FALSE) {
// $line是一个数组,包含CSV的一行数据
//print_r($line);
if($num === 1){
$row = $line;
}else{
if(!empty($line[0])) {
//关键词步骤省略 需要去站长之家搜索并导出 这个步骤由人工操作
//判断是否存在短标题 重复性检测
//相同规则 短标题只能存在一个
$one = Db::name('cms_zl')
->where('title', '=', $line[0])
->where('catid', '=', 18)
->where('gzxh', '=', $rule)
->find();
if (empty($one)) {
//过滤标题是否合法的函数 这个可以用定时任务处理
[$is_use, $desc, $rule_id] = $this->titleHandle($line[0], $rule, $title);
//构建详情
$html = '';
for ($i = 1; $i < 10; $i++) {
$html .= $row[$i] . ':' . $line[$i] . '
';
}
$data = [
'catid' => 18, //短标题
'title' => $line[0], //短标题
'content' => $html,
'create_time' => time(),
'update_time' => time(),
'status' => 0, //默认禁用状态 定时手动开启 自动化再读取即可
'pid' => $pid, //关联日志的aid,可查询到规则序号 主词 文件地址 执行情况
'ptlx' => 0,
'is_use' => $is_use, //是否合法
'desc' => $desc, //非法原因 或者 合法匹配结果
'gzxh' => $rule,
'is_use_id' => (int)$rule_id, //写入具体规则id 可查询到对应规则是什么 判断是否合法
];
//dump($data);
//插入记录
$doc_id = Db::name('cms_zl')->insertGetId($data);
//写入日志
$log_content .= '指令id-' . $doc_id . '-' . json_encode($line, JSON_UNESCAPED_UNICODE) . '
';
$s_num++;
} else {
//写日志
$log_content_error .= '
短标题-' . $line[0] . '-已存在-指令短标题id:' . $one['id'] . '
'; $f_num++; } } } $num++; } //每次操作 1-2条 日志记录 if(!empty($log_content)){ Db::name('log')->insert([ 'catid' => 27, 'title' => '批次'.$task_no.'成功导入处理-'.$s_num.'条数据', 'keywords' => $title, //主词 'description' => $filename,//对应文件地址 'create_time' => time(), 'update_time' => time(), 'status' => 1, 'site_id'=> 1, 'cid' => (int)$rule, //规则序号 'aid' => $pid, //对应记录id 'content' => ''.$log_content.'
', ]); } if(!empty($log_content_error)){ Db::name('log')->insert([ 'catid' => 27, 'title' => '批次'.$task_no.'导入处理已存在-'.$f_num.'条数据', 'keywords' => $title, //主词 'description' => $filename,//对应文件地址 'create_time' => time(), 'update_time' => time(), 'status' => 1, 'site_id'=> 1, 'cid' => (int)$rule, //规则序号 'aid' => $pid, //对应记录id 'content' => ''.$log_content_error.'
', ]); } fclose($file); } /*// 写入CSV文件 $data = [ ['Name', 'Age', 'Email'], ['Alice', 25, 'alice@example.com'], ['Bob', 30, 'bob@example.com'] ]; $filename = 'output.csv'; $file = fopen($filename, 'w'); foreach ($data as $row) { fputcsv($file, $row); } fclose($file);*/ } /* * 模型控制器 操作数据 */ /* * 处理函数 * $title 主词 */ public function titleHandle($line,$rule,$title){ //规则1 $desc = ''; //是否完全匹配主词 if (strpos($line, $title) !== false) { //包含主词 }else{ return [0,'短标题不包含主词['.$title.']',0]; } //1.查询是否存在主词规则 $one = Db::name('cms_zl') ->where('catid','=',17) ->where('title','=',$title) //只能一条 已做标题重复校验 ->where('is_qj','=',0) //非全局 ->where('zllx','=',1) //指令类型是 主词 ->where('gzxh','=',$rule) ->where('status','=',1) //多条需要控制开关 ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条 ->find(); //2.查询全局主词规则 if(empty($one)){ $one = Db::name('cms_zl') ->where('catid','=',17) ->where('title','=','全局-主词类型') //只能一条 已做标题重复校验 ->where('is_qj','=',1) //是全局 ->where('zllx','=',1) //指令类型是 主词 ->where('gzxh','=',$rule) ->where('status','=',1) //多条需要控制开关 ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条 ->find(); } //3.查询全局规则 if(empty($one)){ $one = Db::name('cms_zl') ->where('catid','=',17) ->where('title','=','全局-非主非副') //只能一条 已做标题重复校验 ->where('is_qj','=',1) //是全局 ->where('zllx','=',0) //指令类型是 非主非副 ->where('gzxh','=',$rule) ->where('status','=',1) //多条需要控制开关 ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条 ->find(); } if(empty($one)){ return [0,'不存在全局通用规则,全局主词规则,当前主词规则',0]; } //4.获取到全局或主词的副词 $two = []; if(empty($one['fclb']) || (string)$one['fclb'] === '0'){ //不存在副词规则 $desc .= '不存在副词规则-|-'; }else{ //存在副词规则 $one['fclb'] = $one['fclb'].','; $fclb = explode(',',$one['fclb']); $line_sor = str_replace($title, "", $line); //短标题去除主词 $is_bh = 0; $fc = ''; $fc_num = 0; foreach ($fclb as $k => $v) { //该判断 主词和副词 不一定是连在一起的 if(!empty($v)) { if (strpos($line_sor, $v) !== false) { //包含 $is_bh = 1; $fc = $v; //break; //跳出 目前只匹配一个 存在多个不做处理 以第一个为主 $fc_num++; } } } //存在多个副词 不合理 if($fc_num > 1){ return [0,'存在多个副词,不合法',$one['id']]; } //5.查询是否存在副词 if($is_bh === 1){ //6.查询主词+副词是否存在规则 $two = Db::name('cms_zl') ->where('catid','=',17) ->where('title','=',$title.$fc) //查询设置 按照主词+副词 格式查询 //只能一条 已做标题重复校验 ->where('is_qj','=',0) //非全局 ->where('zllx','=',2) //指令类型是 副词 ->where('gzxh','=',$rule) ->where('status','=',1) //多条需要控制开关 ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条 ->find(); //7.查询副词通用全局规则 if(empty($two)){ $two = Db::name('cms_zl') ->where('catid','=',17) ->where('title','=','全局-副词类型') //查询设置 按照主词+副词 格式查询 //只能一条 已做标题重复校验 ->where('is_qj','=',1) //非全局 ->where('zllx','=',2) //指令类型是 副词 ->where('gzxh','=',$rule) ->where('status','=',1) //多条需要控制开关 ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条 ->find(); } }else{ //短标题不包含副词 $desc .= '短标题不包含副词-|-'; } } //短标题的主词和副词 不一定是连在一起的 if(!empty($two)){ //存在副词规则 按照此规则执行 $data = $two; }else{ //按照$one规则记录执行 $data = $one; } //8.判断是否合法 地区词 [$is_bh,$fc] = $this->isInRule($data['dqc'],$line); if($is_bh > 0){ $desc .= '存在地区词'.$fc.',不合法-|-'; return [0,$desc,$data['id']]; } //9.判断是否合法 分类词 [$is_bh,$fc] = $this->isInRule($data['flc'],$line); if($is_bh > 0){ $desc .= '存在分类词'.$fc.',不合法-|-'; return [0,$desc,$data['id']]; } //10.判断是否合法 时间词 [$is_bh,$fc] = $this->isInRule($data['sjc'],$line); if($is_bh > 0){ $desc .= '存在时间词'.$fc.',不合法-|-'; return [0,$desc,$data['id']]; } //11.判断是否合法 屏蔽词 [$is_bh,$fc] = $this->isInRule($data['pbc'],$line); if($is_bh > 0){ $desc .= '存在屏蔽词'.$fc.',不合法-|-'; return [0,$desc,$data['id']]; } //12.判断是否合法 同时存在触发词和并发词 [$is_bh1,$fc1] = $this->isInRule($data['cfc'],$line); [$is_bh2,$fc2] = $this->isInRule($data['bfc'],$line); if($is_bh1 > 0 && $is_bh2 > 0){ //同时存在 $desc .= '同时存在并发词['.$fc2.']和触发词['.$fc1.']合法'; return [1,$desc,$data['id']]; }else{ $desc .= '不同时存在并发词['.$fc2.']和触发词['.$fc1.'],不合法'; return [0,$desc,$data['id']]; } } /* * 规则设定 */ public function setRule(){ //方案1: 定义config配置文件 //方案2: 直接代码写死 //方案3: 后台设置 -- 采用这个 $json = [ '' ]; } /* * 函数 是否包含 */ public function isInRule($data,$str){ $data = $data.','; $data = explode(',',$data); $is_bh = 0; $fc = ''; foreach ($data as $k => $v) { //该判断 主词和副词 不一定是连在一起的 if(!empty($v)) { if (strpos($str, $v) !== false) { //包含 $is_bh = 1; $fc = $v; break; //跳出 目前只匹配一个 存在多个不做处理 以第一个为主 } } } return [$is_bh,$fc]; } /* * 导出csv * http://console.zx2049.com/api/ai/exportCsv */ public function exportCsv(){ $list = Db::name('cms_zl')->field('id,title,desc')->where('catid','=',18)->select(); /* $data = [ ['Name', 'Age', 'Email'], ['Alice', 25, 'alice@example.com'], ['Bob', 30, 'bob@example.com'] ];*/ $filename = 'output.csv'; $file = fopen($filename, 'w'); foreach ($list as $row) { fputcsv($file, $row); } fclose($file); } }