React权限管理系统实现

news2024/11/15 23:47:07

目录

一、需求

二、逻辑

三、实现

(一)代码

(二)解释

1. 获取权限对照数组 (queryReferencePermissionsInfo)

2. 获取处理对照数组 (queryDisposePermissionsInfo)

3. 获取权限映射表信息并处理 (queryPermissionsInfo)

4. 处理权限信息并获取指定模块和目标字典信息 (handlePermissionsInfo)

5. 获取相应app的权限信息 (queryAppPermissionsInfo)

6. 递归获取权限数组 (renderTreeNodes)

7. 处理权限信息并获取指定模块及目标权限的具体信息 (queryPermissionsChildren)

四、使用

五、总结


一、需求

        今年的4月份,我们的产品被甲方采购,并根据甲方需求更改了一下权限系统,由于原来的老旧权限系统过于臃肿且不够灵活,最重要的是没有注释看着很头大,于是我决定将权限系统重构。

二、逻辑

        其实逻辑很简单,就是将获取的权限数据进行处理然后通过传入不同的参数返回不同的处理后的数据。再用这些返回的数据进行页面上的权限控制。

三、实现

(一)代码

import globalUtil from '../utils/global';
import { formatMessage, FormattedMessage } from 'umi-plugin-locale';
import Exception from '../components/Exception'

const actionMaps = {
    admin: '管理员',
    developer: '开发者',
    viewer: '观察者',
    access: '访问者',
    owner: '拥有者'
};
const En_actionMaps = {
    admin: 'Administrators',
    developer: 'Developer',
    viewer: 'Observer',
    access: 'Visitor',
    owner: 'Owner'
};
const roleMaps = {
    admin: formatMessage({ id: 'utils.role.roleMaps_admin' }),
    app_store: formatMessage({ id: 'utils.role.roleMaps_app_store' })
};
const AccessText = {
    team_overview: '应用管理',
    team_app_create: '新建应用',
    team_app_manage: '应用控制',
    team_gateway_manage: '网关管理',
    team_plugin_manage: '插件管理',
    team_manage: '团队管理',
    app_overview: '应用总览',
    app_release: '应用发布',
    app_gateway_manage: '应用网关',
    app_upgrade: '应用升级',
    app_resources: '应用资源',
    app_config_group: '应用配置',
    route_manage: '路由管理',
    target_services: '目标服务',
    certificate: '证书管理',
    team_member: '成员管理',
    team_region: '集群管理',
    team_role: '角色管理',
    team_registry_auth: '镜像仓库授权管理',
    app_gateway_monitor: '网关监控',
    app_route_manage: '路由管理',
    app_target_services: '目标服务',
    app_certificate: '证书管理',
    team_gateway_monitor: '网关监控',
    team_route_manage: '路由管理',
    team_target_services: '目标服务',
    team_certificate: '证书管理',
    team_dynamic: '动态',
    team_overview_perms: '团队信息',
    app_backup: '应用备份',
    listed_manage: '上架管理',
    application_records: '申请记录',
    team_library_manage: '组件库',
};
const En_AccessText = {
    team_overview: 'Team overview',
    team_app_create: 'Create application',
    team_app_manage: 'Application management',
    team_gateway_manage: 'Gateway management',
    team_plugin_manage: 'Plug-in management',
    team_manage: 'Team management',
    app_overview: 'Application overview',
    app_release: 'Application publishing',
    app_gateway_manage: 'Application gateway',
    app_upgrade: 'Application upgrade',
    app_resources: 'Application resource',
    app_config_group: 'Application management',
    route_manage: 'Route management',
    target_services: 'Target service',
    certificate: 'Certificate management',
    team_member: 'Member management',
    team_region: 'Cluster management',
    team_role: 'Role management',
    team_registry_auth: 'Image warehouse authorization management',
    app_gateway_monitor: 'Gateway monitoring',
    app_route_manage: 'Route management',
    app_target_services: 'Target service',
    app_certificate: 'Certificate management',
    team_gateway_monitor: 'Gateway monitoring',
    team_route_manage: 'Route management',
    team_target_services: 'Target service',
    team_certificate: 'Certificate management',
    team_dynamic: 'Dynamic',
    team_overview_perms: 'Team information',
    app_backup: 'Application backup',
    listed_manage: 'Listed management',
    application_records: 'Application records',
    team_library_manage: 'Component library',
};

// 定义菜单与权限属性的映射结构
const teamMenuPermissionsMap = {
    team_overview_perms: 'isTeamOverview',//团队总览
    app_create: 'isTeamAppCreate',//新建应用
    team_gateway_monitor: 'isTeamGatewayMonitor',//网关监控
    team_route_manage: 'isTeamRouteManage',//路由管理
    team_target_services: 'isTeamTargetServices',//目标服务
    team_certificate: 'isTeamCertificate',//证书管理
    team_dynamic: 'isTeamDynamic',//动态
    team_region: 'isTeamRegion',//集群管理
    team_role: 'isTeamRole',//角色管理
    team_registry_auth: 'isTeamRegistryAuth',//镜像仓库授权管理
    team_plugin_manage: 'isTeamPluginManage',//插件管理
    application_records: 'isAudit',//申请记录
    listed_manage: 'isTeamPutaway',//上架管理
    team_library_manage: 'isTeamLibraryManage',//组件库
};

const appMenuPermissionsMap = {
    app_overview: 'isAppOverview', //应用总览
    app_release: 'isAppRelease',//应用发布
    app_upgrade: 'isAppUpgrade',//应用升级
    app_gateway_monitor: 'isAppGatewayMonitor',//网关监控
    app_route_manage: 'isAppRouteManage',//路由管理
    app_target_services: 'isAppTargetServices',//目标服务
    app_certificate: 'isAppCertificate',//证书管理
    app_resources: 'isAppResources',//应用资源
    app_config_group: 'isAppConfigGroup',//应用管理
    app_backup: 'isAppBackup',//应用备份
};
export default {
    // 身份
    actionMap(name, bool) {
        var keys = ''
        Object.keys(actionMaps).map(item => {
            if (actionMaps[item] == name) {
                return keys = item
            }
        })
        if (bool) {
            return actionMaps[keys] || name;
        } else {
            return En_actionMaps[keys] || name;
        }
    },
    // 角色
    roleMap(name) {
        return roleMaps[name] || name;
    },
    // 权限翻译
    fetchAccessText(text, bool) {
        if (bool) {
            return AccessText[text] || text;
        } else {
            return En_AccessText[text] || text;
        }
    },
    // 获取权限对照数组
    queryReferencePermissionsInfo(type) {
        const defaultTargetArr = [
            'describe',
            'create',
            'edit',
            'delete',
            'install',
            'uninstall'
        ];
        const defaultTargetOperationArr = ['start', 'stop', 'update', 'construct', 'copy', 'restart'];
        switch (type) {
            // 团队级别权限特殊处理
            case 'team_overview_perms':
                return ['describe', 'resource_limit', 'app_list']
                break;
            case 'team_app_create':
            case 'team_gateway_monitor':
            case 'app_gateway_monitor':
            case 'team_dynamic':
                return ['describe']
                break;
            // 应用级别特殊权限
            case 'app_release':
                return ['share', 'export', 'delete', 'describe']
                break;
            case 'app_upgrade':
                return ['app_model_list', 'upgrade_record', 'upgrade', 'rollback']
                break;
            // 组件与应用级别特殊权限
            case 'app_overview':
                return [
                    ...defaultTargetArr,
                    ...defaultTargetOperationArr,
                    ...[
                        'visit_web_terminal',
                        'service_monitor',
                        'telescopic',
                        'env',
                        'rely',
                        'storage',
                        'port',
                        'plugin',
                        'source',
                        'safety',
                        'other_setting'
                    ]
                ];
                break;
            case 'app_backup':
                return [
                    'describe',
                    'add',
                    'import',
                    'recover',
                    'move',
                    'expor',
                    'delete'
                ]
                break;
            default:
                return defaultTargetArr;
                break;
        }
    },
    // 获取处理对照数组
    queryDisposePermissionsInfo(type) {
        const defaultArr = [
            'isAccess',
            'isCreate',
            'isEdit',
            'isDelete',
            'isInstall',
            'isUninstall'
        ];
        const defaultOperationArr = ['isStart', 'isStop', 'isUpdate', 'isConstruct', 'isCopy', 'isRestart' ];
        switch (type) {
            // 团队级别权限特殊处理
            case 'team_overview_perms':
                return ['isAccess', 'isResourceLimit', 'isAppList']
                break;
            case 'team_app_create':
            case 'team_gateway_monitor':
            case 'app_gateway_monitor':
            case 'team_dynamic':
                return ['isAccess']
                break;
            // 应用级别特殊权限
            case 'app_release':
                return ['isShare', 'isExport', 'isDelete', 'isAccess']
                break;
            case 'app_upgrade':
                return ['isAppModelList', 'isUpgradeRecord', 'isUpgrade', 'isRollback']
                break;
            // 组件与应用级别特殊权限
            case 'app_overview':
                return [
                    ...defaultArr,
                    ...defaultOperationArr,
                    ...[
                        'isVisitWebTerminal',
                        'isServiceMonitor',
                        'isTelescopic',
                        'isEnv',
                        'isRely',
                        'isStorage',
                        'isPort',
                        'isPlugin',
                        'isSource',
                        'isSafety',
                        'isOtherSetting',
                    ]
                ];
                break;
            case 'app_backup':
                return [
                    'isAccess',
                    'isAddBackup',
                    'isImportBackup',
                    'isRecoverBackup',
                    'isMoveBackup',
                    'isExportBackup',
                    'isDeleteBackup'
                ]
                break;
            default:
                return defaultArr;
                break;
        }
    },
    /**
     * 获取权限映射表信息并进行处理
     *
     * @param {Object} data - 权限数据对象,包含团队或应用级别的权限信息
     * @param {string} module - 需要处理的目标模块名称
     * @param {string=} appid - (可选)应用ID,若提供,则查找对应应用的权限信息,否则查找团队级别的权限信息
     *
     * @returns {Object} - 返回一个对象,键为处理后的权限标识,值为对应的权限字典信息
    
     * 此函数首先调用queryDisposePermissionsInfo方法获取处理权限的动作列表(disposeActions),
     * 然后调用queryReferencePermissionsInfo方法获取权限对照数组(referencePermissions)。
     * 接着,遍历处理权限的动作列表,对每个动作调用handlePermissionsInfo方法,
       根据提供的module和appid获取对应权限字典信息,并将结果存入一个新的对象(permissionsObj)中,
       其中对象的键为处理权限的动作,值为该动作在目标模块下的权限字典详情。
     */
    queryPermissionsInfo(data, module, appid = '') {
        const disposeActions = this.queryDisposePermissionsInfo(module);
        const referencePermissions = this.queryReferencePermissionsInfo(module);
        const permissionsObj = {};

        disposeActions.forEach((item, index) => {
            permissionsObj[item] = this.handlePermissionsInfo(data, referencePermissions[index], module, appid);
        });

        return permissionsObj;
    },
    /**
     * 处理权限信息并获取指定模块和目标字典信息
     *
     * @param {Object} data - 权限数据对象,包含团队或应用级别的权限信息
     * @param {string} target - 需要查找的目标权限字典名称
     * @param {string} module - 需要查找的目标模块名称
     * @param {string=} appid - (可选)应用ID,若提供,则查找对应应用的权限信息,否则查找团队级别的权限信息
     *
     * @returns {Object|boolean} - 返回查找到的第一个匹配的权限字典信息,若未找到则返回false
     *
     * 此函数根据提供的appid参数决定查找团队还是应用级别的权限信息。
     * 如果appid存在,则先通过queryAppPermissionsInfo函数获取应用权限信息,再利用renderTreeNodes递归获取目标模块的权限信息,
     * 最后通过queryPermissionsChildren获取指定模块和目标字典的具体信息,并存入results数组。
     * 若appid不存在,则直接对团队权限数据进行类似操作。
     * 结束处理后,返回results数组中第一个(或唯一)找到的权限字典信息,若未找到任何匹配项,则返回false。
     */
    handlePermissionsInfo(data, target, module, appid = '') {
        const results = [];
        if (appid) {
            if (data && target && module) {
                const appInfo = this.queryAppPermissionsInfo(data, appid)
                const newAppInfo = this.renderTreeNodes(appInfo, module)
                this.queryPermissionsChildren(newAppInfo, module, target, results);
            }
        } else {
            if (data && target && module) {
                const teamInfo = this.renderTreeNodes(data, module)
                this.queryPermissionsChildren(teamInfo, module, target, results);
            }
        }
        return results.length > 0 ? results[0] : false;
    },

    /**
     * 获取相应app的权限信息
     *
     * @param {Object} data - 整体权限数据对象,通常包含一系列子模型
     * @param {string} appid - 需要查找的目标应用ID
     *
     * @returns {Object} - 返回与目标应用ID相对应的应用权限信息对象,若未找到则返回一个空对象 {}
     *
     * 此函数首先在整体权限数据对象的子模型中查找名为'team_app_manage'的部分,
     * 找到后,在'team_app_manage'的子模型中搜索与给定appid相匹配的应用权限信息,
     * 若找到匹配项,则返回该应用的权限信息对象;否则返回一个空对象。
     */
    queryAppPermissionsInfo(data, appid) {
        const appManagement = this.renderTreeNodes(data, 'team_app_manage');

        if (appManagement) {
            const appSubModels = appManagement.find((item) => Object.keys(item)[0] === 'team_app_manage').team_app_manage.sub_models || [];
            const targetApp = appSubModels.find((app) => Object.keys(app)[0] === appid);

            return targetApp ? targetApp[appid] : {};
        } else {
            return {};
        }
    },

    /**
     * 递归获取权限数组
     *
     * @param {Object[]} data - 权限数据结构,通常为一棵包含子模型(sub_models)的树形结构
     * @param {string} moduleName - 需要查找的目标权限模块名称
     *
     * @returns {Object[]|null} 返回与指定模块名称相符的权限数组,如果未找到,则返回null
     *
     * 此函数遍历给定的数据结构,逐层深入子模型直至找到与 moduleName 匹配的权限模块。
     * 当找到匹配项时,返回该模块所在层级的权限数组。若递归遍历完整棵树仍未找到匹配项,则返回null。
     */
    renderTreeNodes(data, moduleName) {
        const permissionsArr = data.sub_models || [];

        // 遍历当前层级的所有子模型
        for (let i = 0; i < permissionsArr.length; i++) {
            const item = permissionsArr[i];
            const keys = Object.keys(item)[0];

            // 如果当前节点的主键名称与目标模块名称相匹配,则直接返回当前层级的权限数组
            if (keys === moduleName) {
                return permissionsArr;
            }

            // 如果当前节点还包含子模型,并且子模型数量大于0,则递归查找
            if (item[keys] && item[keys].sub_models && item[keys].sub_models.length > 0) {
                const foundNode = this.renderTreeNodes(item[keys], moduleName);

                // 如果递归过程中找到了匹配的权限模块,则返回该模块的权限数组
                if (foundNode) {
                    return foundNode;
                }
            }
        }

        // 如果遍历完成仍没找到匹配的权限模块,则返回null
        return null;
    },

    /**
     * 处理权限信息并获取指定模块及目标权限的具体信息
     *
     * @param {Array<Object>} data - 权限数据列表,每个元素为一个包含模块名称及权限详细信息的对象
     * @param {string} moduleName - 需要检索的目标模块名称
     * @param {string} targets - 需要在目标模块中检索的具体权限名称
     * @param {Array<*>} results - 用于存储匹配到的权限详细信息的数组,函数执行结束后会填充相关数据
     *
     * @returns {void} 无返回值,而是通过修改传入的results参数来存储查找到的权限信息
     *
     * 此函数遍历给定的权限数据列表,查找与moduleName相匹配的模块,并在其中寻找与targets相匹配的权限详细信息。
     * 找到匹配项时,将该权限的详细信息推入results数组中。
     */
    queryPermissionsChildren(data, moduleName, targets, results) {
        return (data || []).map((item) => {
            const keys = Object.keys(item)[0];
            if (keys === moduleName) {
                item[keys].perms.map((item2) => {
                    const name = Object.keys(item2)[0];
                    if (targets === name) {
                        results.push(item2[targets]);
                    }
                });
            }
        });
    },
    /**
     * 通用权限获取方法
     *
     * @param {Object} menuMap - 菜单与权限属性的映射结构,键为菜单类型,值为权限对象上对应的属性名
     * @param {Object} data - 权限数据对象,包含各种菜单类型的权限信息
     * @param {string} appid - (可选)应用ID,默认为空字符串。在某些情况下可能需要根据应用ID获取特定应用的权限信息
     * @param {Function} permissionCheckStrategy - (可选)权限检查策略函数,默认为检查`.isAccess`属性是否存在。
     *                                         该函数接收一个菜单权限对象作为参数,并返回一个布尔值表示用户是否有该菜单的权限。
     *                                         对于特殊情况(如'app_upgrade'),可以通过传入自定义策略函数进行处理。
     *
     * @returns {Object} 返回一个对象,键为菜单类型对应的属性名,值为用户是否拥有该菜单的权限(布尔值)
     */
    queryMenuPermissionsInfo(menuMap, data, appid = '') {
        const obj = {};
        for (const [menuKey, propertyKey] of Object.entries(menuMap)) {
            const menuPermissions = this.queryPermissionsInfo(data, menuKey, appid);
            if (menuKey == 'app_upgrade') {
                obj[propertyKey] = menuPermissions?.isAppModelList || menuPermissions?.isUpgradeRecord || false;
            } else {
                obj[propertyKey] = menuPermissions?.isAccess || false;
            }
        }
        return obj;
    },
    /**
     * 根据团队或应用类型调用通用方法获取菜单权限
     *
     * @param {Object} data - 权限数据对象,包含各种菜单类型的权限信息
     * @param {'team'|'app'} type - 指定获取团队或应用的权限,取值只能为'team'或'app'
     * @param {string} appid - (可选)应用ID,默认为空字符串。当type为'app'时,可能需要根据应用ID获取特定应用的权限信息
     *
     * @returns {Object} 返回一个对象,键为菜单类型对应的属性名,值为用户是否拥有该菜单的权限(布尔值)
     *
     * 此方法根据传入的'type'参数自动选择合适的菜单权限映射表(teamMenuPermissionsMap或appMenuPermissionsMap),
     * 然后调用通用权限获取方法queryMenuPermissionsInfo,从而获取团队或应用的菜单权限信息。
     */
    queryTeamOrAppPermissionsInfo(data, type, appid = '') {
        return this.queryMenuPermissionsInfo(type == 'team' ? teamMenuPermissionsMap : appMenuPermissionsMap, data, appid);
    },
    // 没有权限
    noPermission() {
        return <Exception type={403} style={{ minHeight: 600, height: '80%' }} actions />
    }
};



