This commit is contained in:
qsh
2026-01-30 14:47:56 +08:00
parent ff3b306de0
commit f2c12828ac
6 changed files with 763 additions and 51 deletions

View File

@@ -12,7 +12,7 @@ VITE_APP_ENV = 'development'
# 寻驾/开发环境 # 寻驾/开发环境
# VITE_APP_BASE_API = 'https://cloud.ahduima.com/' # VITE_APP_BASE_API = 'https://cloud.ahduima.com/'
# VITE_APP_BASE_API = 'https://xj.ahduima.com/' # VITE_APP_BASE_API = 'https://xj.ahduima.com/'
VITE_APP_BASE_API = 'http://localhost:48080' VITE_APP_BASE_API = 'http://192.168.31.223:48080'
# #
VITE_WEB_BASE_URL = 'https://xj.ahduima.com' VITE_WEB_BASE_URL = 'https://xj.ahduima.com'
# VITE_WEB_BASE_URL = 'https://xj.ahduima.com' # VITE_WEB_BASE_URL = 'https://xj.ahduima.com'

View File

@@ -2,7 +2,7 @@
"name": "xj-manage-h5", "name": "xj-manage-h5",
"version": "2.0.0", "version": "2.0.0",
"scripts": { "scripts": {
"dev:h5": "uni", "dev:h5": "uni --host",
"dev": "uni -p mp-weixin", "dev": "uni -p mp-weixin",
"dev:dy": "uni -p mp-toutiao", "dev:dy": "uni -p mp-toutiao",
"build:h5": "uni build", "build:h5": "uni build",

View File

@@ -276,6 +276,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/stats/personal",
"style": {
"navigationStyle": "custom"
}
},
{ {
"path": "pages/student/detail", "path": "pages/student/detail",
"style": { "style": {

View File

@@ -4,39 +4,38 @@
<view class="welcome-section"> <view class="welcome-section">
<view class="welcome-title">欢迎使用小程序管理系统</view> <view class="welcome-title">欢迎使用小程序管理系统</view>
<view class="welcome-desc"> <view class="welcome-desc">
<text v-if="userRole === 'admin'">管理员视图</text> <text>{{ userRole.map(role => role.name).join('、') }}</text>
<text v-else>分销员视图</text>
</view> </view>
</view> </view>
<!-- 管理员统计功能 --> <!-- 管理员统计功能 -->
<view v-if="userRole === 'admin'" class="stats-section"> <view class="stats-section">
<!-- 核心数据概览 --> <!-- 核心数据概览 -->
<view class="section"> <view v-if="checkPermi(['home:coreData:index'])" class="section">
<view class="section-title">核心数据概览</view> <view class="section-title">核心数据概览</view>
<view class="stats-grid"> <view class="stats-grid">
<view class="stat-card" @click="goToDistributionStats"> <view v-if="checkPermi(['home:distributionStatistics2:index'])" class="stat-card" @click="goToDistributionStats">
<view class="stat-icon">📊</view> <view class="stat-icon">📊</view>
<view class="stat-content"> <view class="stat-content">
<view class="stat-value">{{ distributionStats.totalProfit }}</view> <view class="stat-value">{{ distributionStats.totalProfit }}</view>
<view class="stat-label">分润总额</view> <view class="stat-label">分润总额</view>
</view> </view>
</view> </view>
<view class="stat-card" @click="goToMemberStats"> <view v-if="checkPermi(['home:memberStatistics2:index'])" class="stat-card" @click="goToMemberStats">
<view class="stat-icon">👥</view> <view class="stat-icon">👥</view>
<view class="stat-content"> <view class="stat-content">
<view class="stat-value">{{ memberStats.totalOrders }}</view> <view class="stat-value">{{ memberStats.totalOrders }}</view>
<view class="stat-label">会员订单</view> <view class="stat-label">会员订单</view>
</view> </view>
</view> </view>
<view class="stat-card" @click="goToStudentStats"> <view v-if="checkPermi(['home:studentStatistics2:index'])" class="stat-card" @click="goToStudentStats">
<view class="stat-icon">🎓</view> <view class="stat-icon">🎓</view>
<view class="stat-content"> <view class="stat-content">
<view class="stat-value">{{ studentStats.totalStudents }}</view> <view class="stat-value">{{ studentStats.totalStudents }}</view>
<view class="stat-label">学员总数</view> <view class="stat-label">学员总数</view>
</view> </view>
</view> </view>
<view class="stat-card" @click="goToDistributionStats"> <view v-if="checkPermi(['home:distributionStatistics2:index'])" class="stat-card" @click="goToDistributionStats">
<view class="stat-icon">📈</view> <view class="stat-icon">📈</view>
<view class="stat-content"> <view class="stat-content">
<view class="stat-value">{{ distributionStats.scanCount }}</view> <view class="stat-value">{{ distributionStats.scanCount }}</view>
@@ -47,9 +46,9 @@
</view> </view>
<!-- 分销业绩统计 --> <!-- 分销业绩统计 -->
<view class="section"> <view class="section" v-if="checkPermi(['home:distributionStatistics:index'])">
<view class="section-title">分销业绩统计</view> <view class="section-title">分销业绩统计</view>
<view class="feature-card" @click="goToDistributionStats"> <view v-if="checkPermi(['home:distributionStatistics2:index'])" class="feature-card" @click="goToDistributionStats">
<view class="feature-icon distributor-icon"> <view class="feature-icon distributor-icon">
<view class="icon-text">📈</view> <view class="icon-text">📈</view>
</view> </view>
@@ -61,9 +60,9 @@
</view> </view>
<!-- 会员运营统计 --> <!-- 会员运营统计 -->
<view class="section"> <view v-if="checkPermi(['home:memberStatistics:index'])" class="section">
<view class="section-title">会员运营统计</view> <view class="section-title">会员运营统计</view>
<view class="feature-card" @click="goToMemberStats"> <view v-if="checkPermi(['home:memberStatistics2:index'])" class="feature-card" @click="goToMemberStats">
<view class="feature-icon user-icon"> <view class="feature-icon user-icon">
<view class="icon-text">👥</view> <view class="icon-text">👥</view>
</view> </view>
@@ -75,9 +74,9 @@
</view> </view>
<!-- 学员学情统计 --> <!-- 学员学情统计 -->
<view class="section"> <view v-if="checkPermi(['home:studentStatistics:index'])" class="section">
<view class="section-title">学员学情统计</view> <view class="section-title">学员学情统计</view>
<view class="feature-card" @click="goToStudentStats"> <view v-if="checkPermi(['home:studentStatistics2:index'])" class="feature-card" @click="goToStudentStats">
<view class="feature-icon notice-icon"> <view class="feature-icon notice-icon">
<view class="icon-text">🎓</view> <view class="icon-text">🎓</view>
</view> </view>
@@ -87,14 +86,10 @@
</view> </view>
</view> </view>
</view> </view>
</view>
<!-- 分销员统计功能 -->
<view v-else-if="userRole === 'distributor'" class="stats-section">
<!-- 个人核心数据 --> <!-- 个人核心数据 -->
<view class="section"> <view v-if="checkPermi(['home:selfStatistics2:index'])" class="section">
<view class="section-title">个人核心数据</view> <view class="section-title">个人核心数据</view>
<view class="stats-grid"> <view class="stats-grid" @click="goToPersonalStats">
<view class="stat-card"> <view class="stat-card">
<view class="stat-icon">📱</view> <view class="stat-icon">📱</view>
<view class="stat-content"> <view class="stat-content">
@@ -127,9 +122,9 @@
</view> </view>
<!-- 个人业绩统计 --> <!-- 个人业绩统计 -->
<view class="section"> <view v-if="checkPermi(['home:selfStatistics:index'])" class="section">
<view class="section-title">个人业绩统计</view> <view class="section-title">个人业绩统计</view>
<view class="feature-card" @click="goToPersonalStats"> <view v-if="checkPermi(['home:selfStatistics2:index'])" class="feature-card" @click="goToPersonalStats">
<view class="feature-icon distributor-icon"> <view class="feature-icon distributor-icon">
<view class="icon-text">📊</view> <view class="icon-text">📊</view>
</view> </view>
@@ -141,7 +136,7 @@
</view> </view>
<!-- 数据分享 --> <!-- 数据分享 -->
<view class="section"> <!-- <view class="section">
<view class="section-title">数据分享</view> <view class="section-title">数据分享</view>
<view class="feature-card" @click="shareData"> <view class="feature-card" @click="shareData">
<view class="feature-icon user-icon"> <view class="feature-icon user-icon">
@@ -152,16 +147,20 @@
<view class="feature-desc">生成业绩数据图片一键分享</view> <view class="feature-desc">生成业绩数据图片一键分享</view>
</view> </view>
</view> </view>
</view> </view> -->
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref, getCurrentInstance, onMounted } from "vue" import { ref, computed, onMounted } from "vue"
import { checkPermi } from "@/utils/permission"
import { useUserStore } from "@/store/modules/user"
const { proxy } = getCurrentInstance()
const userRole = ref('admin') // 模拟角色,实际应从登录状态获取 const userRole = computed(() => {
return useUserStore().roles
})
// 模拟统计数据 // 模拟统计数据
const distributionStats = ref({ const distributionStats = ref({
@@ -193,7 +192,6 @@
onMounted(() => { onMounted(() => {
// 实际项目中应从登录状态或接口获取用户角色和数据 // 实际项目中应从登录状态或接口获取用户角色和数据
// userRole.value = getUserRole()
// loadStatsData() // loadStatsData()
}) })

View File

@@ -0,0 +1,709 @@
<template>
<view class="personal-stats-container">
<!-- 页面标题 -->
<view class="page-header">
<view class="header-left" @click="goBack">
<view class="back-icon"></view>
</view>
<view class="header-title">个人业绩统计</view>
<view class="header-right" @click="shareStats">
<view class="share-btn">分享</view>
</view>
</view>
<!-- 核心数据概览 -->
<view class="core-data-section">
<view class="section-title">核心数据概览</view>
<view class="stats-grid">
<view class="stat-card">
<view class="stat-icon">📱</view>
<view class="stat-content">
<view class="stat-value">{{ coreData.scanCount }}</view>
<view class="stat-label">扫码数</view>
</view>
</view>
<view class="stat-card">
<view class="stat-icon">👥</view>
<view class="stat-content">
<view class="stat-value">{{ coreData.paidCount }}</view>
<view class="stat-label">付费人数</view>
</view>
</view>
<view class="stat-card">
<view class="stat-icon">📈</view>
<view class="stat-content">
<view class="stat-value">{{ coreData.conversionRate }}%</view>
<view class="stat-label">转化率</view>
</view>
</view>
<view class="stat-card">
<view class="stat-icon">💰</view>
<view class="stat-content">
<view class="stat-value">{{ coreData.totalProfit }}</view>
<view class="stat-label">提成总额</view>
</view>
</view>
</view>
</view>
<!-- 近7天趋势 -->
<view class="trend-section">
<view class="section-title">近7天趋势</view>
<view class="trend-card">
<view class="trend-chart">
<!-- 模拟趋势图表 -->
<view class="chart-container">
<view class="chart-grid">
<view v-for="(day, index) in trendData" :key="index" class="chart-column">
<view class="column-bar" :style="{ height: day.value + '%' }"></view>
<view class="column-label">{{ day.date }}</view>
<view class="column-value">{{ day.value }}</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 业绩明细 -->
<view class="detail-section">
<view class="section-header">
<view class="section-title">业绩明细</view>
<view class="section-action" @click="toggleDetail">
<view class="action-text">{{ showDetail ? '收起' : '展开' }}</view>
<view class="action-icon" :class="{ expanded: showDetail }">{{ showDetail ? '▼' : '▶' }}</view>
</view>
</view>
<view v-if="showDetail" class="detail-list">
<view v-for="(item, index) in detailList" :key="index" class="detail-item">
<view class="detail-info">
<view class="detail-title">{{ item.title }}</view>
<view class="detail-meta">
<view class="meta-item">{{ item.date }}</view>
<view class="meta-item">{{ item.type }}</view>
</view>
</view>
<view class="detail-amount" :class="{ positive: item.amount >= 0 }">
{{ item.amount >= 0 ? '+' : '' }}{{ item.amount }}
</view>
</view>
<view v-if="detailList.length === 0" class="empty-detail">
<view class="empty-icon">📋</view>
<view class="empty-text">暂无业绩明细</view>
</view>
</view>
</view>
<!-- 数据分享卡片 -->
<view class="share-section">
<view class="share-card" @click="shareStats">
<view class="share-icon">📱</view>
<view class="share-content">
<view class="share-title">分享业绩数据</view>
<view class="share-desc">生成业绩数据图片一键分享</view>
</view>
<view class="share-arrow"></view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from "vue"
// 核心数据
const coreData = ref({
scanCount: 123,
paidCount: 45,
conversionRate: 36.9,
totalProfit: '¥1,234.56'
})
// 近7天趋势数据
const trendData = ref([
{ date: '1/24', value: 65 },
{ date: '1/25', value: 72 },
{ date: '1/26', value: 58 },
{ date: '1/27', value: 81 },
{ date: '1/28', value: 45 },
{ date: '1/29', value: 59 },
{ date: '1/30', value: 73 }
])
// 业绩明细数据
const detailList = ref([
{
title: '会员购买课程',
date: '2026-01-30 14:30',
type: '课程提成',
amount: 128.00
},
{
title: '会员续费',
date: '2026-01-29 09:15',
type: '续费提成',
amount: 88.00
},
{
title: '推荐新用户',
date: '2026-01-28 16:45',
type: '推荐奖励',
amount: 50.00
}
])
// 显示业绩明细
const showDetail = ref(true)
onMounted(() => {
// 实际项目中应从接口获取数据
// loadPersonalStats()
})
// 返回上一页
function goBack() {
uni.navigateBack({ delta: 1 })
}
// 切换业绩明细显示
function toggleDetail() {
showDetail.value = !showDetail.value
}
// 分享业绩数据
function shareStats() {
uni.showLoading({ title: '生成分享图片...' })
setTimeout(() => {
uni.hideLoading()
uni.showActionSheet({
itemList: ['分享到微信', '分享到朋友圈', '保存图片'],
success: function(res) {
switch(res.tapIndex) {
case 0:
uni.showToast({ title: '分享到微信', duration: 1000 })
break
case 1:
uni.showToast({ title: '分享到朋友圈', duration: 1000 })
break
case 2:
uni.showToast({ title: '图片已保存', duration: 1000 })
break
}
}
})
}, 1500)
}
</script>
<style lang="scss" scoped>
page {
background-color: #f5f7fa;
}
.personal-stats-container {
min-height: 100vh;
}
/* 页面头部 */
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 120rpx;
background-color: #fff;
padding: 0 32rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.header-left {
width: 60rpx;
}
.back-icon {
font-size: 40rpx;
color: #303133;
cursor: pointer;
}
.header-title {
font-size: 32rpx;
font-weight: bold;
color: #303133;
}
.header-right {
width: 60rpx;
text-align: right;
}
.share-btn {
font-size: 24rpx;
color: #409eff;
font-weight: 600;
cursor: pointer;
}
/* 核心数据概览 */
.core-data-section {
background-color: #fff;
margin: 16rpx;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* 趋势部分 */
.trend-section {
background-color: #fff;
margin: 0 16rpx 16rpx;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* 业绩明细 */
.detail-section {
background-color: #fff;
margin: 0 16rpx 16rpx;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* 分享卡片 */
.share-section {
margin: 0 16rpx 32rpx;
}
/* 通用样式 */
.section-title {
font-size: 28rpx;
font-weight: bold;
color: #303133;
margin-bottom: 24rpx;
padding-left: 12rpx;
border-left: 8rpx solid #409eff;
line-height: 1.2;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
}
.section-action {
display: flex;
align-items: center;
cursor: pointer;
}
.action-text {
font-size: 22rpx;
color: #409eff;
margin-right: 4rpx;
}
.action-icon {
font-size: 16rpx;
color: #409eff;
transition: transform 0.3s ease;
}
.action-icon.expanded {
transform: rotate(0deg);
}
/* 统计网格 */
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
}
.stat-card {
background-color: #f9f9f9;
border-radius: 12rpx;
padding: 24rpx;
display: flex;
align-items: center;
}
.stat-icon {
font-size: 48rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.stat-content {
flex: 1;
}
.stat-value {
font-size: 28rpx;
font-weight: bold;
color: #303133;
margin-bottom: 4rpx;
line-height: 1.2;
}
.stat-label {
font-size: 20rpx;
color: #909399;
line-height: 1.3;
}
/* 趋势图表 */
.trend-card {
background-color: #f9f9f9;
border-radius: 12rpx;
padding: 24rpx;
}
.chart-container {
height: 300rpx;
}
.chart-grid {
display: flex;
align-items: flex-end;
height: 100%;
gap: 16rpx;
padding: 20rpx 0;
}
.chart-column {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.column-bar {
width: 32rpx;
background: linear-gradient(180deg, #409eff 0%, #667eea 100%);
border-radius: 4rpx 4rpx 0 0;
margin-bottom: 8rpx;
transition: height 0.5s ease;
}
.column-label {
font-size: 18rpx;
color: #909399;
margin-bottom: 4rpx;
}
.column-value {
font-size: 16rpx;
color: #303133;
font-weight: 500;
}
/* 业绩明细 */
.detail-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
background-color: #f9f9f9;
border-radius: 12rpx;
}
.detail-info {
flex: 1;
}
.detail-title {
font-size: 24rpx;
color: #303133;
font-weight: 500;
margin-bottom: 8rpx;
}
.detail-meta {
display: flex;
gap: 16rpx;
}
.meta-item {
font-size: 20rpx;
color: #909399;
}
.detail-amount {
font-size: 24rpx;
font-weight: bold;
color: #f56c6c;
}
.detail-amount.positive {
color: #67c23a;
}
.empty-detail {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
}
.empty-icon {
font-size: 64rpx;
margin-bottom: 16rpx;
}
.empty-text {
font-size: 22rpx;
color: #909399;
}
/* 分享卡片 */
.share-card {
display: flex;
align-items: center;
background: linear-gradient(135deg, #409eff 0%, #667eea 100%);
border-radius: 16rpx;
padding: 32rpx;
color: #fff;
box-shadow: 0 8rpx 32rpx rgba(64, 158, 255, 0.3);
cursor: pointer;
transition: transform 0.3s ease;
}
.share-card:active {
transform: translateY(2rpx);
}
.share-icon {
font-size: 64rpx;
margin-right: 24rpx;
flex-shrink: 0;
}
.share-content {
flex: 1;
}
.share-title {
font-size: 28rpx;
font-weight: bold;
margin-bottom: 8rpx;
line-height: 1.2;
}
.share-desc {
font-size: 22rpx;
opacity: 0.9;
line-height: 1.4;
}
.share-arrow {
font-size: 24rpx;
opacity: 0.9;
}
/* 平板响应式 */
@media screen and (min-width: 768px) {
.personal-stats-container {
max-width: 900px;
margin: 0 auto;
width: 100%;
}
.core-data-section,
.trend-section,
.detail-section {
margin: 0 32rpx 24rpx;
padding: 32rpx;
}
.share-section {
margin: 0 32rpx 32rpx;
}
.section-title {
font-size: 32rpx;
margin-bottom: 32rpx;
}
.stats-grid {
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
}
.stat-card {
padding: 32rpx;
}
.stat-icon {
font-size: 56rpx;
margin-right: 24rpx;
}
.stat-value {
font-size: 32rpx;
}
.stat-label {
font-size: 22rpx;
}
.trend-card {
padding: 32rpx;
}
.chart-container {
height: 350rpx;
}
.chart-column {
gap: 8rpx;
}
.column-bar {
width: 40rpx;
}
.column-label {
font-size: 20rpx;
}
.column-value {
font-size: 18rpx;
}
.detail-item {
padding: 32rpx;
}
.detail-title {
font-size: 26rpx;
}
.meta-item {
font-size: 22rpx;
}
.detail-amount {
font-size: 28rpx;
}
.share-card {
padding: 40rpx;
}
.share-icon {
font-size: 80rpx;
margin-right: 32rpx;
}
.share-title {
font-size: 32rpx;
}
.share-desc {
font-size: 24rpx;
}
.share-arrow {
font-size: 28rpx;
}
.share-btn {
font-size: 26rpx;
}
}
/* 大屏设备响应式 */
@media screen and (min-width: 1024px) {
.personal-stats-container {
max-width: 1000px;
}
.core-data-section,
.trend-section,
.detail-section {
padding: 36rpx;
}
.section-title {
font-size: 36rpx;
margin-bottom: 36rpx;
}
.stats-grid {
gap: 24rpx;
}
.stat-card {
padding: 36rpx;
}
.stat-icon {
font-size: 64rpx;
}
.stat-value {
font-size: 36rpx;
}
.stat-label {
font-size: 24rpx;
}
.chart-container {
height: 400rpx;
}
.column-bar {
width: 48rpx;
}
.column-label {
font-size: 22rpx;
}
.column-value {
font-size: 20rpx;
}
.detail-item {
padding: 36rpx;
}
.detail-title {
font-size: 28rpx;
}
.detail-amount {
font-size: 32rpx;
}
.share-card {
padding: 48rpx;
}
.share-icon {
font-size: 96rpx;
margin-right: 40rpx;
}
.share-title {
font-size: 36rpx;
}
.share-desc {
font-size: 26rpx;
}
}
</style>

View File

@@ -1,4 +1,4 @@
import store from '@/store' import { useUserStore } from '@/store/modules/user';
/** /**
* 字符权限校验 * 字符权限校验
@@ -7,21 +7,20 @@ import store from '@/store'
*/ */
export function checkPermi(value) { export function checkPermi(value) {
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const permissions = store.getters && store.getters.permissions const permissions = useUserStore().permissions;
const permissionDatas = value const permissionDatas = value;
const all_permission = "*:*:*" const all_permission = '*:*:*';
const hasPermission = permissions.some(permission => { const hasPermission = permissions.some(permission => {
return all_permission === permission || permissionDatas.includes(permission) return all_permission === permission || permissionDatas.includes(permission);
}) });
if (!hasPermission) { if (!hasPermission) {
return false return false;
} }
return true return true;
} else { } else {
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`);
return false return false;
} }
} }
@@ -32,20 +31,20 @@ export function checkPermi(value) {
*/ */
export function checkRole(value) { export function checkRole(value) {
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const roles = store.getters && store.getters.roles const roles = useUserStore().roles; // store.getters && store.getters.roles;
const permissionRoles = value const permissionRoles = value;
const super_admin = "admin" const super_admin = 'admin';
const hasRole = roles.some(role => { const hasRole = roles.some(role => {
return super_admin === role || permissionRoles.includes(role) return super_admin === role || permissionRoles.includes(role);
}) });
if (!hasRole) { if (!hasRole) {
return false return false;
} }
return true return true;
} else { } else {
console.error(`need roles! Like checkRole="['admin','editor']"`) console.error(`need roles! Like checkRole="['admin','editor']"`);
return false return false;
} }
} }