feat(销售时间轴): 添加子时间轴阶段选择功能
实现子时间轴各阶段的点击选择功能,将筛选后的客户数据转换为统一格式并传递给父组件
This commit is contained in:
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 课1-4子时间轴 -->
|
<!-- 课1-4子时间轴 -->
|
||||||
<div v-if="selectedStage === '课1-4'" class="course-sub-timeline">
|
<div v-if="selectedStage === '课1-4'" class="course-sub-timeline">
|
||||||
<div class="sub-timeline-container">
|
<div class="sub-timeline-container">
|
||||||
<!-- 课1子时间轴 -->
|
<!-- 课1子时间轴 -->
|
||||||
@@ -46,14 +46,14 @@
|
|||||||
<span class="course-conversion">转化率: {{ getCourseConversionRate(1) }}%</span>
|
<span class="course-conversion">转化率: {{ getCourseConversionRate(1) }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-timeline">
|
<div class="mini-timeline">
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(1, '课1') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(1, '课1') > 0 }" @click="selectCourseStage(1, '课1')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">课1</span>
|
<span class="mini-title">课1</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(1, '课1') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(1, '课1') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(1, '付定金') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(1, '付定金') > 0 }" @click="selectCourseStage(1, '付定金')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">付定金</span>
|
<span class="mini-title">付定金</span>
|
||||||
@@ -69,35 +69,35 @@
|
|||||||
<span class="course-title">课2</span>
|
<span class="course-title">课2</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-timeline">
|
<div class="mini-timeline">
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '课2') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '课2') > 0 }" @click="selectCourseStage(2, '课2')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">课2</span>
|
<span class="mini-title">课2</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(2, '课2') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(2, '课2') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '点击未支付') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '点击未支付') > 0 }" @click="selectCourseStage(2, '点击未支付')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">点击支付</span>
|
<span class="mini-title">点击支付</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(2, '点击未支付') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(2, '点击未支付') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '付定金') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '付定金') > 0 }" @click="selectCourseStage(2, '付定金')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">付定金</span>
|
<span class="mini-title">付定金</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(2, '付定金') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(2, '付定金') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '定金转化') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '定金转化') > 0 }" @click="selectCourseStage(2, '定金转化')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">定金转化</span>
|
<span class="mini-title">定金转化</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(2, '定金转化') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(2, '定金转化') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '成交') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(2, '成交') > 0 }" @click="selectCourseStage(2, '成交')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">成交</span>
|
<span class="mini-title">成交</span>
|
||||||
@@ -113,35 +113,35 @@
|
|||||||
<span class="course-title">课3</span>
|
<span class="course-title">课3</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-timeline">
|
<div class="mini-timeline">
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '课3') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '课3') > 0 }" @click="selectCourseStage(3, '课3')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">课3</span>
|
<span class="mini-title">课3</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(3, '课3') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(3, '课3') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '点击未支付') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '点击未支付') > 0 }" @click="selectCourseStage(3, '点击未支付')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">点击未支付</span>
|
<span class="mini-title">点击未支付</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(3, '点击未支付') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(3, '点击未支付') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '付定金') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '付定金') > 0 }" @click="selectCourseStage(3, '付定金')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">付定金</span>
|
<span class="mini-title">付定金</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(3, '付定金') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(3, '付定金') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '定金转化') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '定金转化') > 0 }" @click="selectCourseStage(3, '定金转化')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">定金转化</span>
|
<span class="mini-title">定金转化</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(3, '定金转化') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(3, '定金转化') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '成交') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(3, '成交') > 0 }" @click="selectCourseStage(3, '成交')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">成交</span>
|
<span class="mini-title">成交</span>
|
||||||
@@ -157,35 +157,35 @@
|
|||||||
<span class="course-title">课4</span>
|
<span class="course-title">课4</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-timeline">
|
<div class="mini-timeline">
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '课4') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '课4') > 0 }" @click="selectCourseStage(4, '课4')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">课4</span>
|
<span class="mini-title">课4</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(4, '课4') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(4, '课4') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '点击未支付') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '点击未支付') > 0 }" @click="selectCourseStage(4, '点击未支付')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">点击未付</span>
|
<span class="mini-title">点击未付</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(4, '点击未支付') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(4, '点击未支付') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '付定金') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '付定金') > 0 }" @click="selectCourseStage(4, '付定金')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">付定金</span>
|
<span class="mini-title">付定金</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(4, '付定金') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(4, '付定金') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '定金转化') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '定金转化') > 0 }" @click="selectCourseStage(4, '定金转化')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">定金转化</span>
|
<span class="mini-title">定金转化</span>
|
||||||
<span class="mini-count">{{ getCourseStageCount(4, '定金转化') }}</span>
|
<span class="mini-count">{{ getCourseStageCount(4, '定金转化') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '成交') > 0 }">
|
<div class="mini-stage" :class="{ active: getCourseStageCount(4, '成交') > 0 }" @click="selectCourseStage(4, '成交')">
|
||||||
<div class="mini-marker"></div>
|
<div class="mini-marker"></div>
|
||||||
<div class="mini-content">
|
<div class="mini-content">
|
||||||
<span class="mini-title">成交</span>
|
<span class="mini-title">成交</span>
|
||||||
@@ -768,6 +768,55 @@ const getHealthClass = (health) => {
|
|||||||
return 'health-danger';
|
return 'health-danger';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 选择课程阶段
|
||||||
|
const selectCourseStage = (courseNumber, stageType) => {
|
||||||
|
let filteredCustomers = [];
|
||||||
|
|
||||||
|
if (stageType === `课${courseNumber}`) {
|
||||||
|
// 课程阶段:从customersList中筛选
|
||||||
|
filteredCustomers = props.customersList.filter(customer => {
|
||||||
|
const classNum = customer.class_num;
|
||||||
|
const classSituation = customer.class_situation;
|
||||||
|
|
||||||
|
// 检查class_num字段
|
||||||
|
if (classNum && Array.isArray(classNum)) {
|
||||||
|
return classNum.includes(courseNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查class_situation字段
|
||||||
|
if (classSituation) {
|
||||||
|
if (Array.isArray(classSituation)) {
|
||||||
|
return classSituation.includes(courseNumber);
|
||||||
|
}
|
||||||
|
if (typeof classSituation === 'object') {
|
||||||
|
return classSituation.hasOwnProperty(courseNumber.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 其他阶段:从courseCustomers中筛选
|
||||||
|
if (props.courseCustomers?.['课1-4']) {
|
||||||
|
filteredCustomers = props.courseCustomers['课1-4'].filter(customer => {
|
||||||
|
// 检查客户是否参加了指定课程并且类型匹配
|
||||||
|
const hasAttendedCourse = customer.class_num && customer.class_num.includes(courseNumber);
|
||||||
|
return hasAttendedCourse && customer.type === stageType;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送子时间轴选择事件给父组件,使用不同的事件名称避免与主轴冲突
|
||||||
|
emit('sub-stage-select', {
|
||||||
|
filteredCustomers,
|
||||||
|
stageType: `课${courseNumber}-${stageType}`,
|
||||||
|
customerCount: filteredCustomers.length,
|
||||||
|
courseNumber,
|
||||||
|
originalStageType: stageType,
|
||||||
|
keepSubTimeline: true // 标识保持子时间轴显示
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
v-else
|
v-else
|
||||||
:data="timelineData"
|
:data="timelineData"
|
||||||
@stage-select="handleStageSelect"
|
@stage-select="handleStageSelect"
|
||||||
|
@sub-stage-select="handleSubStageSelect"
|
||||||
:selected-stage="selectedStage"
|
:selected-stage="selectedStage"
|
||||||
:contacts="filteredContacts"
|
:contacts="filteredContacts"
|
||||||
:selected-contact-id="selectedContactId"
|
:selected-contact-id="selectedContactId"
|
||||||
@@ -772,6 +773,44 @@ const handleStageSelect = (stage, extraData = null) => {
|
|||||||
currentFilteredCustomers.value = [];
|
currentFilteredCustomers.value = [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理子时间轴阶段选择
|
||||||
|
const handleSubStageSelect = (eventData) => {
|
||||||
|
console.log('子时间轴选择事件:', eventData);
|
||||||
|
|
||||||
|
// 将筛选后的客户数据转换为contacts格式
|
||||||
|
const filteredContacts = eventData.filteredCustomers.map(customer => ({
|
||||||
|
id: customer.customer_name || customer.id,
|
||||||
|
name: customer.customer_name || customer.name,
|
||||||
|
phone: customer.phone,
|
||||||
|
profession: customer.customer_occupation || customer.profession,
|
||||||
|
education: customer.customer_child_education || customer.education,
|
||||||
|
lastMessageTime: customer.latest_message_time || customer.time,
|
||||||
|
avatarUrl: customer.customer_avatar_url || customer.avatar,
|
||||||
|
avatar: customer.customer_avatar_url || customer.avatar || '/default-avatar.svg',
|
||||||
|
type: customer.type || eventData.originalStageType,
|
||||||
|
classNum: customer.class_num,
|
||||||
|
class_num: customer.class_num,
|
||||||
|
salesStage: eventData.stageType,
|
||||||
|
priority: customer.type === '待联系' ? 'high' : 'normal',
|
||||||
|
time: customer.latest_message_time || customer.time || '未知',
|
||||||
|
health: customer.health || 75,
|
||||||
|
// 保留原始数据
|
||||||
|
customer_name: customer.customer_name,
|
||||||
|
customer_occupation: customer.customer_occupation,
|
||||||
|
customer_child_education: customer.customer_child_education,
|
||||||
|
scrm_user_main_code: customer.scrm_user_main_code,
|
||||||
|
weChat_avatar: customer.weChat_avatar,
|
||||||
|
class_situation: customer.class_situation,
|
||||||
|
records: customer.records
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 更新当前筛选的客户数据,但保持selectedStage不变(保持子时间轴显示)
|
||||||
|
currentFilteredCustomers.value = filteredContacts;
|
||||||
|
|
||||||
|
console.log(`已筛选出${eventData.originalStageType}阶段的${filteredContacts.length}位客户`);
|
||||||
|
};
|
||||||
|
|
||||||
const handleViewFormData = async (contact) => {
|
const handleViewFormData = async (contact) => {
|
||||||
// 获取客户表单数据
|
// 获取客户表单数据
|
||||||
await getCustomerForm();
|
await getCustomerForm();
|
||||||
|
|||||||
Reference in New Issue
Block a user