(二)解释

1. 获取权限对照数组 (queryReferencePermissionsInfo)

此函数根据输入的type参数,返回不同场景下的一组基础权限列表。这些列表定义了不同模块或操作下所涉及的基本权限集,如“描述”、“创建”、“编辑”等。对于特定类型的权限(如团队级别、应用级别等),有专门的处理逻辑,返回特定的权限集合。这个函数是权限对照的基础,定义了系统支持的各种权限类型。

2. 获取处理对照数组 (queryDisposePermissionsInfo)

类似于queryReferencePermissionsInfo,但这里的数组是针对权限操作的处理逻辑,如“是否允许访问”、“是否允许创建”等。每个操作对应一个布尔型的检查方法,用于实际权限控制逻辑中的判断依据。这个函数进一步细化了权限的实际运用方式。

3. 获取权限映射表信息并处理 (queryPermissionsInfo)

这是整个权限处理流程的核心函数。它首先调用上述两个函数获取基础权限列表和处理逻辑列表,然后遍历处理逻辑列表,对每个逻辑调用handlePermissionsInfo函数。handlePermissionsInfo负责根据当前模块、目标权限字典以及是否针对特定应用来获取具体的权限字典信息。最终,queryPermissionsInfo会返回一个对象,其键为处理逻辑名称,值为对应的权限字典信息,实现了权限到操作的映射。

