feat(会员详情): 添加二阶分析报告功能并优化指导建议布局
重构会员详情组件,添加二阶分析报告功能,包括周期切换和报告加载状态显示。优化指导建议部分的布局结构,将分析报告与原有指导建议分开显示。调整样式以提升用户体验,并修复部分代码格式问题。
This commit is contained in:
@@ -45,7 +45,7 @@ export const getGroupCallDuration = (params) => {
|
||||
return https.post('/api/v1/manager/group_call_duration', params)
|
||||
}
|
||||
// 二二阶分析报告 /api/v1/sales/get_call_text
|
||||
export const getSecondOrderAnalysisReport = (params) => {
|
||||
export const GetSecondOrderAnalysisReport = (params) => {
|
||||
return https.post('/api/v1/manager/group_call_text', params)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +63,17 @@
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="guidance-cards" v-show="!isGuidanceCollapsed" :class="{ 'collapsing': isGuidanceCollapsed }">
|
||||
<div class="guidance-card" v-if="getGuidanceForMember(memberDetails).length > 0">
|
||||
<div class="guidance-item" v-for="(guidance, index) in getGuidanceForMember(memberDetails)" :key="index">
|
||||
<div class="guidance-content" v-show="!isGuidanceCollapsed" :class="{ 'collapsing': isGuidanceCollapsed }">
|
||||
<!-- 分析报告内容 -->
|
||||
<div class="analysis-report">
|
||||
<div v-if="isReportLoading" class="loading">正在生成分析报告...</div>
|
||||
<div v-else class="report-content">{{ analysisReport }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 原有指导建议内容 -->
|
||||
<div class="guidance-cards">
|
||||
<div class="guidance-card" v-if="getGuidanceForMember(selectedMember).length > 0">
|
||||
<div class="guidance-item" v-for="(guidance, index) in getGuidanceForMember(selectedMember)" :key="index">
|
||||
<div class="guidance-icon" :class="guidance.type">
|
||||
{{ guidance.icon }}
|
||||
</div>
|
||||
@@ -79,10 +87,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-guidance" v-else>
|
||||
<div class="celebration-icon">🎉</div>
|
||||
<h4>表现优秀!</h4>
|
||||
<p>{{ memberDetails?.user_name || selectedMember?.user_name || selectedMember?.name }} 的各项指标都很不错,继续保持这种状态!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -137,8 +141,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineProps, watch, nextTick, reactive } from 'vue'
|
||||
import { ref, defineProps, watch, nextTick, reactive, onMounted } from 'vue'
|
||||
import Tooltip from '@/components/Tooltip.vue'
|
||||
import { GetSecondOrderAnalysisReport } from '@/api/manager.js'
|
||||
import { SimpleChatService } from '@/utils/ChatService.js'
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
@@ -159,7 +165,13 @@ const isDetailsCollapsed = ref(false)
|
||||
const isGuidanceCollapsed = ref(false)
|
||||
|
||||
// 录音列表折叠状态(默认展开)
|
||||
const isRecordingsCollapsed = ref(false)
|
||||
const isRecordingsCollapsed = ref(true)
|
||||
|
||||
// 分析周期
|
||||
const analysisPeriod = ref('day') // 默认周期为当日
|
||||
const analysisReport = ref('') // 分析报告内容
|
||||
const isReportLoading = ref(false) // 报告加载状态
|
||||
const chatService_02 = ref(null) // 用于生成分析报告的聊天服务实例
|
||||
|
||||
// 工具提示状态
|
||||
const tooltip = reactive({
|
||||
@@ -199,6 +211,64 @@ const toggleDetailsCollapse = () => {
|
||||
isDetailsCollapsed.value = !isDetailsCollapsed.value
|
||||
}
|
||||
|
||||
// 切换分析周期
|
||||
const switchAnalysisPeriod = (period) => {
|
||||
analysisPeriod.value = period
|
||||
// 切换周期后重新获取分析报告
|
||||
CenterGetSecondOrderAnalysisReport(analysisPeriod.value )
|
||||
}
|
||||
|
||||
// 获取二阶分析报告
|
||||
async function CenterGetSecondOrderAnalysisReport(time) {
|
||||
// 如果聊天服务实例不存在,则创建一个新的实例
|
||||
if (!chatService_02.value) {
|
||||
// 注意:这里使用与PersonalDashboard.vue相同的API密钥
|
||||
chatService_02.value = new SimpleChatService('app-MGaBOx5QFblsMZ7dSkxKJDKm')
|
||||
}
|
||||
|
||||
// 设置加载状态
|
||||
isReportLoading.value = true
|
||||
analysisReport.value = ''
|
||||
|
||||
try {
|
||||
// 准备请求参数
|
||||
const params = {
|
||||
user_name:props.memberDetails?.user_name,
|
||||
time: time // 使用当前选择的周期
|
||||
}
|
||||
// 调用API获取分析报告数据
|
||||
const response = await GetSecondOrderAnalysisReport(params)
|
||||
|
||||
// 检查数据是否为空
|
||||
if (!response.data.records || response.data.records.length === 0) {
|
||||
console.error('数据为空')
|
||||
analysisReport.value = '数据为空'
|
||||
isReportLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
// 将记录数组转换为字符串
|
||||
const records = response.data.records.join('\n')
|
||||
|
||||
// 使用聊天服务发送消息并处理流式响应
|
||||
chatService_02.value.sendMessage(
|
||||
records, // 使用API返回的文本数据
|
||||
(update) => {
|
||||
// 实时更新报告内容
|
||||
analysisReport.value = update.content
|
||||
},
|
||||
() => {
|
||||
// 流结束时的操作
|
||||
isReportLoading.value = false
|
||||
}
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('获取二阶分析报告失败:', error)
|
||||
analysisReport.value = '获取分析报告失败,请稍后重试。'
|
||||
isReportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 切换指导建议折叠状态
|
||||
const toggleGuidanceCollapse = () => {
|
||||
isGuidanceCollapsed.value = !isGuidanceCollapsed.value
|
||||
@@ -339,20 +409,24 @@ const getGuidanceForMember = (member) => {
|
||||
return guidance.slice(0, 3) // 最多显示3个建议
|
||||
}
|
||||
|
||||
// 监听selectedMember变化,重置滚动条位置
|
||||
watch(() => props.selectedMember, () => {
|
||||
// 监听selectedMember变化
|
||||
watch(() => props.selectedMember, (newMember) => {
|
||||
if (newMember) {
|
||||
// 重置滚动位置
|
||||
nextTick(() => {
|
||||
// 获取member-details容器元素并重置滚动位置
|
||||
const memberDetailsEl = document.querySelector('.member-details')
|
||||
if (memberDetailsEl) {
|
||||
// 使用平滑滚动动画
|
||||
memberDetailsEl.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
const container = document.querySelector('.member-details')
|
||||
if (container) {
|
||||
container.scrollTop = 0
|
||||
}
|
||||
})
|
||||
}, { immediate: false })
|
||||
}
|
||||
})
|
||||
|
||||
// 组件挂载时初始化分析报告
|
||||
onMounted(() => {
|
||||
// 初始化时获取当日的分析报告
|
||||
CenterGetSecondOrderAnalysisReport()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -698,12 +772,69 @@ watch(() => props.selectedMember, () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 分析报告样式
|
||||
.analysis-report {
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1.25rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
min-height: 100px;
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
font-style: italic;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.report-content {
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.5;
|
||||
color: #1e293b;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.guidance-cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
// 周期切换按钮样式
|
||||
.period-switcher {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-left: auto;
|
||||
|
||||
button {
|
||||
padding: 0.25rem 0.75rem;
|
||||
border: 1px solid #cbd5e1;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: #f1f5f9;
|
||||
border-color: #94a3b8;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
border-color: #3b82f6;
|
||||
|
||||
&:hover {
|
||||
background: #2563eb;
|
||||
border-color: #2563eb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.guidance-card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
@@ -911,7 +1042,7 @@ watch(() => props.selectedMember, () => {
|
||||
}
|
||||
|
||||
// 指导建议适配
|
||||
.guidance-section {
|
||||
.guidance-section {
|
||||
margin-top: 1rem;
|
||||
|
||||
.guidance-header {
|
||||
@@ -920,6 +1051,14 @@ watch(() => props.selectedMember, () => {
|
||||
}
|
||||
}
|
||||
|
||||
.analysis-report {
|
||||
padding: 0.75rem;
|
||||
|
||||
.report-content {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.guidance-item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
@@ -951,7 +1090,7 @@ watch(() => props.selectedMember, () => {
|
||||
padding: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
|
||||
Reference in New Issue
Block a user