【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(五)角色管理、菜单管理模块

news2024/9/24 17:18:50

窝来辣😁
在这里插入图片描述

下面是前几篇的内容:

第一篇:【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(一)搭建项目

第二篇:【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(二)日志输出中间件、校验token中间件、配置路由、基础工具函数。

第三篇:【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(三)日志管理(登录日志、操作日志)、用户登录模块

第四篇:【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(四)用户管理、部门管理模块


碎碎念:这几天变得好冷,厚衣服穿得好累😂多穿几天可能就习惯了🤣


本篇内容是角色管理、菜单管理模块,有角色菜单关联权限。废话不多说,直接看代码

角色管理

在这里插入图片描述

controller层:sys_role.go

package sys

import (
	"github.com/gofiber/fiber/v2"
	"github.com/mozillazg/go-pinyin"
	"go-web2/app/common/config"
	"go-web2/app/common/util"
	"go-web2/app/model/sys"
	"strings"
)

type RoleController struct{}

// 角色列表分页
func (RoleController) GetPage(c *fiber.Ctx) error {
	role := sys.SysRole{}
	role.RoleKey = c.Query("code")
	role.RoleName = c.Query("name")
	pageSize := c.QueryInt("pageSize", 10)
	pageNum := c.QueryInt("pageNum", 1)
	return c.Status(200).JSON(config.Success(role.GetPage(pageSize, pageNum)))
}

// 根据id获取角色
func (RoleController) GetById(c *fiber.Ctx) error {
	role := sys.SysRole{}
	role.Id = c.Params("id")
	role.GetById()
	return c.Status(200).JSON(config.Success(role))
}

// 生成角色代码
func (RoleController) CreateCode(c *fiber.Ctx) error {
	roleName := c.Query("roleName")
	p := pinyin.NewArgs()
	p.Style = pinyin.FirstLetter
	roleKey := util.ConvertToPinyin(roleName, p)
	return c.Status(200).JSON(config.Success(roleKey))
}