4. 处理权限信息并获取指定模块和目标字典信息 (handlePermissionsInfo)

该函数根据appid是否存在来区分处理团队或应用级别的权限。它首先调用queryAppPermissionsInfo或直接从团队权限数据开始处理,然后通过递归函数renderTreeNodes定位到目标模块,并通过queryPermissionsChildren在该模块下查找特定的权限信息。最后,它返回查找到的第一个匹配的权限字典信息,或在找不到时返回false

5. 获取相应app的权限信息 (queryAppPermissionsInfo)

此函数从整体权限数据中提取指定appid的应用权限信息。它首先找到“team_app_manage”部分,然后在其中查找与appid匹配的应用权限数据。

6. 递归获取权限数组 (renderTreeNodes)

这个递归函数用于在树形结构的权限数据中查找指定模块的权限数组。它遍历每一层的子模型,直到找到匹配的模块名或遍历完整棵树。

7. 处理权限信息并获取指定模块及目标权限的具体信息 (queryPermissionsChildren)

该函数遍历权限数据列表,定位到指定模块,并从中找出特定权限名称的详细信息,将其加入到结果数组中。

四、使用

import roleUtil from '../../utils/newRole';

roleUtil.queryPermissionsInfo(this.props.currentTeamPermissionsInfo && this.props.currentTeamPermissionsInfo.team, 'team_app_create'),

