高考版优化
审核模式优化
This commit is contained in:
@@ -5,6 +5,7 @@ use app\BaseController;
|
||||
use app\common\service\ResumeUploadsAdminService;
|
||||
use app\controller\admin\concern\ExtractsTestResults;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
use think\facade\Request;
|
||||
|
||||
/**
|
||||
@@ -419,6 +420,200 @@ class AppUser extends BaseController
|
||||
return paginate_response($list, $total, $page, $pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* JOIN 后按去重用户计数(别名 w = wechat_users)
|
||||
* 不可用 fieldRaw + value(别名):ThinkPHP 的 value() 会清空 field 并把参数当成列名,聚合会丢失。
|
||||
*
|
||||
* @param \think\db\Query $query
|
||||
*/
|
||||
private function countDistinctAppUsers($query): int
|
||||
{
|
||||
try {
|
||||
// find() 在无 where 时不执行 SQL(仅 JOIN 也会被跳过),聚合恒错成 0
|
||||
$row = (clone $query)
|
||||
->whereRaw('1=1')
|
||||
->fieldRaw('COUNT(DISTINCT `w`.`id`) AS `_agg_u`')
|
||||
->find();
|
||||
|
||||
if (is_object($row) && method_exists($row, 'toArray')) {
|
||||
$row = $row->toArray();
|
||||
}
|
||||
if (!is_array($row)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) ($row['_agg_u'] ?? 0);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('[AppUser::countDistinctAppUsers] ' . $e->getMessage());
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户画像汇总卡片(与列表同一企业口径)
|
||||
* GET /api/v1/admin/app-users/stats
|
||||
*/
|
||||
public function stats()
|
||||
{
|
||||
$user = $this->request->user ?? null;
|
||||
if (!$user) {
|
||||
return error('未登录', 401);
|
||||
}
|
||||
if (!in_array($user['role'] ?? '', ['admin', 'enterprise_admin'])) {
|
||||
return error('无权限访问', 403);
|
||||
}
|
||||
|
||||
$enterpriseId = $user['enterpriseId'] ?? null;
|
||||
if (!$enterpriseId) {
|
||||
$adminRow = Db::name('users')->where('id', $user['userId'] ?? 0)->find();
|
||||
$enterpriseId = $adminRow['enterpriseId'] ?? null;
|
||||
}
|
||||
|
||||
$out = [
|
||||
'faceCount' => 0,
|
||||
'resumeCount' => 0,
|
||||
'phoneCount' => 0,
|
||||
'anyTestCount' => 0,
|
||||
'cooperationCount' => 0,
|
||||
];
|
||||
|
||||
try {
|
||||
if ($enterpriseId) {
|
||||
$eid = (int) $enterpriseId;
|
||||
$poolSql = Db::name('user_profile')
|
||||
->whereRaw('enterpriseId = ' . $eid)
|
||||
->group('userId')
|
||||
->field('userId')
|
||||
->buildSql(true);
|
||||
|
||||
$dedupSql = Db::name('wechat_users')
|
||||
->alias('w2')
|
||||
->join([$poolSql => 'p2'], 'w2.id = p2.userId')
|
||||
->field('w2.openid, MAX(w2.id) AS mid')
|
||||
->group('w2.openid')
|
||||
->buildSql(true);
|
||||
|
||||
$base = Db::name('wechat_users')->alias('w')
|
||||
->join([$poolSql => 'p'], 'w.id = p.userId')
|
||||
->join([$dedupSql => 'd'], 'w.id = d.mid');
|
||||
|
||||
$tblUp = Db::name('user_profile')->getTable();
|
||||
$tblTr = Db::name('test_results')->getTable();
|
||||
$out['faceCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)->whereRaw(
|
||||
'EXISTS (SELECT 1 FROM `' . $tblUp
|
||||
. '` up WHERE up.userId = `w`.`id` AND up.enterpriseId = ? AND (TRIM(IFNULL(up.coldFaceLevel,\'\')) <> \'\' OR up.coldFaceScore IS NOT NULL))'
|
||||
. ' OR EXISTS (SELECT 1 FROM `' . $tblTr
|
||||
. '` tf WHERE tf.userId = `w`.`id` AND tf.enterpriseId = ? AND tf.testType IN (\'face\',\'ai\'))',
|
||||
[$eid, $eid]
|
||||
)
|
||||
);
|
||||
|
||||
$out['phoneCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
);
|
||||
|
||||
$out['anyTestCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('test_results tr', 'tr.userId = w.id')
|
||||
->where('tr.enterpriseId', $eid)
|
||||
);
|
||||
|
||||
// 与「合作意向」Tab 一致:本企业 user_cooperation_choices 去重人数,不依赖 user_profile 池
|
||||
$coopRow = Db::name('user_cooperation_choices')
|
||||
->where('enterpriseId', $eid)
|
||||
->fieldRaw('COUNT(DISTINCT `userId`) AS `_c`')
|
||||
->find();
|
||||
$out['cooperationCount'] = (int) (is_array($coopRow) ? ($coopRow['_c'] ?? 0) : 0);
|
||||
|
||||
$cntResumeUpload = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('enterprise_resume_uploads eru', 'eru.userId = w.id')
|
||||
->where('eru.enterpriseId', $eid)
|
||||
);
|
||||
|
||||
$cntPhoneAndTest = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
->join('test_results tr2', 'tr2.userId = w.id')
|
||||
->where('tr2.enterpriseId', $eid)
|
||||
);
|
||||
|
||||
$cntBoth = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('enterprise_resume_uploads eru', 'eru.userId = w.id')
|
||||
->where('eru.enterpriseId', $eid)
|
||||
->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
->join('test_results tr3', 'tr3.userId = w.id')
|
||||
->where('tr3.enterpriseId', $eid)
|
||||
);
|
||||
|
||||
$out['resumeCount'] = max(0, $cntResumeUpload + $cntPhoneAndTest - $cntBoth);
|
||||
} else {
|
||||
$dedupSql = Db::name('wechat_users')
|
||||
->alias('w2')
|
||||
->field('w2.openid, MAX(w2.id) AS mid')
|
||||
->group('w2.openid')
|
||||
->buildSql(true);
|
||||
|
||||
$base = Db::name('wechat_users')->alias('w')
|
||||
->join([$dedupSql => 'd'], 'w.id = d.mid');
|
||||
|
||||
$tblUp = Db::name('user_profile')->getTable();
|
||||
$tblTr = Db::name('test_results')->getTable();
|
||||
$out['faceCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)->whereRaw(
|
||||
'EXISTS (SELECT 1 FROM `' . $tblUp
|
||||
. '` up WHERE up.userId = `w`.`id` AND (TRIM(IFNULL(up.coldFaceLevel,\'\')) <> \'\' OR up.coldFaceScore IS NOT NULL))'
|
||||
. ' OR EXISTS (SELECT 1 FROM `' . $tblTr
|
||||
. '` tf WHERE tf.userId = `w`.`id` AND tf.testType IN (\'face\',\'ai\'))'
|
||||
)
|
||||
);
|
||||
|
||||
$out['phoneCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
);
|
||||
|
||||
$out['anyTestCount'] = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('test_results tr', 'tr.userId = w.id')
|
||||
);
|
||||
|
||||
// 与「合作意向」Tab 一致:全平台去重 userId(无企业归属账号)
|
||||
$coopRowAll = Db::name('user_cooperation_choices')
|
||||
->whereRaw('1=1')
|
||||
->fieldRaw('COUNT(DISTINCT `userId`) AS `_c`')
|
||||
->find();
|
||||
$out['cooperationCount'] = (int) (is_array($coopRowAll) ? ($coopRowAll['_c'] ?? 0) : 0);
|
||||
|
||||
$cntResumeUpload = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('enterprise_resume_uploads eru', 'eru.userId = w.id')
|
||||
);
|
||||
|
||||
$cntPhoneAndTest = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
->join('test_results tr2', 'tr2.userId=w.id')
|
||||
);
|
||||
|
||||
$cntBoth = $this->countDistinctAppUsers(
|
||||
(clone $base)
|
||||
->join('enterprise_resume_uploads eru', 'eru.userId=w.id')
|
||||
->whereRaw('TRIM(IFNULL(w.phone,\'\')) <> \'\'')
|
||||
->join('test_results tr3', 'tr3.userId=w.id')
|
||||
);
|
||||
|
||||
$out['resumeCount'] = max(0, $cntResumeUpload + $cntPhoneAndTest - $cntBoth);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('[AppUser::stats] ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
|
||||
}
|
||||
|
||||
return success($out);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试用户详情:基本信息 + 测试记录列表
|
||||
* GET /api/v1/admin/app-users/:id
|
||||
|
||||
Reference in New Issue
Block a user