feat: 完善专家支持中心、简历详情和日历页面功能

- 专家支持中心:填充真实Q&A数据,修改为"多多畅职机器人",按月份分组对话,禁用新对话按钮
- 简历详情:修复14个岗位的简历显示问题,支持markdown解析,添加编辑权限控制提示
- 日历页面:优化AI课和营销能力课显示,使用统一的event-description样式

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KQL
2025-09-14 10:24:42 +08:00
parent 4738a8545c
commit 078082c253
7 changed files with 1208 additions and 612 deletions

View File

@@ -10,6 +10,16 @@
background-image: url("@/assets/images/Common/modal_bg.png");
background-size: 100% 100%;
/* 保存按钮hover提示样式 */
.save-button-wrapper {
position: relative;
display: inline-block;
&:hover .save-button-tooltip {
opacity: 1 !important;
}
}
.close-icon {
position: absolute;
right: 20px;

View File

@@ -68,7 +68,8 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
currentContent = customVersion?.content || '';
} else if (data?.content) {
const hasModified = !!data.content.modified;
currentContent = (!hasModified || version === "1") ? data.content.original : data.content.modified;
// 如果没有modified版本始终使用original
currentContent = (version === "1" || !hasModified) ? data.content.original : data.content.modified;
}
const parsed = parseResumeMarkdown(currentContent);
@@ -209,20 +210,21 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
result.personalInfo.name = positionMatch[1].trim();
}
// 提取项目经历
const projectSectionMatch = markdownContent.match(/# 一、项目经历\s+([\s\S]*?)(?=# 二、专业技能|$)/);
// 提取项目经历 - 兼容"专业技能"和"掌握技能"两种标题
const projectSectionMatch = markdownContent.match(/# 一、项目经历\s+([\s\S]*?)(?=# 二、(?:专业技能|掌握技能)|# 三、|$)/);
if (projectSectionMatch) {
const projectContent = projectSectionMatch[1];
// 提取项目名称
const projectNameMatch = projectContent.match(/### (一)项目名称:(.+)/);
const roleMatch = projectContent.match(/### (二)实习岗位:(.+)/);
const timeMatch = projectContent.match(/### (三)实习时间:(.+)/);
const companyMatch = projectContent.match(/### (四)实习单位(.+)/);
// 提取岗位职责内容 - 从"### (五)岗位职责:"开始到下一个section
const responsibilityMatch = projectContent.match(/### (五)岗位职责:\s+([\s\S]*?)$/);
// 兼容不同的顺序 - 使用非捕获组(?:)
const timeMatch = projectContent.match(/### (?:(三)|(四))实习时间(.+)/);
const companyMatch = projectContent.match(/### (?:(三)|(四))实习单位:(.+)/);
// 提取岗位职责内容 - 兼容有冒号和没有冒号的情况
const responsibilityMatch = projectContent.match(/### (五)岗位职责[:]?\s+([\s\S]*?)$/);
if (projectNameMatch) {
result.projects = [{
name: projectNameMatch[1].trim(),
@@ -234,11 +236,11 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
}
}
// 提取专业技能
const skillsSectionMatch = markdownContent.match(/# 二、专业技能\s+([\s\S]*?)$/);
// 提取专业技能 - 兼容"专业技能"和"掌握技能"两种标题
const skillsSectionMatch = markdownContent.match(/# 二、(?:专业技能|掌握技能)\s+([\s\S]*?)(?=# 三、|$)/);
if (skillsSectionMatch) {
const skillsContent = skillsSectionMatch[1];
// 提取核心能力
const coreSkillsMatch = skillsContent.match(/### (一)核心能力\s+([\s\S]*?)(?=### (二)复合能力|$)/);
if (coreSkillsMatch) {
@@ -248,9 +250,9 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
.map(skill => skill.trim().replace(/\s*$/, ''));
result.skills.core = coreSkills;
}
// 提取复合能力
const additionalSkillsMatch = skillsContent.match(/### (二)复合能力\s+([\s\S]*?)$/);
// 提取复合能力
const additionalSkillsMatch = skillsContent.match(/### (二)复合能力\s+([\s\S]*?)(?=# 三、|$)/);
if (additionalSkillsMatch) {
const additionalSkills = additionalSkillsMatch[1]
.split(/\d+\.\s+/)
@@ -260,6 +262,15 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
}
}
// 提取个人评价/个人总结 - 兼容两种标题
const personalSummaryMatch = markdownContent.match(/# 三、(?:个人评价|个人总结)\s+([\s\S]*?)$/);
if (personalSummaryMatch) {
const summaryText = personalSummaryMatch[1].trim();
if (summaryText) {
result.personalSummary = [summaryText];
}
}
return result;
};
@@ -286,7 +297,8 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
if (data.content.original) {
// 有original字段可能有或没有modified字段
const hasModified = !!data.content.modified;
const selectedContent = (!hasModified || version === "1") ? data.content.original : data.content.modified;
// 如果没有modified版本始终使用original
const selectedContent = (version === "1" || !hasModified) ? data.content.original : data.content.modified;
console.log('选择的内容长度:', selectedContent ? selectedContent.length : 0);
// 如果是markdown格式的字符串使用解析器
@@ -322,7 +334,8 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
console.log('处理content.original结构');
// 处理有content.original的数据结构
const hasModified = !!currentTemplate.content.modified;
const selectedContent = (!hasModified || version === "1") ? currentTemplate.content.original : currentTemplate.content.modified;
// 如果没有modified版本始终使用original
const selectedContent = (version === "1" || !hasModified) ? currentTemplate.content.original : currentTemplate.content.modified;
const parsedContent = parseResumeMarkdown(selectedContent);
if (parsedContent) {
@@ -483,17 +496,45 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
</Button>
) : (
<>
<Button
type="primary"
size="small"
icon={<IconSave />}
onClick={handleSaveEdit}
style={{
borderRadius: '4px'
}}
>
保存
</Button>
<div className="save-button-wrapper">
<Button
type="primary"
size="small"
icon={<IconSave />}
disabled={true}
style={{
borderRadius: '4px',
backgroundColor: '#d9d9d9',
borderColor: '#d9d9d9',
color: '#ffffff',
cursor: 'not-allowed',
opacity: 0.5
}}
>
保存
</Button>
<div
style={{
position: 'absolute',
top: '-35px',
left: '50%',
transform: 'translateX(-50%)',
backgroundColor: 'rgba(0, 0, 0, 0.75)',
color: '#fff',
padding: '6px 12px',
borderRadius: '4px',
fontSize: '12px',
whiteSpace: 'nowrap',
pointerEvents: 'none',
opacity: 0,
transition: 'opacity 0.3s',
zIndex: 1000
}}
className="save-button-tooltip"
>
非学员与导师无修改权限
</div>
</div>
<Button
size="small"
icon={<IconClose />}