这是我的权限树结构,传进去的参数一个是树结构,一个是节点名称,这样返回出来的就是该节点下的所有权限。因为我们这里做了动态权限,所以也有可能传入第三个参数,用于辨认是否是查询某个app的权限列表,这里我就不再赘述,具体可以看上面的代码实现逻辑。

 

五、总结

        整个代码段构建了一套复杂的权限管理系统,能够根据不同的业务场景(如团队、应用级别等)动态地获取并处理权限信息。它通过分层次的函数调用,实现了权限数据的解析、筛选和具体化,以支持系统在运行时进行细粒度的权限控制。这套逻辑不仅灵活地适应了多种权限配置需求,而且保持了代码的模块化和可维护性。

        以上只是个人的实现思路,针对业务的不同不能生搬硬套,具体详细的使用请参照开源项目

https://github.com/goodrain/rainbond-ui/tree/V6.0icon-default.png?t=N7T8https://github.com/goodrain/rainbond-ui/tree/V6.0

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

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

相关文章

awdawdawd

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

2024-06-05-记一次cnvd渗透

前言&#xff1a;挖src挖郁闷了&#xff0c;闲来无事选择挖一个cnvd来练练手&#xff0c;本次的漏洞都没啥难度&#xff0c;企查查资产过了5000万 说一下cnvd证书的下放标准 对于中危及中危以上通用型漏洞&#xff08;CVSS2.0基准评分超过4.0分&#xff09;&#xff0c;以及涉…

