diff --git a/app/controller/DailyController.php b/app/controller/DailyController.php
new file mode 100644
index 0000000..61cc700
--- /dev/null
+++ b/app/controller/DailyController.php
@@ -0,0 +1,100 @@
+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'));
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/controller/FeishuController.php b/app/controller/FeishuController.php
index 94bea1a..319a5de 100644
--- a/app/controller/FeishuController.php
+++ b/app/controller/FeishuController.php
@@ -141,17 +141,18 @@ class FeishuController
/**
- * @param $receiveId openid
- * @param $title 推送标题
- * @param $content 推送内容
- * @param $href 详情链接
+ * @param $receiveId //openid
+ * @param $title //推送标题
+ * @param $content //推送内容
+ * @param $href //详情链接
+ * @param $msgType = 'post'; //卡片消息:interactive,富文本消息:post
* @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);
- 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']);
@@ -160,7 +161,7 @@ class FeishuController
// $receiveId = 'ou_a3b97543acbf1b28d978356bb08f85dd';
// 富文本 类型
- $content = "{
+ /*$content = "{
\"zh_cn\":{
\"title\":\"$title\",
\"content\":[
@@ -179,7 +180,7 @@ class FeishuController
}]
]
}
- }";
+ }";*/
// 卡片 类型
/*$content = "{
@@ -212,13 +213,88 @@ class FeishuController
}
}";*/
// $msgType = 'interactive';
- $msgType = 'post'; //卡片消息:interactive,富文本消息:post
+// $msgType = 'post'; //卡片消息:interactive,富文本消息:post
$receiveIdtype = 'open_id';
$result = $class->sendMessages($receiveId, $content, $msgType, $receiveIdtype);
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()
{
return '
查看详情 - 示例页面
';
diff --git a/app/middleware/DataTracker.php b/app/middleware/DataTracker.php
new file mode 100644
index 0000000..5d06b4d
--- /dev/null
+++ b/app/middleware/DataTracker.php
@@ -0,0 +1,66 @@
+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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/app/model/Daily.php b/app/model/Daily.php
new file mode 100644
index 0000000..2ce3b46
--- /dev/null
+++ b/app/model/Daily.php
@@ -0,0 +1,61 @@
+ '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');
+ }
+}
\ No newline at end of file
diff --git a/app/model/RequestTracks.php b/app/model/RequestTracks.php
new file mode 100644
index 0000000..6313304
--- /dev/null
+++ b/app/model/RequestTracks.php
@@ -0,0 +1,57 @@
+ '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; // 不做任何操作
+ }
+}
\ No newline at end of file
diff --git a/app/process/Task.php b/app/process/Task.php
index 97ae0fe..926a7b6 100644
--- a/app/process/Task.php
+++ b/app/process/Task.php
@@ -6,6 +6,7 @@ use app\controller\FeishuController;
use app\model\Customer;
use app\model\CustomerHis;
use app\model\FeishuUser;
+use app\model\RequestTracks;
use app\model\User;
use support\Log;
use Webman\App;
@@ -65,7 +66,8 @@ class Task
$item->warn = 1;
$item->update();
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(){
echo date('Y-m-d H:i:s') . "\n";
Log::info('send high seas start',[time()]);
@@ -95,6 +97,56 @@ class Task
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()]);
+ });
+
}
}
\ No newline at end of file
diff --git a/config/const.php b/config/const.php
index 12ba463..cfcfe6e 100644
--- a/config/const.php
+++ b/config/const.php
@@ -2,4 +2,9 @@
return [
'rpc_domain' => getenv('RPC_DOMAIN'),
+ 'event_tracking' => [
+ 'follow/save',
+ 'customer/claim',
+ 'customer/save',
+ ],
];
\ No newline at end of file
diff --git a/config/middleware.php b/config/middleware.php
index 8296416..9d8c0e5 100644
--- a/config/middleware.php
+++ b/config/middleware.php
@@ -17,5 +17,12 @@ return [
'' => [
app\middleware\CrossDomain::class, // 全局跨域中间件
app\middleware\AuthMiddleware::class, // 鉴权中间件
+// app\middleware\DataTracker::class, //埋点
+ ],
+
+ // 路由中间件
+ 'route' => [
+// 'track' => app\middleware\DataTracker::class,
]
+
];
\ No newline at end of file