Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
loveisland
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
刘小敏
loveisland
Commits
0295ea54
Commit
0295ea54
authored
May 19, 2026
by
刘小敏
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PV UV 采集代码
parent
1f5ee2ec
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
226 additions
and
0 deletions
+226
-0
PV埋点异步处理方案0519-2.md
PV埋点异步处理方案0519-2.md
+0
-0
Track.php
addons/shopro/controller/api/Track.php
+82
-0
TrackProcessJob.php
addons/shopro/job/TrackProcessJob.php
+144
-0
No files found.
PV埋点异步处理方案0519-2.md
0 → 100644
View file @
0295ea54
This diff is collapsed.
Click to expand it.
addons/shopro/controller/api/Track.php
0 → 100644
View file @
0295ea54
<?php
namespace
addons\shopro\controller\api
;
use
think\Queue
;
//use app\admin\controller\shopro\Common;
use
addons\shopro\controller\Common
;
class
Track
extends
Common
{
/**
* 无需登录的方法
* @var array
*/
protected
$noNeedLogin
=
[
'upload'
,
'stats'
];
protected
$noNeedRight
=
[
'*'
];
/**
* 接收埋点数据(推入队列)
*/
public
function
upload
()
{
// 限制请求大小
if
(
$_SERVER
[
'CONTENT_LENGTH'
]
>
5
*
1024
*
1024
)
{
$this
->
error
(
'请求数据过大'
);
}
// 获取原始数据
$rawData
=
file_get_contents
(
'php://input'
);
if
(
empty
(
$rawData
))
{
$this
->
error
(
'请求数据为空'
);
}
// 解析JSON
$requestData
=
json_decode
(
$rawData
,
true
);
if
(
json_last_error
()
!==
JSON_ERROR_NONE
)
{
$this
->
error
(
'JSON解析失败'
);
}
// 验证必要参数
if
(
!
isset
(
$requestData
[
'list'
])
||
!
is_array
(
$requestData
[
'list'
]))
{
$this
->
error
(
'参数错误'
);
}
//print_r([
// 'data' => $requestData['list'],
// 'ip' => $this->request->ip(),
// 'timestamp' => time()
//]);
// 推入队列
$jobId
=
Queue
::
push
(
'addons\shopro\job\TrackProcessJob@fire'
,
[
'data'
=>
$requestData
[
'list'
],
'ip'
=>
$this
->
request
->
ip
(),
'timestamp'
=>
time
()
],
'shopro-high'
);
if
(
$jobId
)
{
$this
->
success
(
'接收成功'
);
}
else
{
$this
->
error
(
'队列推送失败'
);
}
}
/**
* 获取统计数据
*/
public
function
stats
()
{
$startDate
=
$this
->
request
->
param
(
'start'
,
date
(
'Y-m-d'
,
strtotime
(
'-7 days'
)));
$endDate
=
$this
->
request
->
param
(
'end'
,
date
(
'Y-m-d'
));
// 参数验证
if
(
!
preg_match
(
'/^\d{4}-\d{2}-\d{2}$/'
,
$startDate
)
||
!
preg_match
(
'/^\d{4}-\d{2}-\d{2}$/'
,
$endDate
))
{
$this
->
error
(
'日期格式错误'
);
}
$stats
=
\app\admin\model\shopro\MiniProgramStats
::
whereBetween
(
'date'
,
[
$startDate
,
$endDate
])
->
order
(
'date ASC'
)
->
select
();
$this
->
success
(
'获取成功'
,
$stats
);
}
}
\ No newline at end of file
addons/shopro/job/TrackProcessJob.php
0 → 100644
View file @
0295ea54
<?php
// addons/shopro/job/TrackProcessJob.php
namespace
addons\shopro\job
;
use
think\queue\Job
;
use
think\Db
;
use
think\Queue
;
class
TrackProcessJob
{
/**
* 执行队列任务
*/
public
function
fire
(
Job
$job
,
$data
)
{
try
{
$trackData
=
$data
[
'data'
]
??
[];
$clientIp
=
$data
[
'ip'
]
??
''
;
if
(
empty
(
$trackData
))
{
$job
->
delete
();
return
;
}
// 1. 批量插入埋点数据
$this
->
insertTracks
(
$trackData
,
$clientIp
);
// 2. 更新统计数据
$this
->
updateStats
();
// 3. 删除任务
$job
->
delete
();
}
catch
(
\Exception
$e
)
{
// 重试机制
if
(
$job
->
attempts
()
<
3
)
{
$job
->
release
(
60
);
// 60秒后重试
}
else
{
// 记录失败数据
$this
->
saveFailed
(
$data
,
$e
->
getMessage
());
$job
->
delete
();
}
}
}
/**
* 批量插入埋点数据
*/
protected
function
insertTracks
(
$trackData
,
$clientIp
)
{
$insertData
=
[];
$now
=
time
();
foreach
(
$trackData
as
$item
)
{
$insertData
[]
=
[
'user_id'
=>
$item
[
'user_id'
]
??
0
,
'openid'
=>
$item
[
'openid'
]
??
''
,
'session_id'
=>
$item
[
'session_id'
]
??
''
,
'event_type'
=>
$item
[
'event_type'
]
??
''
,
'page_path'
=>
$item
[
'page_path'
]
??
''
,
'page_title'
=>
$item
[
'page_title'
]
??
''
,
'params'
=>
!
empty
(
$item
[
'params'
])
?
json_encode
(
$item
[
'params'
])
:
''
,
'ip'
=>
$clientIp
,
'create_time'
=>
isset
(
$item
[
'create_time'
])
?
(
int
)(
$item
[
'create_time'
]
/
1000
)
:
$now
];
}
// 分批插入(每批500条)
$batches
=
array_chunk
(
$insertData
,
500
);
foreach
(
$batches
as
$batch
)
{
Db
::
name
(
'shopro_miniprogram_track'
)
->
insertAll
(
$batch
);
}
}
/**
* 更新统计数据
*/
protected
function
updateStats
()
{
$date
=
date
(
'Y-m-d'
);
// 统计UV(按openid去重)
$uv
=
Db
::
name
(
'shopro_miniprogram_track'
)
->
whereDate
(
'create_time'
,
$date
)
->
distinct
(
true
)
->
count
(
'openid'
);
// 统计PV(页面浏览量)
$pv
=
Db
::
name
(
'shopro_miniprogram_track'
)
->
whereDate
(
'create_time'
,
$date
)
->
where
(
'event_type'
,
'page_view'
)
->
count
();
// 更新或插入统计记录
Db
::
name
(
'shopro_miniprogram_stats'
)
->
updateOrCreate
(
[
'date'
=>
$date
],
[
'uv'
=>
$uv
,
'pv'
=>
$pv
,
'update_time'
=>
time
()
]
);
}
/**
* 保存失败数据
*/
protected
function
saveFailed
(
$data
,
$error
)
{
Db
::
name
(
'shopro_track_failed'
)
->
insert
([
'data'
=>
json_encode
(
$data
),
'error'
=>
$error
,
'attempts'
=>
3
,
'create_time'
=>
time
()
]);
}
// 恢复失败数据的脚本
public
function
retryFailed
()
{
$failedList
=
Db
::
name
(
'shopro_track_failed'
)
->
where
(
'status'
,
0
)
->
select
();
foreach
(
$failedList
as
$item
)
{
try
{
$data
=
json_decode
(
$item
[
'data'
],
true
);
// 重新推入队列
Queue
::
push
(
'\addons\shopro\job\TrackProcessJob@fire'
,
$data
,
'shopro-high'
);
// 更新状态为已处理
Db
::
name
(
'shopro_track_failed'
)
->
where
(
'id'
,
$item
[
'id'
])
->
update
([
'status'
=>
1
,
'update_time'
=>
time
()]);
}
catch
(
\Exception
$e
)
{
// 更新状态为已放弃
Db
::
name
(
'shopro_track_failed'
)
->
where
(
'id'
,
$item
[
'id'
])
->
update
([
'status'
=>
2
,
'error'
=>
$e
->
getMessage
(),
'update_time'
=>
time
()]);
}
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment