Files
easygoadmin-wiki/EasyGoAdmin_Iris_AntdVue/zh/modules/user.md
T
2026-10-20 21:19:44 +08:00

6.9 KiB
Raw Blame History

6.1 用户管理

:::tip 概述 用户管理是系统核心模块,继承 BaseTenantLogic 实现租户隔离,支持 CRUD、重置密码、Excel 导入导出。 :::

模块特点

特性 说明
租户隔离 继承 BaseTenantLogic,自动按 tenant_id 过滤
数据权限 配置 dataScopeDeptField='dept_id',支持按部门过滤
编码生成 beforeAdd 自动生成用户编码(租户编码-6位序号,如 T0001-000020)
文件字段 avatar(头像),保存到 user/avatar 目录
唯一校验 username、mobile 全局唯一
枚举映射 gender→gender 字典,status→user_status 字典
密码加密 bcrypt 双重加盐,新增时自动加密
角色关联 通过 UserRole 中间表关联,支持多角色

文件清单

文件 说明
app/controller/UserController.php 控制器(9 个接口)
app/logic/UserLogic.php 逻辑层(含 import/export/resetPassword)
app/model/User.php 模型
app/model/UserRole.php 用户角色关联模型
app/validate/UserValidate.php 验证器

API 接口

方法 路径 权限码 说明
GET /api/user/page sys:user:page 分页列表
GET /api/user/detail/:id sys:user:detail 详情
POST /api/user/add sys:user:add 新增
PUT /api/user/update sys:user:update 修改
PUT /api/user/resetPwd sys:user:resetPwd 重置密码
DELETE /api/user/delete/:id sys:user:delete 删除
DELETE /api/user/batchDelete sys:user:batchDelete 批量删除
POST /api/user/import sys:user:import 导入
GET /api/user/export sys:user:export 导出

特殊逻辑

重置密码

// app/controller/UserController.php

public function resetPwd(): Json
{
    $data = $this->getJsonBody();
    $id = $data['userId'] ?? 0;

    if (empty($id)) {
        return $this->fail('缺少id参数');
    }

    $this->logic->resetPassword($id);
    return $this->success(null, '密码重置成功');
}

请求参数:

参数 类型 必填 说明
userId int 是 用户ID

:::tip 默认密码 重置密码接口无需传递密码参数,系统自动使用 PasswordService::getDefaultPasswordPlain() 作为默认密码。 :::

新增用户(beforeAdd 钩子)

// app/logic/UserLogic.php

/**
 * 新增前处理:生成编码、处理城市、加密密码
 *
 * @param array $data 待新增的数据
 * @return array 处理后的数据
 */
protected function beforeAdd(array $data): array
{
    // 自动生成用户编码:租户编码 + 租户内序号(如 T0001-000020)
    $tenantId = $data['tenantId'] ?? request()->tenantId ?? 0;
    if ($tenantId == 0) {
        $tenantId = config('tenant.default_tenant_id', 1);
    }
    if ($tenantId > 0) {
        $tenant = Tenant::find($tenantId);
        $currentUserCount = User::where('tenant_id', $tenantId)->where('is_delete', 0)->count();
        $nextSeq = $currentUserCount + 1;
        $data['code'] = $tenant->code . '-' . str_pad((string)$nextSeq, 6, '0', STR_PAD_LEFT);
    }

    // 处理城市字段
    if (isset($data['city']) && is_array($data['city'])) {
        $data['province_code'] = $data['city'][0] ?? '';
        $data['city_code'] = $data['city'][1] ?? '';
        $data['district_code'] = $data['city'][2] ?? '';
        $data['street_code'] = $data['city'][3] ?? '';
        $data['city_info'] = City::resolveCityNames($data['city']);
        unset($data['city']);
    }

    // 密码加密
    $password = $data['password'] ?? PasswordService::getDefaultPasswordPlain();
    $encrypted = PasswordService::encrypt($password);
    $data['password'] = $encrypted['password'];
    $data['salt'] = $encrypted['salt'];

    return $data;
}

:::tip 编码规则

  • 用户编码格式:租户编码-6位序号,如 T0001-000020
  • 序号 = 当前租户下未删除用户数 + 1
  • 超级管理员(tenantId=0)自动代入默认租户生成编码
  • 编码由系统自动生成,前端不传,修改时不可变更 :::

新增后保存角色(afterAdd 钩子)

/**
 * 新增后处理:保存用户角色关联
 *
 * @param int   $id   新增用户的主键 ID
 * @param array $data 新增时提交的原始数据
 * @return void
 */
protected function afterAdd(int $id, array $data): void
{
    $roleIds = $data['roles'] ?? [];
    foreach ($roleIds as $roleId) {
        UserRole::create([
            'user_id' => $id,
            'role_id' => $roleId,
            'create_user' => request()->userInfo->username ?? '',
        ]);
    }
}

:::info 多角色支持 前端传 roles: [1, 2, 3] 数组,afterAdd 遍历写入 UserRole 中间表。afterUpdate 同理,先删后插实现全量覆盖。 :::

详情补全(afterDetail 钩子)

/**
 * 详情查询后处理:补充关联数据与格式化输出
 *
 * @param int   $id   用户 ID
 * @param array &$data 详情数据(引用传递)
 * @return void
 */
protected function afterDetail(int $id, array &$data): void
{
    // 补充角色信息
    $roleIds = UserRole::where('user_id', $id)->column('role_id');
    $data['roles'] = $roleIds;

    // 补充关联名称
    $data['levelName'] = Level::getNameMap()[$data['level_id']] ?? '';
    $data['positionName'] = Position::getNameMap()[$data['position_id']] ?? '';
    $data['deptName'] = Dept::getNameMap()[$data['dept_id']] ?? '';

    // 组装城市数组
    $data['city'] = [
        $data['province_code'] ?? '',
        $data['city_code'] ?? '',
        $data['district_code'] ?? '',
        $data['street_code'] ?? '',
    ];

    // 移除敏感字段
    unset($data['password'], $data['salt']);
}

导出(export)

导出为分批导出(chunkExport),每批 500 条,避免内存溢出。

导出列 字段来源
用户编码 code(系统自动生成)
姓名 realname
性别 genderText(DictService 自动转换)
手机号 mobile
邮箱 email
部门 deptName(Dept::getNameMap 映射)
职级 levelName(Level::getNameMap 映射)
岗位 positionName(Position::getNameMap 映射)
城市 cityInfo(4个城市编码拼接为名称字符串)
地址 address
用户名 username
简介 intro
状态 statusText(DictService 自动转换)
备注 note

导入(import)

导入时需处理以下反向映射:

导入列 处理逻辑
性别/状态 非数字时 DictService::getValue 反查
部门/职级/岗位 名称通过 array_flip(getNameMap) 反查 ID
城市 cityInfo 通过 City::resolveCityCodes 拆为4个编码
用户编码 忽略(由 beforeAdd 自动生成)

:::warning 导入不处理 code 导入时即使 Excel 中有「用户编码」列也会被忽略,编码由 beforeAdd 自动生成。 :::