第12讲、Odoo 18 权限控制机制详解
目录
- 引言
- 权限机制概述
- 权限组(Groups)
- 访问控制列表(ACL)
- 记录规则(Record Rules)
- 字段级权限控制
- 按钮级权限控制
- 菜单级权限控制
- 综合案例:多层级权限控制
- 最佳实践与注意事项
- 总结
引言
Odoo 18 提供了一套完整而灵活的权限控制机制,可以精确控制用户对系统各个层面的访问权限。本文将深入介绍 Odoo 18 的权限控制机制,从权限组到记录规则,从字段级别到按钮级别,再到菜单级别,全面解析其工作原理,并附上实际案例说明。
权限机制概述
Odoo 的权限控制体系是多层次的,从粗到细可以分为以下几个层级:
- 菜单级权限:控制用户是否可以看到特定菜单
- 模型级权限(ACL):控制用户对整个模型的读、写、创建、删除权限
- 记录级权限(Record Rules):控制用户可以访问模型中的哪些记录
- 字段级权限:控制用户可以查看或编辑模型中的哪些字段
- 按钮级权限:控制用户可以使用界面上的哪些功能按钮
这些权限控制机制相互配合,形成了一个完整的权限管理体系。下面我们将逐一深入介绍每个层级的权限控制机制。
权限组(Groups)
权限组是 Odoo 权限控制的基础,所有权限都是通过权限组来分配的。用户被分配到不同的权限组,从而获得相应的权限。
工作原理
- 每个权限组都是
res.groups
模型的一条记录 - 用户可以同时属于多个权限组,权限是累加的
- 权限组可以继承其他权限组的权限
- 权限组可以按类别进行分组
实现方式
权限组通常在模块的 XML 文件中定义:
<record id="group_project_manager" model="res.groups"><field name="name">项目经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_user'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
字段说明
name
: 权限组名称category_id
: 权限组所属类别implied_ids
: 该权限组隐含的其他权限组(继承关系)users
: 默认分配到该权限组的用户
案例:项目管理模块的权限组设计
<!-- 项目用户组 -->
<record id="group_project_user" model="res.groups"><field name="name">项目用户</field><field name="category_id" ref="base.module_category_project_management"/>
</record><!-- 项目经理组 -->
<record id="group_project_manager" model="res.groups"><field name="name">项目经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_user'))]"/>
</record><!-- 项目总监组 -->
<record id="group_project_director" model="res.groups"><field name="name">项目总监</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_manager'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
在这个案例中,我们定义了三个权限组:项目用户、项目经理和项目总监。项目经理继承了项目用户的权限,项目总监继承了项目经理的权限,形成了一个权限层级结构。
访问控制列表(ACL)
访问控制列表(ACL)是模型级别的权限控制,用于控制用户对整个模型的读、写、创建、删除权限。
工作原理
- ACL 定义了特定权限组对特定模型的权限
- 每个 ACL 规则都是
ir.model.access
模型的一条记录 - 权限是累加的,如果用户属于多个权限组,则拥有这些权限组的所有权限
- 如果没有明确授予权限,则默认没有权限
实现方式
ACL 通常在模块的 security/ir.model.access.csv
文件中定义:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_task_user,project.task.user,model_project_task,group_project_user,1,0,0,0
access_project_task_manager,project.task.manager,model_project_task,group_project_manager,1,1,1,1
字段说明
id
: ACL 规则的唯一标识符name
: ACL 规则的名称model_id:id
: 目标模型的外部 IDgroup_id:id
: 权限组的外部 IDperm_read
: 是否有读取权限(0 或 1)perm_write
: 是否有修改权限(0 或 1)perm_create
: 是否有创建权限(0 或 1)perm_unlink
: 是否有删除权限(0 或 1)
案例:项目任务的 ACL 设计
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_task_user,project.task.user,model_project_task,group_project_user,1,1,1,0
access_project_task_manager,project.task.manager,model_project_task,group_project_manager,1,1,1,1
access_project_milestone_user,project.milestone.user,model_project_milestone,group_project_user,1,0,0,0
access_project_milestone_manager,project.milestone.manager,model_project_milestone,group_project_manager,1,1,1,1
在这个案例中,项目用户可以读取、修改和创建任务,但不能删除任务;项目经理可以读取、修改、创建和删除任务。对于里程碑,项目用户只能查看,而项目经理可以完全控制。
记录规则(Record Rules)
记录规则是记录级别的权限控制,用于控制用户可以访问模型中的哪些记录。
工作原理
- 记录规则定义了特定权限组可以访问模型中的哪些记录
- 每个记录规则都是
ir.rule
模型的一条记录 - 记录规则使用域表达式(domain)来过滤记录
- 如果用户属于多个权限组,则可以访问满足任一记录规则的记录
- 记录规则可以针对读取、修改、创建和删除操作分别设置
实现方式
记录规则通常在模块的 XML 文件中定义:
<record id="project_task_rule_user" model="ir.rule"><field name="name">项目任务:用户只能看到自己的任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_user'))]"/><field name="perm_read" eval="1"/><field name="perm_write" eval="1"/><field name="perm_create" eval="1"/><field name="perm_unlink" eval="0"/>
</record>
字段说明
name
: 记录规则的名称model_id
: 目标模型的引用domain_force
: 域表达式,用于过滤记录groups
: 适用的权限组perm_read
: 是否适用于读取操作perm_write
: 是否适用于修改操作perm_create
: 是否适用于创建操作perm_unlink
: 是否适用于删除操作
案例:项目任务的记录规则设计
<!-- 项目用户只能看到自己负责的任务 -->
<record id="project_task_rule_user" model="ir.rule"><field name="name">项目任务:用户只能看到自己的任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_user'))]"/>
</record><!-- 项目经理可以看到自己项目中的所有任务 -->
<record id="project_task_rule_manager" model="ir.rule"><field name="name">项目任务:经理可以看到自己项目中的所有任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('project_id.user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_manager'))]"/>
</record><!-- 项目总监可以看到所有任务 -->
<record id="project_task_rule_director" model="ir.rule"><field name="name">项目任务:总监可以看到所有任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[(1, '=', 1)]</field><field name="groups" eval="[(4, ref('group_project_director'))]"/>
</record>
在这个案例中,项目用户只能看到分配给自己的任务,项目经理可以看到自己负责的项目中的所有任务,而项目总监可以看到所有任务。
字段级权限控制
字段级权限控制用于控制用户可以查看或编辑模型中的哪些字段。
工作原理
- 字段级权限通过字段的
groups
属性来控制 - 只有属于指定权限组的用户才能查看或编辑该字段
- 字段级权限可以在模型定义中设置,也可以在视图中设置
实现方式
在模型定义中设置字段级权限
class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'name = fields.Char('任务名称', required=True)description = fields.Text('任务描述')priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')budget = fields.Float('预算', groups='project.group_project_manager')actual_cost = fields.Float('实际成本', groups='project.group_project_director')
在视图中设置字段级权限
<field name="budget" groups="project.group_project_manager"/>
<field name="actual_cost" groups="project.group_project_director"/>
案例:项目任务的字段级权限设计
class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'name = fields.Char('任务名称', required=True)description = fields.Text('任务描述')user_id = fields.Many2one('res.users', string='负责人')date_deadline = fields.Date('截止日期')priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')# 只有项目经理及以上权限才能看到预算字段budget = fields.Float('预算', groups='project.group_project_manager')# 只有项目总监才能看到实际成本字段actual_cost = fields.Float('实际成本', groups='project.group_project_director')# 只有项目总监才能看到利润率字段profit_margin = fields.Float('利润率 (%)', compute='_compute_profit_margin', groups='project.group_project_director')@api.depends('budget', 'actual_cost')def _compute_profit_margin(self):for task in self:if task.budget and task.actual_cost:task.profit_margin = (task.budget - task.actual_cost) / task.budget * 100else:task.profit_margin = 0.0
在视图中的应用:
<record id="view_task_form" model="ir.ui.view"><field name="name">project.task.form</field><field name="model">project.task</field><field name="arch" type="xml"><form><sheet><group><field name="name"/><field name="user_id"/><field name="date_deadline"/><field name="priority"/><!-- 只有项目经理及以上权限才能看到预算字段 --><field name="budget" groups="project.group_project_manager"/><!-- 只有项目总监才能看到实际成本和利润率字段 --><field name="actual_cost" groups="project.group_project_director"/><field name="profit_margin" groups="project.group_project_director"/></group><field name="description"/></sheet></form></field>
</record>
在这个案例中,预算字段只对项目经理及以上权限可见,而实际成本和利润率字段只对项目总监可见。
按钮级权限控制
按钮级权限控制用于控制用户可以使用界面上的哪些功能按钮。
工作原理
- 按钮级权限通过按钮的
groups
属性来控制 - 只有属于指定权限组的用户才能看到和使用该按钮
- 按钮级权限在视图中设置
实现方式
<button name="action_approve" string="批准" type="object" groups="project.group_project_manager"/>
案例:项目任务的按钮级权限设计
<record id="view_task_form" model="ir.ui.view"><field name="name">project.task.form</field><field name="model">project.task</field><field name="arch" type="xml"><form><header><field name="state" widget="statusbar"/><!-- 任何用户都可以提交任务 --><button name="action_submit" string="提交" type="object" attrs="{'invisible': [('state', '!=', 'draft')]}"/><!-- 只有项目经理才能批准任务 --><button name="action_approve" string="批准" type="object" groups="project.group_project_manager"attrs="{'invisible': [('state', '!=', 'submitted')]}"/><!-- 只有项目总监才能关闭任务 --><button name="action_close" string="关闭" type="object" groups="project.group_project_director"attrs="{'invisible': [('state', '!=', 'approved')]}"/><!-- 任何用户都可以取消任务,但需要确认 --><button name="action_cancel" string="取消" type="object" confirm="确定要取消这个任务吗?"attrs="{'invisible': [('state', 'in', ['cancelled', 'done'])]}"/></header><sheet><!-- 表单内容 --></sheet></form></field>
</record>
对应的 Python 方法:
class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'state = fields.Selection([('draft', '草稿'),('submitted', '已提交'),('approved', '已批准'),('done', '已完成'),('cancelled', '已取消'),], string='状态', default='draft', tracking=True)def action_submit(self):self.write({'state': 'submitted'})def action_approve(self):self.write({'state': 'approved'})def action_close(self):self.write({'state': 'done'})def action_cancel(self):self.write({'state': 'cancelled'})
在这个案例中,任何用户都可以提交和取消任务,但只有项目经理才能批准任务,只有项目总监才能关闭任务。
菜单级权限控制
菜单级权限控制用于控制用户可以看到哪些菜单项。
工作原理
- 菜单级权限通过菜单的
groups
属性来控制 - 只有属于指定权限组的用户才能看到该菜单
- 菜单级权限在菜单定义中设置
实现方式
<menuitem id="menu_project_task" name="任务" parent="menu_project" action="action_project_task" groups="group_project_user"/>
案例:项目管理模块的菜单级权限设计
<!-- 主菜单:所有项目用户可见 -->
<menuitem id="menu_project_root" name="项目" sequence="40" groups="group_project_user"/><!-- 项目菜单:所有项目用户可见 -->
<menuitem id="menu_project" name="项目" parent="menu_project_root" sequence="10"/>
<menuitem id="menu_project_list" name="项目列表" parent="menu_project" action="action_project_list" sequence="10"/>
<menuitem id="menu_project_task" name="任务" parent="menu_project" action="action_project_task" sequence="20"/><!-- 报告菜单:只有项目经理可见 -->
<menuitem id="menu_project_report" name="报告" parent="menu_project_root" sequence="20" groups="group_project_manager"/>
<menuitem id="menu_project_task_analysis" name="任务分析" parent="menu_project_report" action="action_project_task_analysis" sequence="10"/><!-- 配置菜单:只有项目总监可见 -->
<menuitem id="menu_project_config" name="配置" parent="menu_project_root" sequence="30" groups="group_project_director"/>
<menuitem id="menu_project_tags" name="标签" parent="menu_project_config" action="action_project_tags" sequence="10"/>
<menuitem id="menu_project_stages" name="阶段" parent="menu_project_config" action="action_project_stages" sequence="20"/>
在这个案例中,所有项目用户都可以看到项目和任务菜单,但只有项目经理才能看到报告菜单,只有项目总监才能看到配置菜单。
综合案例:多层级权限控制
下面我们通过一个完整的项目需求管理系统案例,展示如何综合运用各种权限控制机制。
业务场景
我们要开发一个项目需求管理系统,包含模型 project.requirement
,需求如下:
用户角色 | 权限需求 |
---|---|
普通员工(Employee) | 只能查看和创建需求,只能看到自己创建的需求记录,不能看到预算和成本信息 |
部门经理(Manager) | 可以查看、创建、修改需求,可以看到本部门所有员工的需求,可以看到预算信息但不能看到成本信息,可以批准需求 |
高级管理层(Director) | 拥有所有权限,可以看到所有需求,可以看到预算和成本信息,可以批准和关闭需求 |
实现步骤
1. 定义权限组
<!-- 需求用户组 -->
<record id="group_requirement_user" model="res.groups"><field name="name">需求用户</field><field name="category_id" ref="base.module_category_project_management"/>
</record><!-- 需求经理组 -->
<record id="group_requirement_manager" model="res.groups"><field name="name">需求经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_requirement_user'))]"/>
</record><!-- 需求总监组 -->
<record id="group_requirement_director" model="res.groups"><field name="name">需求总监</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_requirement_manager'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
2. 定义访问控制列表(ACL)
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_requirement_user,project.requirement.user,model_project_requirement,group_requirement_user,1,0,1,0
access_project_requirement_manager,project.requirement.manager,model_project_requirement,group_requirement_manager,1,1,1,0
access_project_requirement_director,project.requirement.director,model_project_requirement,group_requirement_director,1,1,1,1
3. 定义记录规则
<!-- 普通用户只能看到自己创建的需求 -->
<record id="rule_requirement_user_own" model="ir.rule"><field name="name">需求用户只能看到自己的需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[('create_uid', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_requirement_user'))]"/>
</record><!-- 经理可以看到本部门所有需求 -->
<record id="rule_requirement_manager_department" model="ir.rule"><field name="name">需求经理可以看到本部门的需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[('department_id', '=', user.employee_id.department_id.id)]</field><field name="groups" eval="[(4, ref('group_requirement_manager'))]"/>
</record><!-- 总监可以看到所有需求 -->
<record id="rule_requirement_director_all" model="ir.rule"><field name="name">需求总监可以看到所有需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[(1, '=', 1)]</field><field name="groups" eval="[(4, ref('group_requirement_director'))]"/>
</record>
4. 定义模型和字段级权限
class ProjectRequirement(models.Model):_name = 'project.requirement'_description = '项目需求'name = fields.Char('需求名称', required=True)description = fields.Text('需求描述')department_id = fields.Many2one('hr.department', string='所属部门', default=lambda self: self.env.user.employee_id.department_id)priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')state = fields.Selection([('draft', '草稿'),('submitted', '已提交'),('approved', '已批准'),('done', '已完成'),('cancelled', '已取消'),], string='状态', default='draft', tracking=True)# 只有经理及以上权限才能看到预算字段budget = fields.Float('预算', groups='project_requirement.group_requirement_manager')# 只有总监才能看到成本字段cost = fields.Float('成本', groups='project_requirement.group_requirement_director')# 只有总监才能看到利润率字段profit_margin = fields.Float('利润率 (%)', compute='_compute_profit_margin', groups='project_requirement.group_requirement_director')@api.depends('budget', 'cost')def _compute_profit_margin(self):for req in self:if req.budget and req.cost:req.profit_margin = (req.budget - req.cost) / req.budget * 100else:req.profit_margin = 0.0def action_submit(self):self.write({'state': 'submitted'})def action_approve(self):self.write({'state': 'approved'})def action_done(self):self.write({'state': 'done'})def action_cancel(self):self.write({'state': 'cancelled'})
5. 定义视图和按钮级权限
<record id="view_requirement_form" model="ir.ui.view"><field name="name">project.requirement.form</field><field name="model">project.requirement</field><field name="arch" type="xml"><form><header><field name="state" widget="statusbar"/><!-- 任何用户都可以提交需求 --><button name="action_submit" string="提交" type="object" attrs="{'invisible': [('state', '!=', 'draft')]}"/><!-- 只有经理及以上才能批准需求 --><button name="action_approve" string="批准" type="object" groups="project_requirement.group_requirement_manager"attrs="{'invisible': [('state', '!=', 'submitted')]}"/><!-- 只有总监才能完成需求 --><button name="action_done" string="完成" type="object" groups="project_requirement.group_requirement_director"attrs="{'invisible': [('state', '!=', 'approved')]}"/><!-- 任何用户都可以取消需求 --><button name="action_cancel" string="取消" type="object" confirm="确定要取消这个需求吗?"attrs="{'invisible': [('state', 'in', ['cancelled', 'done'])]}"/></header><sheet><group><field name="name"/><field name="department_id"/><field name="priority"/><!-- 只有经理及以上才能看到预算 --><field name="budget" groups="project_requirement.group_requirement_manager"/><!-- 只有总监才能看到成本和利润率 --><field name="cost" groups="project_requirement.group_requirement_director"/><field name="profit_margin" groups="project_requirement.group_requirement_director"/></group><field name="description"/></sheet></form></field>
</record>
6. 定义菜单级权限
<!-- 主菜单:所有需求用户可见 -->
<menuitem id="menu_requirement_root" name="需求管理" sequence="50" groups="project_requirement.group_requirement_user"/><!-- 需求菜单:所有需求用户可见 -->
<menuitem id="menu_requirement" name="需求" parent="menu_requirement_root" sequence="10"/>
<menuitem id="menu_requirement_list" name="需求列表" parent="menu_requirement" action="action_requirement_list" sequence="10"/><!-- 报告菜单:只有经理及以上可见 -->
<menuitem id="menu_requirement_report" name="报告" parent="menu_requirement_root" sequence="20" groups="project_requirement.group_requirement_manager"/>
<menuitem id="menu_requirement_analysis" name="需求分析" parent="menu_requirement_report" action="action_requirement_analysis" sequence="10"/><!-- 配置菜单:只有总监可见 -->
<menuitem id="menu_requirement_config" name="配置" parent="menu_requirement_root" sequence="30" groups="project_requirement.group_requirement_director"/>
<menuitem id="menu_requirement_tags" name="标签" parent="menu_requirement_config" action="action_requirement_tags" sequence="10"/>
权限效果
-
普通员工:
- 可以看到需求管理菜单和需求列表菜单
- 可以查看和创建需求,但不能修改和删除
- 只能看到自己创建的需求
- 看不到预算、成本和利润率字段
- 可以提交和取消需求,但不能批准和完成需求
-
部门经理:
- 可以看到需求管理菜单、需求列表菜单和报告菜单
- 可以查看、创建和修改需求,但不能删除
- 可以看到本部门所有员工的需求
- 可以看到预算字段,但看不到成本和利润率字段
- 可以提交、批准和取消需求,但不能完成需求
-
高级管理层:
- 可以看到所有菜单
- 可以查看、创建、修改和删除需求
- 可以看到所有需求
- 可以看到预算、成本和利润率字段
- 可以执行所有操作(提交、批准、完成和取消需求)
最佳实践与注意事项
-
权限设计原则:
- 遵循最小权限原则,只给用户必要的权限
- 使用权限组继承关系简化权限管理
- 权限控制应该从粗到细,先控制菜单和模型级权限,再控制记录级和字段级权限
-
性能考虑:
- 记录规则会影响查询性能,特别是复杂的域表达式
- 避免使用过于复杂的记录规则
- 考虑使用索引优化记录规则的性能
-
安全注意事项:
- 菜单级权限只是隐藏菜单,不是真正的安全控制
- 必须结合 ACL 和记录规则来实现完整的权限控制
- 不要依赖客户端的权限控制,服务器端必须进行权限验证
-
调试技巧:
- 使用开发者模式查看权限问题
- 检查用户所属的权限组
- 检查模型的 ACL 规则
- 检查记录规则的域表达式
总结
Odoo 18 提供了一套完整而灵活的权限控制机制,可以从多个层面精确控制用户的权限:
- 权限组(Groups):权限控制的基础,用户通过所属的权限组获得相应的权限
- 访问控制列表(ACL):模型级别的权限控制,控制用户对整个模型的读、写、创建、删除权限
- 记录规则(Record Rules):记录级别的权限控制,控制用户可以访问模型中的哪些记录
- 字段级权限:控制用户可以查看或编辑模型中的哪些字段
- 按钮级权限:控制用户可以使用界面上的哪些功能按钮
- 菜单级权限:控制用户可以看到哪些菜单项
这些权限控制机制相互配合,形成了一个完整的权限管理体系,可以满足各种复杂的业务需求。通过合理设计和配置这些权限控制机制,可以确保系统的安全性和可用性,同时提供良好的用户体验。
相关文章:

第12讲、Odoo 18 权限控制机制详解
目录 引言权限机制概述权限组(Groups)访问控制列表(ACL)记录规则(Record Rules)字段级权限控制按钮级权限控制菜单级权限控制综合案例:多层级权限控制最佳实践与注意事项总结 引言 Odoo 18 提…...

8086 处理器 Flags 标志位全解析:CPU 的 “晴雨表” 与 “遥控器”总结:
引入: 你是否好奇,当 CPU 执行一条加法指令时,如何自动判断结果是否超出范围?当程序跳转时,如何快速决定走哪条分支?甚至在调试程序时,为何能让 CPU “一步一停”?这一切的答案&…...

具有离散序列建模的统一多模态大语言模型【AnyGPT】
第1章 Instruction 在人工智能领域、多模态只语言模型的发展正迎来新的篇章。传统的大型语言模型(LLM)在理解和生成人类语言方面展现出了卓越的能力,但这些能力通常局限于 文本处理。然而,现实世界是一个本质上多模态的环境,生物体通过视觉、…...
PHP HTTP 完全指南
PHP HTTP 完全指南 引言 PHP 作为一种流行的服务器端脚本语言,广泛应用于各种Web开发项目中。HTTP(超文本传输协议)是互联网上应用最为广泛的网络协议之一,用于在Web服务器和客户端之间传输数据。本文将详细介绍 PHP 在 HTTP 通信中的应用,帮助开发者更好地理解和利用 P…...

物流项目第九期(MongoDB的应用之作业范围)
本项目专栏: 物流项目_Auc23的博客-CSDN博客 建议先看这期: MongoDB入门之Java的使用-CSDN博客 需求分析 在项目中,会有两个作业范围,分别是机构作业范围和快递员作业范围,这两个作业范围的逻辑是一致的…...

系统思考:经营决策沙盘
今年是我为黄浦区某国有油漆涂料企业提供经营决策沙盘培训的第二年。在这段时间里,我越来越感受到,企业的最大成本往往不在生产环节,而是在决策错误上所带来的长远影响。尤其是在如今这个复杂多变的环境下,企业面临的挑战愈发严峻…...

[网页五子棋][对战模块]实现游戏房间页面,服务器开发(创建落子请求/响应对象)
实现游戏房间页面 创建 css/game_room.css #screen 用于显示当前的状态,例如“等待玩家连接中…”,“轮到你落子”,“轮到对方落子”等 #screen { width: 450px; height: 50px; margin-top: 10px; color: #8f4e19; font-size: 28px; …...
数据结构-代码总结
下面代码自己上完课写着玩的,除了克鲁斯卡尔那里完全ai,其他基本上都是自己写的,具体请参考书本,同时也欢迎各位大佬来纠错 线性表 //线性表--顺序存储结构 #include<iostream> using namespace std; template<typename T> …...
快速掌握 GO 之 RabbitMQ
更多个人笔记见: github个人笔记仓库 gitee 个人笔记仓库 个人学习,学习过程中还会不断补充~ (后续会更新在github和 gitee上) 文章目录 作用经典例子生产者(发送端)消费者(接收端&a…...
SQL Server 事务详解:概念、特性、隔离级别与实践
一、事务的基本概念 事务(Transaction)是数据库操作的基本单位,它是由一组SQL语句组成的逻辑工作单元。事务具有以下关键特性,通常被称为ACID特性: 原子性(Atomicity):事务…...
MAC软件游戏打开提示已损坏
打开「终端.app」,输入以下命令并回车,输入开机密码回车 sudo spctl --master-disable 按照上述步骤操作完成后,打开「系统偏好设置」-「安全与隐私」-「通用」,确保已经修改为「任何来源」。 打开「终端.app」,输入…...
React基础教程(13):路由的使用
文章目录 1、什么是路由?2、路由安装3、路由使用(1)路由方法导入和使用(2)定义路由以及重定向(3)嵌套路由(4)路由跳转方式(5)动态路由动态路由写法一动态路由写法二4、实现效果5、完整代码下载1、什么是路由? 路由是根据不同的url地址展示不同的内容或页面。 一个…...
力扣刷题(第四十三天)
灵感来源 - 保持更新,努力学习 - python脚本学习 解题思路 1. 逐位检查法:通过右移操作逐位检查每一位是否为1,统计计数 2. 位运算优化法:利用 n & (n-1) 操作消除最低位的1,减少循环次数 3. 内置函数法&…...

Centos环境下安装/重装MySQL完整教程
目录 一、卸载残留的MySQL环境: 二、安装MySQL: 1、下载MySQL官方的yum源: 2、更新系统yum源: 3、确保系统中有了对应的MySQL安装包: 4、安装MySQL服务: 5、密钥问题安装失败解决方法: …...

【Linux】环境变量完全解析
9.环境变量 文章目录 9.环境变量一、命令行参数二、获取环境变量程序中获取环境变量1. 使用命令行参数2. 使用系统调用函数getenv("字符串");3. 使用系统提供的全局变量environ 命令行中查询环境变量 三、常见环境变量1. HOME2. OLDPWD3. PATH4. SHELL 四、环境变量与…...
【Java】mybatis-plus乐观锁-基本使用
乐观锁(Optimistic Locking)是解决并发问题的重要机制。它通过在数据更新时验证数据版本来确保数据的一致性,从而避免并发冲突。与悲观锁不同,乐观锁并不依赖数据库的锁机制,而是通过检查数据的版本或标志字段来判断数…...

力扣每日一题——找到离给定两个节点最近的节点
目录 题目链接:2359. 找到离给定两个节点最近的节点 - 力扣(LeetCode) 题目描述 解法一:双指针路径交汇法 基本思路 关键步骤 为什么这样可行呢我请问了? 举个例子 特殊情况 Java写法: C写法&a…...
机器学习与深度学习03-逻辑回归01
目录 上集回顾1. 逻辑回归与线性回归的区别2.逻辑回归的常见目标函数3.逻辑回归如何分类4.Sigmoid函数详解5.逻辑回归模型的参数 上集回顾 上一节文章地址:链接 1. 逻辑回归与线性回归的区别 应用领域 线性回归通常⽤于解决回归问题,其中⽬标是预测⼀…...

卷积神经网络(CNN)入门学习笔记
什么是 CNN? CNN,全称 卷积神经网络(Convolutional Neural Network),是一种专门用来处理图片、语音、文本等结构化数据的神经网络。 它模仿人眼识别图像的方式: 从局部到整体,一步步提取特征&a…...
【优笔】基于STM32的多模态智能门禁系统
代码功能详细描述 该代码实现了一个基于STM32的多模态智能门禁系统,整合密码、指纹、人脸识别(预留)三种验证方式,并提供完善的管理功能。系统架构如下图所示: #mermaid-svg-Uufpcoeo5Lega096 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size…...
Metasploit工具使用详解(上)丨小白WEB安全入门笔记
Metasploit工具使用详解(上)丨小白WEB安全入门笔记 一、课程定位与工具概述 课程性质: 小白WEB安全入门课程聚焦基础操作,非深度专题(Metasploit专题可讲数十节课)目标:掌握基本概念和简单漏洞利用 Metasploit核心定…...
Femap许可证与网络安全策略
随着科技的快速发展,网络安全问题已成为各行各业关注的焦点。在电磁仿真领域,Femap作为一款领先的软件,其许可证的安全性和网络策略的重要性不言而喻。本文将探讨Femap许可证与网络安全策略的关系,确保您的电磁仿真工作能够在一个…...

VLAN的作用和原理
1. 为什么要有vlan? 分割广播域,避免广播风暴,造成网络资源的浪费 可以灵活的组网,便于管理,同时还有安全加固的功能 2. vlan是怎么实现的?端口的原理? 设置VLAN后,流量之间的转…...

深入探讨集合与数组转换方法
目录 1、Arrays.asList() 1.1、方法作用 1.2、内部实现 1.3、修改元素的影响 1.4、注意事项 2、list.toArray() 2.1、方法作用 2.2、内部实现 2.3、修改元素的影响 2.4、特殊情况 1、对象引用 2、数组copy 3、对比总结 4、常见误区与解决方案 5、实际应用建议…...
让大模型看得见自己的推理 — KnowTrace结构化知识追踪
让大模型“看得见”自己的推理 —— KnowTrace 结构化知识追踪式 RAG 全解析 一句话概括:把检索-推理“改造”成 动态知识图构建任务,再让 LLM 只关注这张不断精炼的小图 —— 这就是显式知识追踪的核心价值。 1. 背景:为什么 RAG 仍难以搞定多跳推理? 长上下文负担 传统 I…...

【HarmonyOS 5应用架构详解】深入理解应用程序包与多Module设计机制
⭐本期内容:【HarmonyOS 5应用架构详解】深入理解应用程序包与多Module设计机制 🏆系列专栏:鸿蒙HarmonyOS:探索未来智能生态新纪元 文章目录 前言应用与应用程序包应用程序的基本概念应用程序包的类型标识机制应用安装流程 应用的…...

【Oracle】DCL语言
个人主页:Guiat 归属专栏:Oracle 文章目录 1. DCL概述1.1 什么是DCL?1.2 DCL的核心功能 2. 用户管理2.1 创建用户2.2 修改用户2.3 删除用户2.4 用户信息查询 3. 权限管理3.1 系统权限3.1.1 授予系统权限3.1.2 撤销系统权限 3.2 对象权限3.2.1…...

MySQL强化关键_017_索引
目 录 一、概述 二、索引 1.主键索引 2.唯一索引 3.查看索引 4.添加索引 (1)建表时添加 (2)建表后添加 5.删除索引 三、树 1.二叉树 2.红黑树 3.B树 4.B树 (1)为什么 MySQL 选择B树作为索引…...
stm32——SPI协议
stm32——SPI协议 STM32的SPI(Serial Peripheral Interface,串行外设接口)协议是一种高速、全双工、同步的串行通信协议,广泛评估微控制器与各种外设(如传感器、器件、显示器、模块等)之间的数据传输。STM3…...
Linux 下如何查看进程的资源限制信息?
简介 Linux 上的 cat /proc/$pid/limits 命令提供有关特定进程的资源限制的信息,其中 $pid 是相关进程的进程 ID (pid)。该文件是 /proc 文件系统的一部分,该文件系统是一个虚拟文件系统,提供有关进程和系统资源的信息…...