sc
This commit is contained in:
@@ -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'
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
@@ -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()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
709
src/pages/stats/personal.vue
Normal file
709
src/pages/stats/personal.vue
Normal 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>
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user