Files
DJKB/my-vue-app/src/views/person/components/CustomerDetail.vue
lbw_9527443 a00a20c4ee fix: 移除录音文件数量显示并修复API调用参数传递
移除RawDataCards.vue中不再需要的录音文件数量显示
在CustomerDetail.vue中修复axios调用参数传递方式
2025-09-10 15:00:20 +08:00

1129 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
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>
<div class="customer-detail-container">
<div v-if="selectedContact" class="customer-detail-content">
<!-- 头部信息 -->
<div class="customer-header">
<h3>{{ selectedContact.name }}</h3>
<div class="action-buttons">
<button
@click="startBasicAnalysis"
class="analysis-button"
:disabled="isBasicAnalysisLoading"
>
{{ isBasicAnalysisLoading ? '基础分析中...' : '基础信息分析' }}
</button>
<button
@click="startSopAnalysis"
class="analysis-button sop-button"
:disabled="isSopAnalysisLoading || !hasCallData"
>
{{ isSopAnalysisLoading ? 'SOP分析中...' : (hasCallData ? 'SOP通话分析' : '暂无通话数据') }}
</button>
<!-- <button
@click="startDemandAnalysis"
class="analysis-button demand-button"
:disabled="isDemandAnalysisLoading"
>
{{ isDemandAnalysisLoading ? '诉求分析中...' : '客户诉求分析' }}
</button> -->
</div>
</div>
<!-- 分析区域 -->
<div class="analysis-areas">
<!-- 上方两个区域 -->
<div class="top-row">
<!-- 基础信息分析 -->
<div class="analysis-section basic-analysis">
<div class="section-header">
<h4>基础信息分析</h4>
</div>
<div class="section-content">
<div class="text-content" v-if="basicAnalysisResult">
<div class="analysis-text" v-html="formattedBasicAnalysis"></div>
</div>
<div class="placeholder-text" v-else>
<p>点击"基础信息分析"按钮开始分析客户基础信息</p>
</div>
</div>
</div>
<!-- SOP通话分析 -->
<div class="analysis-section sop-analysis">
<div class="section-header">
<h4>SOP通话分析</h4>
</div>
<div class="section-content">
<div class="text-content" v-if="sopAnalysisResult">
<div class="analysis-text" v-html="formattedSopAnalysis"></div>
</div>
<div class="placeholder-text" v-else>
<p>点击"SOP通话分析"按钮开始分析通话记录</p>
</div>
</div>
</div>
</div>
<!-- 下方整行区域 -->
<!-- <div class="bottom-row">
<div class="analysis-section demand-analysis">
<div class="section-header">
<h4>客户诉求分析</h4>
</div>
<div class="section-content">
<div class="text-content" v-if="demandAnalysisResult">
<div class="analysis-text" v-html="formattedDemandAnalysis"></div>
</div>
<div class="placeholder-text" v-else>
<p>点击"客户诉求分析"按钮开始深度分析客户需求和诉求</p>
</div>
</div>
</div>
</div> -->
</div>
</div>
<!-- 未选择客户时的提示 -->
<div v-else class="no-selection">
<p>请选择一个客户查看详情</p>
</div>
</div>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { SimpleChatService } from '@/utils/ChatService.js';
import MarkdownIt from 'markdown-it';
import https from '@/utils/https'
import axios from 'axios'
// 定义props
const props = defineProps({
selectedContact: {
type: Object,
default: null
},
formInfo: {
type: Object,
default: () => ({})
},
chatRecords: {
type: Array,
default: () => []
},
callRecords: {
type: Array,
default: () => []
}
});
console.log(999999999,props.selectedContact);
// 分析结果状态
const basicAnalysisResult = ref(''); // 基础信息分析结果
const sopAnalysisResult = ref(''); // SOP通话分析结果
const demandAnalysisResult = ref(''); // 客户诉求分析结果
// 加载状态
const isBasicAnalysisLoading = ref(false); // 基础分析加载状态
const isSopAnalysisLoading = ref(false); // SOP分析加载状态
const isDemandAnalysisLoading = ref(false); // 诉求分析加载状态
// Dify API配置
const DIFY_API_KEY_01 = 'app-h4uBo5kOGoiYhjuBF1AHZi8b'; //基础信息分析
const DIFY_API_KEY = 'app-ZIJSFWbcdZLufkwCp9RrvpUR';
// 初始化ChatService
const chatService_01 = new SimpleChatService(DIFY_API_KEY_01);
const chatService = new SimpleChatService(DIFY_API_KEY);
// 初始化markdown-it
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true
});
// 计算属性:格式化基础分析结果
const formattedBasicAnalysis = computed(() => {
if (!basicAnalysisResult.value) return '';
return md.render(basicAnalysisResult.value);
});
// 计算属性格式化SOP分析结果
const formattedSopAnalysis = computed(() => {
if (!sopAnalysisResult.value) return '';
return md.render(sopAnalysisResult.value);
});
// 计算属性:格式化诉求分析结果
const formattedDemandAnalysis = computed(() => {
if (!demandAnalysisResult.value) return '';
return md.render(demandAnalysisResult.value);
});
// 计算属性:检查是否有通话数据
const hasCallData = computed(() => {
return props.callRecords && props.callRecords.length > 0;
});
// 监听selectedContact变化重置所有分析结果
watch(() => props.selectedContact, (newContact) => {
if (newContact) {
// 重置所有分析状态
basicAnalysisResult.value = '';
sopAnalysisResult.value = '';
demandAnalysisResult.value = '';
isBasicAnalysisLoading.value = false;
isSopAnalysisLoading.value = false;
isDemandAnalysisLoading.value = false;
} else {
// 清空所有结果
basicAnalysisResult.value = '';
sopAnalysisResult.value = '';
demandAnalysisResult.value = '';
isBasicAnalysisLoading.value = false;
isSopAnalysisLoading.value = false;
isDemandAnalysisLoading.value = false;
}
}, { immediate: true });
// 基础信息分析
const startBasicAnalysis = async () => {
if (!props.selectedContact) return;
isBasicAnalysisLoading.value = true;
basicAnalysisResult.value = '';
// 构建表单信息
const formData = props.formInfo || {};
let formInfoText = '暂无表单信息';
if (Object.keys(formData).length > 0) {
console.log(888888,formData);
const allInfo = [];
// 处理第一种格式基础信息和additional_info
if (formData.name || formData.mobile || formData.additional_info) {
const basicInfo = [];
const additionalInfo = [];
// 处理基础信息字段
const basicFields = {
name: '姓名',
mobile: '手机号',
occupation: '职业',
territory: '地区',
child_name: '孩子姓名',
child_gender: '孩子性别',
child_education: '孩子教育阶段',
child_relation: '与孩子关系'
};
Object.entries(basicFields).forEach(([key, label]) => {
if (formData[key] && formData[key] !== '暂无' && formData[key] !== '') {
basicInfo.push(`${label}: ${formData[key]}`);
}
});
// 处理 additional_info 数组
if (formData.additional_info && Array.isArray(formData.additional_info)) {
formData.additional_info.forEach(item => {
if (item.topic && item.answer) {
additionalInfo.push(`${item.topic}\n答案: ${item.answer}`);
}
});
}
// 添加基础信息
if (basicInfo.length > 0) {
allInfo.push('=== 基础信息 ===');
allInfo.push(...basicInfo);
}
// 添加问卷信息
if (additionalInfo.length > 0) {
allInfo.push('\n=== 问卷信息 ===');
allInfo.push(...additionalInfo);
}
}
// 处理第二种格式customerExpandFieldMap
if (formData.customerExpandFieldMap) {
const expandInfo = [];
const map = formData.customerExpandFieldMap;
// 处理所有expand字段
Object.entries(map).forEach(([key, value]) => {
// 跳过原型链上的属性
if (!map.hasOwnProperty(key)) return;
// 如果是对象类型包含key和typeCode的字段
if (value && typeof value === 'object' && value.key) {
const question = value.key;
let answer = '';
// 根据不同的类型处理答案
if (value.typeCode === 'SINGLE_SELECT' || value.typeCode === 'MULTIPLE_SELECT') {
if (value.expandValueList && value.expandValueList.length > 0) {
answer = value.expandValueList.map(item => item.itemName).join('、');
}
} else if (value.typeCode === 'TEXT' || value.typeCode === 'TEXTAREA' || value.typeCode === 'NUMBER') {
// 直接从formData中获取对应的expand值
answer = formData[key] || '';
}
// 只添加有答案的问题
if (answer && answer !== '暂无' && answer !== '') {
expandInfo.push(`${question}\n答案: ${answer}`);
}
}
});
// 添加扩展信息
if (expandInfo.length > 0) {
if (allInfo.length > 0) allInfo.push('\n'); // 如果已有其他信息,添加分隔行
allInfo.push('=== 问卷详细信息 ===');
allInfo.push(...expandInfo);
}
}
formInfoText = allInfo.length > 0 ? allInfo.join('\n') : '暂无表单信息';
}
// 构建聊天记录信息
const chatData = props.chatRecords || [];
const chatInfoText = chatData.messages.length > 0 ?
`聊天记录数量: ${chatData.messages.length}\n最近聊天内容: ${JSON.stringify(chatData.messages.slice(-3), null, 2)}` :
'暂无聊天记录';
// 构建通话记录信息
const callData = props.callRecords || [];
const callInfoText = callData.length > 0 ?
`通话记录数量: ${callData.length}\n通话记录详情: ${JSON.stringify(callData, null, 2)}` :
'暂无通话记录';
const query = `请对客户进行基础信息分析:
客户姓名:${props.selectedContact.name}
联系电话:${props.selectedContact.phone || '未提供'}
销售阶段:${props.selectedContact.salesStage || '未知'}
=== 表单信息 ===
${formInfoText}
=== 聊天记录 ===
${chatInfoText}
=== 通话记录 ===
${callData.length > 0 && callData[0].record_context ? callData[0].record_context : callInfoText}
请基于以上客户的表单信息、聊天记录和通话记录,分析客户的基本情况、背景信息和初步画像。`;
console.log(888888,formInfoText);
try {
await chatService_01.sendMessage(
query,
(update) => {
basicAnalysisResult.value = update.content;
},
() => {
isBasicAnalysisLoading.value = false;
console.log('基础信息分析完成');
}
);
} catch (error) {
console.error('基础信息分析失败:', error);
basicAnalysisResult.value = `分析失败: ${error.message}`;
isBasicAnalysisLoading.value = false;
}
};
// SOP通话分析
const startSopAnalysis = async () => {
console.log(888888888777777,props.selectedContact.wechat_id)
if (!props.selectedContact) return;
isSopAnalysisLoading.value = true;
sopAnalysisResult.value = '';
// 构建通话记录信息
const callData = props.callRecords || [];
const callInfoText = callData.length > 0 ?
`通话记录数量: ${callData.length}\n通话记录详情: ${JSON.stringify(callData, null, 2)}` :
'暂无通话记录';
const query = `=== 通话记录 ===
${callData.length > 0 && callData[0].record_context ? callData[0].record_context : callInfoText}`;
try {
// await chatService.sendMessage(
// query,
// (update) => {
// sopAnalysisResult.value = update.content;
// },
// () => {
// isSopAnalysisLoading.value = false;
// console.log('SOP通话分析完成');
// }
// );
const res= await axios.get('http://192.168.3.112:6002/api/v1/call',
{
params:{
wechat_id:props.selectedContact.wechat_id
}
})
sopAnalysisResult.value = res.data.report_content;
} catch (error) {
console.error('SOP通话分析失败:', error);
sopAnalysisResult.value = `分析失败: ${error.message}`;
isSopAnalysisLoading.value = false;
}
};
// 客户诉求分析
const startDemandAnalysis = async () => {
if (!props.selectedContact) return;
isDemandAnalysisLoading.value = true;
demandAnalysisResult.value = '';
const query = `请对客户 ${props.selectedContact.name} 进行深度诉求分析:
请从以下维度分析客户的真实需求和诉求:
1. 显性需求分析(客户明确表达的需求)
2. 隐性需求挖掘(潜在的、未明确表达的需求)
3. 痛点识别(客户面临的主要问题和挑战)
4. 决策因素分析(影响客户决策的关键因素)
5. 价值期望(客户期望获得的价值和收益)
6. 风险顾虑(客户可能的担忧和顾虑)
7. 个性化建议(针对性的解决方案建议)
客户信息:
姓名:${props.selectedContact.name}
公司:${props.selectedContact.company || '未提供'}
职位:${props.selectedContact.position || '未提供'}
销售阶段:${props.selectedContact.salesStage || '未知'}
健康度:${props.selectedContact.health || '未知'}%`;
try {
await chatService.sendMessage(
query,
(update) => {
demandAnalysisResult.value = update.content;
},
() => {
isDemandAnalysisLoading.value = false;
console.log('客户诉求分析完成');
}
);
} catch (error) {
console.error('客户诉求分析失败:', error);
demandAnalysisResult.value = `分析失败: ${error.message}`;
isDemandAnalysisLoading.value = false;
}
};
</script>
<style lang="scss" scoped>
// Color Palette
$slate-50: #f8fafc;
$slate-100: #f1f5f9;
$slate-200: #e2e8f0;
$slate-300: #cbd5e1;
$slate-400: #94a3b8;
$slate-500: #64748b;
$slate-600: #475569;
$slate-700: #334155;
$slate-800: #1e293b;
$white: #ffffff;
$blue: #3b82f6;
$green: #22c55e;
$amber: #f59e0b;
$red: #ef4444;
$indigo: #4f46e5;
$purple: #a855f7;
// 容器样式
.customer-detail-container {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 16px;
// PC端保持一致布局
@media (min-width: 1024px) {
// padding: 24px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
padding: 20px;
}
// 移动端适配
@media (max-width: 768px) {
padding: 12px;
}
// 小屏移动端适配
@media (max-width: 480px) {
padding: 8px;
}
}
// 客户详情内容
.customer-detail-content {
height: 100%;
display: flex;
flex-direction: column;
gap: 16px;
}
// 客户头部信息
.customer-header {
background: $white;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: 1px solid $slate-200;
display: flex;
justify-content: space-between;
align-items: center;
// PC端保持一致布局
@media (min-width: 1024px) {
padding: 20px;
border-radius: 12px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
padding: 18px;
border-radius: 10px;
}
// 移动端适配
@media (max-width: 768px) {
flex-direction: column;
align-items: flex-start;
gap: 16px;
padding: 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
padding: 12px;
gap: 12px;
}
h3 {
margin: 0;
color: $slate-800;
font-size: 20px;
font-weight: 600;
// PC端保持一致布局
@media (min-width: 1024px) {
font-size: 24px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
font-size: 22px;
}
// 移动端适配
@media (max-width: 768px) {
font-size: 18px;
}
// 小屏移动端适配
@media (max-width: 480px) {
font-size: 16px;
}
}
.action-buttons {
display: flex;
gap: 12px;
// 移动端适配
@media (max-width: 768px) {
width: 100%;
flex-direction: column;
gap: 8px;
}
// 小屏移动端适配
@media (max-width: 480px) {
gap: 6px;
}
.analysis-button {
padding: 10px 16px;
background: $blue;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
white-space: nowrap;
// PC端保持一致布局
@media (min-width: 1024px) {
padding: 12px 20px;
font-size: 15px;
border-radius: 8px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
padding: 11px 18px;
font-size: 14px;
border-radius: 7px;
}
// 移动端适配
@media (max-width: 768px) {
width: 100%;
padding: 12px 16px;
font-size: 14px;
text-align: center;
}
// 小屏移动端适配
@media (max-width: 480px) {
padding: 10px 12px;
font-size: 13px;
}
&:hover:not(:disabled) {
background: #2563eb;
transform: translateY(-1px);
}
&:disabled {
background: $slate-400;
cursor: not-allowed;
transform: none;
}
&.sop-button {
background: $green;
&:hover:not(:disabled) {
background: #16a34a;
}
}
&.demand-button {
background: $purple;
&:hover:not(:disabled) {
background: #9333ea;
}
}
}
}
}
// 分析区域
.analysis-areas {
flex: 1;
display: flex;
flex-direction: column;
gap: 16px;
min-height: 0;
}
// 上方行
.top-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
height: 45%;
// PC端保持一致布局
@media (min-width: 1024px) {
gap: 20px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
gap: 18px;
}
// 移动端适配
@media (max-width: 768px) {
grid-template-columns: 1fr;
height: auto;
gap: 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
gap: 12px;
}
}
// 下方行
.bottom-row {
height: 55%;
}
// 分析区域样式
.analysis-section {
background: $white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: 1px solid $slate-200;
display: flex;
flex-direction: column;
overflow: hidden;
// PC端保持一致布局
@media (min-width: 1024px) {
border-radius: 12px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
border-radius: 10px;
}
// 移动端适配
@media (max-width: 768px) {
min-height: 300px;
}
// 小屏移动端适配
@media (max-width: 480px) {
min-height: 250px;
}
.section-header {
padding: 12px 16px;
background: $slate-50;
border-bottom: 1px solid $slate-200;
// PC端保持一致布局
@media (min-width: 1024px) {
padding: 16px 20px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
padding: 14px 18px;
}
// 移动端适配
@media (max-width: 768px) {
padding: 12px 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
padding: 10px 12px;
}
h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: $slate-700;
// PC端保持一致布局
@media (min-width: 1024px) {
font-size: 18px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
font-size: 17px;
}
// 移动端适配
@media (max-width: 768px) {
font-size: 15px;
}
// 小屏移动端适配
@media (max-width: 480px) {
font-size: 14px;
}
}
}
.section-content {
flex: 1;
padding: 16px;
overflow-y: auto;
// PC端保持一致布局
@media (min-width: 1024px) {
padding: 20px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
padding: 18px;
}
// 移动端适配
@media (max-width: 768px) {
padding: 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
padding: 12px;
}
.text-content {
height: 100%;
.analysis-text {
color: $slate-700;
font-size: 14px;
line-height: 1.6;
word-wrap: break-word;
// PC端保持一致布局
@media (min-width: 1024px) {
font-size: 15px;
line-height: 1.7;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
font-size: 14px;
line-height: 1.65;
}
// 移动端适配
@media (max-width: 768px) {
font-size: 13px;
line-height: 1.6;
}
// 小屏移动端适配
@media (max-width: 480px) {
font-size: 12px;
line-height: 1.5;
}
}
}
.placeholder-text {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background: $slate-50;
border-radius: 6px;
border: 2px dashed $slate-200;
p {
margin: 0;
color: $slate-500;
font-size: 14px;
text-align: center;
padding: 16px;
// PC端保持一致布局
@media (min-width: 1024px) {
font-size: 15px;
padding: 20px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
font-size: 14px;
padding: 18px;
}
// 移动端适配
@media (max-width: 768px) {
font-size: 13px;
padding: 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
font-size: 12px;
padding: 12px;
}
}
}
}
// 不同分析区域的主题色
&.basic-analysis {
.section-header {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
h4 {
color: $blue;
}
}
}
&.sop-analysis {
.section-header {
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
h4 {
color: $green;
}
}
}
&.demand-analysis {
.section-header {
background: linear-gradient(135deg, #faf5ff 0%, #f3e8ff 100%);
h4 {
color: $purple;
}
}
}
}
// Markdown样式
.analysis-text {
// Markdown样式
h1, h2, h3, h4, h5, h6 {
margin: 1rem 0 0.5rem 0;
font-weight: 600;
color: $slate-800;
&:first-child {
margin-top: 0;
}
}
h1 { font-size: 1.25rem; }
h2 { font-size: 1.125rem; }
h3 { font-size: 1rem; }
h4 { font-size: 0.875rem; }
h5 { font-size: 0.75rem; }
h6 { font-size: 0.75rem; }
p {
margin: 0.5rem 0;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
ul, ol {
margin: 0.5rem 0;
padding-left: 1.5rem;
li {
margin: 0.25rem 0;
}
}
blockquote {
margin: 1rem 0;
padding: 0.5rem 1rem;
border-left: 4px solid $blue;
background: rgba(59, 130, 246, 0.05);
font-style: italic;
}
code {
background: $slate-100;
padding: 0.125rem 0.25rem;
border-radius: 0.25rem;
font-family: 'Courier New', monospace;
font-size: 0.8rem;
}
pre {
background: $slate-100;
padding: 1rem;
border-radius: 0.5rem;
overflow-x: auto;
margin: 1rem 0;
code {
background: none;
padding: 0;
}
}
strong {
font-weight: 600;
color: $slate-800;
}
em {
font-style: italic;
}
a {
color: $blue;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
hr {
margin: 1.5rem 0;
border: none;
border-top: 1px solid $slate-200;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
th, td {
padding: 0.5rem;
border: 1px solid $slate-200;
text-align: left;
}
th {
background: $slate-50;
font-weight: 600;
}
}
}
// 未选择状态
.no-selection {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background: $slate-50;
border-radius: 8px;
border: 2px dashed $slate-200;
color: $slate-500;
// PC端保持一致布局
@media (min-width: 1024px) {
border-radius: 12px;
min-height: 500px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
border-radius: 10px;
min-height: 450px;
}
// 移动端适配
@media (max-width: 768px) {
height: 400px;
border-radius: 8px;
}
// 小屏移动端适配
@media (max-width: 480px) {
height: 300px;
border-radius: 6px;
}
p {
margin: 0;
font-size: 1rem;
text-align: center;
padding: 1rem;
// PC端保持一致布局
@media (min-width: 1024px) {
font-size: 1.125rem;
padding: 1.5rem;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
font-size: 1.0625rem;
padding: 1.25rem;
}
// 移动端适配
@media (max-width: 768px) {
font-size: 0.875rem;
padding: 1rem;
}
// 小屏移动端适配
@media (max-width: 480px) {
font-size: 0.75rem;
padding: 0.75rem;
}
}
}
h2.section-title {
font-size: 1.25rem;
font-weight: bold;
color: $slate-700;
}
h4 {
font-weight: 600;
color: $slate-700;
margin-bottom: 0.5rem;
}
// Context Panel
.section-card {
background-color: $white;
border-radius: 0.5rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
// padding: 1rem;
// margin-top: 12px;
}
// 分析区域布局优化
.analysis-areas {
// PC端保持一致布局
@media (min-width: 1024px) {
gap: 20px;
}
// 平板端适配
@media (max-width: 1023px) and (min-width: 769px) {
gap: 18px;
}
// 移动端适配
@media (max-width: 768px) {
gap: 16px;
}
// 小屏移动端适配
@media (max-width: 480px) {
gap: 12px;
}
}
// 下方行适配
.bottom-row {
// 移动端适配
@media (max-width: 768px) {
height: auto;
min-height: 300px;
}
// 小屏移动端适配
@media (max-width: 480px) {
min-height: 250px;
}
}
</style>