eclipse添加maven插件

打开eclipse菜单 Help/Install New SoftwareWork with下拉菜单选择 2022-03 - https://download.eclipse.org/releases/2022-03‘type filter text’搜索框中输入 maven选择 M2E - Maven Integration for Eclipse一路next安装&#xff0c;重启eclipseImport项目时&#xff0c;就…

国外视频流量密码!我想要好好的,不要废掉我——早读(逆天打工人爬取热门微信文章解读)

耐心点好吗&#xff1f; 引言Python 代码第一篇 洞见 废掉一个人最隐蔽的方式&#xff1a;陷于底层习惯第二篇 视频信息差结尾 引言 戒骄戒躁 昨天晚上在沙发上睡着了 原因是身体不想睡 神想睡 于是身体躺在沙发上 神就睡着 早上早早就起来 差一点感冒 不过身体在冷水浴 还有呼…

Mac下载Homebrew

通过command空格搜索终端打开 直接输入 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 然后输入电脑密码 然后直接回车等待安装完成 注意⚠️&#xff1a;如果出现报错/opt/homebrew/bin is not in your PATH…

LW-DETR:实时目标检测的Transformer, Apache-2.0 开源可商用,实验超 YOLOv8

LW-DETR&#xff1a;实时目标检测的Transformer&#xff0c; Apache-2.0 开源可商用&#xff0c;实验超 YOLOv8 LW-DETR 架构实例化高效训练高效推理 目的与解法拆解ViT编码器和DETR解码器多级特征图聚合变形交叉注意力窗口注意力和全局注意力 论文&#xff1a;https://arxiv.o…

Vue3实战笔记(57)—一键换肤:在Vuetify中打造个性化主题切换体验

文章目录 前言一键换肤总结 前言 在当今追求极致用户体验的时代&#xff0c;为应用程序提供个性化的主题切换功能已经成为提升用户满意度和留存率的关键因素之一。Vuetify&#xff0c;作为基于Vue.js的流行前端框架&#xff0c;以其丰富的组件库和高度可定制性&#xff0c;为开…

数字影像产业园的三大赋能:科技、创新与无限可能

数字影像产业园作为文创产业的重要载体&#xff0c;以科技为核心驱动力&#xff0c;不断推动产业的技术革新和升级。 园区内汇聚了最前沿的数字技术资源&#xff0c;高清摄影设备、虚拟现实技术、人工智能应用等尖端科技在这里得到广泛应用&#xff0c;不仅提升了生产效率&…

池化层【马赛克】

