人力资源智能化管理项目(day09:权限应用)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject

搭建页面结构

<template><div class="container"><div class="app-container"><el-button class="btn-add" type="primary" size="mini">添加权限</el-button><el-table><el-table-column label="名称" /><el-table-column label="标识" /><el-table-column label="描述" /><el-table-column label="操作"><el-button type="text">添加</el-button><el-button type="text">编辑</el-button><el-button type="text">删除</el-button></el-table-column></el-table></div></div>
</template>
<script>
export default {name: 'Permission'
}
</script>
<style>
.btn-add {margin: 10px;
}
</style>

获取数据转化树形

import request from '@/utils/request'/**** 获取权限列表**/
export function getPermissionList () {return request({url: '/sys/permission',method: 'GET'})
}<template><div class="container"><div class="app-container"><el-button class="btn-add" type="primary" size="mini">添加权限</el-button><el-table default-expand-all :data="list" row-key="id"><el-table-column prop="name" label="名称" /><el-table-column prop="code" label="标识" /><el-table-column prop="description" label="描述" /><el-table-column label="操作"><template v-slot="{ row }"><el-button v-if="row.type === 1" size="mini" type="text">添加</el-button><el-button type="text" size="mini">编辑</el-button><el-button type="text" size="mini">删除</el-button></template></el-table-column></el-table></div></div>
</template>
<script>
import { getPermissionList } from '@/api/permission'
import { transListToTreeData } from '@/utils/index'
export default {name: 'Permission',data () {return {list: []}},created () {this.getPermissionList()},methods: {async getPermissionList () {this.list = transListToTreeData(await getPermissionList(), 0)console.log(this.list)}}
}
</script>
<style>
.btn-add {margin: 10px;
}
</style>

作业 ( 基于权限接口和线上效果完成 权限点的新增- 删除- 编辑 )

本次作业我封装了一个添加组件

子组件:

