作者 lyh
... ... @@ -83,7 +83,7 @@ class HtmlCollect extends Command
//采集html页面,下载资源到本地并替换
try {
$html = curl_c('https://' . $collect_info->domain . $collect_info->route, false);
if ($html == '0' || strpos($html,'404 Not Found') !== false) {
if ($html == '0' || strpos($html, '404 Not Found') !== false) {
$collect_info->status = CollectTask::STATUS_FAIL;
$collect_info->save();
... ... @@ -138,7 +138,7 @@ class HtmlCollect extends Command
}
$update_log = UpdateLog::whereNotIn('project_id', [555, 626])->where('status', UpdateLog::STATUS_COM)->where('collect_status', UpdateLog::COLLECT_STATUS_UN)->orderBy('project_id', 'asc')->first();
$update_log = UpdateLog::where('status', UpdateLog::STATUS_COM)->where('collect_status', UpdateLog::COLLECT_STATUS_UN)->orderBy('project_id', 'asc')->first();
if (!$update_log) {
return false;
}
... ... @@ -286,7 +286,7 @@ class HtmlCollect extends Command
return [
'download' => true,
'url' => $url,
'url_complete' => ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path . ($query ? '?' . $query : '')
'url_complete' => ($scheme ?: 'https') . '://' . $domain . $path . ($query ? '?' . $query : '')
];
} else {
return [
... ...
... ... @@ -302,7 +302,7 @@ class HtmlLanguageCollect extends Command
return [
'download' => true,
'url' => $url,
'url_complete' => ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path . ($query ? '?' . $query : '')
'url_complete' => ($scheme ?: 'https') . '://' . $domain . $path . ($query ? '?' . $query : '')
];
} else {
return [
... ...
<?php
namespace App\Console\Commands\Update;
use App\Models\Collect\CollectSource;
use App\Models\Collect\CollectTask;
use App\Models\Com\UpdateLog;
use App\Models\Com\UpdateOldInfo;
use App\Models\RouteMap\RouteMap;
use App\Services\CosService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
/**
* 4.0,5.0升级到6.0,小语种页面采集
* Class ProjectImport
* @package App\Console\Commands
* @author Akun
* @date 2023/11/20 14:04
*/
class HtmlLanguageSpecialCollect extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'project_html_language_special_collect';
/**
* The console command description.
*
* @var string
*/
protected $description = '执行项目html页面采集';
public function handle()
{
ini_set('memory_limit', '512M');
while (true) {
$this->start_collect();
}
}
protected function start_collect()
{
$task_id = $this->get_task();
if ($task_id === false) {
//所有项目采集完成
sleep(60);
return true;
} elseif ($task_id === 0) {
//当前项目采集完成
sleep(2);
return true;
}
$task_arr = explode('_', $task_id);
$project_id = $task_arr[0];
$collect_id = $task_arr[1];
//设置数据库
$project = ProjectServer::useProject($project_id);
if ($project) {
$collect_info = CollectTask::select(['id', 'domain', 'route', 'language'])->where('id', $collect_id)->where('status', CollectTask::STATUS_UN)->where('language', '=', '')->first();
if (!$collect_info) {
sleep(2);
return true;
}
echo 'date:' . date('Y-m-d H:i:s') . ', project_id: ' . $project_id . ', collect_id: ' . $collect_id . ', collect start' . PHP_EOL;
$collect_info->status = CollectTask::STATUS_ING;
$collect_info->save();
//获取站点正式和测试域名
$domain_en = $this->get_domain_en($project_id);
$old_info = UpdateOldInfo::getOldDomain($project_id, $domain_en);
//采集html页面,下载资源到本地并替换
try {
$html = curl_c('https://' . $collect_info->domain . $collect_info->route, false);
if ($html == '0' || strpos($html,'404 Not Found') !== false) {
$collect_info->status = CollectTask::STATUS_FAIL;
$collect_info->save();
$error = $html == '0' ? 'no html' : '404 not found';
echo 'date:' . date('Y-m-d H:i:s') . ', project_id: ' . $project_id . ', collect_id: ' . $collect_id . ', error: ' . $error . PHP_EOL;
sleep(2);
return true;
}
//如果有base64图片,先替换掉,再进行资源匹配
$new_html = $html;
preg_match_all("/data:([^;]*);base64,(.*)?\"/", $new_html, $result_img);
$img_base64 = $result_img[2] ?? [];
foreach ($img_base64 as $v64) {
$new_html = str_replace($v64, '', $new_html);
}
$source_list = $this->html_preg($new_html, $project_id, $domain_en, $old_info['web_url_domain'], $old_info['home_url']);
if ($source_list) {
$html = $this->upload_source($html, $source_list, $project_id, $domain_en, $old_info['web_url_domain'], $old_info['home_url']);
}
} catch (\Exception $e) {
$collect_info->status = CollectTask::STATUS_FAIL;
$collect_info->save();
echo 'date:' . date('Y-m-d H:i:s') . ', project_id: ' . $project_id . ', collect_id: ' . $collect_id . ', error: ' . $e->getMessage() . PHP_EOL;
sleep(2);
return true;
}
$collect_info->html = $html;
$collect_info->status = CollectTask::STATUS_COM;
$collect_info->save();
echo 'date:' . date('Y-m-d H:i:s') . ', project_id: ' . $project_id . ', collect_id: ' . $collect_id . ', collect end' . PHP_EOL;
}
//关闭数据库
DB::disconnect('custom_mysql');
sleep(2);
return true;
}
//获取任务
protected function get_task()
{
$key = 'console_html_language_special_collect_task';
$task_id = Redis::rpop($key);
if ($task_id) {
return $task_id;
}
$update_log = UpdateLog::whereIn('project_id', [555, 626])->where('status', UpdateLog::STATUS_COM)->where('collect_status', UpdateLog::COLLECT_STATUS_UN)->first();
if (!$update_log) {
return false;
}
switch ($update_log->api_type) {
case 'page':
$source = RouteMap::SOURCE_PAGE;
break;
case 'news':
$source = RouteMap::SOURCE_NEWS;
break;
case 'blog':
$source = RouteMap::SOURCE_BLOG;
break;
default:
$source = RouteMap::SOURCE_PRODUCT;
break;
}
$complete = false;
//设置数据库
$project = ProjectServer::useProject($update_log->project_id);
if ($project) {
$collect_list = CollectTask::select(['id', 'project_id'])->where('project_id', $update_log['project_id'])->where('source', $source)->where('language', '=', '')->where('status', CollectTask::STATUS_UN)->orderBy('id', 'asc')->limit(50)->get();
if ($collect_list->count() == 0) {
$complete = true;
} else {
foreach ($collect_list as $collect) {
Redis::lpush($key, $collect['project_id'] . '_' . $collect['id']);
}
}
}
//关闭数据库
DB::disconnect('custom_mysql');
if ($complete) {
$update_log->collect_status = UpdateLog::COLLECT_STATUS_COM;
$update_log->save();
return 0;
}
$task_id = Redis::rpop($key);
return $task_id;
}
//获取英文站域名
protected function get_domain_en($project_id)
{
$key = 'console_html_language_domain_en';
$domain = Cache::get($key);
if (!$domain) {
$domain = CollectTask::where('project_id', $project_id)->where('language', '')->value('domain');
Cache::add($key, $domain, 3600);
}
return $domain;
}
//正则匹配html资源
protected function html_preg($html, $project_id, $domain, $web_url_domain, $home_url)
{
$source = [];
if (!$html) {
return $source;
}
//image
preg_match_all('/<img\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_img);
$img = $result_img[2] ?? [];
foreach ($img as $vi) {
$check_vi = $this->url_check($vi, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vi && (!in_array($check_vi, $source))) {
$check_vi && $source[] = $check_vi;
}
}
//js
preg_match_all('/<script\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_js);
$js = $result_js[2] ?? [];
foreach ($js as $vj) {
$check_vj = $this->url_check($vj, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vj && (!in_array($check_vj, $source))) {
$check_vj && $source[] = $check_vj;
}
}
//video
preg_match_all('/<source\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_video);
$video = $result_video[2] ?? [];
foreach ($video as $vv) {
$check_vv = $this->url_check($vv, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vv && (!in_array($check_vv, $source))) {
$check_vv && $source[] = $check_vv;
}
}
//css
preg_match_all('/<link\s+[^>]*?href\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_css);
$css = $result_css[2] ?? [];
foreach ($css as $vc) {
$check_vc = $this->url_check($vc, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vc && (!in_array($check_vc, $source))) {
$check_vc && $source[] = $check_vc;
}
}
//css background
preg_match_all("/url\(['\"]?(\s*[^>]+?)['\"]?\)/i", $html, $result_css_b);
$css_b = $result_css_b[1] ?? [];
foreach ($css_b as $vc_b) {
$check_vc_b = $this->url_check($vc_b, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vc_b && (!in_array($check_vc_b, $source))) {
$check_vc_b && $source[] = $check_vc_b;
}
}
//a标签下载资源
preg_match_all('/<a\s+[^>]*?href\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_a);
$down = $result_a[2] ?? [];
foreach ($down as $vd) {
$check_vd = $this->url_check($vd, $project_id, $domain, $web_url_domain, $home_url);
if ($check_vd && (!in_array($check_vd, $source))) {
$check_vd && $source[] = $check_vd;
}
}
return $source;
}
//判断资源是否需要下载
protected function url_check($url, $project_id, $domain, $web_url_domain, $home_url)
{
if ($url) {
$url = str_replace('&quot;', '', $url);
$arr = parse_url($url);
$scheme = $arr['scheme'] ?? '';
$host = $arr['host'] ?? '';
$path = $arr['path'] ?? '';
$query = $arr['query'] ?? '';
$path_arr = explode('.', $path);
$path_end = end($path_arr);
if (
(empty($scheme) || $scheme == 'https' || $scheme == 'http')
&& (empty($host) || (strpos($web_url_domain, $host) !== false) || (strpos($home_url, $host) !== false))
&& $path
&& (substr($path, 0, 1) == '/')
&& (strpos($path, '.') !== false)
&& (strpos($path_end, 'html') === false)
&& (strpos($path_end, 'php') === false)
&& (strpos($path_end, 'com') === false)
&& (strpos($path_end, 'xml') === false)
) {
$source = CollectSource::where('project_id', $project_id)->where('origin', $url)->first();
if (!$source) {
$new_url = str_replace($web_url_domain, $home_url, $url);
$source_new = CollectSource::where('project_id', $project_id)->where('origin', $new_url)->first();
if (!$source_new) {
return [
'download' => true,
'url' => $url,
'url_complete' => ($scheme ?: 'https') . '://' . $home_url . $path . ($query ? '?' . $query : '')
];
} else {
return [
'download' => false,
'url' => $url,
'url_complete' => $source_new['target']
];
}
} else {
return [
'download' => false,
'url' => $url,
'url_complete' => $source['target']
];
}
} else {
return false;
}
} else {
return false;
}
}
//下载并替换资源
protected function upload_source($html, $source, $project_id, $domain, $web_url_domain, $home_url)
{
foreach ($source as $vs) {
if ($vs['download']) {
$new_source = CosService::uploadRemote($project_id, 'source', $vs['url_complete']);
if ($new_source) {
CollectSource::insert([
'project_id' => $project_id,
'origin' => $vs['url'],
'target' => $new_source,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$html = str_replace($vs['url'], getImageUrl($new_source), $html);
if (substr($new_source, -3, 3) == 'css' || substr($new_source, -2, 2) == 'js') {
$source_html = curl_c(getImageUrl($new_source), false);
if (substr($new_source, -3, 3) == 'css') {
preg_match_all("/url\(['\"]?(\s*[^>]+?)['\"]?\)/i", $source_html, $result_source);
} else {
preg_match_all("/[large|thumb]+URL:['\"]+(\s*[^>]+?)['\"]+,/i", $source_html, $result_source);
}
$js_css_source = $result_source[1] ?? [];
if ($js_css_source) {
foreach ($js_css_source as $vjs) {
if (strpos($vjs, 'URL:"') !== false) {
$vjs = substr($vjs, strpos($vjs, 'URL:"') + 5);
}
$vjs_down = str_replace('&quot;', '', $vjs);
if (strpos($vjs_down, 'data:') !== false) {
//过滤二进制文件
continue;
}
if (strlen($vjs_down) > 255) {
//过滤太长文件
continue;
}
$vjs_down_arr = parse_url($vjs_down);
$vjs_down_host = $vjs_down_arr['host'] ?? '';
$cos = config('filesystems.disks.cos');
$cosCdn = $cos['cdn'];
if ($vjs_down_host && $vjs_down_host == $cosCdn) {
//过滤已经下载的
continue;
}
if (empty($vjs_down_host) && substr($vjs_down, 0, 1) != '/') {
//相对路径
$url_arr = explode('/', $vs['url']);
$url_arr[count($url_arr) - 1] = $vjs_down;
$vjs_down = implode('/', $url_arr);
}
$vjs_result = $this->url_check($vjs_down, $project_id, $domain, $web_url_domain, $home_url);
if (!$vjs_result) {
continue;
}
if ($vjs_result['download']) {
$new_vjs = CosService::uploadRemote($project_id, 'source', $vjs_result['url_complete']);
if ($new_vjs) {
CollectSource::insert([
'project_id' => $project_id,
'origin' => $vjs_result['url'],
'target' => $new_vjs,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$source_html = str_replace($vjs, getImageUrl($new_vjs), $source_html);
}
} else {
$source_html = str_replace($vjs, getImageUrl($vjs_result['url_complete']), $source_html);
}
}
CosService::uploadRemote($project_id, 'source', $new_source, $new_source, $source_html);
}
}
}
} else {
$html = str_replace($vs['url'], getImageUrl($vs['url_complete']), $html);
}
}
return $html;
}
}
<?php
namespace App\Http\Controllers\Bside\ProjectAssociation;
namespace App\Http\Controllers\Aside\ProjectAssociation;
use App\Enums\Common\Code;
use App\Exceptions\BsideGlobalException;
use App\Http\Controllers\Bside\BaseController;
use App\Http\Logic\Aside\ProjectAssociation\ProjectAssociationLogic;
use App\Models\ProjectAssociation\ProjectAssociation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use App\Services\Aside\ProjectAssociation\ProjectAssociationServices;
class ProjectAssociationController extends BaseController
{
private $ProjectAssociationLogic;
public function __construct(Request $request)
{
$this->ProjectAssociationLogic = new ProjectAssociationLogic();
parent::__construct($request);
}
/**
* V6与AICC数据关联
* @return void
* @throws BsideGlobalException
*/
public function saveWeChatData()
public function save()
{
$project_id = (int)request()->post('project_id', 0);
if (empty($project_id)) {
$this->fail('请选择项目!', Code::USER_PARAMS_ERROE);
$this->response('请选择项目!', Code::USER_PARAMS_ERROE);
}
$status = (bool)request()->post('status', 1); # 1 - 正常, 0 - 禁用
$user_id = (int)env('AICC_WECHAT_USER_ID') ?? 0;
if (empty($user_id) && $status) {
$this->fail('请选择要绑定的AICC用户!', Code::USER_PARAMS_ERROE);
$this->response('请选择要绑定的AICC用户!', Code::USER_PARAMS_ERROE);
}
$friend_id = (int)request()->post('friend_id', 0);
if (empty($friend_id) && $status) {
$this->fail('请选择要绑定的AICC用户列表!', Code::USER_PARAMS_ERROE);
$this->response('请选择要绑定的AICC用户列表!', Code::USER_PARAMS_ERROE);
}
$app = (int)request()->post('app', ProjectAssociation::ENTERPRISE_WECHAT);
$app = ProjectAssociation::getApplicationID($app);
$nickname = request()->post('nickname', '');
$user_name = request()->post('user_name', '');
$image = request()->post('image', '');
$data = compact('project_id', 'user_id', 'friend_id', 'nickname', 'user_name', 'image');
$this->ProjectAssociationLogic->saveWeChatData($data);
$data = compact('project_id', 'user_id', 'friend_id', 'nickname', 'user_name', 'image', 'app');
ProjectAssociationServices::getInstance()->save($data);
$this->response('绑定成功');
}
... ... @@ -58,27 +49,34 @@ class ProjectAssociationController extends BaseController
public function check()
{
$project_id = (int)request()->input('project_id', 0);
if (empty($project_id)) {
$this->response('请输入项目信息!', Code::SERVER_ERROR);
}
// 项目绑定状态
$app = (int)request()->input('type', ProjectAssociation::ENTERPRISE_WECHAT);
$app = ProjectAssociation::getApplicationID($app);
$status = request()->input('status');
// 重载redis缓存
$cache = request()->input('cache');
if (isset($status)) {
$status = (int)$status ? ProjectAssociation::STATUS_NORMAL : ProjectAssociation::STATUS_DISABLED;
}
$isRes = $this->ProjectAssociationLogic->normal($project_id);
$isRes = ProjectAssociationServices::getInstance()->normal($project_id, $app);
// 当数据不存在时并开启状态,自动添加一条数据
if (is_null($isRes) && (!is_null($status) && $status)) {
$isRes = $this->ProjectAssociationLogic->saveProject($project_id, $status);
if (is_null($isRes)) {
$value = ProjectAssociationServices::getInstance()->saveProject($project_id, $status, $app);
if (empty($value['bool'])) {
// 保存数据失败
$this->response('绑定AICC数据失败!', Code::SERVER_ERROR);
}
$isRes = $value['isRes'];
} // 关闭状态
elseif (!is_null($isRes) && (!is_null($status) && empty($status))) {
$bool = $this->ProjectAssociationLogic->closedState($isRes, $status);
$bool = ProjectAssociationServices::getInstance()->closedState($isRes, $status);
if ($bool) {
// 关闭aicc绑定成功
$this->response('关闭aicc绑定 - 成功!');
}else{
} else {
// 关闭aicc绑定失败
$this->response('关闭aicc绑定 - 失败!');
}
... ... @@ -88,7 +86,7 @@ class ProjectAssociationController extends BaseController
$this->response('success', Code::SERVER_ERROR);
}
$cache = isset($cache);
$result = $this->ProjectAssociationLogic->getAiccWechatLists($isRes, $cache);
$result = ProjectAssociationServices::getInstance()->getAiccWechatLists($isRes, $app, $cache);
$this->response('success', Code::SUCCESS, $result);
}
}
... ...
... ... @@ -5,6 +5,7 @@ namespace App\Models\ProjectAssociation;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* App\Models\ProjectAssociation\ProjectAssociation
*
... ... @@ -17,11 +18,13 @@ use Illuminate\Database\Eloquent\Model;
* @property string|null $image AICC朋友头像
* @property int|null $status 1 - 正常, 0 - 禁用
* @property int|null $m_status 统计当月是否生成数据
* @property int|null $binding_app 1 - 企业微信 2 - 个人微信
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method Builder|ProjectAssociation newModelQuery()
* @method Builder|ProjectAssociation newQuery()
* @method static Builder|ProjectAssociation query()
* @method Builder|ProjectAssociation whereBindingApp($value)
* @method Builder|ProjectAssociation whereCreatedAt($value)
* @method Builder|ProjectAssociation whereFriendId($value)
* @method Builder|ProjectAssociation whereId($value)
... ... @@ -46,60 +49,30 @@ class ProjectAssociation extends Model
/** @var int 数据状态 - 禁用 */
const STATUS_DISABLED = 0;
/**
* 保存|修改数据
* @param array $data
* @return bool
*/
public function saveData(array $data): bool
{
# V6项目ID
$project_id = (int)$data['project_id'] ?? 0;
$isRes = self::query()->where('project_id', $project_id)->first();
if (!$isRes) {
$isRes = new self();
$isRes->project_id = $project_id;
}
# AICC朋友ID
$isRes->friend_id = $data['friend_id'] ?? 0;
# AICC朋友昵称
$isRes->nickname = $data['nickname'] ?? 0;
# AICC用户ID
$isRes->user_id = $data['user_id'] ?? 0;
# AICC用户姓名
$isRes->user_name = $data['user_name'] ?? '';
# AICC朋友头像
$isRes->image = $data['image'] ?? '';
return $isRes->save();
}
/** @var int 企业微信 */
const ENTERPRISE_WECHAT = 1;
/**
* 检查项目是否存在
* @param $project_id
* @return Builder|Model|object|null
*/
public function check($project_id)
/** @var int 个人微信 */
const PERSONAL_WECHAT = 2;
public static function getApplicationApiUrl($app)
{
return self::query()->where('project_id', $project_id)->first();
return [
1 => env('AICC_ENTERPRISE_WECHAT_FRIEND_API_URL'),
2 => env('AICC_WECHAT_FRIEND_API_URL'),
][$app];
}
/**
* @param int $page
* @param int $perPage
* @return array
* 返回绑定的APP应用类型
* @param $app
* @return int
*/
public function allData(int $page = 1, int $perPage = 15)
public static function getApplicationID($app)
{
$status = 1; # 1 - 正常, 0 - 禁用
$lists = self::query()->where('status', $status)
->where('project_id', '!=', 0)
->where('friend_id', '!=', 0)
->where('user_id', '!=', 0)
->paginate($perPage, ['project_id', 'friend_id', 'user_id'], 'page', $page);
$items = $lists->Items();
$totalPage = $lists->lastPage();
$total = $lists->total();
$currentPage = $lists->currentPage();
return compact('total', 'items', 'totalPage', 'currentPage');
return [
1 => self::ENTERPRISE_WECHAT,
2 => self::PERSONAL_WECHAT,
][$app] ?? self::ENTERPRISE_WECHAT;
}
}
... ...
<?php
namespace App\Http\Logic\Aside\ProjectAssociation;
namespace App\Services\Aside\ProjectAssociation;
use App\Enums\Common\Code;
use App\Http\Logic\Logic;
use App\Exceptions\BsideGlobalException;
use App\Models\ProjectAssociation\ProjectAssociation;
use App\Services\BaseService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class ProjectAssociationLogic extends Logic
class ProjectAssociationServices extends BaseService
{
public function saveWeChatData($data)
/**
* 保存aicc与项目关系数据
* @param array $data
* @return bool
* @throws BsideGlobalException
*/
public function save(array $data)
{
$wx = new ProjectAssociation();
$bool = false;
DB::beginTransaction();
try {
$status = $wx->saveData($data);
# V6项目ID
$project_id = (int)$data['project_id'] ?? 0;
$isRes = ProjectAssociation::query()->where('project_id', $project_id)->first();
if (!$isRes) {
$isRes = new ProjectAssociation();
$isRes->project_id = $project_id;
}
# AICC朋友ID
$isRes->friend_id = $data['friend_id'] ?? 0;
# AICC朋友昵称
$isRes->nickname = $data['nickname'] ?? 0;
# AICC用户ID
$isRes->user_id = $data['user_id'] ?? 0;
# AICC用户姓名
$isRes->user_name = $data['user_name'] ?? '';
# AICC朋友头像
$isRes->image = $data['image'] ?? '';
$isRes->binding_app = $data['app'] ?? 1;
$bool = $isRes->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
$e->getMessage();
errorLog('V6与AICC关联失败', $wx, $e);
errorLog('V6与AICC关联失败', $data, $e);
$this->fail('请检查操作是否正确!', Code::SERVER_MYSQL_ERROR);
}
return $status;
return $bool;
}
/**
* status - 正常
* @param $project_id
* @param $app
* @return ProjectAssociation|Builder|Model|object|null
*/
public function normal($project_id)
public function normal($project_id, $app)
{
return ProjectAssociation::query()->whereProjectId($project_id)->whereStatus(ProjectAssociation::STATUS_NORMAL)->first();
return ProjectAssociation::query()->whereProjectId($project_id)->whereStatus(ProjectAssociation::STATUS_NORMAL)->whereBindingApp($app)->first();
}
/**
* status - 禁用
* @param $project_id
... ... @@ -50,11 +75,12 @@ class ProjectAssociationLogic extends Logic
/**
* 初始化数据/修改数据
* @param int $project_id
* @param int $status
* @return Builder|Model|object|ProjectAssociation|null
* @param $project_id
* @param $status
* @param $app
* @return array
*/
public function saveProject($project_id, $status)
public function saveProject($project_id, $status, $app)
{
$bool = false;
DB::beginTransaction();
... ... @@ -65,29 +91,55 @@ class ProjectAssociationLogic extends Logic
$isRes->project_id = $project_id;
$isRes->user_id = (int)env('AICC_WECHAT_USER_ID');
$isRes->status = $status;
$isRes->binding_app = $app;
try {
$bool = $isRes->save();
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
}
return compact('bool', 'isRes');
}
/**
* 关闭状态
* @param ProjectAssociation $res
* @param int $status 1 - 正常, 0 - 禁用
* @return bool
*/
public function closedState($res, $status)
{
DB::beginTransaction();
$bool = false;
try {
$isRes->save();
$res->status = $status;
$bool = $res->save();
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
}
return $isRes;
return $bool;
}
/**
* 获取AICC微信列表数据
* @param ProjectAssociation $res
* @param bool $cache
* @param int $type 绑定app应用类型
* @param bool $cache 是否缓存
* @return mixed
*/
public function getAiccWechatLists($res, $cache = false)
public function getAiccWechatLists($res, $type = ProjectAssociation::PERSONAL_WECHAT, $cache = false)
{
$redis_key = 'aicc_friend_lists_' . (int)env('AICC_WECHAT_USER_ID');
$redis_key = 'aicc_friend_lists_' . $type . '_' . (int)env('AICC_WECHAT_USER_ID');
$result = $cache ? false : redis_get($redis_key);
if (empty($result)) {
$url = env('AICC_URL') . env('AICC_WECHAT_FRIEND_API_URL');
$apiUrl = ProjectAssociation::getApplicationApiUrl($type);
$url = env('AICC_URL') . $apiUrl;
$result = curlGet($url);
if ($result['data']) {
redis_set($redis_key, json_encode($result), 60);
}
} else {
$result = json_decode($result, true);
}
... ... @@ -99,24 +151,4 @@ class ProjectAssociationLogic extends Logic
];
return $result;
}
/**
* 关闭状态
* @param ProjectAssociation $res
* @param int $status 1 - 正常, 0 - 禁用
* @return bool
*/
public function closedState($res, $status)
{
DB::beginTransaction();
$bool = false;
try {
$res->status = $status;
$bool = $res->save();
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
}
return $bool;
}
}
... ...
... ... @@ -8,10 +8,56 @@ namespace App\Services;
use App\Enums\Common\Code;
use App\Exceptions\BsideGlobalException;
use Mockery;
class BaseService
{
/**
* 单例模式
* 特点:三私,两静,一公
* 三私:三个私有方法,(静态变量、构造函数、克隆函数)
* 两静:两个静态方法,(一个静态变量,一个静态方法)
* 一公:单例模式的出口
*
* 优点:
* 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
* 2、避免对资源的多重占用(比如写文件操作)。
*/
protected static $instance;
/**
* @return static
*/
public static function getInstance()
{
if ((static::$instance[static::class] ?? null) instanceof static) {
return static::$instance[static::class];
}
return static::$instance[static::class] = new static();
}
/**
* @return Mockery\Mock
*/
public static function mockInstance()
{
return static::$instance[static::class] = Mockery::mock(static::class)
->makePartial()
->shouldAllowMockingProtectedMethods();
}
private function __construct()
{
}
private function __clone()
{
// TODO: Implement __clone() method.
}
/**
* @notes: 手动抛出异常
* @param string $msg
* @param string $code
... ...
... ... @@ -4,7 +4,7 @@
*/
use App\Http\Controllers\Aside;
use App\Http\Controllers\Bside\ProjectAssociation\ProjectAssociationController;
use App\Http\Controllers\Aside\ProjectAssociation\ProjectAssociationController;
use Illuminate\Support\Facades\Route;
... ... @@ -72,7 +72,7 @@ Route::middleware(['aloginauth'])->group(function () {
//发送记录
Route::any('/log', [Aside\Ai\AiLogController::class, 'lists'])->name('admin.lists');
// 绑定AICC微信应用
Route::post('/wechat', [ProjectAssociationController::class, 'saveWeChatData'])->name('admin.aicc.wechat');
Route::post('/binding/save', [ProjectAssociationController::class, 'save'])->name('admin.binding.save');
// OA后台开启关闭AICC用户绑定
Route::post('/check', [ProjectAssociationController::class, 'check'])->name('admin.aicc.check');
});
... ...