最大池化&#xff0c;也叫下采样。 公式&#xff1a; 参数&#xff1a; celling的意思&#xff1a; 例子&#xff1a; 尺寸&#xff1a; code: import torchimport torchvision.datasetsfrom tensorboardX import SummaryWriterfrom torch import nnfrom torch.nn import MaxP…

自定义类型:枚举和联合体

在之前我们已经深入学习了自定义类型中的结构体类型 &#xff0c;了解了结构体当中的内存对齐&#xff0c;位段等知识&#xff0c;接下来在本篇中将继续学习剩下的两个自定义类型&#xff1a;枚举类型与联合体类型&#xff0c;一起加油&#xff01;&#xff01; 1.枚举类型 …

flink Jobmanager metaspace oom 分析

文章目录 现象作业背景分析现象分析类卸载条件MAT 分析 解决办法flink 官方提示 现象 通过flink 页面提交程序&#xff0c;多次提交后&#xff0c;jobmanager 报metaspace oom 作业背景 用户代码是flink 代码Spring nacos 分析 现象分析 从现象来看肯定是因为有的类没有被…

HDFS文件块损坏处理方案

1、问题概述 flume采集文本文件存储到hdfs中hive的ods层目录,并在hive中通过msck repair table刷新元数据,加载文本文件。报错如下: 2、问题分析 文件块BP-531411289-172.31.57.12-1539657748238出现了未知异常,导致namenode不能获取该文件块的信息,该文件块是由flume采…

Django项目部署(命令函部署)

Django项目搭建 一. 下载宝塔面板 我这里使用的是命令函部署 , 下载宝塔主要为了是方便操作 , 宝塔的终端支持复制粘贴 , 而且可以帮助我们快速的检索文件目录以及避免一些软件的环境配置 下载方法: ​ 打开浏览器访问 : 宝塔面板下载&#xff0c;免费全能的服务器运维软件…

关于stm32的软件复位

使用软件复位的目的&#xff1a; 软件复位并不会擦除存储器中的数据&#xff0c;它只是将处理器恢复到复位状态&#xff0c;即中断使能位被清除&#xff0c;系统寄存器被重置&#xff0c;但RAM和Flash存储器中的数据保持不变。 STM32软件复位(基于库文件V3.5) &#xff0c;对…

Junit(Java单元测试)

配置文件 要想使用 Junit 进行单元测试需要引入以下第三方库&#xff1a; 引入后可以使用 Test&#xff0c;BeforeEach等注解 <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter<…

JVM之垃圾回收面试总结

文章目录 1.GC概述1.1 什么是垃圾1.2 为什么需要GC&#xff1f;1.3 早期垃圾回收1.4 Java垃圾回收机制1.5 评估GC的性能指标 2.垃圾回收相关算法2.1 垃圾标记阶段的算法2.1.1 引用计数算法(Java没有使用)2.1.2 可达性分析算法 2.2 垃圾清除阶段的算法2.2.1 标记-清除(Mark-Swee…

C语言 | Leetcode C语言题解之第128题最长连续序列

题目&#xff1a; 题解&#xff1a; typedef struct {int key;UT_hash_handle hh; }Hash; int longestConsecutive(int* nums, int numsSize) {Hash* headNULL;Hash* tempNULL;for(int i0;i<numsSize;i){int numnums[i];HASH_FIND_INT(head,&num,temp);if(!temp){temp…

Java编程常见问题汇总六

系列文章目录 文章目录 系列文章目录前言一、反射使用不当二、不必要的同步三、错误的选择List类型四、HashMap size陷阱五、对Hashtable, HashMap 和 HashSet了解不够 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

Ruoyi-Blog 基于若依后台的博客系统,长期维护

RuoYiBlog-一个基于若依的超级漂亮的博客系统 ✨项目介绍 一直想做一个博客平台&#xff0c;看过许多优秀的开源项目&#xff0c;但没有找到合适的。于是我利用业余时间把若依后台管理和pb-cms结合起来&#xff0c;在自己的参考中开发了一部分&#xff0c;就有了这个 项目可用…

【数学建模】MATLAB入门教程:插值与拟合(下)

前言 插值与拟合在数据处理和科学计算中扮演着非常重要的角色&#xff0c;它们用于估算未知数据点的值&#xff0c;帮助我们理解和预测数据趋势 一、一维插值 1、一维插值定义 已知n1个节点(,)(j0,1,...,n,其中互不相同&#xff0c;不妨设a<<...<b),求任一插值点(…