文件
xionggeshop/addons/shopro_huifu/library/onboard/HuifuOnboardAdminView.php
2026-09-29 15:51:26 +08:00

541 行
19 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace addons\shopro_huifu\library\onboard;
use think\Db;
class HuifuOnboardAdminView
{
public static function enrichListRow($row)
{
if (!$row) {
return $row;
}
$data = is_array($row) ? $row : $row->toArray();
$payload = self::parsePayload($data['payload'] ?? '');
$user = self::fetchUser($data['user_id']);
$biz = self::businessStatus($data);
$data['user_nickname'] = $user['nickname'] ?? '';
$data['user_mobile'] = $user['mobile'] ?? '';
$data['payload_name'] = $payload['name'] ?? '';
$data['payload_mobile'] = $payload['mobile_no'] ?? '';
$data['payload_cert_no'] = self::maskCertNo($payload['cert_no'] ?? '');
$data['payload_card_tail'] = self::maskCardTail($payload['card_no'] ?? '');
$data['business_status'] = $biz['status'];
$data['business_status_text'] = $biz['status_text'];
$data['audit_url'] = $biz['audit_url'];
return $data;
}
public static function buildDetail($row)
{
if (!$row) {
return null;
}
$data = is_array($row) ? $row : $row->toArray();
$payload = self::parsePayload($data['payload'] ?? '');
$user = self::fetchUser($data['user_id']);
$biz = self::businessStatus($data);
$fileMap = self::parsePayload($data['file_map'] ?? '');
$validityMap = ['0' => '非长期有效', '1' => '长期有效'];
$form = [
'account_type' => $payload['account_type'] ?? 'indv',
'account_type_text' => ($payload['account_type'] ?? 'indv') === 'ent' ? '个体户/企业' : '个人',
'reg_name' => $payload['reg_name'] ?? '',
'license_code' => $payload['license_code'] ?? '',
'legal_name' => $payload['legal_name'] ?? '',
'branch_name' => $payload['branch_name'] ?? '',
'name' => $payload['name'] ?? '',
'cert_no' => $payload['cert_no'] ?? '',
'cert_no_masked' => self::maskCertNo($payload['cert_no'] ?? ''),
'cert_validity_type' => $payload['cert_validity_type'] ?? '',
'cert_validity_text' => $validityMap[$payload['cert_validity_type'] ?? ''] ?? '-',
'cert_begin_date' => self::formatYmd($payload['cert_begin_date'] ?? ''),
'cert_end_date' => self::formatYmd($payload['cert_end_date'] ?? ''),
'mobile_no' => $payload['mobile_no'] ?? '',
'card_no' => $payload['card_no'] ?? '',
'card_no_masked' => self::maskCardNo($payload['card_no'] ?? ''),
'card_name' => $payload['card_name'] ?? '',
'branch_code' => $payload['branch_code'] ?? '',
'prov_id' => $payload['prov_id'] ?? '',
'area_id' => $payload['area_id'] ?? '',
'id_card_front_url' => self::fullUrl($payload['id_card_front_url'] ?? ''),
'id_card_back_url' => self::fullUrl($payload['id_card_back_url'] ?? ''),
'bank_card_url' => self::fullUrl($payload['bank_card_url'] ?? ''),
];
return [
'record' => [
'id' => $data['id'],
'user_id' => $data['user_id'],
'role_type' => $data['role_type'],
'role_ref_id' => $data['role_ref_id'],
'onboard_status' => $data['onboard_status'],
'huifu_id' => $data['huifu_id'] ?? '',
'apply_no' => $data['apply_no'] ?? '',
'reject_reason' => $data['reject_reason'] ?? '',
'createtime' => $data['createtime'] ?? 0,
'updatetime' => $data['updatetime'] ?? 0,
],
'user' => [
'id' => $user['id'] ?? $data['user_id'],
'nickname' => $user['nickname'] ?? '',
'mobile' => $user['mobile'] ?? '',
'avatar' => self::fullUrl($user['avatar'] ?? ''),
],
'business' => $biz,
'form' => $form,
'file_map' => $fileMap,
'can_submit_huifu' => ($data['onboard_status'] ?? '') === 'draft',
'can_retry_huifu' => in_array($data['onboard_status'] ?? '', ['rejected', 'failed'], true),
'can_poll' => !in_array($data['onboard_status'] ?? '', ['draft', 'approved'], true),
];
}
public static function fetchUserPublic($userId)
{
return self::fetchUser($userId);
}
protected static function fetchUser($userId)
{
$userId = intval($userId);
if ($userId <= 0) {
return [];
}
try {
return Db::name('user')->where('id', $userId)->field('id,nickname,username,mobile,avatar')->find() ?: [];
} catch (\Throwable $e) {
return [];
}
}
/**
* 后台进件:搜索可选用户(下拉展示昵称/实名/手机/ID)
*/
public static function searchUsers($keyword, $limit = 20)
{
$keyword = trim((string) $keyword);
if ($keyword === '') {
return [];
}
$limit = max(1, min(50, intval($limit)));
$idKeyword = is_numeric($keyword) ? intval($keyword) : 0;
$query = Db::name('user')->where(function ($q) use ($keyword, $idKeyword) {
if ($idKeyword > 0) {
$q->whereOr('id', '=', $idKeyword);
}
$q->whereOr('nickname', 'like', "%{$keyword}%")
->whereOr('mobile', 'like', "%{$keyword}%")
->whereOr('username', 'like', "%{$keyword}%");
});
$list = $query->field('id,nickname,username,mobile,avatar')->order('id desc')->limit($limit)->select();
$userIds = [];
foreach ($list as $user) {
$userIds[] = intval($user['id']);
}
$roleMap = self::listRoleSummariesForUsers($userIds);
$rows = [];
foreach ($list as $user) {
$uid = intval($user['id']);
$rows[] = self::formatUserOption($user, $roleMap[$uid] ?? []);
}
return $rows;
}
public static function formatUserOption($user, array $roles = null)
{
$user = is_array($user) ? $user : (method_exists($user, 'toArray') ? $user->toArray() : []);
$id = intval($user['id'] ?? 0);
if ($id <= 0) {
return [];
}
$nickname = trim((string) ($user['nickname'] ?? ''));
$username = trim((string) ($user['username'] ?? ''));
$mobile = trim((string) ($user['mobile'] ?? ''));
$avatar = self::fullUrl($user['avatar'] ?? '');
$realName = self::fetchUserRealNameHint($id);
$displayName = self::resolveUserDisplayName($id, $nickname, $username, $realName);
if ($roles === null) {
$roles = self::listRoleSummariesForUsers([$id])[$id] ?? [];
}
$rolesText = self::buildRolesText($roles);
return [
'id' => $id,
'nickname' => $nickname,
'username' => $username,
'mobile' => $mobile,
'avatar' => $avatar,
'display_name' => $displayName,
'real_name' => $realName,
'roles' => $roles,
'roles_text' => $rolesText,
'option_label' => self::buildUserOptionLabel($displayName, $realName, $mobile, $id, $rolesText),
];
}
protected static function resolveUserDisplayName($id, $nickname, $username, $realName = '')
{
if ($nickname !== '' && $nickname !== (string) $id) {
return $nickname;
}
if ($username !== '' && $username !== (string) $id) {
return $username;
}
if ($realName !== '') {
return $realName;
}
if ($nickname !== '') {
return $nickname;
}
return '用户' . $id;
}
protected static function fetchUserRealNameHint($userId)
{
$userId = intval($userId);
if ($userId <= 0) {
return '';
}
try {
$row = Db::name('shopro_huifu_onboard')->where('user_id', $userId)->order('id desc')->find();
if (!$row) {
return '';
}
$payload = self::parsePayload($row['payload'] ?? '');
return trim((string) ($payload['name'] ?? $payload['legal_name'] ?? $payload['reg_name'] ?? ''));
} catch (\Throwable $e) {
return '';
}
}
protected static function buildUserOptionLabel($displayName, $realName, $mobile, $id, $rolesText = '')
{
$parts = [$displayName];
if ($rolesText !== '') {
$parts[] = $rolesText;
}
if ($realName !== '' && $realName !== $displayName) {
$parts[] = '实名:' . $realName;
}
if ($mobile !== '') {
$parts[] = $mobile;
}
$parts[] = 'ID:' . $id;
return implode(' · ', $parts);
}
/**
* 批量获取用户可进件角色摘要(分销商/区域公司等)
*/
public static function listRoleSummariesForUsers(array $userIds)
{
$userIds = array_values(array_unique(array_filter(array_map('intval', $userIds))));
$map = [];
foreach ($userIds as $uid) {
$map[$uid] = [];
}
if (!$userIds) {
return $map;
}
$statusMap = [
'pending' => '待审核',
'normal' => '已通过',
'needinfo' => '待完善',
'reject' => '已驳回',
'forbidden' => '已禁用',
'freeze' => '已冻结',
];
$commissionAgents = Db::name('shopro_commission_agent')->where('user_id', 'in', $userIds)->select();
foreach ($commissionAgents as $agent) {
$uid = intval($agent['user_id']);
$status = $agent['status'] ?? '';
$map[$uid][] = [
'role_type' => 'promoter',
'role_label' => '分销商',
'status' => $status,
'status_text' => $statusMap[$status] ?? ($status ?: ''),
];
}
$regionalAgents = Db::name('shopro_regional_agent')->where('user_id', 'in', $userIds)->order('id desc')->select();
foreach ($regionalAgents as $agent) {
$uid = intval($agent['user_id']);
$label = '区域公司';
if (!empty($agent['area_name'])) {
$label .= '(' . $agent['area_name'] . ')';
}
$status = $agent['status'] ?? '';
$map[$uid][] = [
'role_type' => 'regional_agent',
'role_label' => $label,
'status' => $status,
'status_text' => $statusMap[$status] ?? ($status ?: ''),
];
}
return $map;
}
protected static function buildRolesText(array $roles)
{
if (!$roles) {
return '无进件角色';
}
$parts = [];
foreach ($roles as $role) {
$text = trim((string) ($role['role_label'] ?? ''));
$statusText = trim((string) ($role['status_text'] ?? ''));
if ($text === '') {
continue;
}
if ($statusText !== '') {
$text .= '[' . $statusText . ']';
}
$parts[] = $text;
}
return $parts ? implode('、', $parts) : '无进件角色';
}
protected static function businessStatus(array $data)
{
$roleType = $data['role_type'] ?? '';
$userId = intval($data['user_id'] ?? 0);
$roleRefId = intval($data['role_ref_id'] ?? 0);
$statusMap = [
'pending' => '待审核',
'normal' => '已通过',
'needinfo' => '待完善资料',
'reject' => '已驳回',
'forbidden' => '已禁用',
'freeze' => '已冻结',
];
if ($roleType === 'regional_agent') {
$agent = Db::name('shopro_regional_agent')->where('id', $roleRefId)->find();
$status = $agent['status'] ?? '';
return [
'type' => 'regional_agent',
'type_text' => '区域公司',
'status' => $status,
'status_text' => $statusMap[$status] ?? ($status ?: '未知'),
'area_name' => $agent['area_name'] ?? '',
'audit_url' => $roleRefId ? ('shopro/regional_agent/agent/index') : '',
];
}
$agent = Db::name('shopro_commission_agent')->where('user_id', $userId)->find();
$status = $agent['status'] ?? '';
return [
'type' => 'promoter',
'type_text' => '推广员/分销商',
'status' => $status,
'status_text' => $statusMap[$status] ?? ($status ?: '未成为分销商'),
'area_name' => '',
'audit_url' => 'shopro/commission/agent/index',
];
}
protected static function parsePayload($raw)
{
if (!$raw) {
return [];
}
if (is_array($raw)) {
return $raw;
}
$data = json_decode($raw, true);
return is_array($data) ? $data : [];
}
protected static function fullUrl($url)
{
$url = trim((string) $url);
if ($url === '') {
return '';
}
if (preg_match('/^https?:\/\//i', $url)) {
return $url;
}
return cdnurl($url, true);
}
protected static function maskCertNo($certNo)
{
$certNo = trim((string) $certNo);
if (strlen($certNo) < 8) {
return $certNo;
}
return substr($certNo, 0, 6) . '********' . substr($certNo, -4);
}
protected static function maskCardNo($cardNo)
{
$cardNo = preg_replace('/\s+/', '', (string) $cardNo);
$len = strlen($cardNo);
if ($len <= 4) {
return $cardNo;
}
return str_repeat('*', max(0, $len - 4)) . substr($cardNo, -4);
}
protected static function maskCardTail($cardNo)
{
$cardNo = preg_replace('/\s+/', '', (string) $cardNo);
if ($cardNo === '') {
return '';
}
return '****' . substr($cardNo, -4);
}
protected static function formatYmd($value)
{
$value = preg_replace('/\D/', '', (string) $value);
if (strlen($value) !== 8) {
return $value;
}
return substr($value, 0, 4) . '-' . substr($value, 4, 2) . '-' . substr($value, 6, 2);
}
/**
* 后台新建/编辑进件:列出用户可绑定的角色
*/
public static function listRolesForUser($userId)
{
$userId = intval($userId);
if ($userId <= 0) {
return [];
}
$roles = [];
$commissionAgent = Db::name('shopro_commission_agent')->where('user_id', $userId)->find();
if ($commissionAgent) {
$row = \addons\shopro_huifu\model\Onboard::findByRole($userId, 'promoter', $userId);
$roles[] = self::buildRoleOption(
'promoter',
$userId,
'分销商',
$commissionAgent['status'] ?? '',
$row
);
}
$regionalAgents = Db::name('shopro_regional_agent')->where('user_id', $userId)->order('id desc')->select();
foreach ($regionalAgents as $agent) {
$row = \addons\shopro_huifu\model\Onboard::findByRole($userId, 'regional_agent', $agent['id']);
$label = '区域公司';
if (!empty($agent['area_name'])) {
$label .= '(' . $agent['area_name'] . ')';
}
$roles[] = self::buildRoleOption(
'regional_agent',
$agent['id'],
$label,
$agent['status'] ?? '',
$row
);
}
return $roles;
}
protected static function buildRoleOption($roleType, $roleRefId, $label, $agentStatus, $onboardRow)
{
$onboardStatus = $onboardRow ? ($onboardRow['onboard_status'] ?? '') : '';
$blocked = $onboardRow && in_array($onboardStatus, [
\addons\shopro_huifu\model\Onboard::STATUS_SUBMITTING,
\addons\shopro_huifu\model\Onboard::STATUS_BASIC_OK,
\addons\shopro_huifu\model\Onboard::STATUS_BUSI_PENDING,
\addons\shopro_huifu\model\Onboard::STATUS_APPROVED,
], true);
return [
'role_type' => $roleType,
'role_ref_id' => $roleRefId,
'role_label' => $label,
'agent_status' => $agentStatus,
'onboard_id' => $onboardRow ? intval($onboardRow['id']) : 0,
'onboard_status' => $onboardStatus ?: null,
'can_save' => !$blocked,
'disabled_reason' => $blocked ? '该角色进件处理中或已通过,不可新建/覆盖' : '',
];
}
public static function defaultFormData()
{
return [
'account_type' => 'indv',
'bank_account_type' => '0',
'name' => '',
'cert_no' => '',
'cert_validity_type' => '1',
'cert_begin_date' => '',
'cert_end_date' => '',
'mobile_no' => '',
'reg_detail' => '',
'shopro_province_id' => '',
'shopro_city_id' => '',
'shopro_district_id' => '',
'prov_id' => '',
'area_id' => '',
'district_id' => '',
'card_no' => '',
'card_name' => '',
'branch_code' => '',
'branch_name' => '',
'mp' => '',
'id_card_front_url' => '',
'id_card_back_url' => '',
'bank_card_url' => '',
'reg_name' => '',
'license_code' => '',
'license_validity_type' => '1',
'license_begin_date' => '',
'license_end_date' => '',
'legal_name' => '',
'legal_mobile' => '',
'legal_cert_no' => '',
'legal_cert_validity_type' => '1',
'legal_cert_begin_date' => '',
'legal_cert_end_date' => '',
'license_url' => '',
'legal_id_front_url' => '',
'legal_id_back_url' => '',
'account_permit_url' => '',
];
}
public static function formDataFromRow($row)
{
$data = is_array($row) ? $row : $row->toArray();
$payload = self::parsePayload($data['payload'] ?? '');
$form = array_merge(self::defaultFormData(), $payload);
foreach (['id_card_front_url', 'id_card_back_url', 'bank_card_url', 'license_url', 'legal_id_front_url', 'legal_id_back_url', 'account_permit_url'] as $field) {
if (!empty($form[$field])) {
$form[$field] = self::fullUrl($form[$field]);
}
}
$user = self::fetchUser($data['user_id'] ?? 0);
$roles = self::listRolesForUser($data['user_id'] ?? 0);
$roleLabel = '';
foreach ($roles as $role) {
if ($role['role_type'] === ($data['role_type'] ?? '') && intval($role['role_ref_id']) === intval($data['role_ref_id'] ?? 0)) {
$roleLabel = $role['role_label'];
break;
}
}
return [
'onboard_id' => intval($data['id'] ?? 0),
'user_id' => intval($data['user_id'] ?? 0),
'user_label' => trim(($user['nickname'] ?? '') . ' (' . ($user['mobile'] ?? $data['user_id']) . ')'),
'role_type' => $data['role_type'] ?? '',
'role_ref_id' => intval($data['role_ref_id'] ?? 0),
'role_label' => $roleLabel,
'onboard_status' => $data['onboard_status'] ?? '',
'form' => $form,
];
}
}