日报
This commit is contained in:
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\controller;
|
||||||
|
|
||||||
|
use app\middleware\DataTracker;
|
||||||
|
use app\model\Daily;
|
||||||
|
use app\model\FeishuUser;
|
||||||
|
use app\model\User;
|
||||||
|
use app\util\Util;
|
||||||
|
use config\constants\Constants;
|
||||||
|
use support\Log;
|
||||||
|
use support\Request;
|
||||||
|
use support\exception\BusinessException;
|
||||||
|
|
||||||
|
class DailyController
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日报列表
|
||||||
|
* @return \support\Response
|
||||||
|
*/
|
||||||
|
public function list(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$page = $request->input('page', 1);
|
||||||
|
$perPage = $request->input('per_page', 10);
|
||||||
|
|
||||||
|
//id
|
||||||
|
$user_id = $request->user['id'];
|
||||||
|
if(Util::isEmpty($user_id)){
|
||||||
|
return Util::fail([],'user_id'.trans('not_null'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$where = [];
|
||||||
|
$where['user_id'] = $user_id;
|
||||||
|
|
||||||
|
// 执行分页查询
|
||||||
|
$data = Daily::with('user')->where($where)
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->paginate($perPage, ['*'], 'page', $page);
|
||||||
|
|
||||||
|
return Util::success($data,trans('success'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日报列表
|
||||||
|
* @return \support\Response
|
||||||
|
*/
|
||||||
|
public function detail(Request $request)
|
||||||
|
{
|
||||||
|
//日报id
|
||||||
|
$id = Util::getParam($request,'id');
|
||||||
|
if(Util::isEmpty($id)){
|
||||||
|
return Util::fail([],'id'.trans('not_null'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$where = [];
|
||||||
|
$where['id'] = $id;
|
||||||
|
|
||||||
|
// 执行分页查询
|
||||||
|
$data = Daily::with('user')->where($where)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$data['self'] = 0;
|
||||||
|
|
||||||
|
return Util::success($data,trans('success'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日报编辑
|
||||||
|
* @param Request $request
|
||||||
|
* @return \support\Response
|
||||||
|
*/
|
||||||
|
public function save(Request $request)
|
||||||
|
{
|
||||||
|
$id = Util::getParam($request, 'id');
|
||||||
|
$text = Util::getParam($request, 'text');
|
||||||
|
|
||||||
|
if (empty($id)) {
|
||||||
|
return Util::fail([], '日报id' . trans('not_null'));
|
||||||
|
}
|
||||||
|
if (Util::isEmpty($text)) {
|
||||||
|
return Util::fail([], 'text' . trans('not_null'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'text' => $text,
|
||||||
|
'remark' => Util::getParam($request, 'remark', '')
|
||||||
|
];
|
||||||
|
|
||||||
|
$res = Daily::where(['id' => $id])->update($data);
|
||||||
|
|
||||||
|
if ($res) {
|
||||||
|
return Util::success($res,trans('save_success'));
|
||||||
|
} else {
|
||||||
|
return Util::fail($res,trans('save_fail'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -141,17 +141,18 @@ class FeishuController
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $receiveId openid
|
* @param $receiveId //openid
|
||||||
* @param $title 推送标题
|
* @param $title //推送标题
|
||||||
* @param $content 推送内容
|
* @param $content //推送内容
|
||||||
* @param $href 详情链接
|
* @param $href //详情链接
|
||||||
|
* @param $msgType = 'post'; //卡片消息:interactive,富文本消息:post
|
||||||
* @return \support\Response
|
* @return \support\Response
|
||||||
*/
|
*/
|
||||||
public static function send($config='xinyouhe',$receiveId='ou_e33bb3017ada6c4781398a68e55a4696',$title='ceshi',$content='测试',$href='http://219.157.255.213:8085/pages/index/mine')
|
public static function send($config='xinyouhe',$receiveId='ou_e33bb3017ada6c4781398a68e55a4696',$content = '' , $msgType = 'post')
|
||||||
{
|
{
|
||||||
// 获取凭证
|
// 获取凭证
|
||||||
$certificate = config('feishu.'.$config);
|
$certificate = config('feishu.'.$config);
|
||||||
Log::info('feishu send', [$certificate,'config'=>$config,'receiveId' => $receiveId, 'title' => $title, 'content' => $content, 'href' => $href]);
|
Log::info('feishu send', [$certificate,'config'=>$config,'receiveId' => $receiveId, 'content' => $content]);
|
||||||
|
|
||||||
// 飞书服务
|
// 飞书服务
|
||||||
$class = new \app\service\FeishuService($certificate['appId'], $certificate['appSecret'], $certificate['state']);
|
$class = new \app\service\FeishuService($certificate['appId'], $certificate['appSecret'], $certificate['state']);
|
||||||
@@ -160,7 +161,7 @@ class FeishuController
|
|||||||
// $receiveId = 'ou_a3b97543acbf1b28d978356bb08f85dd';
|
// $receiveId = 'ou_a3b97543acbf1b28d978356bb08f85dd';
|
||||||
|
|
||||||
// 富文本 类型
|
// 富文本 类型
|
||||||
$content = "{
|
/*$content = "{
|
||||||
\"zh_cn\":{
|
\"zh_cn\":{
|
||||||
\"title\":\"$title\",
|
\"title\":\"$title\",
|
||||||
\"content\":[
|
\"content\":[
|
||||||
@@ -179,7 +180,7 @@ class FeishuController
|
|||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}";
|
}";*/
|
||||||
|
|
||||||
// 卡片 类型
|
// 卡片 类型
|
||||||
/*$content = "{
|
/*$content = "{
|
||||||
@@ -212,13 +213,88 @@ class FeishuController
|
|||||||
}
|
}
|
||||||
}";*/
|
}";*/
|
||||||
// $msgType = 'interactive';
|
// $msgType = 'interactive';
|
||||||
$msgType = 'post'; //卡片消息:interactive,富文本消息:post
|
// $msgType = 'post'; //卡片消息:interactive,富文本消息:post
|
||||||
$receiveIdtype = 'open_id';
|
$receiveIdtype = 'open_id';
|
||||||
|
|
||||||
$result = $class->sendMessages($receiveId, $content, $msgType, $receiveIdtype);
|
$result = $class->sendMessages($receiveId, $content, $msgType, $receiveIdtype);
|
||||||
return json($result);
|
return json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 富文本消息
|
||||||
|
* @param $title
|
||||||
|
* @param $content
|
||||||
|
* @param $href
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function postMsg($title,$content,$href)
|
||||||
|
{
|
||||||
|
// 富文本 类型
|
||||||
|
$content = "{
|
||||||
|
\"zh_cn\":{
|
||||||
|
\"title\":\"$title\",
|
||||||
|
\"content\":[
|
||||||
|
[{
|
||||||
|
\"tag\":\"text\",
|
||||||
|
\"text\":\"$content\",
|
||||||
|
\"style\":[\"bold\"]
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
\"tag\":\"hr\"
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
\"tag\":\"a\",
|
||||||
|
\"href\":\"$href\",
|
||||||
|
\"text\":\"查看详情\"
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卡片消息
|
||||||
|
* @param $title
|
||||||
|
* @param $content
|
||||||
|
* @param $href
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function interactiveMsg($title,$content,$href)
|
||||||
|
{
|
||||||
|
// 富文本 类型
|
||||||
|
$content = "{
|
||||||
|
\"config\":{
|
||||||
|
\"wide_screen_mode\":true
|
||||||
|
},
|
||||||
|
\"elements\":[{
|
||||||
|
\"tag\":\"div\",
|
||||||
|
\"text\":{
|
||||||
|
\"content\":\"$content \",
|
||||||
|
\"tag\":\"lark_md\"
|
||||||
|
}},{
|
||||||
|
\"actions\":[{
|
||||||
|
\"tag\":\"button\",
|
||||||
|
\"text\":{
|
||||||
|
\"content\":\"立即查看\",
|
||||||
|
\"tag\":\"plain_text\"
|
||||||
|
},
|
||||||
|
\"type\":\"primary\",
|
||||||
|
\"url\":\"$href\"
|
||||||
|
}],
|
||||||
|
\"tag\":\"action\"
|
||||||
|
}],
|
||||||
|
\"header\":{
|
||||||
|
\"template\":\"turquoise\",
|
||||||
|
\"title\":{
|
||||||
|
\"content\":\"📚$title\",
|
||||||
|
\"tag\":\"plain_text\"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
return '<div>查看详情 - 示例页面</div>';
|
return '<div>查看详情 - 示例页面</div>';
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\middleware;
|
||||||
|
|
||||||
|
use app\model\RequestTracks;
|
||||||
|
|
||||||
|
class DataTracker
|
||||||
|
{
|
||||||
|
public function process($request, \Closure $next)
|
||||||
|
{
|
||||||
|
// 前置处理
|
||||||
|
if($request->path() != 'user/login'){
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
$this->logRequestData($request);
|
||||||
|
|
||||||
|
$response = $next($request);
|
||||||
|
|
||||||
|
// 后置处理
|
||||||
|
// $this->logResponseData($response);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function logRequestData($request)
|
||||||
|
{
|
||||||
|
$trackData = [
|
||||||
|
'app_id' => 'crm/api',
|
||||||
|
'user_id' => $request->user['id'],
|
||||||
|
'ip' => $request->getRealIp(),
|
||||||
|
'method' => $request->method(),
|
||||||
|
'path' => $request->path(),
|
||||||
|
'params' => json_encode($request->all()),
|
||||||
|
'header' => json_encode($request->header()),
|
||||||
|
'uuid' => $this->generateTraceId(),
|
||||||
|
'user_agent' => $request->header('user-agent'),
|
||||||
|
'referer' => $request->header('referer'),
|
||||||
|
];
|
||||||
|
$requestTrack = RequestTracks::create($trackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function sendToQueue($data)
|
||||||
|
{
|
||||||
|
// 使用Redis队列
|
||||||
|
try {
|
||||||
|
redis()->lpush('track_queue', json_encode($data));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 失败降级处理
|
||||||
|
file_put_contents(
|
||||||
|
runtime_path('logs/track_fallback.log'),
|
||||||
|
json_encode($data) . PHP_EOL,
|
||||||
|
FILE_APPEND
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTraceId()
|
||||||
|
{
|
||||||
|
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||||
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||||
|
mt_rand(0, 0xffff),
|
||||||
|
mt_rand(0, 0x0fff) | 0x4000,
|
||||||
|
mt_rand(0, 0x3fff) | 0x8000,
|
||||||
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\model;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
class Daily extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'daily';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key associated with the table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
//设置黑名单
|
||||||
|
protected $guarded = ['id','created_at','updated_at'];
|
||||||
|
|
||||||
|
// 指定日期字段存储格式为时间戳
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model should be timestamped.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = true;
|
||||||
|
|
||||||
|
// protected $dates = ['deleted_at'];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新格式化时间
|
||||||
|
* @param DateTimeInterface $date
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function serializeDate(DateTimeInterface $date): string
|
||||||
|
{
|
||||||
|
return $date->format(Carbon::parse($date)->toDateTimeString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 定义反向多对一关联
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\model;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use support\Model;
|
||||||
|
|
||||||
|
class RequestTracks extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'request_tracks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key associated with the table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
//设置黑名单
|
||||||
|
protected $guarded = ['id','created_at'];
|
||||||
|
|
||||||
|
// 指定日期字段存储格式为时间戳
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model should be timestamped.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = true;
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新格式化时间
|
||||||
|
* @param DateTimeInterface $date
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function serializeDate(DateTimeInterface $date): string
|
||||||
|
{
|
||||||
|
return $date->format(Carbon::parse($date)->toDateTimeString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁用 updated_at 的自动更新
|
||||||
|
public function setUpdatedAt($value)
|
||||||
|
{
|
||||||
|
return $this; // 不做任何操作
|
||||||
|
}
|
||||||
|
}
|
||||||
+54
-2
@@ -6,6 +6,7 @@ use app\controller\FeishuController;
|
|||||||
use app\model\Customer;
|
use app\model\Customer;
|
||||||
use app\model\CustomerHis;
|
use app\model\CustomerHis;
|
||||||
use app\model\FeishuUser;
|
use app\model\FeishuUser;
|
||||||
|
use app\model\RequestTracks;
|
||||||
use app\model\User;
|
use app\model\User;
|
||||||
use support\Log;
|
use support\Log;
|
||||||
use Webman\App;
|
use Webman\App;
|
||||||
@@ -65,7 +66,8 @@ class Task
|
|||||||
$item->warn = 1;
|
$item->warn = 1;
|
||||||
$item->update();
|
$item->update();
|
||||||
Log::info('send',['open_id'=>$item['open_id'],'url'=>$url]);
|
Log::info('send',['open_id'=>$item['open_id'],'url'=>$url]);
|
||||||
FeishuController::send($feishuUser->sign, $feishuUser->open_id, '跟进提醒', '您有新的跟进提醒', $url);
|
$content = FeishuController::postMsg( '跟进提醒', '您有新的跟进提醒', $url);
|
||||||
|
FeishuController::send($feishuUser->sign, $feishuUser->open_id, $content, 'post');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ class Task
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 每小时执行一次
|
//回收站客户转向公海 每小时执行一次
|
||||||
new Crontab('0 10 * * * *', function(){
|
new Crontab('0 10 * * * *', function(){
|
||||||
echo date('Y-m-d H:i:s') . "\n";
|
echo date('Y-m-d H:i:s') . "\n";
|
||||||
Log::info('send high seas start',[time()]);
|
Log::info('send high seas start',[time()]);
|
||||||
@@ -95,6 +97,56 @@ class Task
|
|||||||
Log::info('send high seas end',[time()]);
|
Log::info('send high seas end',[time()]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//总结日报, 每天执行一次
|
||||||
|
new Crontab('0 30 17 * * *', function () {
|
||||||
|
echo date('Y-m-d H:i:s') . "\n";
|
||||||
|
Log::info('start daily', [time()]);
|
||||||
|
|
||||||
|
$where = [
|
||||||
|
['created_at', '<=', time() - (3600 * 24)],
|
||||||
|
];
|
||||||
|
$requestTracks = RequestTracks::select('*, COUNT(*) as count')
|
||||||
|
->where($where)
|
||||||
|
->whereIn('path', ['customer/claim', 'customer/save', 'follow/save', 'customer/collect'])
|
||||||
|
->groupBy('user_id','path')
|
||||||
|
->orderBy('user_id', 'asc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$statistics = [];
|
||||||
|
$users = [];
|
||||||
|
$daily = '';
|
||||||
|
foreach ($requestTracks as $item) {
|
||||||
|
$statistics[$item->user_id][$item->path] = $item->count;
|
||||||
|
$users[] = $item->user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($users as $userId) {
|
||||||
|
$daily .= date('Y-m-d') . "\n";
|
||||||
|
$daily .= '领取客户'.$statistics[$userId]['customer/claim'].'位\n';
|
||||||
|
$daily .= '创建或修改客户'.$statistics[$userId]['customer/save'].'位\n';
|
||||||
|
$daily .= '添加跟进'.$statistics[$userId]['follow/save'].'次\n';
|
||||||
|
$daily .= '询盘跟单客户'.$statistics[$userId]['customer/collect'].'位\n';
|
||||||
|
$daily .= '请及时查看,30分钟后将向主管发送';
|
||||||
|
|
||||||
|
$feishuUser = FeishuUser::where(['user_id' => $userId])->first();
|
||||||
|
if ($feishuUser) {
|
||||||
|
// 获取凭证
|
||||||
|
$certificate = config('feishu.'.$feishuUser->sign);
|
||||||
|
// 使用parse_url解析URL
|
||||||
|
$parsedUrl = parse_url($certificate['rUrl']);
|
||||||
|
// 获取域名和端口
|
||||||
|
$host = $parsedUrl['host'];
|
||||||
|
$port = isset($parsedUrl['port']) ? ':' . $parsedUrl['port'] : '';
|
||||||
|
$url = 'http://'. $host .$port. '/pages/customer/detile?id=';
|
||||||
|
$content = FeishuController::postMsg( '跟进提醒', $daily, $url);
|
||||||
|
FeishuController::send($feishuUser->sign, $feishuUser->open_id, $content, 'post');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('send high seas end', [time()]);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,4 +2,9 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'rpc_domain' => getenv('RPC_DOMAIN'),
|
'rpc_domain' => getenv('RPC_DOMAIN'),
|
||||||
|
'event_tracking' => [
|
||||||
|
'follow/save',
|
||||||
|
'customer/claim',
|
||||||
|
'customer/save',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
@@ -17,5 +17,12 @@ return [
|
|||||||
'' => [
|
'' => [
|
||||||
app\middleware\CrossDomain::class, // 全局跨域中间件
|
app\middleware\CrossDomain::class, // 全局跨域中间件
|
||||||
app\middleware\AuthMiddleware::class, // 鉴权中间件
|
app\middleware\AuthMiddleware::class, // 鉴权中间件
|
||||||
|
// app\middleware\DataTracker::class, //埋点
|
||||||
|
],
|
||||||
|
|
||||||
|
// 路由中间件
|
||||||
|
'route' => [
|
||||||
|
// 'track' => app\middleware\DataTracker::class,
|
||||||
]
|
]
|
||||||
|
|
||||||
];
|
];
|
||||||
Reference in New Issue
Block a user