星云 ERP
项目简介
下载源码
项目部署
项目模块
liyade-dependencies-common
liyade-dependencies-web-starter
启用缓存机制
实现图片验证码
解决Lettuce连接池超时问题
ImportSelector实战解析
liyade-admin
liyade-settle
liyade-sc
liyade-chart
liyade-basedata
liyade-common
liyade-dependencies-activemq-starter
liyade-core
liyade-template
liyade-dependencies-cloud-starter
liyade-dependencies-mq-starter
liyade-dependencies-websocket-starter
liyade-template-core
liyade-dependencies-web-common
spring.factories
lombok.config
event
lombok.config 文件详解
使用手册
登录功能
系统管理
菜单管理
部门管理
数据库字典
菜单收藏(sys_menu_collect)
库存成本调整单明细(tbl_stock_cost_adjust_sheet_detail)
库存盘点参数设置(tbl_take_stock_config)
库存盘点任务(tbl_take_stock_plan)
库存盘点任务明细(tbl_take_stock_plan_detail)
库存盘点单(tbl_take_stock_sheet)
库存盘点单明细(tbl_take_stock_sheet_detail)
系统参数(sys_parameter)
门店(tbl_shop)
角色与菜单关系表(sys_role_menu)
角色(sys_role)
岗位(sys_position)
库存成本调整单(tbl_stock_cost_adjust_sheet)
菜单(sys_menu)
部门(sys_dept)
商品库存变动记录(tbl_product_stock_log)
商品库存(tbl_product_stock)
商品批次库存(tbl_product_lot_stock)
商品批次(tbl_product_lot)
库存预先盘点单明细(tbl_pre_take_stock_sheet_detail)
库存预先盘点单(tbl_pre_take_stock_sheet)
订单图表数据(tbl_order_chart)
用户绑定手机号表(sys_user_telephone)
零售出库单批次明细(tbl_retail_out_sheet_detail_lot)
采购参数设置(tbl_purchase_config)
采购订单(tbl_purchase_order)
采购订单明细(tbl_purchase_order_detail)
采购退单(tbl_purchase_return)
采购退单明细(tbl_purchase_return_detail)
采购收货单(tbl_receive_sheet)
采购收货单明细(tbl_receive_sheet_detail)
零售参数设置(tbl_retail_config)
零售出库单(tbl_retail_out_sheet)
零售出库单明细(tbl_retail_out_sheet_detail)
用户与角色关系表(sys_user_role)
零售退单(tbl_retail_return)
零售退单明细(tbl_retail_return_detail)
销售参数设置(tbl_sale_config)
销售订单(tbl_sale_order)
销售订单明细(tbl_sale_order_detail)
销售出库单(tbl_sale_out_sheet)
销售出库单明细(tbl_sale_out_sheet_detail)
销售出库单批次明细(tbl_sale_out_sheet_detail_lot)
销售退单(tbl_sale_return)
销售退单明细(tbl_sale_return_detail)
商品零售价(base_data_product_retail)
代码生成基本信息(gen_generate_info)
数据对象列信息(gen_data_object_column)
数据对象(gen_data_object)
新增功能代码生成配置(gen_create_column_config)
地区字典表(dic_city)
供应商(base_data_supplier)
仓库(base_data_store_center)
商品和销售属性值关系表(base_data_product_saleprop_item_relation)
商品销售属性值(base_data_product_saleprop_item)
商品销售属性组(base_data_product_saleprop_group)
商品销售价(base_data_product_sale)
查询功能代码生成配置(gen_query_column_config)
商品采购价(base_data_product_purchase)
商品属性值(base_data_product_property_item)
商品属性(base_data_product_property)
商品SPU和商品属性关系表(base_data_product_poly_property)
商品SPU(base_data_product_poly)
商品类目和商品属性关系表(base_data_product_category_property)
商品类目(base_data_product_category)
商品品牌(base_data_product_brand)
商品(base_data_product)
会员(base_data_member)
收入项目(settle_in_item)
用户与岗位关系表(sys_user_position)
用户与部门关系表(sys_user_dept)
用户(sys_user)
详情功能代码生成配置(gen_detail_column_config)
系统设置(sys_config)
供应商结算单明细(settle_sheet_detail)
供应商结算单(settle_sheet)
供应商预付款单明细(settle_pre_sheet_detail)
供应商预付款单(settle_pre_sheet)
支出项目(settle_out_item)
客户(base_data_customer)
供应商费用单明细(settle_fee_sheet_detail)
供应商费用单(settle_fee_sheet)
供应商对账单明细(settle_check_sheet_detail)
供应商对账单(settle_check_sheet)
树形数据节点关系表(recursion_mapping)
操作日志(op_logs)
修改功能代码生成配置(gen_update_column_config)
数据库单表列信息(gen_simple_table_column)
数据库单表(gen_simple_table)
查询参数功能代码生成配置(gen_query_params_column_config)
-
+
首页
登录功能
## 前端代码 ### 登录接口 > `rc/api/sys/user.ts` 作用是与后端控制器交互 ``` export function loginApi(params: LoginParams): Promise<LoginResultModel> { return defHttp.post<LoginResultModel>( { url: Api.Login, params, }, { contentType: ContentTypeEnum.FORM_URLENCODED, region, }, ); } ``` ### 登录方法 > `rc/store/modules/user.ts` 作用是登录并将返回的 Token 值保存到内存当中,并返回 userInfo 信息 ``` async login(params: LoginParams): Promise<GetUserInfoModel | null> { try { const data = await loginApi(params); const { token } = data; // save token this.setToken(token); const userInfo = { roles: data.roles.map((role) => { return { roleName: role, value: role, } as RoleInfo; }), name: data.user.name, }; await this.afterLoginAction(userInfo); return userInfo; } catch (error) { return Promise.reject(error); } }, ``` ### 登录后置方法 > `src/store/modules/user.ts` 作用是检测是否登录成功,并将用户信息保存到内存中 ``` async afterLoginAction(userInfo): Promise<void> { if (!this.getToken) return; const userStore = useUserStore(); userStore.setUserInfo(userInfo); // 登录成功后跳转到ERP首页 await router.replace(PageEnum.BASE_HOME); return userInfo; }, ``` ## 后端代码 ### 控制器层 > `liyade-template/src/main/java/tech/liyade/erp/template/inner/controller/AuthController.java` ``` @ApiOperation("登录") @OpenApi @PostMapping("/auth/login") public InvokeResult<LoginBo> login(@Valid LoginVo vo) { // 账号 String username = vo.getUsername(); // 密码 String password = vo.getPassword(); // 租户ID String tenantId = null; // 判断:是否启用多租户,开启返回 true , 未开启返回 false if (TenantUtil.enableTenant()) { // 多用户账号是 tenantId + @ + username // 根据 @ 分开 tenantId 和 username String[] tmpArr = username.split("@"); // 如果分开后的字符串数组小于等于 1 ,就抛出错误提示 if (tmpArr.length <= 1) { throw new DefaultClientException("用户名或密码错误!"); } // 将字符串数组中的 tenantId 和 username 赋值 tenantId = tmpArr[0]; username = tmpArr[1]; // 检查租户是否存在,如果不存在就抛出错误提示 Tenant tenant = tenantService.getById(tenantId); if (tenant == null) { throw new DefaultClientException("用户名或密码错误!"); } // 判断当前租户是否停用,停用就抛出错误提示 if (!tenant.getAvailable()) { throw new DefaultClientException("用户已停用,无法登录!"); } // 向当前线程中设置登录者的租户ID TenantContextHolder.setTenantId(tenant.getId()); } // 输出登录日志 log.info("用户 {} {} 开始登录", tenantId, username); // 获取登录时是否需要验证码,true:需要;false:不需要。 String loginCaptchaEnabled = sysParameterService.findByKey("login-captcha.enabled", "true"); // 输出日志 log.info("当前用户登录需要验证码 = {}", loginCaptchaEnabled); // 判断是否需要验证码,如果需要就判断验证码 if (Boolean.valueOf(loginCaptchaEnabled)) { String sn = vo.getSn(); String captcha = vo.getCaptcha(); captchaValidator.validate(sn, captcha); } // 验证租户、账号、密码是否正确 this.checkUserLogin(tenantId == null ? null : Integer.valueOf(tenantId), username, password); // 根据用户名称获取用户详细信息 AbstractUserDetails user = userDetailsService.loadUserByUsername(username); // 检测当前用户是否可以正常登录 LoginDto dto = this.doLogin(user); // 向 seesion 中设置用户等信息 this.addAttributesToSession(user); // 返回用户信息 return InvokeResultBuilder.success(new LoginBo(dto)); } ``` ### 服务层 接口类 > `liyade-dependencies/liyade-dependencies-web-starter/src/main/java/tech/liyade/starter/web/components/security/UserDetailsService.java` ``` public interface UserDetailsService { /** * 根据用户名查询 用于登录认证 */ AbstractUserDetails loadUserByUsername(String username) throws UserLoginException; } ``` 实现类 > `liyade-template/src/main/java/tech/liyade/erp/template/inner/impl/AbstractUserDetailsService.java` ``` @Override public AbstractUserDetails loadUserByUsername(String username) throws UserLoginException { // 根据登录名查询用户信息 AbstractUserDetails userDetails = this.findByUsername(username); // 判断是否有该用户 if (ObjectUtil.isEmpty(userDetails)) { log.debug("用户名 {} 不存在", username); throw new UserLoginException("用户名或密码错误!"); } // 将租户ID赋值到用户信息里 userDetails.setTenantId(TenantContextHolder.getTenantId()); // 获取登录IP,并赋值到用户信息里 userDetails.setIp(RequestUtil.getRequestIp()); // 定义租户模块列表容器 List<Integer> moduleIds = null; // 如果开启多租户功能 if (TenantUtil.enableTenant()) { // 获取当前租户可以使用的模块 moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( TenantContextHolder.getTenantId()); } // 先取角色的权限 userDetails.setPermissions(sysMenuService.getRolePermissionByUserId(userDetails.getId())); // 判断当前用户是否是管理员 userDetails.setIsAdmin( userDetails.getPermissions().contains(SecurityConstants.PERMISSION_ADMIN_NAME)); // 再取菜单的权限 Set<String> permissions = sysMenuService.getPermissionsByUserId(userDetails.getId(), userDetails.isAdmin(), moduleIds); // 合并权限:将菜单权限和角色权限合并 permissions.addAll(userDetails.getPermissions()); // 是否移除内置权限,针对admin等内置权限,因为内置权限等同于通配符权限,设置为true时会用具体的权限将内置权限替换掉,生产环境建议设置为true if (this.removeFixedPermission) { permissions.remove(SecurityConstants.PERMISSION_ADMIN_NAME); } // 将权限信息设置到用户详细信息中 userDetails.setPermissions(permissions); // 返回用户详细信息 return userDetails; } ``` ### 数据访问层 > `liyade-template/src/main/java/tech/liyade/erp/template/inner/mappers/UserDetailsMapper.java` ``` public interface UserDetailsMapper extends BaseMapper { /** * 根据登录名查询 */ DefaultUserDetails findByUsername(String username); } ``` > `liyade-template/src/main/resources/mappers/UserDetailsMapper.xml` ``` <select id="findByUsername" resultType="tech.liyade.starter.web.common.security.DefaultUserDetails"> SELECT id, username, password, name, email, telephone, available, lock_status FROM sys_user WHERE username = #{username} </select> ``` ### 数据表 ``` CREATE TABLE `sys_user` ( `id` varchar(32) NOT NULL COMMENT 'ID', `code` varchar(20) NOT NULL COMMENT '编号', `name` varchar(20) NOT NULL COMMENT '姓名', `username` varchar(30) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `telephone` varchar(11) DEFAULT NULL COMMENT '联系电话', `gender` tinyint(3) NOT NULL DEFAULT '0' COMMENT '性别 0-未知 1-男 2-女', `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1-在用 0停用', `lock_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '锁定状态', `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', `create_by` varchar(32) NOT NULL COMMENT '创建人', `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', `create_time` datetime NOT NULL COMMENT '创建时间', `update_by` varchar(32) NOT NULL COMMENT '修改人', `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `code` (`code`) USING BTREE, UNIQUE KEY `username` (`username`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='用户'; ```
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码