// 新增角色
func (RoleController) Insert(c *fiber.Ctx) error {
	role := sys.SysRole{}
	if err := c.BodyParser(&role); err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	role.Token = c.Get(config.TokenHeader)
	err := role.Insert()
	if err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 修改角色
func (RoleController) Update(c *fiber.Ctx) error {
	role := sys.SysRole{}
	if err := c.BodyParser(&role); err != nil {
		//log.Error(err.Error())
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	err := role.Update()
	if err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 修改角色状态
func (RoleController) UpdateState(c *fiber.Ctx) error {
	role := sys.SysRole{}
	if err := c.BodyParser(&role); err != nil {
		//log.Error(err.Error())
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	err := role.UpdateState()
	if err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 删除角色
func (RoleController) Delete(c *fiber.Ctx) error {
	role := sys.SysRole{}
	if err := c.BodyParser(&role); err != nil {
		//log.Error(err.Error())
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	ids := strings.Split(role.Id, ",")
	if err := role.Delete(ids); err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 角色下拉列表
func (RoleController) GetSelectList(c *fiber.Ctx) error {
	role := sys.SysRole{}
	return c.Status(200).JSON(config.Success(role.GetSelectList()))
}

model层:sys_role.go

package sys

import (
	"fmt"
	"github.com/google/uuid"
	"github.com/pkg/errors"
	"go-web2/app/common/config"
	"strings"
	"time"
)

// 角色管理
type SysRole struct {
	config.BaseModel
	RoleKey  string   `json:"roleKey" form:"roleKey"`          // 角色代码
	RoleName string   `json:"roleName" form:"roleName"`        // 角色名称
	IsOpen   bool     `json:"isOpen" form:"isOpen"`            // 菜单树是否展开(0折叠 1展开 )
	State    int      `json:"state" form:"state"`              // 角色状态(1正常 2停用 3删除)
	Remark   string   `json:"remark" form:"remark"`            // 备注
	MenuIds  []string `gorm:"-" json:"menuIds" form:"menuIds"` // 菜单组
}

// 获取表名
func (SysRole) TableName() string {
	return "sys_role"
}

// 列表
func (e *SysRole) GetPage(pageSize int, pageNum int) config.PageInfo {
	var list []SysRole // 查询结果
	var total int64    // 总数
	query := config.DB.Table(e.TableName())
	if e.RoleName != "" {
		query.Where("role_name like ?", fmt.Sprintf("%%%s%%", e.RoleName))
	}
	if e.RoleKey != "" {
		query.Where("role_key like ?", fmt.Sprintf("%%%s%%", e.RoleKey))
	}
	offset := (pageNum - 1) * pageSize                                                 // 计算跳过的记录数
	query.Debug().Order("create_time desc").Offset(offset).Limit(pageSize).Find(&list) // 分页查询,根据offset和limit来查询
	query.Count(&total)
	return config.PageInfo{list, total}
}

// 详情
func (e *SysRole) GetById() {
	config.DB.Table(e.TableName()).Where("id = ?", e.Id).Find(e)
}

// 新增
func (e *SysRole) Insert() (err error) {
	// 校验角色名称和角色代码
	if checkRoleNameAndKey(e.RoleName, "", "") {
		err = errors.New("角色名称已存在!")
		return
	}
	if checkRoleNameAndKey("", e.RoleKey, "") {
		err = errors.New("角色代码已存在!")
		return
	}
	e.Id = strings.ReplaceAll(uuid.NewString(), "-", "")
	e.CreatorId = GetLoginId(e.Token)
	e.CreateTime = time.Now()
	config.DB.Table(e.TableName()).Create(e)
	// 保存菜单树
	roleMenu := SysRoleMenu{RoleId: e.Id}
	roleMenu.Insert(e.MenuIds)
	return
}

// 修改
func (e *SysRole) Update() (err error) {
	// 校验角色名称和角色代码
	if checkRoleNameAndKey(e.RoleName, "", e.Id) {
		err = errors.New("角色名称已存在!")
		return
	}
	if checkRoleNameAndKey("", e.RoleKey, e.Id) {
		err = errors.New("角色代码已存在!")
		return
	}
	config.DB.Model(&SysRole{}).Select("role_key", "role_name", "is_open", "state", "remark").Where("id = ?", e.Id).Save(e)
	// 保存菜单树
	roleMenu := SysRoleMenu{RoleId: e.Id}
	roleMenu.Insert(e.MenuIds)
	return
}

// 修改状态
func (e *SysRole) UpdateState() (err error) {
	config.DB.Model(&SysRole{}).Select("state").Where("id = ?", e.Id).Save(e)
	return
}

// 删除
func (e *SysRole) Delete(ids []string) (err error) {
	for _, id := range ids {
		e.Id = id
		e.GetById()
		// 首先查询角色是否已分配用户
		if CheckRoleExistUser(id) {
			err = errors.New(fmt.Sprintf("%s角色已分配,不允许删除", e.RoleName))
			return
		}
	}
	if err = config.DB.Table(e.TableName()).Delete(&SysRole{}, ids).Error; err != nil {
		return
	}
	// 删除角色同时删除角色菜单关联
	roleMenu := &SysRoleMenu{}
	roleMenu.Delete(ids)
	return
}

// 角色下拉列表
func (e *SysRole) GetSelectList() []SysRole {
	var list []SysRole // 查询结果
	config.DB.Table(e.TableName()).Find(&list)
	return list
}

// 校验角色名称和代码是否存在
func checkRoleNameAndKey(roleName, roleKey, id string) bool {
	var count int64
	query := config.DB.Table(SysRole{}.TableName())
	if roleName != "" {
		query.Where("role_name = ?", roleName)
	}
	if roleKey != "" {
		query.Where("role_key = ?", roleKey)
	}
	if id != "" {
		query.Where("id <> ?", id)
	}
	query.Count(&count)
	return count > 0
}

菜单管理

在这里插入图片描述

controller层:sys_menu.go

package sys

import (
	"github.com/gofiber/fiber/v2"
	"go-web2/app/common/config"
	"go-web2/app/model/sys"
)

type MenuController struct{}

// 菜单树列表
func (MenuController) GetList(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	menu.Name = c.Query("name")
	menu.State = c.QueryInt("state")
	return c.Status(200).JSON(config.Success(menu.GetList()))
}

// 路由列表
func (MenuController) GetRouters(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	token := c.Get(config.TokenHeader)
	menu.Id = sys.GetLoginUser(token).RoleId
	return c.Status(200).JSON(config.Success(menu.GetRouters()))
}

// 根据id获取菜单
func (MenuController) GetById(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	menu.Id = c.Params("id")
	menu.GetById()
	return c.Status(200).JSON(config.Success(menu))
}

// 获取对应角色菜单列表树
func (MenuController) RoleMenuTree(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	roleMenu := sys.SysRoleMenu{}
	roleMenu.RoleId = c.Params("roleId")
	checkedIds := roleMenu.GetMenuIdByRoleId() // 根据角色id获取当前角色选中的菜单id
	result := map[string]any{}
	result["menus"] = menu.GetList()   // 获取所有菜单
	result["checkedKeys"] = checkedIds // 当前角色选中的菜单id
	return c.Status(200).JSON(config.Success(result))
}

// 新增菜单
func (MenuController) Insert(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	if err := c.BodyParser(&menu); err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	menu.Token = c.Get(config.TokenHeader)
	err := menu.Insert()
	if err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 修改菜单
func (MenuController) Update(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	if err := c.BodyParser(&menu); err != nil {
		//log.Error(err.Error())
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	err := menu.Update()
	if err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

// 删除菜单
func (MenuController) Delete(c *fiber.Ctx) error {
	menu := sys.SysMenu{}
	menu.Id = c.Params("id")
	if err := menu.Delete(); err != nil {
		return c.Status(200).JSON(config.Error(err.Error()))
	}
	return c.Status(200).JSON(config.Success(nil))
}

model层:sys_menu.go

package sys

import (
	"fmt"
	"github.com/google/uuid"
	"github.com/pkg/errors"
	"go-web2/app/common/config"
	"strings"
	"time"
)

// 菜单管理
type SysMenu struct {
	config.BaseModel
	ParentId   string    `json:"parentId" form:"parentId"`     // 上级部门id
	Name       string    `json:"name" form:"name"`             // 菜单名称
	Sort       int       `json:"sort" form:"sort"`             // 排序
	Url        string    `json:"url" form:"url"`               // 访问路径
	Path       string    `son:"path" form:"path"`              // 组件名称
	Type       string    `json:"type" form:"type"`             // 菜单类型(M目录 C菜单 F按钮)
	State      int       `json:"state" form:"state"`           // 菜单状态(1正常 2停用 3删除)
	Perms      string    `json:"perms" form:"perms"`           // 权限标识
	Visible    bool      `json:"visible" form:"visible"`       // 显示状态(0隐藏  1显示)
	Icon       string    `json:"icon" form:"icon"`             // 菜单图标
	ActiveMenu string    `json:"activeMenu" form:"activeMenu"` // 菜单高亮
	IsFrame    bool      `json:"isFrame" form:"isFrame"`       // 是否外链(0 否 1 是)
	Remark     string    `json:"remark" form:"remark"`         // 备注
	Children   []SysMenu `gorm:"-" json:"children"`            // 子级数据
}

type Meta struct {
	Title      string `json:"title"`      // 设置该路由在侧边栏和面包屑中展示的名字
	Icon       string `json:"icon"`       // 菜单图标
	ActiveMenu string `json:"activeMenu"` // 菜单高亮
	RedDot     bool   `json:"redDot" `
}

// 前端路由
type Router struct {
	Name       string   `json:"name"`       // 菜单名称
	Path       string   `json:"path"`       // 组件名称
	Hidden     bool     `json:"hidden"`     // 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现
	Redirect   string   `json:"redirect"`   // 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
	Component  string   `json:"component"`  // 组件地址
	AlwaysShow bool     `json:"alwaysShow"` // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
	ActiveMenu string   `json:"activeMenu"` // 菜单高亮
	Meta       Meta     `json:"meta"`       // 其他元素
	Children   []Router `json:"children"`   // 子级数据
}

// 获取表名
func (SysMenu) TableName() string {
	return "sys_menu"
}

// 查询菜单列表的sql
var sql = `
		select a.id,parent_id,name,type,url,path,state,ifnull(perms,'') as perms,icon, sort,visible,active_menu,is_frame
        from sys_menu a
        left join sys_role_menu b on a.id = b.menu_id
`

// 树形菜单列表
func (e *SysMenu) GetList() interface{} {
	var list []SysMenu // 查询结果
	query := config.DB.Table(e.TableName())
	if e.Id != "" { // 角色id不为空,根据角色获取菜单
		where := sql + " where b.role_id = ?"
		args := []interface{}{e.Id}
		if e.Name != "" {
			where += " and name like ?"
			args = append(args, fmt.Sprintf("%%%s%%", e.Name))
		}
		if e.State != 0 {
			where += " and state = ?"
			args = append(args, e.State)
		}
		query.Debug().Order("parent_id,sort asc").Raw(where, args...).Find(&list)
	} else {
		if e.Name != "" {
			query.Where("name like ?", fmt.Sprintf("%%%s%%", e.Name))
		}
		if e.State != 0 {
			query.Where("state = ?", e.State)
		}
		query.Debug().Order("parent_id,sort asc").Find(&list)
	}
	return e.BuildTree(list, "ROOT")
}

// 获取路由(根据当前用户的角色id)
func (e *SysMenu) GetRouters() interface{} {
	var list []SysMenu // 查询结果
	where := ` where b.role_id = ? and type in ('M', 'C') and a.state = 1`
	where = sql + where
	config.DB.Table(e.TableName()).Debug().Order("parent_id,sort asc").Raw(where, e.Id).Find(&list)
	return buildMenus(e.BuildTree(list, "ROOT"))
}

// 详情
func (e *SysMenu) GetById() {
	config.DB.Table(e.TableName()).Where("id = ?", e.Id).Find(e)
}

// 根据角色id获取菜单权限标识
func GetPermsMenuByRoleId(roleId string) []string {
	var list []SysMenu
	sql := `
		select a.id,perms
        from sys_menu a
        left join sys_role_menu b on a.id = b.menu_id
        where b.role_id = ?
        order by parent_id,sort
	`
	config.DB.Raw(sql, roleId).Find(&list)
	var result []string
	for _, menu := range list {
		result = append(result, menu.Perms)
	}
	return result
}

// 新增
func (e *SysMenu) Insert() (err error) {
	var count int64
	// 校验角色名称和角色代码
	query := config.DB.Table(e.TableName())
	if e.ParentId == "0" {
		e.ParentId = "ROOT"
	}
	query.Where("name = ? and parent_id = ?", e.Name, e.ParentId).Count(&count)
	if count > 0 {
		err = errors.New("菜单名称已存在!")
		return
	}
	e.Id = strings.ReplaceAll(uuid.NewString(), "-", "")
	e.CreatorId = GetLoginId(e.Token)
	e.CreateTime = time.Now()
	config.DB.Table(e.TableName()).Create(e)
	return
}

// 修改
func (e *SysMenu) Update() (err error) {
	var count int64
	// 校验角色名称和角色代码
	query := config.DB.Table(e.TableName())
	if e.ParentId == "0" {
		e.ParentId = "ROOT"
	}
	if e.Id == e.ParentId {
		err = errors.New("上级菜单不能是自己!")
		return
	}
	query.Where("name = ? and parent_id = ? and id <> ?", e.Name, e.ParentId, e.Id).Count(&count)
	if count > 0 {
		err = errors.New("菜单名称已存在!")
		return
	}
	//config.DB.Model(&SysMenu{}).Select("parent_id", "name", "sort", "url", "path", "type", "state", "perms", "visible", "icon", "active_menu", "is_frame", "remark").Where("id = ?", e.Id).Save(e)
	config.DB.Model(&SysMenu{}).Omit("id", "create_time").Where("id = ?", e.Id).Save(e)
	return
}

// 删除
func (e *SysMenu) Delete() (err error) {
	// 1、校验是否存在下级
	var count int64
	query := config.DB.Table(e.TableName())
	query.Where("parent_id = ?", e.Id).Count(&count)
	if count > 0 {
		err = errors.New("存在子级菜单,不允许删除")
		return
	}
	// 2、校验是否存在用户
	if CheckMenuExistRole(e.Id) {
		err = errors.New("菜单已分配,不允许删除")
		return
	}
	if err = config.DB.Table(e.TableName()).Where("id = ?", e.Id).Delete(SysMenu{}).Error; err != nil {
		return
	}
	return
}

// 构建树结构
func (e *SysMenu) BuildTree(list []SysMenu, parentId string) []SysMenu {
	var tree []SysMenu
	for _, item := range list {
		if item.ParentId == parentId {
			children := e.BuildTree(list, item.Id)
			if len(children) > 0 {
				item.Children = children
			}
			tree = append(tree, item)
		}
	}
	return tree
}

// 构建前端所需要的路由菜单
func buildMenus(menus []SysMenu) []Router {
	routerList := []Router{}
	for _, menu := range menus {
		router := Router{Hidden: menu.Visible, Name: strings.Title(menu.Path), Path: getRouterPath(menu), Component: menu.Url}
		meta := Meta{Title: menu.Name, Icon: menu.Icon, ActiveMenu: menu.ActiveMenu}
		router.Meta = meta
		cMenus := menu.Children
		if len(cMenus) > 0 && menu.Type == "M" {
			router.AlwaysShow = true
			router.Redirect = "noRedirect"
			router.Children = buildMenus(cMenus)
		} else if menu.Type == "C" && menu.ParentId == "ROOT" {
			childrenList := []Router{}
			children := Router{Name: strings.Title(menu.Path), Path: menu.Path, Component: menu.Url}
			childMeta := Meta{Title: menu.Name, Icon: menu.Icon, ActiveMenu: menu.ActiveMenu}
			children.Meta = childMeta
			childrenList = append(childrenList, children)
			router.Children = childrenList
		}
		routerList = append(routerList, router)
	}
	return routerList
}

// 获取路由地址
func getRouterPath(menu SysMenu) string {
	routerPath := menu.Path
	if menu.Type == "M" {
		if menu.Url != config.PARENT_VIEW {
			routerPath = "/" + menu.Path
		}
	} else if menu.Type == "C" && menu.ParentId == "ROOT" {
		routerPath = "/"
	}
	return routerPath
}

角色菜单关联

model层:sys_role_menu.go

package sys

import "go-web2/app/common/config"

// 角色菜单关联
type SysRoleMenu struct {
	RoleId string `json:"roleId" form:"roleId"` // 角色ID
	MenuId string `json:"menuId" form:"menuId"` // 菜单ID
}

// 获取表名
func (SysRoleMenu) TableName() string {
	return "sys_role_menu"
}

// 新增角色和菜单关联
func (e *SysRoleMenu) Insert(menuIds []string) {
	// 先删除当前角色关联的菜单id
	config.DB.Table(e.TableName()).Where("role_id = ?", e.RoleId).Delete(SysRoleMenu{})
	// 再添加当前角色关联的菜单id
	var list []SysRoleMenu // 存放要添加的数据
	for _, menuId := range menuIds {
		item := SysRoleMenu{RoleId: e.RoleId, MenuId: menuId}
		list = append(list, item)
	}
	config.DB.Table(e.TableName()).Create(&list)
}

// 删除角色和菜单关联
func (e *SysRoleMenu) Delete(roleIds []string) {
	// DELETE FROM `sys_role_menu` WHERE role_id in ('1','2','3')
	config.DB.Table(e.TableName()).Where("role_id in (?)", roleIds).Delete(SysRoleMenu{})
}

// 根据角色id获取菜单列表id
func (e *SysRoleMenu) GetMenuIdByRoleId() []string {
	var list []SysRoleMenu
	var result []string
	query := config.DB.Table(e.TableName())
	query.Where("role_id = ?", e.RoleId)
	query.Find(&list)
	for _, menu := range list {
		result = append(result, menu.MenuId)
	}
	return result
}

// 根据菜单id校验该菜单是否已分配给角色
func CheckMenuExistRole(menuId string) bool {
	var count int64
	config.DB.Table(SysRoleMenu{}.TableName()).Where("menu_id = ?", menuId).Count(&count)
	return count > 0
}

最后

好像没啥需要特别注意的地方。


好啦,以上就是本篇文章的全部内容辣,等我更完这个项目的全部文章,我会放出完整代码的地址,到现在的话,大概还剩下一篇文章的内容了,很快这个专栏就能更完了,欢迎大家多多点赞支持下,最后可以关注我不迷路~

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

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

相关文章

自监督学习综述

1.简介 其实自监督学习的核心思想很简单&#xff0c;利用大量的无标签数据训练模型&#xff0c;然后将其作为预训练模型在下游任务上进行微调&#xff08;有标签&#xff09;。在用无标签图像训练模型时主要通过设计辅助任务&#xff0c;用图像自身的信息作为标签训练。常见的…

【Pytorch】学习记录分享5——PyTorch卷积神经网络

卷积神经网络 1. 卷积层涉及参数及其含义1. 滑动窗口步长&#xff1a;2. 卷积核尺寸&#xff1a;通常3*3 5*5等等3. 边缘填充&#xff1a;pad1 zero_padding,以0为边缘的填充4. 卷积核个数5. 卷积结果计算公式6. 卷积参数共享 2. 池化层涉及参数及其含义1. 最大池化 MAX POOLIN…

融云观察:给 ChatGPT 加上声音和脸庞,AI 社交的多模态试验

&#xff08;&#x1f446;点击获取行业首款《社交泛娱乐出海作战地图》&#xff09; 如果将短剧的爆火简单粗暴地归因为剧情上头、狗血反转和精妙卡点&#xff0c;那 GenAI 世界这一年来可以说是一部短剧 Live Show。关注【融云全球互联网通信云】了解更多 这厢 Open AI 宫斗…

[PyTorch][chapter 8][李宏毅深度学习][Back propagation]

前言&#xff1a; 反向传播算法(英:Backpropagation algorithm&#xff0c;简称:BP算法)是一种监督学习算法&#xff0c;常被用来训练多层感知机。 它用于计算梯度计算中&#xff0c;降低误差。 目录&#xff1a; 链式法则 模型简介&#xff08;Model&#xff09; 损失函…

godot 报错Unable to initialize Vulkan video driver解决

版本 godot 4.2.1 现象 godot4.2.1 默认使用vulkan驱动&#xff0c;如果再不支持vulkan驱动的主机上&#xff0c;进入引擎编辑器将报错如下 解决 启动参数添加 –rendering-driver opengl3 即可进入引擎编辑器 此时运行项目仍然会报错无法初始化驱动 在项目设置中配置编…

Apache Tomcat httpoxy 安全漏洞 CVE-2016-5388 已亲自复现

Apache Tomcat httpoxy 安全漏洞 CVE-2016-5388 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用修复建议 总结 漏洞名称 漏洞描述 在Apache Tomcat中发现了一个被归类为关键的漏洞&#xff0c;该漏洞在8.5.4(Application Server Soft ware)以下。受影响的是组…

Python---IP 地址的介绍

1. IP 地址的概念 IP 地址就是标识网络中设备的一个地址&#xff0c;好比现实生活中的家庭地址。 网络中的设备效果图: 2. IP 地址的表现形式 说明: IP 地址分为两类&#xff1a; IPv4 和 IPv6 IPv4 是目前使用的ip地址 IPv6 是未来使用的ip地址 IPv4 是由点分十进制组成 …

跟着我学Python进阶篇:01.试用Python完成一些简单问题

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

类和对象(中篇)

类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a; 用户没有显式实现&#xff0c;编译器会…

Linux上随机输出谚语的程序fortune

概要&#xff1a; Linux上有一个随机输出谚语的程序叫fortune 手册对它的描述是&#xff1a;输出一个随机的、充满希望的、有趣的谚语 本篇所用的系统是Ubuntu22.04 一、fortune的安装 sudo apt install fortune-mod 二、fortune的使用 1、示例一 这个谚语是什么意思啊…

[DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案

[网络故障] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案 问题描述 最近&#xff0c;我在使用CSDN插件浏览 MOOC 网站时&#xff0c;遇到了一些网络故障。具体表现为&#xff1a; MOOC 中国大学慕课网&#xff1a;www.icourse163.org点击CSDN插件首页的 MOOC&#xff08…

SLAM算法与工程实践——RTKLIB编译

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

linux 内核的 lru_list 的结构

在linux的slab分配的入口slab_alloc有一个传入参数lru&#xff0c;它的作用是使每个slab对象在unused&#xff0c;但可能后面继续使用的时候&#xff0c;不需要free&#xff0c;可以先放在lru_list上。lru_list的结构为&#xff1a; struct list_lru {struct list_lru_node *n…

网工内推 | 上市公司中级网工,思科、华为认证优先,有带薪年假

01 新晨科技 招聘岗位&#xff1a;中级网络工程师 职责描述&#xff1a; 1. 负责公司网络系统的规划、设计、实施、维护和优化&#xff1b; 2. 负责网络设备的选型、采购、安装、配置和调试&#xff1b; 3. 负责网络安全策略的制定和实施&#xff0c;保障公司网络安全&#xf…

fastjson1.2.24 反序列化漏洞(CVE-2017-18349)分析

FastJson在< 1.2.24 版本中存在反序列化漏洞&#xff0c;主要原因FastJson支持的两个特性&#xff1a; fastjson反序列化时&#xff0c;JSON字符串中的type字段&#xff0c;用来表明指定反序列化的目标恶意对象类。fastjson反序列化时&#xff0c;字符串时会自动调用恶意对…

国标28181平台只能连接视频监控吗?

在一些视频监控项目中&#xff0c;国标28181平台成为了必不可少的工具。这个平台的主要作用在于将分布在不同区域的视频监控录像机、摄像头等设备进行联网管理&#xff0c;同时还能将视频监控连接到上一级的国标监控平台。 可以说&#xff0c;国标监控平台是一个非常重要的承上…

原子学习笔记3——使用tslib库

一、tslib介绍 tslib 是专门为触摸屏设备所开发的 Linux 应用层函数库&#xff0c;并且是开源。 tslib 为触摸屏驱动和应用层之间的适配层&#xff0c;它把应用程序中读取触摸屏 struct input_event 类型数据&#xff08;这是输入设备上报给应用层的原始数据&#xff09;并进行…

动力电池系统介绍(十四)——热管理系统

动力电池系统介绍&#xff08;十四&#xff09; 一、梗概二、座舱热管理&#xff08;汽车空调&#xff09;2.1 空调制冷2.2 空调制热2.2.1 传统燃油汽车空调制热2.2.2 新能源汽车空调制热 三、动力系统热管理3.1 燃油车发动机热管理3.1.1 冷却系统3.1.2 润滑系统3.1.3 进排气系…

网络编程day5

作业 1> 使用select完成TCP客户端程序 //client #include<myhead.h> #define CLINET_IP "192.168.125.79" #define CLINET_PORT 9999 #define SERVE_IP "192.168.125.79" #define SERVE_PORT 8888 int main(int argc, const char *argv[]) {/…

音视频直播核心技术介绍

直播流程 采集&#xff1a; 是视频直播开始的第一个环节&#xff0c;用户可以通过不同的终端采集视频&#xff0c;比如 iOS、Android、Mac、Windows 等。 前处理&#xff1a;主要就是美颜美型技术&#xff0c;以及还有加水印、模糊、去噪、滤镜等图像处理技术等等。 编码&#…