feat: 完善专家支持中心和项目库单元导航功能
- 添加真实的文旅产业Q&A数据到专家支持中心 - 实现项目库到课程直播间的单元导航 - 新增CourseList组件的expandUnitByName方法 - 优化项目详情模态框的单元显示和交互 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,60 @@ const CourseList = forwardRef(({ className = "", onCourseClick }, ref) => {
|
||||
|
||||
// 暴露方法给父组件调用
|
||||
useImperativeHandle(ref, () => ({
|
||||
// 新增:通过单元名称展开对应的折叠面板
|
||||
expandUnitByName: (unitName) => {
|
||||
console.log('CourseList - expandUnitByName called:', unitName);
|
||||
|
||||
// 在两个列表中查找单元
|
||||
const allLists = [
|
||||
{ list: compoundCourseList, type: 'compound' },
|
||||
{ list: verticalCourseList, type: 'vertical' }
|
||||
];
|
||||
|
||||
for (const { list, type } of allLists) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const unit = list[i];
|
||||
console.log(`Checking ${type} unit:`, unit.unitName);
|
||||
|
||||
if (unit.unitName === unitName) {
|
||||
console.log('Found matching unit:', unit.unitName);
|
||||
|
||||
// 计算正确的 activeKey
|
||||
let activeKey;
|
||||
if (type === 'compound') {
|
||||
activeKey = String(i + 1);
|
||||
} else {
|
||||
// 垂直课程使用特定的前缀
|
||||
activeKey = `vertical-${i + 1}`;
|
||||
}
|
||||
|
||||
// 展开对应的单元
|
||||
setActiveKeys(prevKeys => {
|
||||
if (!prevKeys.includes(activeKey)) {
|
||||
console.log('Adding activeKey:', activeKey, 'to existing keys:', prevKeys);
|
||||
return [...prevKeys, activeKey];
|
||||
}
|
||||
return prevKeys;
|
||||
});
|
||||
|
||||
// 滚动到对应的单元位置
|
||||
setTimeout(() => {
|
||||
const collapseItems = document.querySelectorAll('.course-list-item');
|
||||
if (collapseItems[type === 'compound' ? i : i + compoundCourseList.length]) {
|
||||
collapseItems[type === 'compound' ? i : i + compoundCourseList.length].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
}
|
||||
}, 300);
|
||||
|
||||
return; // 找到后退出
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Unit not found:', unitName);
|
||||
},
|
||||
selectCourse: (courseId, courseName) => {
|
||||
console.log('CourseList - selectCourse called:', courseId, courseName);
|
||||
console.log('CourseList - compoundCourseList:', compoundCourseList);
|
||||
|
||||
517
src/data/expertSupportData.js
Normal file
517
src/data/expertSupportData.js
Normal file
@@ -0,0 +1,517 @@
|
||||
// 专家支持中心问答数据
|
||||
const expertSupportData = {
|
||||
conversations: [
|
||||
{
|
||||
id: 1,
|
||||
title: "文旅产业的就业前景如何?",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "你好,我是一名大学生,对文旅产业很感兴趣。请问文旅产业的就业前景如何?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "你好!文旅产业的就业前景非常广阔。根据最新数据,中国文旅产业规模已超过5万亿元,预计到2025年将达到10万亿元。这个行业涵盖了旅游、文化、娱乐、餐饮、住宿等多个领域,提供了大量的就业机会。特别是在数字化转型的背景下,文旅产业需要大量懂技术、懂运营、懂文化的复合型人才。",
|
||||
mentor: "李老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "文旅产业有哪些主要的就业方向?",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "请问文旅产业有哪些主要的就业方向?我应该如何选择?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅产业的就业方向非常多样化:\n1. 旅游规划与开发:景区规划师、旅游产品设计师\n2. 运营管理:景区运营、酒店管理、民宿运营\n3. 市场营销:文旅营销策划、新媒体运营、品牌推广\n4. 文化创意:文创产品设计、IP开发、展览策划\n5. 数字文旅:智慧旅游平台运营、VR/AR体验设计\n6. 活动策展:会展策划、节庆活动组织、演艺制作\n\n选择时建议结合自己的兴趣特长和市场需求。",
|
||||
mentor: "张老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "想进入文旅行业需要具备哪些技能?",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "我想进入文旅行业,需要具备哪些技能?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "进入文旅行业需要的核心技能包括:\n\n基础技能:\n- 良好的沟通表达能力\n- 团队协作能力\n- 服务意识和客户思维\n- 基本的英语交流能力\n\n专业技能:\n- 旅游规划与线路设计\n- 市场营销与品牌推广\n- 新媒体运营(抖音、小红书等)\n- 数据分析能力\n- 项目管理能力\n\n加分技能:\n- 摄影摄像技术\n- 文案写作能力\n- 第二外语\n- 数字化工具使用",
|
||||
mentor: "王老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "文旅行业的薪资待遇怎么样?",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "请问文旅行业的薪资待遇怎么样?不同岗位差别大吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅行业的薪资待遇因岗位和地区而异:\n\n初级岗位(1-3年):\n- 旅游顾问:4-6K/月\n- 活动执行:5-8K/月\n- 新媒体运营:5-8K/月\n\n中级岗位(3-5年):\n- 产品经理:8-15K/月\n- 营销主管:10-15K/月\n- 景区运营经理:8-12K/月\n\n高级岗位(5年以上):\n- 运营总监:15-30K/月\n- 项目总监:20-40K/月\n- 区域负责人:25-50K/月\n\n一线城市薪资普遍高30-50%,创新型岗位和数字化岗位薪资更高。",
|
||||
mentor: "朱老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "如何准备文旅企业的面试?",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "我马上要参加一家文旅企业的面试,应该如何准备?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅企业面试准备建议:\n\n1. 了解企业背景\n- 研究公司的主营业务、发展历程、企业文化\n- 了解公司的代表性项目或产品\n- 关注公司最新动态和行业地位\n\n2. 准备常见问题\n- 为什么选择文旅行业?\n- 对文旅行业的理解和看法\n- 个人优势和相关经历\n- 职业规划\n\n3. 展示专业能力\n- 准备相关作品集或案例\n- 了解行业趋势和热点\n- 准备一个创新的文旅项目想法\n\n4. 注意形象礼仪\n- 着装得体,展现亲和力\n- 保持微笑,体现服务意识",
|
||||
mentor: "陈老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "文旅产业的数字化转型趋势",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "听说文旅产业正在进行数字化转型,具体是什么情况?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅产业的数字化转型是当前最重要的趋势之一:\n\n1. 智慧旅游平台\n- 一站式旅游服务APP\n- 智能行程规划系统\n- 在线预订和支付系统\n\n2. 沉浸式体验\n- VR/AR景区导览\n- 数字博物馆和云展览\n- 元宇宙文旅项目\n\n3. 大数据应用\n- 游客行为分析\n- 精准营销推送\n- 景区流量预测和管理\n\n4. 内容营销创新\n- 短视频营销(抖音、小红书)\n- 直播带货和云旅游\n- KOL/KOC合作推广\n\n这些变化创造了大量新的就业机会,特别需要既懂文旅又懂技术的人才。",
|
||||
mentor: "赵老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: "文旅行业的创业机会",
|
||||
status: "finish",
|
||||
date: "7天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "我想在文旅行业创业,有什么好的方向吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅行业的创业机会很多,以下是一些有潜力的方向:\n\n低成本创业:\n- 旅游自媒体和内容创作\n- 定制旅游服务(小众线路设计)\n- 民宿运营和管理\n- 文创产品设计和销售\n\n中等投入:\n- 研学旅行组织\n- 露营地运营\n- 特色餐饮+文旅融合\n- 本地生活体验项目\n\n创新方向:\n- 文旅科技产品开发\n- IP授权和运营\n- 沉浸式演艺项目\n- 康养旅游服务\n\n建议从自己熟悉的领域入手,先做小而美的项目,积累经验后再扩大规模。",
|
||||
mentor: "刘老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: "非旅游专业如何转行文旅?",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "我是学计算机的,但对文旅行业很感兴趣,可以转行吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "计算机专业转行文旅其实很有优势!\n\n你的技术背景在文旅行业非常受欢迎:\n1. 智慧旅游系统开发\n2. 旅游大数据分析\n3. 文旅APP和小程序开发\n4. VR/AR旅游体验设计\n5. 旅游电商平台运营\n\n转行建议:\n- 先从文旅科技公司入手\n- 参与文旅相关的技术项目\n- 学习文旅行业知识和运营思维\n- 可以考虑OTA平台的技术岗位\n\n很多成功的文旅创业者都是跨界背景,你的技术能力反而是差异化优势。",
|
||||
mentor: "周老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
title: "文旅行业的职业发展路径",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "在文旅行业工作,职业发展路径是怎样的?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅行业的职业发展路径比较多元化:\n\n传统晋升路径:\n基层员工 → 主管 → 经理 → 总监 → VP/合伙人\n\n专业发展路径:\n1. 运营线:运营专员 → 运营主管 → 运营经理 → 运营总监\n2. 产品线:产品助理 → 产品经理 → 高级产品经理 → 产品总监\n3. 营销线:营销专员 → 营销主管 → 营销经理 → CMO\n\n横向发展机会:\n- 从执行岗转向策划岗\n- 从单一业务转向综合管理\n- 从传统文旅转向数字文旅\n- 从企业转向自主创业\n\n建议在职业早期多尝试不同岗位,找到最适合自己的发展方向。",
|
||||
mentor: "吴老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
title: "文旅实习经历的重要性",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "大学期间的文旅实习经历重要吗?应该如何选择实习?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅实习经历非常重要,是进入行业的敲门砖!\n\n实习的价值:\n- 了解行业实际运作\n- 积累实战经验\n- 建立行业人脉\n- 明确职业方向\n- 增加就业竞争力\n\n选择实习的建议:\n1. 大型企业:学习规范流程和管理体系\n2. 创业公司:接触更多业务,成长更快\n3. 知名景区:了解一线运营\n4. OTA平台:学习互联网思维\n5. 文旅局:了解政策和规划\n\n时间安排:\n- 大二:基础认知实习(1-2个月)\n- 大三:专业深度实习(3-6个月)\n- 大四:就业导向实习(可转正)",
|
||||
mentor: "郑老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
title: "乡村振兴中的文旅机遇",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "听说乡村振兴有很多文旅项目,有什么机会吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "乡村振兴确实为文旅行业带来了巨大机遇!\n\n政策支持:\n- 国家大力支持乡村旅游发展\n- 各地都有补贴和扶持政策\n- 用地、税收等优惠措施\n\n发展机会:\n1. 乡村民宿开发运营\n2. 农文旅融合项目\n3. 田园综合体规划\n4. 乡村文创产品开发\n5. 研学基地建设\n6. 康养度假村\n\n就业岗位:\n- 乡村运营官\n- 民宿管家\n- 农旅策划师\n- 乡创导师\n\n这是一个充满机遇的蓝海市场,特别适合有情怀、懂运营的年轻人。",
|
||||
mentor: "孙老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
title: "文旅行业需要考哪些证书?",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "进入文旅行业需要考哪些证书吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅行业的证书分为必需和加分两类:\n\n基础证书:\n- 导游资格证(从事导游工作必需)\n- 普通话等级证书(二级乙等以上)\n- 英语四六级证书\n\n专业证书:\n- 旅游规划师\n- 研学旅行指导师\n- 酒店管理师\n- 会展策划师\n- 茶艺师/咖啡师(特色项目)\n\n加分证书:\n- 项目管理PMP\n- 市场营销类证书\n- 新媒体运营证书\n- 急救证书\n- 其他语言证书\n\n建议:证书不是越多越好,要结合自己的职业规划有针对性地考取。实践经验往往比证书更重要。",
|
||||
mentor: "钱老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
title: "如何打造个人文旅IP?",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "看到很多旅游博主很成功,如何打造个人文旅IP?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "打造个人文旅IP是很好的发展方向:\n\n第一步:找准定位\n- 确定内容方向(美食、民宿、小众景点等)\n- 明确目标受众\n- 打造个人特色和记忆点\n\n第二步:内容创作\n- 保持更新频率\n- 注重内容质量\n- 真实、有用、有趣\n- 视频+图文结合\n\n第三步:平台运营\n- 多平台分发(抖音、小红书、B站)\n- 了解平台规则和算法\n- 积极互动,建立粉丝群\n\n第四步:商业变现\n- 广告合作\n- 定制旅游服务\n- 知识付费\n- 电商带货\n\n成功案例:房琪kiki、@幻想家japaul等都是很好的学习对象。",
|
||||
mentor: "马老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
title: "文旅企业最看重什么能力?",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "文旅企业招聘时最看重应聘者的什么能力?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "根据我们对多家文旅企业的调研,最看重以下能力:\n\n核心能力TOP5:\n1. 沟通表达能力(90%企业提及)\n2. 学习能力和适应性(85%)\n3. 团队协作精神(80%)\n4. 创新思维(75%)\n5. 抗压能力(70%)\n\n专业能力要求:\n- 市场敏感度\n- 数据分析能力\n- 内容创作能力\n- 项目管理能力\n- 客户服务意识\n\n加分项:\n- 有相关实习经验\n- 会新媒体运营\n- 有成功案例或作品\n- 多语言能力\n- 有资源或人脉\n\n建议在校期间多参与实践,培养综合能力。",
|
||||
mentor: "冯老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
title: "文旅行业的工作生活平衡",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "听说文旅行业经常要加班,工作生活平衡怎么样?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅行业的工作节奏确实有其特点:\n\n行业特性:\n- 旺季(节假日)工作强度大\n- 淡季相对轻松\n- 周末和节假日是工作高峰\n- 可能需要出差或驻场\n\n不同岗位差异:\n- 一线服务:班制,相对规律\n- 活动策划:项目制,忙闲不均\n- 后台运营:相对稳定\n- 新媒体:需要追热点,时间灵活\n\n平衡建议:\n- 选择适合自己节奏的岗位\n- 学会时间管理\n- 淡季好好休息充电\n- 把工作当成生活的一部分\n\n其实热爱这个行业的人,工作本身就是一种生活方式。",
|
||||
mentor: "杨老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
title: "海外文旅市场的机会",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "有机会去海外从事文旅工作吗?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "海外文旅市场机会很多,特别是:\n\n主要方向:\n1. 出境游地接社\n2. 国际酒店集团\n3. 邮轮公司\n4. 国际会展公司\n5. 海外中文导游\n\n热门目的地:\n- 东南亚(泰国、新加坡、马来西亚)\n- 日韩\n- 欧洲(法国、意大利、瑞士)\n- 澳新\n- 迪拜\n\n准备要求:\n- 良好的外语能力\n- 了解目的地文化\n- 有国内工作经验\n- 适应能力强\n- 办理工作签证\n\n发展优势:\n- 薪资待遇好\n- 开阔国际视野\n- 积累独特经验\n- 有助于回国发展",
|
||||
mentor: "何老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
title: "文旅+教育的发展前景",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "研学旅行现在很火,文旅+教育有什么发展前景?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅+教育是非常有前景的细分赛道!\n\n市场规模:\n- 研学旅行市场规模超千亿\n- 政策大力支持\n- 家长教育投入意愿强\n\n主要业态:\n1. 研学旅行\n2. 营地教育\n3. 自然教育\n4. 博物馆教育\n5. 非遗传承体验\n6. 劳动教育基地\n\n就业岗位:\n- 研学课程设计师\n- 研学导师\n- 营地运营管理\n- 教育产品经理\n- 亲子活动策划\n\n发展建议:\n- 需要教育学背景或教师资格证\n- 了解不同年龄段孩子特点\n- 掌握课程设计能力\n- 注重安全管理\n\n这个领域既有社会价值又有商业前景。",
|
||||
mentor: "徐老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
title: "文旅行业的新技术应用",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "AI、元宇宙这些新技术在文旅行业有什么应用?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "新技术在文旅行业的应用越来越广泛:\n\nAI应用:\n- 智能客服和问答系统\n- 个性化推荐算法\n- 动态定价系统\n- 图像识别导览\n- 多语言实时翻译\n\n元宇宙应用:\n- 虚拟景区游览\n- 数字藏品和NFT\n- 虚拟演唱会和展览\n- 沉浸式历史体验\n- 云旅游直播\n\n其他技术:\n- 区块链票务系统\n- IoT智慧景区管理\n- 5G+8K直播\n- 无人机航拍服务\n\n就业机会:\n- 数字文旅产品经理\n- XR内容创作者\n- 智慧旅游工程师\n- 数据分析师\n\n掌握这些技术的文旅人才非常抢手!",
|
||||
mentor: "唐老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
title: "如何提升文旅项目策划能力?",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "想做文旅项目策划,如何提升策划能力?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "提升文旅项目策划能力的方法:\n\n基础积累:\n1. 多看案例\n- 研究成功项目\n- 分析失败案例\n- 关注行业报告\n\n2. 理论学习\n- 项目管理知识\n- 市场营销理论\n- 消费者心理学\n- 文化创意理论\n\n3. 实践训练\n- 参与学校项目\n- 实习项目策划\n- 参加策划比赛\n- 自己做小项目\n\n4. 能力培养\n- 逻辑思维能力\n- 创意思维训练\n- 文案写作能力\n- PPT制作技巧\n\n5. 资源积累\n- 建立供应商库\n- 积累人脉资源\n- 收集素材库\n\n推荐书籍:《文旅项目策划实战》《体验经济》等。",
|
||||
mentor: "韩老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
title: "文旅行业的区域发展差异",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "不同地区的文旅发展有什么差异?去哪里发展比较好?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "中国文旅发展确实存在区域差异:\n\n一线城市(北上广深):\n- 国际化程度高\n- 薪资待遇好\n- 竞争激烈\n- 主要是企业总部\n\n新一线城市(成都、杭州、西安等):\n- 文旅资源丰富\n- 发展潜力大\n- 生活成本适中\n- 创新氛围好\n\n旅游城市(三亚、丽江、桂林等):\n- 一线实践机会多\n- 季节性明显\n- 发展空间有限\n\n特色地区:\n- 长三角:主题乐园、水乡古镇\n- 珠三角:主题公园、商务旅游\n- 西部:自然景观、民族文化\n- 东北:冰雪旅游、森林康养\n\n建议:刚毕业去大城市学习,积累经验后可以去二三线城市发展机会更多。",
|
||||
mentor: "蔡老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
title: "文创产品开发的要点",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "想做文创产品开发,有什么要注意的?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文创产品开发的成功要素:\n\n产品定位:\n- 明确目标客群\n- 确定价格区间\n- 突出文化内涵\n- 强调实用性\n\n设计原则:\n1. 文化性:深挖文化内涵\n2. 创意性:新颖独特\n3. 实用性:不只是摆设\n4. 系列化:形成产品体系\n5. 故事性:有故事可讲\n\n开发流程:\n- 市场调研\n- 创意设计\n- 打样测试\n- 批量生产\n- 营销推广\n\n常见误区:\n- 过度追求低价\n- 忽视版权保护\n- 同质化严重\n- 缺乏文化内涵\n\n成功案例:故宫文创、敦煌文创、三星堆盲盒等都值得学习。",
|
||||
mentor: "魏老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
title: "民宿运营的核心要素",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "想开一家民宿,运营的核心要素是什么?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "民宿运营的核心要素:\n\n选址定位:\n- 风景优美或交通便利\n- 周边配套完善\n- 目标客群明确\n- 差异化定位\n\n设计装修:\n- 风格独特统一\n- 注重体验设计\n- 功能布局合理\n- 成本控制\n\n运营管理:\n1. 服务标准化\n2. 卫生管理严格\n3. 安全保障到位\n4. 管家服务专业\n5. 维护保养及时\n\n营销推广:\n- OTA平台运营\n- 社交媒体营销\n- 口碑营销\n- 会员体系建设\n\n盈利模式:\n- 住宿收入\n- 餐饮收入\n- 体验活动\n- 产品销售\n\n建议先从小规模开始,积累经验后再扩大。",
|
||||
mentor: "潘老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
title: "新媒体营销在文旅中的应用",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "新媒体营销对文旅行业有多重要?怎么做?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "新媒体营销已成为文旅营销的主战场:\n\n重要性:\n- 获客成本低\n- 传播速度快\n- 互动性强\n- 可精准定位\n- 数据可追踪\n\n主要平台策略:\n1. 抖音:短视频种草\n2. 小红书:图文攻略\n3. 微信:私域运营\n4. B站:深度内容\n5. 微博:热点营销\n\n内容策略:\n- 美景展示\n- 美食诱惑\n- 文化故事\n- 达人体验\n- 用户UGC\n\n运营技巧:\n- 保持更新频率\n- 蹭热点话题\n- 互动回复及时\n- 数据分析优化\n- KOL合作\n\n成功案例:重庆、西安等网红城市都是新媒体营销的受益者。",
|
||||
mentor: "邓老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
title: "文旅项目的融资渠道",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "文旅项目一般通过什么渠道融资?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅项目的融资渠道比较多样:\n\n传统融资:\n1. 银行贷款\n2. 政府补贴\n3. 产业基金\n4. 企业自筹\n\n股权融资:\n- 天使投资\n- VC/PE投资\n- 产业资本\n- 上市融资\n\n创新模式:\n- 众筹平台\n- REITs(房地产信托)\n- PPP模式\n- 资产证券化\n\n政策支持:\n- 文旅专项资金\n- 税收优惠\n- 土地政策\n- 贴息贷款\n\n注意事项:\n- 项目策划要专业\n- 财务模型要清晰\n- 回报周期要合理\n- 风险控制要到位\n\n建议找专业的融资顾问协助。",
|
||||
mentor: "石老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
title: "景区运营管理的要点",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "景区运营管理主要做什么?有哪些要点?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "景区运营管理是个系统工程:\n\n日常运营:\n1. 游客服务管理\n2. 安全保障\n3. 设施维护\n4. 环境卫生\n5. 秩序维护\n\n营销管理:\n- 市场推广\n- 渠道管理\n- 活动策划\n- 品牌建设\n\n收益管理:\n- 门票定价\n- 二次消费\n- 商业租赁\n- 成本控制\n\n服务提升:\n- 智慧化建设\n- 服务标准化\n- 投诉处理\n- 员工培训\n\n创新发展:\n- 产品更新\n- 业态创新\n- 科技应用\n- 文化挖掘\n\n关键指标:游客满意度、安全零事故、收入增长率、口碑传播度。",
|
||||
mentor: "谭老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 26,
|
||||
title: "会展活动策划的流程",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "想做会展活动策划,具体流程是怎样的?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "会展活动策划的标准流程:\n\n前期准备(3-6个月前):\n1. 需求分析\n2. 方案策划\n3. 预算制定\n4. 场地选择\n5. 团队组建\n\n中期筹备(1-3个月):\n- 供应商对接\n- 嘉宾邀请\n- 宣传推广\n- 物料制作\n- 流程细化\n\n执行阶段(活动当天):\n- 现场搭建\n- 签到接待\n- 流程把控\n- 应急处理\n- 现场协调\n\n后期总结:\n- 撤展清场\n- 费用结算\n- 效果评估\n- 资料归档\n- 经验总结\n\n核心能力:\n- 统筹协调\n- 创意设计\n- 成本控制\n- 危机处理\n\n这个领域需要很强的执行力和抗压能力。",
|
||||
mentor: "程老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 27,
|
||||
title: "康养旅游的发展趋势",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "听说康养旅游很有前景,具体是什么情况?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "康养旅游确实是未来的重要方向:\n\n市场驱动:\n- 老龄化社会到来\n- 健康意识提升\n- 消费升级\n- 疫后健康需求\n\n主要类型:\n1. 温泉康养\n2. 森林康养\n3. 中医康养\n4. 运动康养\n5. 禅修康养\n6. 候鸟式康养\n\n产品形态:\n- 康养度假村\n- 康养小镇\n- 康养民宿\n- 康养基地\n\n就业机会:\n- 康养产品设计\n- 健康管理师\n- 康养活动策划\n- 养生指导师\n\n发展建议:\n- 学习健康管理知识\n- 了解中医养生文化\n- 掌握康养项目运营\n\n预计未来5年,康养旅游市场规模将超过2万亿。",
|
||||
mentor: "宋老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
title: "文旅IP打造与运营",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "什么是文旅IP?如何打造和运营?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "文旅IP是文旅产业的核心竞争力:\n\n什么是文旅IP:\n- 独特的文化符号\n- 可识别的形象\n- 持续的影响力\n- 商业价值\n\nIP打造步骤:\n1. 挖掘文化内核\n2. 设计视觉形象\n3. 构建故事体系\n4. 创造体验场景\n5. 持续内容输出\n\n运营策略:\n- 多渠道传播\n- 衍生品开发\n- 跨界合作\n- 粉丝运营\n- 版权保护\n\n变现方式:\n- 门票收入\n- 授权费用\n- 衍生品销售\n- 品牌合作\n\n成功案例:\n- 迪士尼米老鼠\n- 故宫文创\n- 熊本熊\n- 不倒翁小姐姐\n\n一个成功的IP可以带动整个目的地发展。",
|
||||
mentor: "许老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 29,
|
||||
title: "露营经济的商业模式",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "露营现在很火,想了解露营地的商业模式。"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "露营经济正处于快速发展期:\n\n市场现状:\n- 市场规模超300亿\n- 用户超1亿\n- 年增长率超30%\n\n商业模式:\n1. 基础模式\n- 场地租赁\n- 装备租赁\n- 餐饮服务\n\n2. 增值服务\n- 主题活动\n- 亲子教育\n- 团建拓展\n- 户外课程\n\n3. 产品销售\n- 露营装备\n- 户外用品\n- 文创产品\n- 本地特产\n\n投资要点:\n- 选址(近郊1-2小时车程)\n- 基础设施(水电、卫生间)\n- 安全管理\n- 特色打造\n\n发展趋势:\n- 精致露营\n- 主题露营\n- 露营+X模式\n\n初期投资20-50万即可起步,回本周期1-2年。",
|
||||
mentor: "罗老师"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
title: "文旅行业的可持续发展",
|
||||
status: "finish",
|
||||
date: "30天内",
|
||||
messages: [
|
||||
{
|
||||
type: "user",
|
||||
content: "文旅行业如何实现可持续发展?"
|
||||
},
|
||||
{
|
||||
type: "assistant",
|
||||
content: "可持续发展是文旅行业的必然趋势:\n\n环境保护:\n- 生态旅游开发\n- 碳中和实践\n- 垃圾分类管理\n- 资源循环利用\n- 野生动植物保护\n\n文化传承:\n- 非遗保护传承\n- 传统技艺活化\n- 民俗文化展示\n- 历史建筑修复\n\n社区共享:\n- 当地就业优先\n- 利益共享机制\n- 社区参与决策\n- 扶贫带动发展\n\n经济效益:\n- 产业链延伸\n- 四季运营\n- 多元化收入\n- 品牌价值提升\n\n实践案例:\n- 莫干山民宿集群\n- 袁家村乡村旅游\n- 乌镇模式\n\n未来趋势:ESG理念将成为文旅企业的核心竞争力。",
|
||||
mentor: "曹老师"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default expertSupportData;
|
||||
129
src/data/projectUnitsMapping.js
Normal file
129
src/data/projectUnitsMapping.js
Normal file
@@ -0,0 +1,129 @@
|
||||
// 项目案例对应单元映射数据
|
||||
// 基于 网页未导入数据/文旅产业/项目案例对应单元.json
|
||||
|
||||
export const projectUnitsMapping = {
|
||||
"舟山某民宿180天提升入住率项目": {
|
||||
compoundUnits: ["全栈新媒体运营赋能文旅营销"],
|
||||
verticalUnits: ["营销传播与品牌推广", "民宿运营策划与个性化体验"]
|
||||
},
|
||||
"希尔顿欢朋酒店经营管理与服务一体化优化项目": {
|
||||
compoundUnits: ["文旅服务:形象、沟通与体验的融合艺术"],
|
||||
verticalUnits: ["酒店项目经营与品牌塑造", "财务控制与风险防范", "营销传播与品牌推广", "项目全周期运营管理"]
|
||||
},
|
||||
"长安汽车新款车型线下推广活动": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["品牌招商展全案策划与招商运营", "商业活动全程策划执行与运营优化"]
|
||||
},
|
||||
"春风 450MT新品上市营销活动策划项目": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["品牌招商展全案策划与招商运营", "商业活动全程策划执行与运营优化"]
|
||||
},
|
||||
"敦煌文创品牌策划与IP运营": {
|
||||
compoundUnits: ["商业设计基础"],
|
||||
verticalUnits: ["商业空间与文创产品设计", "文旅衍生文创产品设计"]
|
||||
},
|
||||
"'长安幻夜'文创IP运营与品牌建设项目": {
|
||||
compoundUnits: ["商业设计基础"],
|
||||
verticalUnits: ["品牌招商展全案策划与招商运营", "商业空间与文创产品设计", "文旅衍生文创产品设计"]
|
||||
},
|
||||
"2024年深圳国际家具展策划项目": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["商业活动策略设计与创意策划", "商业活动全程策划执行与运营优化", "商业空间与文创产品设计"]
|
||||
},
|
||||
"2024 合肥国际 3C 电子产业博览会策划项目": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["消费电子展品牌策划与执行", "商业活动策略设计与创意策划", "商业活动全程策划执行与运营优化"]
|
||||
},
|
||||
"盐城第九届 ICGC 动漫嘉年华漫展策划项目": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["商业活动策略设计与创意策划", "商业活动全程策划执行与运营优化", "漫展与二次元活动策划与执行"]
|
||||
},
|
||||
"某地森林湿地自然景区多平台新媒体运营方案": {
|
||||
compoundUnits: ["全栈新媒体运营赋能文旅营销"],
|
||||
verticalUnits: ["营销传播与品牌推广", "项目全周期运营管理"]
|
||||
},
|
||||
"漓江畔水墨居度假酒店新媒体直播运营方案": {
|
||||
compoundUnits: ["全栈新媒体运营赋能文旅营销"],
|
||||
verticalUnits: ["酒店项目经营与品牌塑造", "营销传播与品牌推广", "项目全周期运营管理"]
|
||||
},
|
||||
"某自驾游平台SEO/SEM全流程优化项目": {
|
||||
compoundUnits: ["全栈新媒体运营赋能文旅营销"],
|
||||
verticalUnits: ["营销传播与品牌推广"]
|
||||
},
|
||||
"环渤海经济圈城市足球冠军赛策划与执行项目": {
|
||||
compoundUnits: ["文旅服务:形象、沟通与体验的融合艺术", "旅游产业全景与文旅基础知识"],
|
||||
verticalUnits: ["传统体育赛事商业开发", "体育赛事经纪职业认知与服务实务"]
|
||||
},
|
||||
"某歌手2025公益演唱会策划与执行项目": {
|
||||
compoundUnits: ["文旅服务:形象、沟通与体验的融合艺术", "旅游产业全景与文旅基础知识"],
|
||||
verticalUnits: ["演艺经纪基础实务与从业规范", "艺人IP孵化与商业开发实操"]
|
||||
},
|
||||
"轻奢露营市集玩乐活动运营项目": {
|
||||
compoundUnits: ["活动策划基础"],
|
||||
verticalUnits: ["露营地规划与经营管理", "营销传播与品牌推广"]
|
||||
},
|
||||
"'水墨苏乡'文化创意产品设计与量产落地项目": {
|
||||
compoundUnits: ["商业设计基础"],
|
||||
verticalUnits: ["品牌招商展全案策划与招商运营", "商业空间与文创产品设计", "文旅衍生文创产品设计"]
|
||||
},
|
||||
"中国科学院武汉植物园生态科普与文旅运营项目": {
|
||||
compoundUnits: ["文旅与供应链基础", "旅游产业全景与文旅基础知识"],
|
||||
verticalUnits: ["文旅项目策划与设计", "项目全周期运营管理"]
|
||||
},
|
||||
"谷子店开店与经营管理": {
|
||||
compoundUnits: ["文旅与供应链基础"],
|
||||
verticalUnits: ["二次元周边店经营与粉丝经济构建", "营销传播与品牌推广"]
|
||||
},
|
||||
"贵州黔东南非遗文化探索之旅线路设计项目": {
|
||||
compoundUnits: ["文旅与供应链基础", "旅游产业全景与文旅基础知识"],
|
||||
verticalUnits: ["文旅项目策划与设计", "项目全周期运营管理"]
|
||||
},
|
||||
"某宠物生活馆经营改善项目": {
|
||||
compoundUnits: ["文旅与供应链基础"],
|
||||
verticalUnits: ["财务控制与风险防范", "项目全周期运营管理", "宠物乐园式门店经营与创新"]
|
||||
}
|
||||
};
|
||||
|
||||
// 获取项目的复合能力课程
|
||||
export const getCompoundUnits = (projectTitle) => {
|
||||
if (!projectTitle) return [];
|
||||
|
||||
// 直接匹配
|
||||
if (projectUnitsMapping[projectTitle]) {
|
||||
return projectUnitsMapping[projectTitle].compoundUnits || [];
|
||||
}
|
||||
|
||||
// 尝试去除后缀后匹配(如"详情")
|
||||
const cleanTitle = projectTitle.replace(/详情$/, '');
|
||||
if (projectUnitsMapping[cleanTitle]) {
|
||||
return projectUnitsMapping[cleanTitle].compoundUnits || [];
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// 获取项目的垂直能力课程
|
||||
export const getVerticalUnits = (projectTitle) => {
|
||||
if (!projectTitle) return [];
|
||||
|
||||
// 直接匹配
|
||||
if (projectUnitsMapping[projectTitle]) {
|
||||
return projectUnitsMapping[projectTitle].verticalUnits || [];
|
||||
}
|
||||
|
||||
// 尝试去除后缀后匹配(如"详情")
|
||||
const cleanTitle = projectTitle.replace(/详情$/, '');
|
||||
if (projectUnitsMapping[cleanTitle]) {
|
||||
return projectUnitsMapping[cleanTitle].verticalUnits || [];
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// 获取项目的所有对应单元
|
||||
export const getProjectUnits = (projectTitle) => {
|
||||
const mapping = projectUnitsMapping[projectTitle];
|
||||
if (!mapping) return [];
|
||||
|
||||
return [...mapping.compoundUnits, ...mapping.verticalUnits];
|
||||
};
|
||||
@@ -144,12 +144,24 @@
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
> li {
|
||||
border: 1px solid #e5e6eb;
|
||||
box-sizing: border-box;
|
||||
padding: 3px 8px;
|
||||
padding: 5px 12px;
|
||||
background-color: #fff;
|
||||
margin-right: 5px;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f3f5;
|
||||
border-color: #0077ff;
|
||||
color: #0077ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,9 @@ const init = [
|
||||
|
||||
const MyIM = React.forwardRef((props, ref) => {
|
||||
const { hanldeClickOpenModalBtn, initialMessages } = props;
|
||||
const [currentMessages, setCurrentMessages] = useState(init);
|
||||
// 使用ChatUI的消息管理hook
|
||||
const { messages, appendMsg } = useMessages(initialMessages || init);
|
||||
const { messages, appendMsg, setMessages } = useMessages(currentMessages);
|
||||
const [isInit, setIsInit] = useState(true);
|
||||
const id = useRef(undefined);
|
||||
const childRef = useRef();
|
||||
@@ -65,6 +66,59 @@ const MyIM = React.forwardRef((props, ref) => {
|
||||
[studentInfo]
|
||||
);
|
||||
|
||||
// 处理对话内容变化
|
||||
useEffect(() => {
|
||||
if (initialMessages && initialMessages.length > 0) {
|
||||
// 构建新的消息数组
|
||||
const newMessages = [];
|
||||
|
||||
initialMessages.forEach((msg) => {
|
||||
if (msg.type === "user") {
|
||||
newMessages.push({
|
||||
type: "text",
|
||||
content: { text: msg.content },
|
||||
position: "right",
|
||||
user: {
|
||||
avatar: studentInfo?.avatar,
|
||||
name: userAvatarDom,
|
||||
},
|
||||
});
|
||||
} else if (msg.type === "assistant") {
|
||||
const mentorName = msg.mentor ? `${msg.mentor}` : "专家";
|
||||
const assistantAvatarDom = (
|
||||
<div className="user-avatar-wrapper">
|
||||
<span className="user-avatar-name">{mentorName}</span>
|
||||
<div className="user-avatar-tag">专家</div>
|
||||
<span className="user-avatar-time">
|
||||
{dayjs().format("YYYY-MM-DD HH:mm")}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
newMessages.push({
|
||||
type: "text",
|
||||
content: { text: msg.content },
|
||||
position: "left",
|
||||
user: {
|
||||
avatar: ICONURL,
|
||||
name: assistantAvatarDom,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 设置新消息
|
||||
if (setMessages) {
|
||||
setMessages(newMessages);
|
||||
} else {
|
||||
// 如果setMessages不存在,重新创建组件实例
|
||||
setCurrentMessages(newMessages);
|
||||
}
|
||||
|
||||
setIsInit(false);
|
||||
}
|
||||
}, [initialMessages, studentInfo, userAvatarDom]);
|
||||
|
||||
// 处理发送消息
|
||||
const handleSend = async (type, val, showBtn = false) => {
|
||||
setIsInit(false);
|
||||
|
||||
@@ -91,6 +91,17 @@
|
||||
background-color: #f4f7f9;
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #e8ecf0;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: #e8f0ff;
|
||||
border-left: 3px solid #2c7aff;
|
||||
}
|
||||
|
||||
> P {
|
||||
width: 70%;
|
||||
@@ -101,6 +112,9 @@
|
||||
color: #1d2129;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.support-list-content-item-status {
|
||||
width: 52px;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import IconFont from "@/components/IconFont";
|
||||
import expertSupportData from "@/data/expertSupportData";
|
||||
import "./index.css";
|
||||
|
||||
const STATUS = {
|
||||
@@ -8,11 +9,25 @@ const STATUS = {
|
||||
finish: { key: "finish", text: "已解决" },
|
||||
};
|
||||
|
||||
const Index = () => {
|
||||
const Index = ({ onSelectConversation }) => {
|
||||
const [selectedId, setSelectedId] = useState(null);
|
||||
|
||||
const handleClickNew = () => {
|
||||
console.log("点击了新对话");
|
||||
};
|
||||
|
||||
const handleSelectConversation = (conversation) => {
|
||||
setSelectedId(conversation.id);
|
||||
if (onSelectConversation) {
|
||||
onSelectConversation(conversation);
|
||||
}
|
||||
};
|
||||
|
||||
// 根据日期分组对话
|
||||
const todayConversations = expertSupportData.conversations.filter(c => c.date === "今天");
|
||||
const weekConversations = expertSupportData.conversations.filter(c => c.date === "7天内");
|
||||
const monthConversations = expertSupportData.conversations.filter(c => c.date === "30天内");
|
||||
|
||||
return (
|
||||
<div className="support-list-wrapper">
|
||||
<div className="support-list-title">
|
||||
@@ -26,114 +41,66 @@ const Index = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="support-list">
|
||||
<>
|
||||
<p className="support-list-date">今天</p>
|
||||
<ul className="support-list-content">
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-waiting">
|
||||
{STATUS.waiting.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-processing">
|
||||
{STATUS.processing.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
<>
|
||||
<p className="support-list-date">7天内</p>
|
||||
<ul className="support-list-content">
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
<>
|
||||
<p className="support-list-date">30天内</p>
|
||||
<ul className="support-list-content">
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
<li className="support-list-content-item">
|
||||
<p>这里是对话名称</p>
|
||||
<div className="support-list-content-item-status status-finish">
|
||||
{STATUS.finish.text}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
{todayConversations.length > 0 && (
|
||||
<>
|
||||
<p className="support-list-date">今天</p>
|
||||
<ul className="support-list-content">
|
||||
{todayConversations.map(conversation => (
|
||||
<li
|
||||
key={conversation.id}
|
||||
className={`support-list-content-item ${selectedId === conversation.id ? 'selected' : ''}`}
|
||||
onClick={() => handleSelectConversation(conversation)}
|
||||
>
|
||||
<p>{conversation.title}</p>
|
||||
<div className={`support-list-content-item-status status-${conversation.status}`}>
|
||||
{STATUS[conversation.status].text}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{weekConversations.length > 0 && (
|
||||
<>
|
||||
<p className="support-list-date">7天内</p>
|
||||
<ul className="support-list-content">
|
||||
{weekConversations.map(conversation => (
|
||||
<li
|
||||
key={conversation.id}
|
||||
className={`support-list-content-item ${selectedId === conversation.id ? 'selected' : ''}`}
|
||||
onClick={() => handleSelectConversation(conversation)}
|
||||
>
|
||||
<p>{conversation.title}</p>
|
||||
<div className={`support-list-content-item-status status-${conversation.status}`}>
|
||||
{STATUS[conversation.status].text}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{monthConversations.length > 0 && (
|
||||
<>
|
||||
<p className="support-list-date">30天内</p>
|
||||
<ul className="support-list-content">
|
||||
{monthConversations.map(conversation => (
|
||||
<li
|
||||
key={conversation.id}
|
||||
className={`support-list-content-item ${selectedId === conversation.id ? 'selected' : ''}`}
|
||||
onClick={() => handleSelectConversation(conversation)}
|
||||
>
|
||||
<p>{conversation.title}</p>
|
||||
<div className={`support-list-content-item-status status-${conversation.status}`}>
|
||||
{STATUS[conversation.status].text}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
export default Index;
|
||||
@@ -24,6 +24,7 @@ const ExpertSupportPage = () => {
|
||||
const IMRef = useRef(null);
|
||||
const [formVisible, setFormVisible] = useState(false);
|
||||
const [initialMessages, setInitialMessages] = useState(null); // 设置消息
|
||||
const [selectedConversation, setSelectedConversation] = useState(null);
|
||||
|
||||
const handleClose = () => {
|
||||
setFormVisible(false);
|
||||
@@ -33,6 +34,12 @@ const ExpertSupportPage = () => {
|
||||
setFormVisible(true);
|
||||
};
|
||||
|
||||
// 处理对话选择
|
||||
const handleSelectConversation = (conversation) => {
|
||||
setSelectedConversation(conversation);
|
||||
setInitialMessages(conversation.messages);
|
||||
};
|
||||
|
||||
// 调用子组件的方法
|
||||
const handleSend = (type, val, showBtn) => {
|
||||
if (IMRef.current) {
|
||||
@@ -44,7 +51,7 @@ const ExpertSupportPage = () => {
|
||||
<>
|
||||
<div className="expert-support-page">
|
||||
<div className="expert-support-left-wrapper">
|
||||
<SupportList />
|
||||
<SupportList onSelectConversation={handleSelectConversation} />
|
||||
</div>
|
||||
<div className="expert-support-right-wrapper">
|
||||
<div className="expert-support-right-title-wrapper">
|
||||
|
||||
@@ -10,19 +10,27 @@ const LivePage = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const courseListRef = useRef(null);
|
||||
|
||||
// 检查URL参数,如果有courseId或courseTitle则自动打开对应课程
|
||||
// 检查URL参数,如果有courseId或courseTitle则自动打开对应课程或单元
|
||||
useEffect(() => {
|
||||
const courseId = searchParams.get('courseId');
|
||||
const courseTitle = searchParams.get('courseTitle');
|
||||
const courseType = searchParams.get('courseType');
|
||||
|
||||
console.log('LivePage - URL params:', { courseId, courseTitle });
|
||||
console.log('LivePage - URL params:', { courseId, courseTitle, courseType });
|
||||
|
||||
if (courseId || courseTitle) {
|
||||
// 需要给组件时间加载数据
|
||||
const timer = setTimeout(() => {
|
||||
if (courseListRef.current) {
|
||||
console.log('LivePage - Calling selectCourse via ref');
|
||||
courseListRef.current.selectCourse(courseId, courseTitle);
|
||||
// 如果courseTitle是单元名称(从项目库跳转过来),则展开对应的单元
|
||||
if (courseType && (courseType === 'compound-skill' || courseType === 'vertical-skill')) {
|
||||
console.log('LivePage - Calling expandUnitByName for unit:', courseTitle);
|
||||
courseListRef.current.expandUnitByName(courseTitle);
|
||||
} else {
|
||||
// 否则按原来的逻辑选择课程
|
||||
console.log('LivePage - Calling selectCourse via ref');
|
||||
courseListRef.current.selectCourse(courseId, courseTitle);
|
||||
}
|
||||
}
|
||||
}, 500); // 等待数据加载
|
||||
|
||||
|
||||
@@ -510,3 +510,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 可点击单元样式 */
|
||||
.clickable-unit {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.clickable-unit:hover {
|
||||
background-color: #e8f4ff !important;
|
||||
border-color: #4080ff !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(64, 128, 255, 0.15);
|
||||
}
|
||||
|
||||
.clickable-unit:active {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import PDFICON from "@/assets/images/Common/pdf_icon.png";
|
||||
import FileIcon from "@/components/FileIcon";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import ImagePreviewModal from "../ImagePreviewModal";
|
||||
import { getCompoundUnits, getVerticalUnits } from "@/data/projectUnitsMapping";
|
||||
import "./index.css";
|
||||
|
||||
export default ({ visible, onClose, data }) => {
|
||||
@@ -30,6 +31,30 @@ export default ({ visible, onClose, data }) => {
|
||||
setPreviewVisible(true);
|
||||
};
|
||||
|
||||
// 处理单元点击跳转到课程直播间
|
||||
const handleUnitClick = (unitName, isCompound) => {
|
||||
console.log('Unit clicked:', unitName, 'isCompound:', isCompound);
|
||||
|
||||
// 关闭当前模态框
|
||||
onClose();
|
||||
|
||||
// 构建URL参数
|
||||
const params = new URLSearchParams();
|
||||
params.append('courseTitle', unitName);
|
||||
|
||||
// 根据单元类型设置课程类型
|
||||
if (isCompound) {
|
||||
params.append('courseType', 'compound-skill');
|
||||
} else {
|
||||
params.append('courseType', 'vertical-skill');
|
||||
}
|
||||
|
||||
console.log('Navigate to live with params:', params.toString());
|
||||
|
||||
// 跳转到课程直播间
|
||||
navigate(`/live?${params.toString()}`);
|
||||
};
|
||||
|
||||
// 将换行符转换为Markdown格式
|
||||
const formatMarkdownContent = (content) => {
|
||||
if (!content) return "";
|
||||
@@ -37,6 +62,7 @@ export default ({ visible, onClose, data }) => {
|
||||
return content.replace(/\\n/g, '\n');
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Modal visible={visible} onClose={handleCloseModal}>
|
||||
<div className="project-cases-modal">
|
||||
@@ -128,25 +154,20 @@ export default ({ visible, onClose, data }) => {
|
||||
<div className="unit-category-section">
|
||||
<p className="unit-category-subtitle">复合能力课</p>
|
||||
<ul className="project-cases-modal-horizontal-list">
|
||||
{data?.units?.filter(unit =>
|
||||
unit.includes('商业活动') ||
|
||||
unit.includes('营销') ||
|
||||
unit.includes('品牌') ||
|
||||
unit.includes('项目全周期')
|
||||
).map((unit, index) => (
|
||||
<li key={`compound-${index}`} className="class-list-item">
|
||||
{getCompoundUnits(data?.title).map((unit, index) => (
|
||||
<li
|
||||
key={`compound-${index}`}
|
||||
className="class-list-item clickable-unit"
|
||||
onClick={() => handleUnitClick(unit, true)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="class-list-item-title">
|
||||
<i />
|
||||
<span>{unit}</span>
|
||||
</div>
|
||||
</li>
|
||||
)) || null}
|
||||
{(!data?.units || data?.units?.filter(unit =>
|
||||
unit.includes('商业活动') ||
|
||||
unit.includes('营销') ||
|
||||
unit.includes('品牌') ||
|
||||
unit.includes('项目全周期')
|
||||
).length === 0) && (
|
||||
))}
|
||||
{getCompoundUnits(data?.title).length === 0 && (
|
||||
<li className="class-list-item">
|
||||
<div className="class-list-item-title">
|
||||
<i />
|
||||
@@ -161,25 +182,20 @@ export default ({ visible, onClose, data }) => {
|
||||
<div className="unit-category-section">
|
||||
<p className="unit-category-subtitle">垂直能力课</p>
|
||||
<ul className="project-cases-modal-horizontal-list">
|
||||
{data?.units?.filter(unit =>
|
||||
!unit.includes('商业活动') &&
|
||||
!unit.includes('营销') &&
|
||||
!unit.includes('品牌') &&
|
||||
!unit.includes('项目全周期')
|
||||
).map((unit, index) => (
|
||||
<li key={`vertical-${index}`} className="class-list-item">
|
||||
{getVerticalUnits(data?.title).map((unit, index) => (
|
||||
<li
|
||||
key={`vertical-${index}`}
|
||||
className="class-list-item clickable-unit"
|
||||
onClick={() => handleUnitClick(unit, false)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="class-list-item-title">
|
||||
<i />
|
||||
<span>{unit}</span>
|
||||
</div>
|
||||
</li>
|
||||
)) || null}
|
||||
{(!data?.units || data?.units?.filter(unit =>
|
||||
!unit.includes('商业活动') &&
|
||||
!unit.includes('营销') &&
|
||||
!unit.includes('品牌') &&
|
||||
!unit.includes('项目全周期')
|
||||
).length === 0) && (
|
||||
))}
|
||||
{getVerticalUnits(data?.title).length === 0 && (
|
||||
<li className="class-list-item">
|
||||
<div className="class-list-item-title">
|
||||
<i />
|
||||
|
||||
Reference in New Issue
Block a user