feat(分析报告): 添加二期分析报告功能并优化UI
- 在MemberDetails和PersonalDashboard组件中添加二期分析报告功能 - 统一分析周期参数为'day'、'camp'、'month' - 优化模态框头部布局和按钮样式 - 添加获取二期分析报告的API调用 - 调整baseURL为本地开发环境
This commit is contained in:
@@ -5,8 +5,8 @@ import { useUserStore } from '@/stores/user'
|
|||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: 'https://mldash.nycjy.cn/' || '', // API基础路径,支持完整URL
|
// baseURL: 'https://mldash.nycjy.cn/' || '', // API基础路径,支持完整URL
|
||||||
// baseURL: 'http://192.168.15.121:8890' || '', // API基础路径,支持完整URL
|
baseURL: 'http://192.168.15.121:8890' || '', // API基础路径,支持完整URL
|
||||||
timeout: 100000, // 请求超时时间
|
timeout: 100000, // 请求超时时间
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json;charset=UTF-8'
|
'Content-Type': 'application/json;charset=UTF-8'
|
||||||
|
|||||||
@@ -52,6 +52,11 @@
|
|||||||
<div class="guidance-section">
|
<div class="guidance-section">
|
||||||
<div class="guidance-header" @click="toggleGuidanceCollapse">
|
<div class="guidance-header" @click="toggleGuidanceCollapse">
|
||||||
<h3>💡 指导建议</h3>
|
<h3>💡 指导建议</h3>
|
||||||
|
<div class="period-switcher">
|
||||||
|
<button @click="switchAnalysisPeriod('day')" :class="{ active: analysisPeriod === 'day' }">当日</button>
|
||||||
|
<button @click="switchAnalysisPeriod('camp')" :class="{ active: analysisPeriod === 'camp' }">当期</button>
|
||||||
|
<button @click="switchAnalysisPeriod('month')" :class="{ active: analysisPeriod === 'month' }">当月</button>
|
||||||
|
</div>
|
||||||
<div class="collapse-toggle" :class="{ 'collapsed': isGuidanceCollapsed }">
|
<div class="collapse-toggle" :class="{ 'collapsed': isGuidanceCollapsed }">
|
||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M8 4l4 4H4l4-4z"/>
|
<path d="M8 4l4 4H4l4-4z"/>
|
||||||
|
|||||||
@@ -111,20 +111,20 @@
|
|||||||
<div class="modal-container">
|
<div class="modal-container">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h3 class="modal-title">阶段分析报告</h3>
|
<h3 class="modal-title">阶段分析报告</h3>
|
||||||
|
<div class="period-switcher">
|
||||||
|
<button @click="switchAnalysisPeriod('day')" :class="{ active: analysisPeriod === 'day' }">当日</button>
|
||||||
|
<button @click="switchAnalysisPeriod('camp')" :class="{ active: analysisPeriod === 'camp' }">当期</button>
|
||||||
|
<button @click="switchAnalysisPeriod('month')" :class="{ active: analysisPeriod === 'month' }">当月</button>
|
||||||
|
</div>
|
||||||
<button class="modal-close-btn" @click="closeAnalysisModal">×</button>
|
<button class="modal-close-btn" @click="closeAnalysisModal">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="period-switcher">
|
|
||||||
<button @click="switchAnalysisPeriod('today')" :class="{ active: analysisPeriod === 'today' }">当日</button>
|
|
||||||
<button @click="switchAnalysisPeriod('current')" :class="{ active: analysisPeriod === 'current' }">当期</button>
|
|
||||||
<button @click="switchAnalysisPeriod('month')" :class="{ active: analysisPeriod === 'month' }">当月</button>
|
|
||||||
</div>
|
|
||||||
<div class="analysis-content">
|
<div class="analysis-content">
|
||||||
<div v-if="analysisPeriod === 'today'">
|
<div v-if="analysisPeriod === 'day'">
|
||||||
<h4>当日分析报告</h4>
|
<h4>当日分析报告</h4>
|
||||||
<p>这里是当日分析报告的占位文本。</p>
|
<p>这里是当日分析报告的占位文本。</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="analysisPeriod === 'current'">
|
<div v-if="analysisPeriod === 'camp'">
|
||||||
<h4>当期分析报告</h4>
|
<h4>当期分析报告</h4>
|
||||||
<p>这里是当期分析报告的占位文本。</p>
|
<p>这里是当期分析报告的占位文本。</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,11 +146,30 @@ import { ref, reactive, onMounted, onBeforeUnmount, computed, watch } from 'vue'
|
|||||||
import StatisticData from './StatisticData.vue';
|
import StatisticData from './StatisticData.vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
import {getTableFillingRate,getAverageResponseTime,getWeeklyActiveCommunicationRate,getTimeoutResponseRate} from "@/api/api.js"
|
import {getSecondOrderAnalysisReport} from "@/api/api.js"
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
// 用户store
|
// 用户store
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
// 路由实例
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 获取通用请求参数的函数
|
||||||
|
const getRequestParams = () => {
|
||||||
|
const params = {}
|
||||||
|
// 只从路由参数获取
|
||||||
|
const routeUserLevel = router.currentRoute.value.query.user_level || router.currentRoute.value.params.user_level
|
||||||
|
const routeUserName = router.currentRoute.value.query.user_name || router.currentRoute.value.params.user_name
|
||||||
|
// 如果路由有参数,使用路由参数
|
||||||
|
if (routeUserLevel) {
|
||||||
|
params.user_level = routeUserLevel.toString()
|
||||||
|
}
|
||||||
|
if (routeUserName) {
|
||||||
|
params.user_name = routeUserName
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
// 定义props
|
// 定义props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
kpiData: {
|
kpiData: {
|
||||||
@@ -191,112 +210,12 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 分析报告数据
|
async function CenterGetSecondOrderAnalysisReport(time) {
|
||||||
const analysisData = ref({
|
const params = getRequestParams()
|
||||||
today: {
|
const hasParams = {...params,time:time}
|
||||||
overallScore: 82,
|
const res = await getSecondOrderAnalysisReport(hasParams)
|
||||||
targetCompletion: 72,
|
console.log(res)
|
||||||
keyMetrics: [
|
|
||||||
{
|
|
||||||
name: '通话量',
|
|
||||||
current: 42,
|
|
||||||
target: 50,
|
|
||||||
trend: 'positive',
|
|
||||||
trendText: '↗ +5%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '接通率',
|
|
||||||
current: 75,
|
|
||||||
target: 80,
|
|
||||||
trend: 'neutral',
|
|
||||||
trendText: '→ 持平'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '转化率',
|
|
||||||
current: 15,
|
|
||||||
target: 15,
|
|
||||||
trend: 'positive',
|
|
||||||
trendText: '↗ +2%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '客户满意度',
|
|
||||||
current: 4.5,
|
|
||||||
target: 4.5,
|
|
||||||
trend: 'positive',
|
|
||||||
trendText: '↗ +0.3'
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
|
||||||
current: {
|
|
||||||
overallScore: 78,
|
|
||||||
targetCompletion: 65,
|
|
||||||
keyMetrics: [
|
|
||||||
{
|
|
||||||
name: '通话量',
|
|
||||||
current: 185,
|
|
||||||
target: 200,
|
|
||||||
trend: 'neutral',
|
|
||||||
trendText: '→ -2%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '接通率',
|
|
||||||
current: 68,
|
|
||||||
target: 80,
|
|
||||||
trend: 'negative',
|
|
||||||
trendText: '↘ -5%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '转化率',
|
|
||||||
current: 12,
|
|
||||||
target: 15,
|
|
||||||
trend: 'negative',
|
|
||||||
trendText: '↘ -3%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '客户满意度',
|
|
||||||
current: 4.2,
|
|
||||||
target: 4.5,
|
|
||||||
trend: 'neutral',
|
|
||||||
trendText: '→ -0.1'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
month: {
|
|
||||||
overallScore: 85,
|
|
||||||
targetCompletion: 78,
|
|
||||||
keyMetrics: [
|
|
||||||
{
|
|
||||||
name: '通话量',
|
|
||||||
current: 520,
|
|
||||||
target: 600,
|
|
||||||
trend: 'positive',
|
|
||||||
trendText: '↗ +8%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '接通率',
|
|
||||||
current: 72,
|
|
||||||
target: 80,
|
|
||||||
trend: 'neutral',
|
|
||||||
trendText: '→ -1%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '转化率',
|
|
||||||
current: 14,
|
|
||||||
target: 15,
|
|
||||||
trend: 'neutral',
|
|
||||||
trendText: '→ -0.5%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '客户满意度',
|
|
||||||
current: 4.3,
|
|
||||||
target: 4.5,
|
|
||||||
trend: 'positive',
|
|
||||||
trendText: '↗ +0.1'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Chart.js 实例
|
// Chart.js 实例
|
||||||
const chartInstances = {};
|
const chartInstances = {};
|
||||||
|
|
||||||
@@ -454,11 +373,12 @@ const hideTooltip = () => {
|
|||||||
|
|
||||||
// 阶段分析报告模态框状态
|
// 阶段分析报告模态框状态
|
||||||
const showAnalysisModal = ref(false);
|
const showAnalysisModal = ref(false);
|
||||||
const analysisPeriod = ref('today'); // 'today', 'current', 'month'
|
const analysisPeriod = ref('day'); // 'day', 'current', 'month'
|
||||||
|
|
||||||
// 显示阶段分析报告模态框
|
// 显示阶段分析报告模态框
|
||||||
const showSecondOrderAnalysisReport = () => {
|
const showSecondOrderAnalysisReport = () => {
|
||||||
showAnalysisModal.value = true;
|
showAnalysisModal.value = true;
|
||||||
|
CenterGetSecondOrderAnalysisReport(analysisPeriod.value)
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭阶段分析报告模态框
|
// 关闭阶段分析报告模态框
|
||||||
@@ -469,6 +389,7 @@ const closeAnalysisModal = () => {
|
|||||||
// 切换分析周期
|
// 切换分析周期
|
||||||
const switchAnalysisPeriod = (period) => {
|
const switchAnalysisPeriod = (period) => {
|
||||||
analysisPeriod.value = period;
|
analysisPeriod.value = period;
|
||||||
|
CenterGetSecondOrderAnalysisReport(period)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -870,7 +791,14 @@ $white: #ffffff;
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -929,10 +857,10 @@ $white: #ffffff;
|
|||||||
|
|
||||||
.modal-header {
|
.modal-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-title {
|
.modal-title {
|
||||||
@@ -940,6 +868,7 @@ $white: #ffffff;
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
|
margin-right: auto; // 将标题推到最左边
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close-btn {
|
.modal-close-btn {
|
||||||
@@ -954,6 +883,9 @@ $white: #ffffff;
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-left: 16px; // 与按钮组保持间距
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #303133;
|
color: #303133;
|
||||||
@@ -968,32 +900,45 @@ $white: #ffffff;
|
|||||||
|
|
||||||
.period-switcher {
|
.period-switcher {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
flex-shrink: 0; // 防止按钮组在空间不足时被压缩
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-switcher button {
|
.period-switcher button {
|
||||||
flex: 1;
|
padding: 6px 14px;
|
||||||
padding: 10px 15px;
|
|
||||||
border: 1px solid #dcdfe6;
|
border: 1px solid #dcdfe6;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
margin-left: -1px; // 让边框重叠,形成一体化效果
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #409eff;
|
border-color: #a0cfff;
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
|
z-index: 1;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: #409eff;
|
background: #409eff;
|
||||||
border-color: #409eff;
|
border-color: #409eff;
|
||||||
color: white;
|
color: white;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.analysis-content h4 {
|
.analysis-content h4 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
@@ -1005,4 +950,4 @@ $white: #ffffff;
|
|||||||
color: #606266;
|
color: #606266;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
</style>```
|
</style>
|
||||||
@@ -189,7 +189,7 @@ import FeedbackForm from "@/components/FeedbackForm.vue";
|
|||||||
import {getCustomerAttendance,getTodayCall,getProblemDistribution,getTableFillingRate,getAverageResponseTime,
|
import {getCustomerAttendance,getTodayCall,getProblemDistribution,getTableFillingRate,getAverageResponseTime,
|
||||||
getWeeklyActiveCommunicationRate,getTimeoutResponseRate,getCustomerCallInfo,getCustomerChatInfo,getCustomerFormInfo,
|
getWeeklyActiveCommunicationRate,getTimeoutResponseRate,getCustomerCallInfo,getCustomerChatInfo,getCustomerFormInfo,
|
||||||
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,
|
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,
|
||||||
getAvgCallTime,getCallSuccessRate} from "@/api/api.js"
|
getAvgCallTime,getCallSuccessRate,getSecondOrderAnalysisReport} from "@/api/api.js"
|
||||||
|
|
||||||
// 路由实例
|
// 路由实例
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
Reference in New Issue
Block a user