<template><el-dialog :title="showTitle" :visible="showDialog" @close="close"><!-- 放置弹层内容 --><el-form ref="addDept" label-width="120px" :model="formData" :rules="rules"><el-form-item label="权限名称" prop="name"><el-input v-model="formData.name" style="width: 80%" size="mini" /></el-form-item><el-form-item label="权限标识" prop="code"><el-input v-model="formData.code" style="width: 80%" size="mini" /></el-form-item><el-form-item label="权限描述" prop="description"><el-inputv-model="formData.description"style="width: 80%"size="mini"/></el-form-item><!-- 如果不需要校验,就不需要写prop属性 --><!-- 重置表单数据,需要prop属性 --><el-form-item label="启用" prop="enVisible"><el-switchv-model="formData.enVisible":active-value="1":inactive-value="0"size="mini"/></el-form-item><el-form-item><el-row type="flex" justify="center"><el-col :span="12"><el-button type="primary" size="mini" @click="btnOk">确定</el-button><el-button size="mini" @click="close">取消</el-button></el-col></el-row></el-form-item></el-form></el-dialog>
</template><script>
import {addPermission,getPermissionDetail,editPermission
} from '@/api/permission'
export default {props: {showDialog: {type: Boolean,default: false},pid: {// 获取主组件传递的id,根据这个id进行第二级权限的添加type: Number,default: null},sonId: {// 获取主组件传递的id,根据这个id进行权限的编辑type: Number,default: null}},data () {return {list: [],formData: {name: '', // 权限点名字code: '', // 权限点标识description: '', // 权限点描述enVisible: '', // 权限点开启状态type: null, // 权限点类型pid: null // 权限点父级id},rules: {name: [{ required: true, message: '权限点名字不能为空', trigger: 'blur' }], // 权限点名字code: [{ required: true, message: '权限点标识不能为空', trigger: 'blur' }] // 权限点标识}}},computed: {// 标题不是表单所以不能绑定v-model事件,使用计算属性进行更新showTitle () {return this.sonId ? '编辑权限点' : '新增权限点'}},watch: {sonId: function () {this.getPermissionDetail()}},methods: {close () {// 修改父组件的值,子传父// .sync会自动监听update:showDialog事件// resetFields只能重置在模板中绑定的数据this.formData = {name: '', // 权限点名字code: '', // 权限点标识description: '', // 权限点描述enVisible: '0', // 权限点开启状态type: null, // 权限点类型pid: null // 权限点父级id}this.$refs.addDept.resetFields() // 重置表单this.$emit('clearId')this.$emit('update:showDialog', false)},btnOk () {this.$refs.addDept.validate(async isOk => {if (isOk) {let msg = '新增'if (this.sonId == null) {// 如果父组件传id回来了,应该是二级组件if (this.pid != null) {this.formData.pid = this.pid}// 判断是否是一级添加if (this.formData.pid == null) {this.formData.type = 1this.formData.pid = 0await addPermission(this.formData)console.log('一级添加')} else {this.formData.type = 2await addPermission(this.formData)console.log('二级添加')}} else {msg = '修改'await editPermission(this.formData)}// 通知父组件更新this.$emit('updatePermission')// 提示信息this.$message.success(`${msg}权限点成功`)this.close()}})},async getPermissionDetail () {if (this.sonId != null) {this.formData = await getPermissionDetail(this.sonId)}} // 获取权限点的详情}
}
</script><style></style>

api接口:

import request from '@/utils/request'/**** 获取权限列表**/
export function getPermissionList () {return request({url: '/sys/permission',method: 'GET'})
}/**** 删除-权限点**/
export function delPermission (id) {return request({url: `/sys/permission/${id}`,method: 'DELETE'})
}/**** 新增-权限点**/
export function addPermission (data) {return request({url: '/sys/permission',method: 'POST',data})
}/**** 获取-权限点详情**/
export function getPermissionDetail (id) {return request({url: `/sys/permission/${id}`,method: 'GET'})
}/**** 修改-权限点详情**/
export function editPermission (data) {return request({url: `/sys/permission/${data.id}`,method: 'PUT',data})
}

父组件:

<template><div class="container"><div class="app-container"><el-buttonclass="btn-add"type="primary"size="mini"@click="showDialog = true">添加权限</el-button><el-table default-expand-all :data="list" row-key="id"><el-table-column prop="name" label="名称" /><el-table-column prop="code" label="标识" /><el-table-column prop="description" label="描述" /><el-table-column label="操作"><template v-slot="{ row }"><el-buttonv-if="row.type === 1"size="mini"type="text"@click="addPermissionSecond(row.id)">添加</el-button><el-button type="text" size="mini" @click="editPermission(row.id)">编辑</el-button><el-button type="text" size="mini" @click="delPermission(row.id)">删除</el-button></template></el-table-column></el-table></div><addPermission:son-id="id":show-dialog.sync="showDialog":pid="fatherId"@updatePermission="getPermissionList"@clearId="clearId"/></div>
</template>
<script>
import { getPermissionList, delPermission } from '@/api/permission'
import { transListToTreeData } from '@/utils/index'
import addPermission from './components/add-permission.vue'
export default {name: 'Permission',components: { addPermission },data () {return {list: [],showDialog: false, // 控制弹层的显隐fatherId: null, // 传递父节点的id给子组件用于增加二级权限点id: null // 传递父节点的id给子组件用于编辑权限点}},created () {this.getPermissionList()},methods: {async getPermissionList () {this.list = transListToTreeData(await getPermissionList(), 0)},// 删除权限点delPermission (id) {this.$confirm('此操作将永久删除该部门, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async () => {await delPermission(id)this.$message({type: 'success',message: '删除成功!'})this.getPermissionList()}).catch(() => {this.$message({type: 'info',message: '已取消删除'})})},// 增加二级权限点addPermissionSecond (id) {this.showDialog = truethis.fatherId = id},// 编辑权限点editPermission (id) {this.showDialog = truethis.id = id},clearId () {this.id = null}}
}
</script>
<style>
.btn-add {margin: 10px;
}
</style>

权限概念

分配过程

员工分配角色-弹出层

 /**** 获取-已启用的角色列表**/
export function getEnableRoleList () {return request({url: '/sys/role/list/enabled',method: 'GET'})
}showRoleDialog: false, // 控制角色弹层的显隐roleList: [], // 接收角色列表roleIds: [], // 用于多选框数据双向绑定,存储选中的id// 点击角色按钮弹出层async btnRole () {this.roleList = await getEnableRoleList()this.showRoleDialog = true},<!-- 放置角色弹层 --><el-dialog :visible.sync="showRoleDialog" title="分配角色"><!-- 内容 --><el-checkbox-group v-model="roleIds"><!-- 要执行checkbox的存储值 item.id --><el-checkbox v-for="item in roleList" :key="item.id" :label="item.id">{{ item.name }}</el-checkbox></el-checkbox-group></el-dialog><el-button size="mini" type="text" @click="btnRole">角色</el-button>

员工分配角色-回显数据并提交

/**** 获取-员工-基本信息**/
export function getEmployeeDetail (id) {return request({url: `/sys/user/${id}`,method: 'GET'})
}/**** 获取-已启用的角色列表**/
export function assignRole (data) {return request({url: '/sys/user/assignRoles',method: 'PUT',data})
}// 点击角色按钮弹出层async btnRole (id) {this.roleList = await getEnableRoleList()// 记录当前点击的id 因为后边 确定取消要存取给对应的用户this.currentUserId = idconst { roleIds } = await getEmployeeDetail(id)this.roleIds = roleIdsthis.showRoleDialog = true},// 点击角色的确定async btnRoleOk () {await assignRole({id: this.currentUserId,roleIds: this.roleIds})this.$message.success('分配用户角色成功')this.showRoleDialog = false}<!-- 放置角色弹层 --><el-dialog :visible.sync="showRoleDialog" title="分配角色"><!-- 内容 --><el-checkbox-group v-model="roleIds"><!-- 要执行checkbox的存储值 item.id --><el-checkbox v-for="item in roleList" :key="item.id" :label="item.id">{{ item.name }}</el-checkbox></el-checkbox-group><el-row slot="footer" type="flex" justify="center"><el-col :span="6"><el-buttontype="primary"size="mini"justify="center"@click="btnRoleOk">确定</el-button><el-button size="mini" @click="showRoleDialog = false">取消</el-button></el-col></el-row></el-dialog><el-button size="mini" type="text" @click="btnRole(row.id)">角色</el-button>

给角色分配权限-弹出层

      showPermissionDialog: false, // 控制权限弹层的显隐permissionData: [] // 接收权限树数据<el-button size="mini" type="text" @click="btnPermission">分配权限</el-button><!-- 放置权限弹层 --><el-dialog :visible.sync="showPermissionDialog" title="分配权限"><!-- 内容 --><el-tree:data="permissionData":props="{ label: 'name' }"show-checkboxdefault-expand-all=""/></el-dialog>// 分配权限async btnPermission () {this.showPermissionDialog = truethis.permissionData = transListToTreeData(await getPermissionList(), 0)}

角色分配权限-显示已有权限数据

/**** 获取-角色详情**/
export function getRoleDetail (id) {return request({url: `/sys/role/${id}`,method: 'GET'})
}// 分配权限async btnPermission (id) {this.currentRoleId = idconst { permIds } = await getRoleDetail(id)this.permIds = permIdsthis.permissionData = transListToTreeData(await getPermissionList(), 0)this.showPermissionDialog = true}<!-- 内容 --><el-treenode-key="id":data="permissionData":props="{ label: 'name' }"show-checkboxdefault-expand-all:default-checked-keys="permIds"/>

角色分配权限-确定提交

/**** 分配权限-角色**/
export function assignPrem (data) {return request({url: '/sys/role/assignPrem',method: 'PUT',data})
}<el-row slot="footer" type="flex" justify="center"><el-col :span="6"><el-button type="primary" size="mini" @click="btnPermissionOk">确定</el-button><el-button size="mini" @click="showPermissionDialog = false">取消</el-button></el-col></el-row>async btnPermissionOk () {await assignPrem({id: this.currentRoleId,permIds: this.$refs.permTree.getCheckedKeys()})this.$message.success('角色分配权限成功')this.showPermissionDialog = false}

拆分静态路由和动态路由

// 静态路由
export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首页', icon: 'dashboard' }}]},// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true }
]
// 动态路由
export const asyncRoutes = [department,role,employee,permission,attendance,approval,salary,social
]
const createRouter = () =>new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes // 默认引入静态路由})

根据用户权限添加动态路由

permission完整代码

router.beforeEach(async (to, from, next) => {nprogress.start() // 开启进度条// 判断是否有tokenif (store.getters.token) {// 如果有token,则判断是否是登录页if (to.path === '/login') {// 如果是则跳转到主页next('/')// next有地址的话并没有执行后置守卫,所以要手动调用一下进度条关闭nprogress.done()} else {// 如果不是则放过// 判断是否获取过资料if (!store.getters.userId) {// 如果没有则获取资料const { roles } = await store.dispatch('user/getUserInfo')const filterRoutes = asyncRoutes.filter(item => {return roles.menus.includes(item.name)}) // 筛选后的路由router.addRoutes([...filterRoutes,{ path: '*', redirect: '/404', hidden: true }]) // 添加动态路由信息到路由表// router添加动态路由之后 需要转发一下next(to.path) // 目的是让路由拥有信息 router的已知缺陷} else {next() // 放过}}} else {// 判断是否在白名单里面if (whiteList.includes(to.path)) {// 如果在就放过next()} else {// 如果不在,就跳转到登录next('/login')nprogress.done()}}
})
// 静态路由
export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首页', icon: 'dashboard' }}]}// 404 page must be placed at the end !!!
]
// 动态路由
export const asyncRoutes = [department,role,employee,permission,attendance,approval,salary,social
]
const createRouter = () =>new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes // 默认引入静态路由})
// 获取用户的基本资料async getUserInfo (context) {const result = await getUserInfo()context.commit('setUserInfo', result)return result // 返回数据}

这里以approval路由为例,其他路由都要添加name属性

import layout from '@/layout'
export default {path: '/approval',name: 'approval',component: layout,children: [{path: '',name: 'approval',component: () => import('@/views/approval'),meta: {title: '审批',icon: 'tree-table'}}]
}

根据权限显示左侧菜单

import { constantRoutes } from '@/router'// 存放数据
const state = {routes: constantRoutes // 存储路由信息,默认存储的是静态路由
}
// 修改数据
const mutations = {setRoutes (state, newRoutes) {state.routes = [...constantRoutes, ...newRoutes] // 静态路由+动态路由}
}
const getters = {routes: state => state.user.routes
}
// getters编辑访问
export default getters
const { roles } = await store.dispatch('user/getUserInfo')const filterRoutes = asyncRoutes.filter(item => {return roles.menus.includes(item.name)}) // 筛选后的路由store.commit('user/setRoutes', filterRoutes)router.addRoutes([...filterRoutes,{ path: '*', redirect: '/404', hidden: true }]) // 添加动态路由信息到路由表
computed: {...mapGetters(['sidebar', 'routes']),// 路由信息的计算属性// routes () {//   // 当前路由的所有信息//   return this.$router.options.routes// },}

退出登录重置路由

import { resetRouter } from '@/router'
// 异步操作
const actions = {// 退出登录logout (context) {// 1.删除tokencontext.commit('removeToken')// 2.删除用户信息context.commit('setUserInfo', {})// 重置路由resetRouter()}
}

功能权限-按钮权限标识

自定义指令应用功能权限

代码层面:

// 注册自定义指令,控制功能权限
Vue.directive('permission', {// 会在指令作用的元素插入dom之后执行inserted (el, binding) {// el是当前指令作用的dom元素的对象// binding是v-permission="表达式"的信息const points = store.state.user.userInfo?.roles?.points || []// 判断当前登录用户(数组)是否包含权限点,不存在就要将对应的按钮删除或禁用if (!points.includes(binding.value)) {// 删除el.remove()// 禁用// el.disabled = true}}
})
<el-buttonv-permission="add - employee"size="mini"type="primary"@click="$router.push('/employee/detail')">添加员工</el-button>

页面层面(标识要和代码一致):

其他模块-集成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/685630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【COMP337 LEC4】

Classifier Evaluation Numerous measures exist (as we will shortly see) to compare the predicted labels by the trained classifier and actual ( target) labels in the test dataset 存在许多度量方法&#xff08;我们很快将会看到&#xff09;来比较训练过的分类器…

6、内网安全-横向移动WmiSmbCrackMapExecProxyChainsImpacket

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 前言&#xff1a; 在内网环境中&#xff0c;主机192.168.3.31有外网网卡能出网&#xff0c;在取得该主机权限后上线&#xff0c;搭建web应用构造后门下载地址&#xff0c;利用该主机执行相…

H.264官方手册之帧间预测

一、 框架 只有解码 P和 B类型的宏块时才能调用该过程。 该过程的输出为当前宏块的帧间预测采样点&#xff0c;是一个16x16的亮度采样点 pred(Luma)。以及当ChromaArrayType不等于0时输出 pred(Cb)与pred(Cr) 如果mb_type为B_Skip或者B_Direct_16x16&#xff0c;mbPartIdx的范…

【HarmonyOS】鸿蒙开发之渲染控制——第2.3章

if/eles条件渲染 if的使用方法与javascript&#xff0c;java中使用的if/eles条件渲染使用基本一致。 案例: Entry Component struct IfElseDemo{State isShow:boolean false;build(){Column() {TitleBar({titleBarAttribute: {title: "ifElse使用案例",backShow:…

【图论经典题目讲解】CF786B - Legacy 一道线段树优化建图的经典题目

C F 786 B − L e g a c y \mathrm{CF786B - Legacy} CF786B−Legacy D e s c r i p t i o n \mathrm{Description} Description 给定 1 1 1 张 n n n 个点的有向图&#xff0c;初始没有边&#xff0c;接下来有 q q q 次操作&#xff0c;形式如下&#xff1a; 1 u v w 表示…

STM32F1 - 中断系统

Interrupt 1> 硬件框图2> NVIC 中断管理3> EXTI 中断管理3.1> EXTI与NVIC3.2> EXTI内部框图 4> 外部中断实验4.1> 实验概述4.2> 程序设计 5> 总结 1> 硬件框图 NVIC&#xff1a;Nested Vectored Interrupt Controller【嵌套向量中断控制器】 管理…

拿捏c语言指针(上)

目录 前言 ​编辑 指针 内存与地址 计算机常见单位 理解编址 取地址&#xff0c;指针变量&#xff0c;解引用 取地址 指针变量 解引用 指针变量大小 指针类型的作用 char*解引用后 指针-整数 应用 void*指针 const修饰指针变量 const修饰普通变量 const修饰指…

自动化测试-RIDE编写自动化脚本

自动化脚本软件测试的必修内容&#xff0c;是自动化测试的核心&#xff0c;脚本的逻辑严谨性、可维护性非常重要&#xff0c;优秀的自动化脚本需要能兼顾用例的正确有效性和自动化测试的效率&#xff0c;本篇文章将介绍如何用RIDE写自动化脚本。我们将深入探讨RIDE的具体用法&a…

相机图像质量研究(22)常见问题总结:CMOS期间对成像的影响--光学串扰

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

Linux POSIX信号量 线程池

Linux POSIX信号量 线程池 一. 什么是POSIX信号量&#xff1f;二. POSIX信号量实现原理三. POSIX信号量接口函数四. 基于环形队列的生产消费模型五. 线程池 一. 什么是POSIX信号量&#xff1f; POSIX信号量是一种用于同步和互斥操作的机制&#xff0c;属于POSIX&#xff08;Po…

项目管理工具软件Maven趣闻

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Maven这个单词来自于意第绪语&#xff08;Yiddish&#xff09;&#xff0c;这是一种与德语和希伯来语有密切关系的犹太民族语言。在这个语境中&#xff0c;Maven意为“知识的…

ChatGPT高效提问—prompt实践(智能辅导-心理咨询-职业规划)

ChatGPT高效提问—prompt实践&#xff08;智能辅导-心理咨询-职业规划&#xff09; ​ 智能辅导是指利用人工智能技术&#xff0c;为学习者提供个性化、高效的学习辅助服务。它基于大数据分析和机器学习算法&#xff0c;可以针对学习者的学习行为、状态和能力进行评估和预测&a…

MATLAB知识点:datasample函数(★★☆☆☆)随机抽样的函数,能对矩阵数据进行随机抽样

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章&#xff1a;课后习题讲解中拓展的函数 在讲解第三…

数据类型与变量

目录 作业回顾 有关JDK, JRE, JVM三者&#xff1a; 判断题 新课学习 字面常量 数据类型 变量 整型变量 长整型变量 短整型变量 字节型变量 浮点型变量 字符型变量 布尔型变量 类型转换 自动类型转换&#xff08;隐式&#xff09; 强制类型转换&#xff08;显式…

Navicat安装使用连接MySQL

目录 安装登录MySQL登录MySQL用Navicat连接MySQL 安装 选择“我同意”&#xff0c;点击下一步。 选择安装的目标文件夹&#xff0c;点击下一步。 点击下一步。 点击下一步。 点击安装。 软件安装需要一些时间&#xff0c;请耐心等待 点击“完成”。 注册 输入 密钥&#x…

Crypto-RSA3

题目&#xff1a;&#xff08;BUUCTF在线评测 (buuoj.cn)&#xff09; 共模攻击 ​ 前提&#xff1a;有两组及以上的RSA加密过程&#xff0c;而且其中两次的m和n都是相同的&#xff0c;那么就可以在不计算出d而直接计算出m的值。 ​ 设模数为n&#xff0c;两个用户的公钥分别为…

LeetCode 0103.二叉树的锯齿形层序遍历:层序遍历 + 适时翻转

【LetMeFly】103.二叉树的锯齿形层序遍历&#xff1a;层序遍历 适时翻转 力扣题目链接&#xff1a;https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/ 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往…

Java与JavaScript同源不同性

Java是目前编程领域使用非常广泛的编程语言&#xff0c;相较于JavaScript&#xff0c;Java更被人们熟知。很多Java程序员想学门脚本语言&#xff0c;一看JavaScript和Java这么像&#xff0c;很有亲切感&#xff0c;那干脆就学它了&#xff0c;这也间接的帮助了JavaScript的发展…

HTML | DOM | 网页前端 | 常见HTML标签总结

文章目录 1.前端开发简单分类2.前端开发环境配置3.HTML的简单介绍4.常用的HTML标签介绍 1.前端开发简单分类 前端开发&#xff0c;这里是一个广义的概念&#xff0c;不单指网页开发&#xff0c;它的常见分类 网页开发&#xff1a;前端开发的主要领域&#xff0c;使用HTML、CS…

OpenCV中的边缘检测技术及实现

介绍: 边缘检测是计算机视觉中非常重要的技术之一。它用于有效地识别图像中的边缘和轮廓&#xff0c;对于图像分析和目标检测任务至关重要。OpenCV提供了多种边缘检测技术的实现&#xff0c;本博客将介绍其中的两种常用方法&#xff1a;Canny边缘检测和Sobel边缘检测。 理论介…