用户选择组件增加角色标签显示
这个提交包含在:
@@ -116,6 +116,19 @@
|
||||
.user-option-nick { margin-right: 4px; }
|
||||
.user-option-real { font-weight: 400; color: #7536D0; font-size: 12px; }
|
||||
.user-option-meta { font-size: 12px; color: #909399; margin-top: 2px; }
|
||||
.user-role-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
|
||||
.user-role-tag {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
border-radius: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.user-role-tag--promoter { background: #f0e8ff; color: #7536D0; }
|
||||
.user-role-tag--regional_agent { background: #e8f7ef; color: #2e9f6a; }
|
||||
.user-role-tag--empty { background: #f4f4f5; color: #909399; }
|
||||
</style>
|
||||
<script src="__CDN__/assets/addons/shopro/libs/vue.js"></script>
|
||||
<script src="__CDN__/assets/addons/shopro/libs/element/element.js"></script>
|
||||
@@ -155,6 +168,14 @@
|
||||
<template v-if="item.mobile"> · 手机 {{ item.mobile }}</template>
|
||||
<template v-if="item.nickname && item.nickname !== item.display_name"> · 昵称 {{ item.nickname }}</template>
|
||||
</div>
|
||||
<div class="user-role-tags">
|
||||
<template v-if="item.roles && item.roles.length">
|
||||
<span v-for="(role, rIdx) in item.roles" :key="rIdx" class="user-role-tag" :class="'user-role-tag--' + role.role_type">
|
||||
{{ role.role_label }}<template v-if="role.status_text">[{{ role.status_text }}]</template>
|
||||
</span>
|
||||
</template>
|
||||
<span v-else class="user-role-tag user-role-tag--empty">无进件角色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-option>
|
||||
@@ -163,8 +184,16 @@
|
||||
<img v-if="selectedUser.avatar" :src="selectedUser.avatar" class="user-selected-avatar" style="border-radius:50%;">
|
||||
<div v-else class="user-selected-avatar">{{ userAvatarText(selectedUser) }}</div>
|
||||
<div>
|
||||
<div class="user-selected-name">{{ selectedUser.option_label }}</div>
|
||||
<div class="user-selected-meta" v-if="selectedUser.real_name">实名:{{ selectedUser.real_name }}</div>
|
||||
<div class="user-selected-name">{{ selectedUser.display_name }} · ID {{ selectedUser.id }}<template v-if="selectedUser.mobile"> · {{ selectedUser.mobile }}</template></div>
|
||||
<div class="user-selected-meta" v-if="selectedUser.real_name && selectedUser.real_name !== selectedUser.display_name">实名:{{ selectedUser.real_name }}</div>
|
||||
<div class="user-role-tags">
|
||||
<template v-if="selectedUser.roles && selectedUser.roles.length">
|
||||
<span v-for="(role, rIdx) in selectedUser.roles" :key="rIdx" class="user-role-tag" :class="'user-role-tag--' + role.role_type">
|
||||
{{ role.role_label }}<template v-if="role.status_text">[{{ role.status_text }}]</template>
|
||||
</span>
|
||||
</template>
|
||||
<span v-else class="user-role-tag user-role-tag--empty">无进件角色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -132,14 +132,20 @@ class HuifuOnboardAdminView
|
||||
->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) {
|
||||
$rows[] = self::formatUserOption($user);
|
||||
$uid = intval($user['id']);
|
||||
$rows[] = self::formatUserOption($user, $roleMap[$uid] ?? []);
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public static function formatUserOption($user)
|
||||
public static function formatUserOption($user, array $roles = null)
|
||||
{
|
||||
$user = is_array($user) ? $user : (method_exists($user, 'toArray') ? $user->toArray() : []);
|
||||
$id = intval($user['id'] ?? 0);
|
||||
@@ -152,6 +158,10 @@ class HuifuOnboardAdminView
|
||||
$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,
|
||||
@@ -161,7 +171,9 @@ class HuifuOnboardAdminView
|
||||
'avatar' => $avatar,
|
||||
'display_name' => $displayName,
|
||||
'real_name' => $realName,
|
||||
'option_label' => self::buildUserOptionLabel($displayName, $realName, $mobile, $id),
|
||||
'roles' => $roles,
|
||||
'roles_text' => $rolesText,
|
||||
'option_label' => self::buildUserOptionLabel($displayName, $realName, $mobile, $id, $rolesText),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -200,9 +212,12 @@ class HuifuOnboardAdminView
|
||||
}
|
||||
}
|
||||
|
||||
protected static function buildUserOptionLabel($displayName, $realName, $mobile, $id)
|
||||
protected static function buildUserOptionLabel($displayName, $realName, $mobile, $id, $rolesText = '')
|
||||
{
|
||||
$parts = [$displayName];
|
||||
if ($rolesText !== '') {
|
||||
$parts[] = $rolesText;
|
||||
}
|
||||
if ($realName !== '' && $realName !== $displayName) {
|
||||
$parts[] = '实名:' . $realName;
|
||||
}
|
||||
@@ -213,6 +228,80 @@ class HuifuOnboardAdminView
|
||||
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'] ?? '';
|
||||
|
||||
@@ -116,6 +116,19 @@
|
||||
.user-option-nick { margin-right: 4px; }
|
||||
.user-option-real { font-weight: 400; color: #7536D0; font-size: 12px; }
|
||||
.user-option-meta { font-size: 12px; color: #909399; margin-top: 2px; }
|
||||
.user-role-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
|
||||
.user-role-tag {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
border-radius: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.user-role-tag--promoter { background: #f0e8ff; color: #7536D0; }
|
||||
.user-role-tag--regional_agent { background: #e8f7ef; color: #2e9f6a; }
|
||||
.user-role-tag--empty { background: #f4f4f5; color: #909399; }
|
||||
</style>
|
||||
<script src="__CDN__/assets/addons/shopro/libs/vue.js"></script>
|
||||
<script src="__CDN__/assets/addons/shopro/libs/element/element.js"></script>
|
||||
@@ -155,6 +168,14 @@
|
||||
<template v-if="item.mobile"> · 手机 {{ item.mobile }}</template>
|
||||
<template v-if="item.nickname && item.nickname !== item.display_name"> · 昵称 {{ item.nickname }}</template>
|
||||
</div>
|
||||
<div class="user-role-tags">
|
||||
<template v-if="item.roles && item.roles.length">
|
||||
<span v-for="(role, rIdx) in item.roles" :key="rIdx" class="user-role-tag" :class="'user-role-tag--' + role.role_type">
|
||||
{{ role.role_label }}<template v-if="role.status_text">[{{ role.status_text }}]</template>
|
||||
</span>
|
||||
</template>
|
||||
<span v-else class="user-role-tag user-role-tag--empty">无进件角色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-option>
|
||||
@@ -163,8 +184,16 @@
|
||||
<img v-if="selectedUser.avatar" :src="selectedUser.avatar" class="user-selected-avatar" style="border-radius:50%;">
|
||||
<div v-else class="user-selected-avatar">{{ userAvatarText(selectedUser) }}</div>
|
||||
<div>
|
||||
<div class="user-selected-name">{{ selectedUser.option_label }}</div>
|
||||
<div class="user-selected-meta" v-if="selectedUser.real_name">实名:{{ selectedUser.real_name }}</div>
|
||||
<div class="user-selected-name">{{ selectedUser.display_name }} · ID {{ selectedUser.id }}<template v-if="selectedUser.mobile"> · {{ selectedUser.mobile }}</template></div>
|
||||
<div class="user-selected-meta" v-if="selectedUser.real_name && selectedUser.real_name !== selectedUser.display_name">实名:{{ selectedUser.real_name }}</div>
|
||||
<div class="user-role-tags">
|
||||
<template v-if="selectedUser.roles && selectedUser.roles.length">
|
||||
<span v-for="(role, rIdx) in selectedUser.roles" :key="rIdx" class="user-role-tag" :class="'user-role-tag--' + role.role_type">
|
||||
{{ role.role_label }}<template v-if="role.status_text">[{{ role.status_text }}]</template>
|
||||
</span>
|
||||
</template>
|
||||
<span v-else class="user-role-tag user-role-tag--empty">无进件角色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
在新工单中引用
屏蔽一个用户