【二开】CRMEB开源版按钮权限控制

使用方法

v-unique_auth="'order-refund'"
<el-dropdown-itemv-unique_auth="'order-refund'">立即退款</el-dropdown-item
>

或者 满足其中一个即可

v-unique_auth="['order-delete','order-dels']"

通过管理端权限维护按钮即可

1. 存储权限

template/admin/src/pages/account/login/index.vue

登录成功后存储

Local.set('unique_auth', data.unique_auth);

完整代码

<template><div class="page-account"><div class="container" :class="[fullWidth > 768 ? 'containerSamll' : 'containerBig']"><swiper :options="swiperOption" class="swiperPross" v-if="fullWidth > 768"><swiper-slide class="swiperPic" v-for="(item, index) in swiperList" :key="index"><img :src="item.slide" alt="" /></swiper-slide><div class="swiper-pagination" slot="pagination"></div></swiper><div class="index_from page-account-container from-wh"><div class="page-account-top"><div class="page-account-top-logo"><img :src="login_logo" alt="logo" style="width: 100%; height: 74px" /></div></div><el-form ref="formInline" :model="formInline" :rules="ruleInline" @keyup.enter="handleSubmit('formInline')"><el-form-item prop="username"><el-inputtype="text"v-model="formInline.username"prefix="ios-contact-outline"placeholder="请输入用户名"size="large"/></el-form-item><el-form-item prop="password"><el-inputtype="password"v-model="formInline.password"prefix="ios-lock-outline"placeholder="请输入密码"size="large"show-password/></el-form-item><!-- <el-form-item prop="code"><div class="code"><el-inputtype="text"v-model="formInline.code"prefix="ios-keypad-outline"placeholder="请输入验证码"size="large"/><img :src="imgcode" class="pictrue" v-db-click @click="captchas" /></div></el-form-item> --><el-form-item class="pt10"><el-buttontype="primary":loading="loading"size="large"v-db-click@click="handleSubmit('formInline')"class="btn">登录</el-button></el-form-item></el-form></div></div><Verify@success="success"captchaType="blockPuzzle":imgSize="{ width: '330px', height: '155px' }"ref="verify"></Verify><div class="footer"><div class="pull-right" v-if="copyright">{{ copyright }}</div><div class="pull-right" v-else>Copyright © 2014-2025 <a href="https://www.crmeb.com" target="_blank">{{ version }}</a></div></div></div>
</template>
<script>
import { AccountLogin, loginInfoApi } from '@/api/account';
import { getWorkermanUrl } from '@/api/kefu';
import { setCookies } from '@/libs/util';
import '@/assets/js/canvas-nest.min';
import Verify from '@/components/verifition/Verify';
import { PrevLoading } from '@/utils/loading.js';
import { formatFlatteningRoutes, findFirstNonNullChildren } from '@/libs/system';
import { Local } from '@/utils/storage.js';export default {components: {Verify,},data() {return {fullWidth: document.documentElement.clientWidth,swiperOption: {pagination: '.swiper-pagination',autoplay: true,},loading: false,isShow: false,imgcode: '',formInline: {username: '',password: '',},ruleInline: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' }],},login_captcha: 0,login_logo: '',swiperList: [],defaultSwiperList: require('@/assets/images/sw.png'),key: '',copyright: '',version: '',timer: null,};},created() {document.onkeydown = (e) => {if (this.$route.name === 'login' && (e.keyCode === 13 || e.which === 13)) {this.handleSubmit('formInline');}};window.addEventListener('resize', this.handleResize);},mounted() {this.$nextTick(() => {this.handleResize();this.swiperData();});},beforeDestroy() {window.removeEventListener('resize', this.handleResize);document.onkeydown = null;const canvas = document.getElementsByTagName('canvas')[0];if (canvas) canvas.removeAttribute('class', 'index_bg');},methods: {swiperData() {loginInfoApi().then((res) => {const data = res.data || {};document.title = `${data.site_name} - 登录`;localStorage.setItem('ADMIN_TITLE', data.site_name || '');this.$store.commit('setAdminTitle', data.site_name);this.login_logo = data.login_logo || require('@/assets/images/logo.png');this.swiperList = data.slide && data.slide.length ? data.slide : [{ slide: this.defaultSwiperList }];this.key = data.key;this.copyright = data.copyright;this.version = data.version;this.login_captcha = data.login_captcha;}).catch((err) => {this.$message.error(err);this.login_logo = require('@/assets/images/logo.png');this.swiperList = [{ slide: this.defaultSwiperList }];});},success(params) {this.closeModel(params);},closeModel(params) {this.isShow = false;this.loading = true;AccountLogin({account: this.formInline.username,pwd: this.formInline.password,key: this.key,captchaType: 'blockPuzzle',captchaVerification: params ? params.captchaVerification : '',}).then(async (res) => {const data = res.data;const expires = this.getExpiresTime(data.expires_time);setCookies('uuid', data.user_info.id, expires);setCookies('token', data.token, expires);setCookies('expires_time', data.expires_time, expires);Local.set('PERMISSIONS', data.site_func);Local.set('unique_auth', data.unique_auth);this.$store.commit('userInfo/uniqueAuth', data.unique_auth);this.$store.commit('userInfo/userInfo', data.user_info);this.$store.commit('menus/setopenMenus', []);this.$store.commit('menus/getmenusNav', data.menus);this.$store.dispatch('routesList/setRoutesList', data.menus);const arr = formatFlatteningRoutes(this.$router.options.routes);this.formatTwoStageRoutes(arr);this.$store.commit('menus/setOneLvMenus', arr);const routes = formatFlatteningRoutes(data.menus);this.$store.commit('menus/setOneLvRoute', routes);this.$store.commit('userInfo/name', data.user_info.account);this.$store.commit('userInfo/avatar', data.user_info.head_pic);this.$store.commit('userInfo/access', data.unique_auth);this.$store.commit('userInfo/logo', data.logo);this.$store.commit('userInfo/logoSmall', data.logo_square);this.$store.commit('userInfo/version', data.version);this.$store.commit('userInfo/newOrderAudioLink', data.newOrderAudioLink);this.login_captcha = 0;try {if (data.queue === false) {this.$notify.warning({title: '温馨提示',dangerouslyUseHTMLString: true,message:'您的【消息队列】未开启,没有开启会导致异步任务无法执行。请尽快执行命令开启!!<a href="https://doc.crmeb.com/single/v54/13667" target="_blank">点击查看开启方法</a>',duration: 30000,});}if (data.timer === false) {setTimeout(() => {this.$notify.warning({title: '温馨提示',dangerouslyUseHTMLString: true,message:'您的【定时任务】未开启,没有开启会导致自动收货、未支付自动取消订单、订单自动好评、拼团到期退款等任务无法正常执行。请尽快执行命令开启!!<a href="https://doc.crmeb.com/single/v54/13667" target="_blank">点击查看开启方法</a>',duration: 30000,});}, 0);}this.checkSocket();} catch (e) {}PrevLoading.start();this.$router.push({path: data.menus.length ? findFirstNonNullChildren(data.menus).path : this.$routeProStr + '/',});}).catch((res) => {const data = res || {};this.$message.error(data.msg || '登录失败');if (res && res.data) this.login_captcha = res.data.login_captcha;}).finally(() => {setTimeout(() => {this.loading = false;}, 1000);});},formatTwoStageRoutes(arr) {if (!arr.length) return false;const cacheList = [];arr.forEach((v) => {if (v && v.meta && v.meta.keepAlive) {cacheList.push(v.name);}});if (cacheList.length) {this.$store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);}},checkSocket() {getWorkermanUrl().then((res) => {const url = res.data.admin;let isNotice = false;const socket = new window.WebSocket(url);socket.onopen = () => {isNotice = true;socket.close();};socket.onerror = socket.onclose = () => {if (!isNotice) {isNotice = true;this.$notify.warning({title: '温馨提示',message:'您的【长连接】未开启,没有开启会导致系统默认客服无法使用,后台订单通知无法收到。请尽快执行命令开启!!<a href="https://doc.crmeb.com/single/v54/13667" target="_blank">点击查看开启方法</a>',dangerouslyUseHTMLString: true,duration: 30000,});}};});},getExpiresTime(expiresTime) {const nowTimeNum = Math.round(Date.now() / 1000);const expiresTimeNum = expiresTime - nowTimeNum;return parseFloat(expiresTimeNum / 60 / 60 / 24);},closefail() {this.$message.error('校验错误');},handleResize() {this.fullWidth = document.documentElement.clientWidth;const canvas = document.getElementsByTagName('canvas')[0];if (canvas) {if (this.fullWidth < 768) {canvas.removeAttribute('class', 'index_bg');} else {canvas.className = 'index_bg';}}},handleSubmit(name) {this.$refs[name].validate((valid) => {if (valid) {if (this.login_captcha === 1) {this.$refs.verify.show();} else {this.closeModel();}}});},},
};
</script>
<style lang="scss" scoped>
.page-account {display: flex;width: 100%;background-image: url('../../../assets/images/bg.jpg');background-size: cover;background-position: center;flex-direction: column;justify-content: center;align-items: center;height: 100vh;overflow: auto;
}
.page-account .code {display: flex;align-items: center;justify-content: center;
}
.page-account .code .pictrue {height: 40px;
}
.swiperPross {border-radius: 12px 0px 0px 12px;
}
.swiperPross,
.swiperPic,
.swiperPic img {width: 510px;height: 100%;
}
.swiperPic img {width: 100%;height: 100%;
}
.container {height: 400px !important;padding: 0 !important;border-radius: 12px;z-index: 1;display: flex;
}
.containerSamll {/* width: 56% !important; */background: #fff !important;
}
.containerBig {width: auto !important;background: #f7f7f7 !important;
}
.index_from {padding: 32px 40px 32px 40px;height: 400px;box-sizing: border-box;
}
.page-account-top {padding: 20px 0 24px 0 !important;box-sizing: border-box !important;display: flex;justify-content: center;
}
.page-account-container {border-radius: 0px 6px 6px 0px;
}
.btn {width: 100%;background: linear-gradient(90deg, rgba(25, 180, 241, 1) 0%, rgba(14, 115, 232, 1) 100%) !important;
}
.captchaBox {width: 310px;
}input {display: block;width: 290px;line-height: 40px;margin: 10px 0;padding: 0 10px;outline: none;border: 1px solid #c8cccf;border-radius: 4px;color: #6a6f77;
}#msg {width: 100%;line-height: 40px;font-size: 14px;text-align: center;
}a:link,
a:visited,
a:hover,
a:active {margin-left: 100px;color: #0366d6;
}
.index_from ::v-deep .ivu-input-large {font-size: 14px !important;
}
.from-wh {width: 400px;
}
.pull-right {float: right !important;
}
::v-deep .el-button--primary {border: none;
}
::v-deep .el-button {padding: 13px 20px !important;
}
.pull-right {float: right !important;color: #666;
}
.pull-right a {margin-left: 0;color: #666;
}
.footer {position: fixed;bottom: 0;width: 100%;left: 0;margin: 0;background: rgba(255, 255, 255, 0.8);border-top: 1px solid #e7eaec;overflow: hidden;padding: 10px 20px;height: 36px;line-height: 18px;z-index: 999;
}
</style>

2. 创建权限验证 js

template/admin/src/directive/module/unique_auth.js

import { Local } from '@/utils/storage.js';/*** 判断传入的 key 是否在数组 arr 中存在* @param {string} key - 待判断的字符串* @returns {boolean} - 返回布尔值,表示是否有权限*/
function checkArray(key) {// seckill 秒杀 bargain 砍价 combination 拼团let arr = Local.get('unique_auth'); // 定义一个数组,包含三种类型if(!key){return false;}if(key instanceof Array){for (let i = 0; i < key.length; i++){let keytmp = key[i]if(!keytmp){continue}let index = arr.indexOf(keytmp); // 获取 key 在数组中的索引console.info('所有权限', index, keytmp, arr)if (index > -1) {// 如果索引大于 -1,说明 key 存在于数组中return true; // 有权限} else {return false; // 无权限}}return false}let index = arr.indexOf(key); // 获取 key 在数组中的索引console.info('所有权限', index, key, arr)if (index > -1) {// 如果索引大于 -1,说明 key 存在于数组中return true; // 有权限} else {return false; // 无权限}
}/*** @description 一个Vue指令,用于控制组件的显示和隐藏* @param {Object} el - 指令绑定的DOM元素* @param {Object} binding - 指令绑定的对象*/
const unique_auth = {inserted: function (el, binding) {console.info('权限验证', binding.value, el)let permission = binding.value; // 获取到 v-permission的值if (permission) {let hasPermission = checkArray(permission); // 调用checkArray函数判断是否有权限if (!hasPermission) {console.info('无权限', permission)// 没有权限 移除Dom元素el.parentNode && el.parentNode.removeChild(el);}}},
};export default unique_auth;

3. 配置directives

import unique_auth from './module/unique_auth';const directives = {draggable,clipboard,auth,permission, unique_auth,dbClick,
};

template/admin/src/directive/directives.js

import draggable from './module/draggable';
import clipboard from './module/clipboard';
import auth from './module/auth';
import permission from './module/permission';
import dbClick from './module/dbClick';
import unique_auth from './module/unique_auth';const directives = {draggable,clipboard,auth,permission, unique_auth,dbClick,
};export default directives;

4.配置指令

  Vue.directive('unique_auth', directive.unique_auth);

template/admin/src/directive/index.js

import directive from './directives';const importDirective = (Vue) => {/*** 拖拽指令 v-draggable="options"* options = {*  trigger: /这里传入作为拖拽触发器的CSS选择器/,*  body:    /这里传入需要移动容器的CSS选择器/,*  recover: /拖动结束之后是否恢复到原来的位置/* }*/Vue.directive('draggable', directive.draggable);/*** clipboard指令 v-draggable="options"* options = {*  value:    /在输入框中使用v-model绑定的值/,*  success:  /复制成功后的回调/,*  error:    /复制失败后的回调/* }*/Vue.directive('clipboard', directive.clipboard);/*** v-auth="['string-string']"* */Vue.directive('auth', directive.auth);Vue.directive('permission', directive.permission);Vue.directive('unique_auth', directive.unique_auth);Vue.directive('dbClick', directive.dbClick);
};export default importDirective;

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

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

相关文章

AOSP源码下载及编译错误解决

源码下载 软件下载sudo apt-get updatesudo apt-get install gitsudo apt-get install curlsudo apt-get install adbsudo apt-get install reposudo apt-get install vimsudo apt-get install -y git devscripts equivs config-package-dev debhelper-compat golang curl配置g…

实验-高级acl(简单)

实验-高级acl&#xff08;简单&#xff09;预习一、实验设备二、拓扑图三、配置3.1、网络互通3.2、配置ACL3.3、取消配置步骤1&#xff1a;先移除接口上的ACL应用步骤2&#xff1a;修改或删除ACL中的错误规则方法A&#xff1a;直接删除错误规则&#xff08;保留其他正确规则&am…

IoC / DI 实操

1. 建三层类包结构&#xff1a;com.lib ├─ config ├─ controller ├─ service ├─ repository ├─ model └─ annotation // 自定义限定符① 实体 Bookpackage com.lib.model; public class Book {private Integer id;private String title;// 全参构造 gette…

AdsPower RPA 从excel中依次读取多个TikTok账号对多个TikTok账号目标发送信息

多个账号对多个目标发送子场景 B&#xff1a;多个账号向“不同的”目标循环发送&#xff08;最复杂的群发逻辑&#xff09;流程&#xff1a;Excel表中有一个“目标用户”列表。RPA流程会进行嵌套循环&#xff1a;外层循环&#xff1a;遍历Excel中的每一行数据&#xff08;即每一…

扩散模型进化史

一幅精美的图片&#xff0c;一段精彩的视频&#xff0c;可能始于一片纯粹的噪声。 2024年的计算机视觉顶会CVPR上&#xff0c;扩散模型成为绝对主角。从图像生成到视频理解&#xff0c;从超分辨率到3D建模&#xff0c;扩散模型正以惊人的速度重塑着AIGC&#xff08;AI生成内容&…

一次 Linux 高负载 (Load) 异常问题排查实录

一次 Linux 高负载&#xff08;Load&#xff09;异常排查实录一、背景及排查过程材料二、排查分析2.1Load 的真正含义2.2&#xff1a;确认异常进程2.3&#xff1a;线程卡在哪&#xff08;wchan&#xff09;2.4&#xff1a;perf 采样&#xff08;用户态/内核态热点&#xff09;2…

浅析Linux进程信号处理机制:基本原理及应用

文章目录概述信号类型可靠信号与不可靠信号Fatal信号与Non Fatal信号不可捕获/忽略信号信号工作机制信号处理方式信号嵌套处理信号使用信号发送kill命令注册信号处理函数信号安全与函数可重入性可重入函数线程安全与可重入性相关参考概述 Linux信号机制是进程间通信的一种方式…

【学习K230-例程19】GT6700-TCP-Client

B站视频 TCP TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff0c;传输控制协议/网际协议&#xff09;是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP 协议不仅仅指的是 TCP和 IP 两个协议&#xff0c;而是指一个由 FTP、SMTP、TCP、UDP、I…

o2oa待办流程和已办流程表

在o2oa系统中每个用户有两种唯一标识&#xff1a;第一种是姓名个人钉钉ID&#xff08;或者o2oa创建该用户时设置的id&#xff09;ORG_PERSON.xdistinguishedName刘准3013692136672430P第二种是姓名所在部门的钉钉id个人钉钉idORG_IDENTITY.xdistinguishedName刘准966488616_301…

QT零基础入门教程

基础篇第一章 QT 基础认知1.1 什么是 QT&#xff08;What&#xff09;​定义&#xff1a;跨平台 C 应用开发框架&#xff0c;不仅用于 UI 设计&#xff0c;还包含核心功能&#xff08;如事件、网络、数据库&#xff09;。​核心特性&#xff1a;​跨平台&#xff1a;一套代码支…

远程依赖管理新范式:cpolar赋能Nexus全球协作

文章目录 前言一. Docker安装Nexus二. 本地访问Nexus三. Linux安装Cpolar四. 配置Nexus界面公网地址五. 远程访问 Nexus界面六. 固定Nexus公网地址七. 固定地址访问Nexus 前言 Nexus作为一款企业级仓库管理工具&#xff0c;其核心功能在于集中管理各类软件依赖&#xff0c;提供…

Prompt技术深度解析:从基础原理到前沿应用的全面指南

引言 在人工智能技术飞速发展的今天&#xff0c;Prompt技术&#xff08;提示词工程&#xff09;已成为连接人类智慧与机器智能的重要桥梁。随着GPT-4、Claude、Gemini等大型语言模型的广泛应用&#xff0c;如何有效地与这些AI系统进行交互&#xff0c;已成为决定AI应用成功与否…

性能测试工具Jmeter之java.net.BindException: Address already in use

首先请参考连接&#xff1a;https://blog.csdn.net/weixin_46190208/article/details/115229733 。配置完注册表后一般就能解决问题。但并未解决我的问题 注册表的MaxUserPort&#xff0c;TcpTimedWaitDelay两个参数我只能配置MaxUserPort&#xff0c;设置TcpTimedWaitDelay后&…

JDK 新特性

JDK 新特性引入模块Java 9 开始引入了模块&#xff08;Module&#xff09;&#xff0c;目的是为了管理依赖。使用模块可以按需打包 JRE 和进一步限制类的访问权限。接口支持私有方法JAVA 9 开始&#xff0c;接口里可以添加私有方法&#xff0c;JAVA 8 对接口增加了默认方法的支…

如何高效应对网站反爬虫策略?

现在大型网站的反爬策略越来越高明了&#xff0c;不仅是对IP访问频率、User-Agent请求头进行异常识别&#xff0c;还会分析IP地址、浏览器指纹、JS动态加载、API逆向、行为模式等方式各种设卡&#xff0c;动不动跳出五花八门的验证码&#xff0c;非常难搞。 怎么应对反爬是个系…

c++ shared_ptr理解

不是一个智能指针对于一个计数器吗&#xff1f;怎么变成共有资源的计数器了&#xff1f;你的意思是多个对象共用一个计数器&#xff1f;你问到了 std::shared_ptr 最核心、最精妙的设计机制&#xff01;你的问题非常深刻&#xff1a;“不是一个智能指针对应一个计数器吗&#x…

002 Rust环境搭建

Rust环境搭建 现在很多集成开发环境(IDE)基本上都支持Rust开发。官方公布的支持工具&#xff1a;https://www.rust-lang.org/zh-CN/tools 这里以Windows 10 64位系统 Visual Studio Code为例来搭建Rust开发环境。 Rust安装 Rust 的编译工具依赖 C 语言的编译工具&#xff0…

【Unity进阶】Unity发布PC端,隐藏并自定义默认标题栏

开发环境&#xff1a; Unity2019.3.16f1c1 - 个人版 Visual Studio Community 2019 Windows10 专业版 x64嘿&#xff0c;各位朋友们&#xff01;当咱们欢欢喜喜地把项目打包成PC平台的exe窗口程序&#xff0c;准备在电脑上一展游戏风采时&#xff0c;却发现冒出来个Windows风格…

国产延时芯片EH3B05上电延时3秒开关机芯片方案超低功耗

EH3B05-4941-24A1延时开关芯片是一款专为低功耗电子产品设计的高效时序控制器件&#xff0c;其核心功能在于提供精确的多通道延时信号输出。该芯片采用SOT23-6超小封装&#xff0c;体积仅为2.9mm2.8mm1.3mm&#xff0c;特别适合空间受限的便携式设备。其工作电压范围覆盖2.0V至…

大数据与财务管理专业如何转型做金融科技?

在数字经济加速演进的今天&#xff0c;金融行业的边界正在被数据与技术重新定义。传统金融岗位正经历深刻变革&#xff0c;而"金融科技"&#xff08;FinTech&#xff09;作为技术与金融深度融合的产物&#xff0c;已成为行业转型升级的核心引擎。越来越多具备数据背景…