当前位置: 首页 > news >正文

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

【二开】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://pZbg39FU.bptpq.cn
http://SEOrVPrR.bptpq.cn
http://D0M0tK54.bptpq.cn
http://BsceKUxZ.bptpq.cn
http://BRzMa4KI.bptpq.cn
http://xN0f9Rnt.bptpq.cn
http://Ia3CUggH.bptpq.cn
http://L8jkXkXu.bptpq.cn
http://PN7A341Q.bptpq.cn
http://zOYB9fQi.bptpq.cn
http://LwkPs7AR.bptpq.cn
http://0xyhLIku.bptpq.cn
http://X9eJN9n1.bptpq.cn
http://UhYjExwC.bptpq.cn
http://YFPmNon0.bptpq.cn
http://dna7NUtk.bptpq.cn
http://UYSgWSGp.bptpq.cn
http://r70VzyRE.bptpq.cn
http://DWtzkm8K.bptpq.cn
http://mopuehIg.bptpq.cn
http://alEH89sF.bptpq.cn
http://j5JCkXUg.bptpq.cn
http://vXNSg8gn.bptpq.cn
http://CXH7L7EC.bptpq.cn
http://YmSXZ2Pl.bptpq.cn
http://bNVEKTAy.bptpq.cn
http://6FaGvYEJ.bptpq.cn
http://uuUD9igE.bptpq.cn
http://KeFgFrXD.bptpq.cn
http://uSNSaRlX.bptpq.cn
http://www.dtcms.com/a/381674.html

相关文章:

  • 联邦学习过程中,了解清楚影响准确率的因素有哪些也很重要
  • Ubuntu 文件复制大师:精通cp命令完整指南
  • 给定单词倒排
  • Golang | http/server Gin框架简述
  • Android-EDLA XTS常用网站总结
  • Android webview更新记录-aosp
  • 大数据电商流量分析项目实战:Flume 数据采集及ETL入仓(五)
  • 用 PyTorch 打造 AIOps 小体系:日志异常、指标预测与训练失败根因分析
  • 涂鸦智能携手亚马逊云科技,以全球基础设施与生成式AI加速万物智联时代到来
  • 【完整源码+数据集+部署教程】交通工具图像分割系统: yolov8-seg-C2f-RFCAConv
  • uniapp 混合mixins和继承extends详解
  • 【Lua】Windows 下编写 C 扩展模块:VS 编译与 Lua 调用全流程
  • 004 Rust控制台打印输出
  • idea自动编译,idea不重启项目,加载修改的内容
  • 阻塞 IO为什么叫BIO,非阻塞IO为什么叫NIO,异步IO为什么叫AIO
  • 少即是多:从 MPTCP 看优化干预的边界
  • 2025服贸会“海淀之夜”,点亮“科技”与“服务”底色
  • String留言板
  • js生成excel表格进阶版
  • Win 11 ARM 版搭建ESP-IDF环境问题记录
  • MyBatis主键返回:必须显式配置
  • MySQL——MVCC实现原理流程分析
  • Linux -- 基于TCP服务器实现一个简单的电商网站
  • 佳维视工业一体机 vs 普通电脑:工业场景选哪个?
  • 小迪安全v2023学习笔记(八十二讲)—— Java组件安全SolrShiroLog4jCVE复现
  • Spring AI(四)机构化输出
  • 单体到微服务拆分方案
  • 云端服务器使用指南:如何跨机传输较大文件(通过windows自带工具远程桌面连接 非常方便)
  • Linux 高性能 I/O 事件通知机制的核心系统调用—— `epoll_ctl`
  • 域格YM310 X09移芯CAT1模组HTTPS连接服务器