Files
smartDriveEEUniApp/components/ai-analysis-dashboard-body.vue
2026-04-18 14:33:16 +08:00

407 lines
12 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="ai-dashboard-body">
<view class="content">
<scroll-view
class="content-scroll"
scroll-y="true"
:style="{ top: scrollTop, bottom: scrollBottom }"
>
<view class="category-section quick-links-section">
<view class="category-header">
<text class="category-icon">🚀</text>
<text class="category-title">接待</text>
</view>
<view class="function-grid">
<view class="function-item" @click="quickJumpReceptionTab('reception')">
<view class="function-icon">🤝</view>
<text class="function-name">开始接待</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="quickJumpReceptionTab('status')">
<view class="function-icon">📋</view>
<text class="function-name">服务中</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="quickJumpReceptionInProgress">
<view class="function-icon"></view>
<text class="function-name">接待中</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="quickJumpReceptionTab('tag')">
<view class="function-icon">🏷</view>
<text class="function-name">标签管理</text>
<text class="function-desc"></text>
</view>
</view>
</view>
<view class="category-section two-column">
<view class="category-header">
<text class="category-icon">👤</text>
<text class="category-title">AI分析</text>
</view>
<view class="function-grid">
<view class="function-item" @click="quickJumpCustomerTab('customer')">
<view class="function-icon">👥</view>
<text class="function-name">客户列表</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="quickJumpCustomerTab('service')">
<view class="function-icon">📝</view>
<text class="function-name">服务记录</text>
<text class="function-desc"></text>
</view>
</view>
</view>
<view class="category-section two-column">
<view class="category-header">
<text class="category-icon">📊</text>
<text class="category-title">录音和接待统计</text>
</view>
<view class="function-grid">
<view class="function-item" @click="navigateToPage('recording_duration')">
<view class="function-icon"></view>
<text class="function-name">录音时长</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="navigateToPage('customer_count')">
<view class="function-icon">👥</view>
<text class="function-name">接待客户数</text>
<text class="function-desc"></text>
</view>
</view>
</view>
<view class="category-section two-column">
<view class="category-header">
<text class="category-icon"></text>
<text class="category-title">质量管控</text>
</view>
<view class="function-grid">
<view class="function-item" @click="showQualityCoveragePopup">
<view class="function-icon">📊</view>
<text class="function-name">质检覆盖率</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="navigateToPage('speech_rating')">
<view class="function-icon">🗣</view>
<text class="function-name">员工话术评分</text>
<text class="function-desc"></text>
</view>
</view>
</view>
<view class="category-section sales-analysis">
<view class="category-header">
<text class="category-icon">📈</text>
<text class="category-title">销售分析</text>
</view>
<view class="function-grid">
<view class="function-item full-row-item" @click="navigateToPage('intent_level')">
<view class="function-icon">🎯</view>
<text class="function-name">客户意向分级</text>
<text class="function-desc"></text>
</view>
<view class="function-item full-row-item" @click="navigateToPage('deal_attribution')">
<view class="function-icon">💰</view>
<text class="function-name">成交归因</text>
<text class="function-desc"></text>
</view>
<view class="function-item full-row-item new-line-item" @click="navigateToPage('opening_rate')">
<view class="function-icon">🚪</view>
<text class="function-name">开口率</text>
<text class="function-desc"></text>
</view>
</view>
</view>
<view class="category-section two-column">
<view class="category-header">
<text class="category-icon"></text>
<text class="category-title">风险监控</text>
</view>
<view class="function-grid">
<view class="function-item" @click="navigateToPage('over_commitment')">
<view class="function-icon">🚨</view>
<text class="function-name">过度承诺统计</text>
<text class="function-desc"></text>
</view>
<view class="function-item" @click="navigateToPage('red_line_touch')">
<view class="function-icon">🔴</view>
<text class="function-name">触及红线统计</text>
<text class="function-desc"></text>
</view>
</view>
</view>
</scroll-view>
</view>
<QualityCoveragePopup
v-if="showQualityCoverage"
:open-trigger="openQualityCoverageTrigger"
@close="onQualityCoveragePopupClose"
/>
</view>
</template>
<script>
export default {
name: 'AiAnalysisDashboardBody',
props: {
contentTop: {
type: String,
default: '',
},
contentBottom: {
type: String,
default: '96rpx',
},
},
data() {
return {
showQualityCoverage: false,
openQualityCoverageTrigger: 0,
};
},
computed: {
scrollTop() {
return this.contentTop || '88rpx';
},
scrollBottom() {
return this.contentBottom || '96rpx';
},
},
methods: {
showQualityCoveragePopup() {
this.showQualityCoverage = true;
this.$nextTick(() => {
this.openQualityCoverageTrigger++;
});
},
onQualityCoveragePopupClose() {
this.showQualityCoverage = false;
},
navigateToPage(pageName) {
const pagePath = `pages-subpackage/ai_features/${pageName}/${pageName}`;
uni.navigateTo({
url: `/${pagePath}`,
fail: (err) => {
console.error('导航失败:', err);
uni.showToast({
title: '页面跳转失败',
icon: 'none',
});
},
});
},
quickJumpReceptionTab(tabKey) {
const allowedTabs = ['status', 'reception', 'tag'];
if (!allowedTabs.includes(tabKey)) {
return;
}
try {
uni.setStorageSync('workbench-reception-tab', tabKey);
} catch (e) {
console.warn('[AiAnalysisDashboardBody] 写入接待tab快捷跳转参数失败:', e);
}
uni.navigateTo({
url: `/pages-subpackage/furniture_reception/furniture_reception_entry?tab=${encodeURIComponent(tabKey)}`,
fail: (err) => {
console.error('[AiAnalysisDashboardBody] 快捷跳转接待页失败:', err);
uni.showToast({
title: '跳转失败,请稍后重试',
icon: 'none',
});
},
});
},
quickJumpReceptionInProgress() {
uni.navigateTo({
url: '/pages-subpackage/furniture_reception/reception_in_progress',
fail: (err) => {
console.error('[AiAnalysisDashboardBody] 快捷跳转接待中页失败:', err);
uni.showToast({
title: '跳转失败,请稍后重试',
icon: 'none',
});
},
});
},
quickJumpCustomerTab(tabKey) {
const allowedTabs = ['service', 'customer'];
if (!allowedTabs.includes(tabKey)) {
return;
}
uni.navigateTo({
url: `/pages-subpackage/furniture_customer/furniture_customer?tab=${tabKey}`,
fail: (err) => {
console.error('[AiAnalysisDashboardBody] 快捷跳转客户页失败:', err);
uni.showToast({
title: '跳转失败,请稍后重试',
icon: 'none',
});
},
});
},
},
};
</script>
<style scoped>
.ai-dashboard-body {
position: relative;
width: 100%;
}
/* 内层 scroll 为 absolute此处必须给出可计算高度否则整块高度为 0嵌入工作台时尤其明显 */
.content {
padding-top: 0 !important;
margin-top: 0 !important;
position: relative;
top: 0;
min-height: calc(100vh - 200rpx);
}
.content-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 0 !important;
padding-bottom: 0 !important;
margin: 0 !important;
box-sizing: border-box;
}
.content-scroll > view {
margin-top: 0;
padding-top: 0;
margin-bottom: 0;
padding-bottom: 0;
}
.category-section {
margin: 20rpx 30rpx;
background: #ffffff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.category-section:first-child {
margin-top: 0;
}
.category-section:last-child {
margin-bottom: 0;
}
.category-header {
display: flex;
align-items: center;
padding: 30rpx;
background: #ffffff;
border-bottom: 1rpx solid #f0f0f0;
}
.category-icon {
font-size: 32rpx;
margin-right: 20rpx;
}
.category-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
.function-grid {
display: flex;
flex-wrap: wrap;
padding: 10rpx;
}
.quick-links-section .function-item {
width: calc(33.333% - 10rpx);
background: #ffffff;
border-radius: 12rpx;
padding: 24rpx 12rpx;
margin: 5rpx;
text-align: center;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
border: 1rpx solid #f0f0f0;
box-sizing: border-box;
}
.two-column .function-item {
flex: 1;
background: #ffffff;
border-radius: 12rpx;
padding: 24rpx 16rpx;
margin: 0 5rpx;
text-align: center;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
border: 1rpx solid #f0f0f0;
}
.three-column .function-item {
width: 31%;
background: #ffffff;
border-radius: 12rpx;
padding: 24rpx 12rpx;
margin: 1%;
text-align: center;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
border: 1rpx solid #f0f0f0;
}
.sales-analysis .function-item.full-row-item {
flex: 1;
width: calc(50% - 10rpx);
background: #ffffff;
border-radius: 12rpx;
padding: 24rpx 16rpx;
margin: 0 5rpx;
text-align: center;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
border: 1rpx solid #f0f0f0;
}
.sales-analysis .function-item.new-line-item {
flex-basis: 100%;
width: calc(50% - 10rpx);
margin-top: 10rpx;
}
.function-item:active {
transform: scale(0.95);
box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.1);
}
.function-icon {
font-size: 48rpx;
margin-bottom: 12rpx;
}
.function-name {
display: block;
font-size: 28rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.function-desc {
display: block;
font-size: 24rpx;
color: #666;
line-height: 1.4;
}
</style>