feat: 实现日历课程点击跳转到直播间功能

- 添加日历课程详情弹窗的点击跳转功能
- 公共课直播间和课程直播间支持URL参数自动选中课程
- 优化岗位详情页面样式,复用简洁卡片样式
- 为岗位详情标题添加图标
- 调整不同类型课程的跳转逻辑

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KQL
2025-09-11 14:14:45 +08:00
parent 60bd9bb142
commit 561d5c286d
107 changed files with 101383 additions and 478 deletions

View File

@@ -55,7 +55,8 @@
"Bash(git clean:*)",
"Bash(xxd:*)",
"Bash(kill:*)",
"Bash(find:*)"
"Bash(find:*)",
"Bash(pgrep:*)"
],
"deny": [],
"ask": []

72
apply_resume_updates.py Normal file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取数据
with open('resume_updates.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取当前的resumeInterviewMock.js文件
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
# 定义需要更新的岗位和其所属行业
position_mapping = {
'露营地运营专员': '露营地运营', # 需要创建新行业
'文创产品设计师': '文旅产品设计',
'文创产品策划师': '文旅产品设计',
'文创产品设计师助理': '文旅产品设计',
'品牌策划运营专员': '品牌运营',
'品牌公关': '品牌运营',
'品牌推广专员': '品牌运营',
'ip运营': '品牌运营',
'IP运营总监助理': '品牌运营',
'品牌公关管培生': '品牌运营'
}
# 生成更新代码
for update in updates:
position = update['position']
student_info = update['studentInfo']
# 清理数据中的额外空格和错误文本
if student_info['project_experience']['project_name']:
student_info['project_experience']['project_name'] = student_info['project_experience']['project_name'].strip()
if student_info['project_experience']['position']:
student_info['project_experience']['position'] = student_info['project_experience']['position'].strip()
if student_info['project_experience']['time_period']:
student_info['project_experience']['time_period'] = student_info['project_experience']['time_period'].strip()
if student_info['project_experience']['company']:
student_info['project_experience']['company'] = student_info['project_experience']['company'].strip()
# 清理core_skills中的错误文本
cleaned_core_skills = []
for skill in student_info['core_skills']:
# 移除开头的"chubu "等错误文本
skill = re.sub(r'^chubu\s+', '', skill)
skill = skill.strip()
if skill:
cleaned_core_skills.append(skill)
student_info['core_skills'] = cleaned_core_skills
# 清理compound_skills
cleaned_compound_skills = []
for skill in student_info['compound_skills']:
skill = skill.strip()
if skill:
cleaned_compound_skills.append(skill)
student_info['compound_skills'] = cleaned_compound_skills
print(f"\n处理岗位: {position}")
print(f" - 项目名称: {student_info['project_experience']['project_name']}")
print(f" - 核心技能数: {len(student_info['core_skills'])}")
print(f" - 复合技能数: {len(student_info['compound_skills'])}")
print(f" - 个人总结长度: {len(student_info['personal_summary'])}")
# 保存清理后的数据
with open('resume_updates_cleaned.json', 'w', encoding='utf-8') as f:
json.dump(updates, f, ensure_ascii=False, indent=2)
print("\n数据清理完成,保存到 resume_updates_cleaned.json")

99
batch_update_resumes.py Normal file
View File

@@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取resumeInterviewMock.js
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
mock_content = f.read()
# 首先检查是否存在露营地运营行业
if '"露营地运营":' not in mock_content:
# 需要添加露营地运营行业
print("添加露营地运营行业...")
# 找到resumeTemplates的结束位置
templates_end = mock_content.find('};', mock_content.find('const resumeTemplates'))
if templates_end > 0:
# 在最后一个行业后添加露营地运营
insert_pos = mock_content.rfind(']', 0, templates_end)
if insert_pos > 0:
# 找到适合的插入位置(在最后一个行业数组的']'后)
next_brace = mock_content.find('}', insert_pos)
if next_brace > 0:
# 在最后一个行业后添加逗号和新行业
new_industry = ''',
"露营地运营": []'''
mock_content = mock_content[:next_brace] + new_industry + '\n ' + mock_content[next_brace:]
print("露营地运营行业已添加")
# 保存备份
with open('src/mocks/resumeInterviewMock.js.backup_batch_update', 'w', encoding='utf-8') as f:
f.write(mock_content)
# 为每个岗位创建更新
for update in updates:
position = update['position']
student_info = update['studentInfo']
print(f"\n处理: {position}")
# 根据岗位名称确定行业
industry_map = {
'露营地运营专员': '露营地运营',
'文创产品设计师': '文旅产品设计',
'文创产品策划师': '文旅产品设计',
'文创产品设计师助理': '文旅产品设计',
'品牌策划运营专员': '品牌运营',
'品牌公关': '品牌运营',
'品牌推广专员': '品牌运营',
'ip运营': '品牌运营',
'IP运营总监助理': '品牌运营',
'品牌公关管培生': '品牌运营'
}
industry = industry_map.get(position)
if not industry:
print(f" 警告: 未找到{position}的行业映射")
continue
# 查找该岗位是否已存在于resumeTemplates中
pattern = f'position: "{position}"'
if pattern in mock_content:
print(f" {position} 已存在于简历模板中")
# 检查是否有studentInfo
pos = mock_content.find(pattern)
# 查找这个岗位的结束位置
next_position = mock_content.find('position:', pos + len(pattern))
if next_position == -1:
next_position = len(mock_content)
section = mock_content[pos:next_position]
if 'studentInfo: null' in section or 'studentInfo: {' not in section:
print(f" 需要更新 {position} 的 studentInfo")
# 生成要插入的studentInfo JSON
student_info_json = json.dumps(student_info, ensure_ascii=False, indent=10)
# 调整缩进
student_info_json = student_info_json.replace('\n', '\n ')
# 创建更新文件
with open(f'update_{position.replace("/", "_")}.txt', 'w', encoding='utf-8') as f:
f.write(f"岗位: {position}\n")
f.write(f"行业: {industry}\n")
f.write(f"studentInfo: {student_info_json}\n")
else:
print(f" {position} 不存在于简历模板中,需要创建")
# 创建新岗位数据文件
with open(f'create_{position.replace("/", "_")}.txt', 'w', encoding='utf-8') as f:
f.write(f"岗位: {position}\n")
f.write(f"行业: {industry}\n")
f.write(f"需要在 {industry} 行业下创建新岗位\n")
print("\n已生成所有更新文件")

100
check_positions.js Normal file
View File

@@ -0,0 +1,100 @@
#!/usr/bin/env node
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 读取文件
const filePath = path.join(__dirname, 'src/mocks/resumeInterviewMock.js');
const content = fs.readFileSync(filePath, 'utf-8');
// 需要检查的岗位列表
const positionsToCheck = [
'民宿管家',
'民宿客房管家',
'民宿运营专员',
'露营地运营专员',
'新媒体运营专员',
'文创产品设计师',
'文创产品策划师',
'文创产品设计师助理',
'品牌策划运营专员',
'品牌公关',
'品牌推广专员',
'ip运营',
'IP运营总监助理',
'品牌公关管培生'
];
console.log('检查岗位数据完整性...');
console.log('=' * 50);
// 提取industries数据
const industriesMatch = content.match(/const industries = \[([\s\S]*?)\];/);
if (!industriesMatch) {
console.log('未找到industries数据');
process.exit(1);
}
// 提取resumeTemplates数据
const templatesMatch = content.match(/const resumeTemplates = \{([\s\S]*?)\n\};/);
if (!templatesMatch) {
console.log('未找到resumeTemplates数据');
process.exit(1);
}
// 分析每个岗位
const results = [];
for (const position of positionsToCheck) {
// 在industries中查找
const industryRegex = new RegExp(`title: "${position}"`, 'g');
const industryMatches = [...content.matchAll(industryRegex)];
// 在resumeTemplates中查找
const templateRegex = new RegExp(`position: "${position}"[\\s\\S]*?studentInfo:`, 'g');
const templateMatches = [...content.matchAll(templateRegex)];
// 检查是否有studentInfo
let hasStudentInfo = false;
for (const match of templateMatches) {
const afterMatch = content.substring(match.index, match.index + 1000);
if (afterMatch.includes('studentInfo: {')) {
// 检查studentInfo是否包含必要字段
const studentInfoEnd = afterMatch.indexOf('},') + match.index;
const studentInfoContent = content.substring(match.index, studentInfoEnd);
hasStudentInfo =
studentInfoContent.includes('project_experience:') &&
studentInfoContent.includes('core_skills:') &&
studentInfoContent.includes('personal_summary:');
}
}
results.push({
position,
inIndustries: industryMatches.length > 0,
inTemplates: templateMatches.length > 0,
hasStudentInfo
});
}
// 输出结果
console.log('\n检查结果\n');
console.log('岗位名称 | 在industries中 | 在templates中 | 有studentInfo');
console.log('-'.repeat(60));
let missingCount = 0;
for (const result of results) {
const status = result.hasStudentInfo ? '✅' : '❌';
console.log(`${result.position.padEnd(20)} | ${result.inIndustries ? '是' : '否'} | ${result.inTemplates ? '是' : '否'} | ${status}`);
if (!result.hasStudentInfo) {
missingCount++;
}
}
console.log('\n' + '='.repeat(50));
console.log(`总计:${results.length}个岗位,${missingCount}个缺少studentInfo数据`);

89
complete_all_updates.py Normal file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取resumeInterviewMock.js
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
print("批量更新所有岗位的完整studentInfo数据...")
# 需要更新的所有岗位
all_positions = [
'文创产品设计师',
'文创产品策划师',
'文创产品设计师助理',
'品牌策划运营专员',
'品牌公关',
'品牌推广专员',
'ip运营',
'IP运营总监助理',
'品牌公关管培生'
]
success_count = 0
for position in all_positions:
update_data = next((u for u in updates if u['position'] == position), None)
if not update_data:
print(f"⚠ 未找到{position}的更新数据")
continue
# 准备完整的studentInfo数据
student_info = update_data['studentInfo']
# 构建完整的studentInfo字符串
student_info_str = f'''studentInfo: {{
project_experience: {{
project_name: "{student_info['project_experience']['project_name']}",
position: "{student_info['project_experience']['position']}",
time_period: "{student_info['project_experience']['time_period']}",
company: "{student_info['project_experience']['company']}",
description: `{student_info['project_experience']['description']}`
}},
core_skills: {json.dumps(student_info['core_skills'], ensure_ascii=False, indent=10).replace('"', '`')},
compound_skills: {json.dumps(student_info['compound_skills'], ensure_ascii=False, indent=10).replace('"', '`')},
personal_summary: "{student_info['personal_summary']}"
}}'''
# 使用正则表达式替换整个studentInfo部分
# 查找模式position: "岗位名"...studentInfo: {...}
pattern = rf'(position:\s*"{re.escape(position)}"[^}}]*?)studentInfo:\s*{{[^}}]*(?:{{[^}}]*}}[^}}]*)*}}'
# 替换为新的studentInfo
replacement = rf'\1{student_info_str}'
# 执行替换
new_content, count = re.subn(pattern, replacement, content, flags=re.DOTALL)
if count > 0:
content = new_content
print(f"{position} studentInfo已完整更新")
success_count += 1
else:
print(f"{position} 未能匹配到studentInfo位置")
# 保存更新后的文件
with open('src/mocks/resumeInterviewMock.js', 'w', encoding='utf-8') as f:
f.write(content)
print(f"\n✓ 成功更新 {success_count}/{len(all_positions)} 个岗位的数据!")
# 验证更新
print("\n验证更新结果...")
for position in all_positions[:3]: # 验证前3个
if f'position: "{position}"' in content:
pos = content.find(f'position: "{position}"')
section = content[pos:pos+500]
if 'project_experience: null' in section:
print(f"{position} 仍有null值")
elif 'project_experience: {' in section:
print(f"{position} 已更新")
else:
print(f" ? {position} 状态未知")

View File

@@ -0,0 +1,3 @@
岗位: 露营地运营专员
行业: 露营地运营
需要在 露营地运营 行业下创建新岗位

62
extract_resume_data.py Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
def extract_position_data(position_names):
"""从JSON文件中提取指定岗位的数据"""
result = {}
# 读取所有part文件
for i in range(1, 4):
file_path = f'/Users/apple/Documents/cursor/教务系统/frontend/网页未导入数据/文旅产业/个人简历内容_part{i}.json'
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
position = item.get('❌岗位名称查询', '')
if position in position_names:
result[position] = item
print(f"找到: {position} in part{i}")
except Exception as e:
print(f"Error reading part{i}: {e}")
# 也读取主文件
main_file = '/Users/apple/Documents/cursor/教务系统/frontend/网页未导入数据/文旅产业/个人简历内容.json'
try:
with open(main_file, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
position = item.get('❌岗位名称查询', '')
if position in position_names and position not in result:
result[position] = item
print(f"找到: {position} in main file")
except Exception as e:
print(f"Error reading main file: {e}")
return result
# 需要提取的岗位
positions_to_extract = [
'露营地运营专员',
'文创产品设计师', '文创产品策划师', '文创产品设计师助理',
'品牌策划运营专员', '品牌公关', '品牌推广专员',
'ip运营', 'IP运营总监助理', '品牌公关管培生'
]
# 提取数据
extracted_data = extract_position_data(positions_to_extract)
# 保存提取的数据
output_file = '/Users/apple/Documents/cursor/教务系统/frontend/extracted_resume_data.json'
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(extracted_data, f, ensure_ascii=False, indent=2)
print(f"\n成功提取 {len(extracted_data)} 个岗位的数据")
print(f"已保存到: {output_file}")
# 显示缺失的岗位
missing = set(positions_to_extract) - set(extracted_data.keys())
if missing:
print(f"\n未找到的岗位: {missing}")

File diff suppressed because one or more lines are too long

128
final_update_resumes.py Normal file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取resumeInterviewMock.js
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
print("开始批量更新简历数据...")
# 1. 首先添加露营地运营行业(如果不存在)
if '"露营地运营":' not in content:
print("\n1. 添加露营地运营行业...")
# 在宠物店经营后面添加
insert_pattern = r'("宠物店经营":\s*\[[^\]]*\])'
replacement = r'\1,\n "露营地运营": []'
content = re.sub(insert_pattern, replacement, content)
print(" ✓ 露营地运营行业已添加")
# 2. 为露营地运营专员添加完整数据
print("\n2. 添加露营地运营专员数据...")
luyingdi_data = next((u for u in updates if u['position'] == '露营地运营专员'), None)
if luyingdi_data:
# 构建完整的岗位数据
luyingdi_entry = f''' {{
position: "露营地运营专员",
level: "普通岗",
content: {{
original: "露营地运营专员简历内容",
modified: "露营地运营专员简历内容"
}},
studentInfo: {{
project_experience: {{
project_name: "{luyingdi_data['studentInfo']['project_experience']['project_name']}",
position: "{luyingdi_data['studentInfo']['project_experience']['position']}",
time_period: "{luyingdi_data['studentInfo']['project_experience']['time_period']}",
company: "{luyingdi_data['studentInfo']['project_experience']['company']}",
description: `{luyingdi_data['studentInfo']['project_experience']['description']}`
}},
core_skills: {json.dumps(luyingdi_data['studentInfo']['core_skills'], ensure_ascii=False, indent=10)},
compound_skills: {json.dumps(luyingdi_data['studentInfo']['compound_skills'], ensure_ascii=False, indent=10)},
personal_summary: "{luyingdi_data['studentInfo']['personal_summary']}"
}}
}}'''
# 在露营地运营数组中添加数据
pattern = r'("露营地运营":\s*\[)(\s*\])'
replacement = rf'\1\n{luyingdi_entry}\n \2'
content = re.sub(pattern, replacement, content)
print(" ✓ 露营地运营专员数据已添加")
# 3. 更新其他岗位的studentInfo
positions_to_update = [
('文创产品设计师', '文旅产品设计'),
('文创产品策划师', '文旅产品设计'),
('文创产品设计师助理', '文旅产品设计'),
('品牌策划运营专员', '品牌运营'),
('品牌公关', '品牌运营'),
('品牌推广专员', '品牌运营'),
('ip运营', '品牌运营'),
('IP运营总监助理', '品牌运营'),
('品牌公关管培生', '品牌运营')
]
print("\n3. 更新其他岗位的studentInfo...")
for position, industry in positions_to_update:
update_data = next((u for u in updates if u['position'] == position), None)
if not update_data:
print(f" ⚠ 未找到{position}的更新数据")
continue
# 构建studentInfo
student_info = f'''{{
project_experience: {{
project_name: "{update_data['studentInfo']['project_experience']['project_name']}",
position: "{update_data['studentInfo']['project_experience']['position']}",
time_period: "{update_data['studentInfo']['project_experience']['time_period']}",
company: "{update_data['studentInfo']['project_experience']['company']}",
description: `{update_data['studentInfo']['project_experience']['description']}`
}},
core_skills: {json.dumps(update_data['studentInfo']['core_skills'], ensure_ascii=False, indent=10)},
compound_skills: {json.dumps(update_data['studentInfo']['compound_skills'], ensure_ascii=False, indent=10)},
personal_summary: "{update_data['studentInfo']['personal_summary']}"
}}'''
# 查找并替换studentInfo: null或缺失的studentInfo
# 查找该岗位的位置
position_pattern = f'position: "{position}"'
pos = content.find(position_pattern)
if pos != -1:
# 找到该岗位结束的位置(下一个岗位或数组结束)
next_pos = content.find('position:', pos + len(position_pattern))
if next_pos == -1:
# 可能是最后一个岗位,找数组结束
next_pos = content.find(']', pos)
# 获取这段内容
section = content[pos:next_pos]
# 检查是否有studentInfo: null
if 'studentInfo: null' in section:
# 替换studentInfo: null
pattern = rf'(position: "{position}".*?studentInfo:\s*)null'
replacement = rf'\1{student_info}'
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
print(f"{position} studentInfo已更新")
elif 'studentInfo:' not in section:
# 没有studentInfo需要添加
# 在content后面添加
pattern = rf'(position: "{position}".*?content:\s*{{[^}}]*}})(\s*}})'
replacement = rf'\1,\n studentInfo: {student_info}\2'
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
print(f"{position} studentInfo已添加")
else:
print(f" {position} 已有studentInfo")
# 保存更新后的文件
with open('src/mocks/resumeInterviewMock.js', 'w', encoding='utf-8') as f:
f.write(content)
print("\n✓ 所有更新已完成!")

63
fix_assistant_designer.py Normal file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 获取文创产品设计师助理的数据
assistant_data = next((u for u in updates if u['position'] == '文创产品设计师助理'), None)
if not assistant_data:
print("未找到文创产品设计师助理数据")
exit(1)
# 读取文件
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
# 构建要替换的studentInfo
student_info = assistant_data['studentInfo']
project_exp = student_info['project_experience']
# 转义特殊字符
description = project_exp['description'].replace('`', '\\`').replace('"', '\\"')
personal_summary = student_info['personal_summary'].replace('"', '\\"')
# 构建新的studentInfo内容
new_student_info = f'''{{
project_experience: {{
project_name: "{project_exp['project_name']}",
position: "{project_exp['position']}",
time_period: "{project_exp['time_period']}",
company: "{project_exp['company']}",
description: `{description}`
}},
core_skills: {json.dumps(student_info['core_skills'], ensure_ascii=False, indent=10)},
compound_skills: {json.dumps(student_info['compound_skills'], ensure_ascii=False, indent=10)},
personal_summary: "{personal_summary}"
}}'''
# 查找文创产品设计师助理在resumeTemplates中的位置第三个位置
# 使用更精确的模式来定位第三个实例
pattern = r'(position: "文创产品设计师助理",\s+level: "普通岗",[\s\S]*?studentInfo: )(\{[^}]*(?:\{[^}]*\}[^}]*)*\})'
matches = list(re.finditer(pattern, content))
print(f"找到 {len(matches)} 个匹配")
if len(matches) > 0:
# 使用最后一个匹配应该是在resumeTemplates中的
match = matches[-1]
# 替换studentInfo
new_content = content[:match.start(2)] + new_student_info + content[match.end(2):]
# 保存文件
with open('src/mocks/resumeInterviewMock.js', 'w', encoding='utf-8') as f:
f.write(new_content)
print("✅ 文创产品设计师助理已更新")
else:
print("❌ 未找到正确的替换位置")

101
precise_update.py Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取当前文件
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
# 需要更新的岗位列表
positions_to_update = [
'文创产品设计师',
'文创产品策划师',
'文创产品设计师助理',
'品牌策划运营专员',
'品牌公关',
'品牌推广专员',
'ip运营',
'IP运营总监助理',
'品牌公关管培生'
]
print("开始精确更新九个岗位的数据...")
print("-" * 50)
for position_name in positions_to_update:
# 获取该岗位的数据
position_data = next((u for u in updates if u['position'] == position_name), None)
if not position_data:
print(f"❌ 未找到 {position_name} 的数据")
continue
# 准备要替换的内容
student_info = position_data['studentInfo']
# 查找该岗位在文件中的位置
search_str = f'position: "{position_name}"'
pos = content.find(search_str)
if pos == -1:
print(f"❌ 未找到 {position_name} 的位置")
continue
# 找到该岗位的studentInfo: { ... } 部分
student_info_start = content.find('studentInfo: {', pos)
if student_info_start == -1:
print(f"❌ 未找到 {position_name} 的studentInfo")
continue
# 找到对应的结束大括号
brace_count = 0
i = student_info_start + len('studentInfo: {')
start_brace_pos = i - 1
while i < len(content):
if content[i] == '{':
brace_count += 1
elif content[i] == '}':
if brace_count == 0:
end_brace_pos = i
break
brace_count -= 1
i += 1
# 构建新的studentInfo内容
project_exp = student_info['project_experience']
# 对描述中的引号进行转义
description = project_exp['description'].replace('`', '\\`').replace('"', '\\"')
# 对个人总结中的引号进行转义
personal_summary = student_info['personal_summary'].replace('"', '\\"')
new_student_info = f'''studentInfo: {{
project_experience: {{
project_name: "{project_exp['project_name']}",
position: "{project_exp['position']}",
time_period: "{project_exp['time_period']}",
company: "{project_exp['company']}",
description: `{description}`
}},
core_skills: {json.dumps(student_info['core_skills'], ensure_ascii=False, indent=10)},
compound_skills: {json.dumps(student_info['compound_skills'], ensure_ascii=False, indent=10)},
personal_summary: "{personal_summary}"
}}'''
# 替换内容
content = content[:student_info_start] + new_student_info + content[end_brace_pos+1:]
print(f"✅ 已更新 {position_name}")
# 保存文件
with open('src/mocks/resumeInterviewMock.js', 'w', encoding='utf-8') as f:
f.write(content)
print("-" * 50)
print("✅ 所有岗位更新完成!")

27
reorder_script.js Normal file
View File

@@ -0,0 +1,27 @@
const fs = require('fs');
// 读取文件
const filePath = '/Users/apple/Documents/cursor/教务系统/frontend/src/mocks/resumeInterviewMock.js';
let fileContent = fs.readFileSync(filePath, 'utf8');
// 定义新的顺序 - 根据用户要求重新排列
const newOrder = [
"会展策划与执行", // 保持第一位
"旅游", // 移到第二位
"酒店经营",
"演艺经纪",
"景区运营",
"活动策划与执行",
"露营地运营",
"宠物店经营",
"新媒体运营",
"文旅产品设计",
"品牌运营",
"二次元周边店铺运营", // 移到最后
"民宿经营" // 移到最后
];
console.log('目标排序:', newOrder);
// 现在手动重排 - 这个脚本用于显示目标顺序
console.log('需要重新排列industries数组为以上顺序');

332
resume_updates.json Normal file
View File

@@ -0,0 +1,332 @@
[
{
"position": "露营地运营专员",
"studentInfo": {
"project_experience": {
"project_name": "轻奢露营市集玩乐活动运营项目 ",
"position": "露营地运营专员 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助整理《活动总述》《区域规划图》与《应急与安全方案》等前期资料,参与六大功能区规划讨论,初步熟悉露营地场景布局与功能设计逻辑;\n参与KV主视觉海报、倒计时物料与招募话术的内容校对与素材归档辅助完成社群渠道报名表的发布与数据登记\n在布置阶段协助场地标识、签到区、导视系统及打卡区域的布设工作配合布置市集摊位、帐篷区及照明装饰保证视觉统一与体验顺畅\n活动当天负责签到引导、票务核验、手环发放及礼品包分发协助游客入场分流与体验区问询保障人流动线与秩序稳定\n参与“帐篷搭建赛”“森林音乐会”“星空影院”等活动的流程协助与舞台支持协助主持人控场并负责节目表的时间提示与衔接\n协助运营组整理现场视频/照片素材,参与“云相册”上线与素材初筛,配合后期剪辑团队完成线上传播内容初步编排;\n活动结束后协助物资回收、摊位清理及满意度问卷收集并参与复盘会议内容整理输出基础版运营反馈报告。"
},
"core_skills": [
"chubu 掌握营地日常运营全流程管理包括接待流程优化、设施巡检维护及运营数据统计分析能力能独立运用Office办公软件完成经营报表制作与可视化呈现",
"具备线上线下活动落地执行经验,熟悉场景搭建、活动动线规划与现场摄影直播技术操作,能熟练操作无人机航拍、手持云台等设备完成多媒体素材采集",
"精通数字化营地管理工具应用包括OTA渠道管理后台如携程商旅、美团商家端、微信群控工具、自媒体运营平台抖音企业号、小红书专业号的数据分析与内容发布",
"具备团队管理与标准化建设能力,熟悉服务业人员排班调度、绩效考核方案设计,能通过钉钉/企业微信等协同工具实现跨部门任务分配与进度管控",
"擅长用户社群运营与私域流量转化具备客户需求分析、会员体系搭建及精准营销活动策划能力熟练使用SCRM系统进行客户分层管理与精准触达",
"掌握露营行业趋势分析与竞品调研方法论,能通过行业垂直平台(如露营天下、户外资料网)持续更新运营策略,具备基础商业计划书撰写与营收模型构建能力"
],
"compound_skills": [
"活动执行与现场管理能力: 了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力: 具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"新媒体平台运营能力: 具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"智慧文旅应用能力: 了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。",
"服务体验优化和资源协同能力: 理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"文化IP策划与品牌传播能力 理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力 了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力: 了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"产品营销基础: 具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,在露营地运营项目中担任助理角色,接触了从活动前期策划到现场执行、再到后期传播的全流程,对文旅活动的实际运作有了较为清晰的认识。在项目中,我能够主动承担任务、及时响应需求、配合团队完成细节工作。虽然经验尚浅,但我有较强的责任感与适应能力,愿意从基层做起,逐步积累经验,努力成长为一名综合型的运营人才。"
}
},
{
"position": "文创产品设计师",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目 ",
"position": "文创产品设计师助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助主设计师进行“水墨苏乡”主题视觉元素的图像处理与文化语义归类,使用 Photoshop 对采集的江南水乡图像进行图层拆解与结构化归纳,提取“马头墙、小桥、窗棂、屋檐”等造型语汇,用于后续概念设计参考;\n使用 Rhino 对整套“新文房四宝”产品进行3D建模包括笔架窗棂结构、笔搁屋檐线条、镇纸小桥拱形、砚台小舟轮廓等器物确保建模结果在尺寸结构上具备装配逻辑和可加工性\n使用 KeyShot 对各款器物建模成果进行材质与光照渲染,展示“竹木/陶瓷/金属”多种材质搭配效果,用于评审会展示与用户调研材料;\n使用 AutoCAD 绘制产品结构平面图与关键尺寸标注图,重点完成笔搁凹槽尺寸、砚台出墨区斜率、镇纸重心分布等人机关键结构的二维表达;\n运用 Illustrator 参与绘制初步产品概念草图与器物功能图示,协助完成“功能+结构+文化元素”之间的逻辑表达文件,用于概念提案阶段汇报;\n使用 Figma 协助制作产品陈列组合的用户引导图,完成“组合即场景”状态下的摆放路径、限位点与安全区域说明图,提升用户理解与复现准确率。"
},
"core_skills": [
"文创产品全流程设计能力: 熟悉文创产品从概念挖掘、方案构思、设计执行到质量把控的基础流程,具备将创意转化为具体产品方案的能力。",
"专业设计软件操作: 初步掌握Photoshop, Illustrator, InDesign等软件进行图形设计、插画绘制及排版了解基础3D建模软件Rhino / SketchUp / Blender用于产品造型设计。",
"包装与印刷工艺知识: 熟悉包装设计规范及常用材料特性(如纸张、特种纸、环保材料),了解基础印刷工艺(四色印刷、专色、烫金/银、UV、击凸、压凹对设计实现的影响能配合跟进打样与生产环节。",
"市场调研与用户洞察基础: 掌握基础的定性/定量市场调研方法(如问卷设计、竞品分析、桌面研究),具备初步的消费者需求分析能力,能将调研结果辅助设计决策。",
"平面视觉传达设计: 具备品牌视觉元素应用能力,能完成海报、宣传物料、活动视觉等平面设计任务,确保设计符合品牌调性。",
"高效协作与沟通能力: 理解跨部门协作(如与产品、供应链、市场部门)的重要性,具备清晰表达设计理念、有效接收反馈并协作推进项目落地的沟通技巧。",
"快速学习与流程优化意识: 具备强烈的学习意愿和快速吸收新知识的能力,关注设计流程效率,有意识总结项目经验并乐于参与优化标准化工作方法。",
"创意发散与审美能力: 拥有活跃的创意思维和扎实的美学基础,能够持续输出符合市场趋势与文化内涵的创意设计方案。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,热爱文化与设计融合的表达方式。在“水墨苏乡”文创项目中,我系统接触了从文化图像分析、三维建模到产品展示的全流程任务,能熟练运用多款设计软件支持团队工作,并具备良好的视觉表达与图纸制作能力。实习期间,我积极配合导师完成任务,善于沟通反馈,能够快速理解设计意图并落实为具体输出。虽然目前仍处于学习阶段,但我具备较强的执行能力与持续学习意愿,期待在贵公司继续提升并贡献价值。"
}
},
{
"position": "文创产品策划师",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目 ",
"position": "文创产品策划师助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "参与江南建筑意象调研,通过图片资料收集与用户访谈协助构建“马头墙、小桥、窗棂”等视觉元素清单,完成《文化元素映射表》初稿;\n协助产品策划师完成“新文房四宝”概念模型的语义解读工作整理各器物功能定义与使用场景文案用于支持初期设计逻辑说明\n配合工程人员完成不同材质组合样品的数据记录与对比包括竹木、陶瓷、金属等材料的热胀冷缩差异、装配公差与手感测试结果\n协助撰写《用户陈列与功能使用观察报告》参与家庭书房场景下的使用试验记录承托角度、稳定性及用户反馈形成优化建议表\n参与终端品牌包装提案的草稿整理与信息审核工作协助准备品牌叙事文本、器物摆放图示及包装结构可持续性材料说明。"
},
"core_skills": [
"能够基于品牌调性进行深度挖掘,独立创作具有文化内涵和情感共鸣的产品故事、命名方案及核心立意文案。",
"理解品牌定位的基本原则,并能将定位转化为具体的产品概念和传播语言。",
"熟悉文创产品从需求分析(含客户需求调研)、市场/品类选品研究、创意构思与方案策划、设计方向沟通指导到打样跟进的关键流程。",
"掌握 Adobe Photoshop (PS) 和 Adobe Illustrator (AI) 的基础操作(如图像处理、基础排版、查看设计稿),能够有效理解设计师工作并与设计师进行专业沟通,准确传达策划意图和反馈意见。",
"具备基础的客户访谈与信息收集技巧,能够协助进行客户公司背景及产品需求的调研分析。",
"能清晰整理需求要点并参与内部讨论或辅助准备面向客户的提案材料PPT/文档),学习将客户需求转化为具体的策划方向。",
"熟练运用 Microsoft Excel 进行市场数据(如竞品信息、用户偏好、品类趋势等)的收集、整理和基础分析(如数据透视表、图表制作)。",
"理解产品开发中与设计师、采购、生产等环节协作的重要性,具备良好的书面和口头沟通能力,确保信息准确传递。",
"了解常见文创产品的 基础生产工艺流程(如印刷、包装、常见材质特性)和 成本构成要素,能够协助跟进打样过程,理解设计落地的基本限制与可能性。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专生,在校期间积极参与实训项目,曾在“水墨苏乡”文创设计项目中担任策划师助理,协助完成从文化调研、概念提炼到用户测试等多个环节的任务。实习过程中,我具备较强的信息归纳与整理能力,善于从细节中发现优化点,并能在多方沟通中保持良好的协作态度。虽然我仍在学习阶段,但我热爱文化创意行业,具备持续学习与思考的能力,希望能在贵公司获得深入实践与成长的机会。"
}
},
{
"position": "品牌策划运营专员",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目 ",
"position": "品牌运营专员 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助梳理项目IP的角色人设与传播语料参与撰写“唐小驼”“镜灵”等角色的品牌故事文案用于宣传视频、短视频脚本及产品包装文案等传播渠道\n配合完成项目在B站与抖音平台的账号内容更新与粉丝互动包括视频上传、回复评论、整理热门话题标签增强用户粘性\n协助进行联名产品的线上活动策划与宣传物料制作如“胡旋舞”饮料联名的H5页面内容策划、“镜灵守护”手环表盘文案配图整理支持品牌曝光\n参与UGC共创平台“幻夜工坊”的日常用户运营任务包括用户投稿内容审核、优秀作品推送素材整理、月度创作榜单初筛等提高用户参与感\n协助整理多平台运营数据如小程序访问量、盲盒销售情况、文创IP关键词搜索热度等按周输出简易数据看板并提出初步优化建议支持团队运营决策。"
},
"core_skills": [
"基础内容运营能力: 掌握微信公众号、小程序、抖音、小红书等新媒体平台的基础运维与操作。",
"文案撰写与编辑: 初步具备良好的文字功底,能够协助撰写新闻稿件、活动简报及日常社交媒体文案。",
"宣传海报设计:熟悉使用 Photoshop制作基础画报宣传图能完成活动物料与社交平台配图初稿设计",
"活动执行支持: 了解市场推广活动执行流程,能有效协助活动落地与现场支持,并具备基础活动数据跟踪意识。",
"办公软件熟练应用: 精通Word、Excel、PPT等办公软件能高效处理文档、数据整理及制作基础演示材料。",
"项目事务跟进能力: 具备较强的责任心与细致度,能有效跟进项目执行进度,协助完成材料整理、申报及基础沟通协调工作。",
"信息收集与整理: 擅长收集行业信息、媒体动态及竞品资料,并能进行有效归纳整理。",
"团队协作与沟通: 具备良好的沟通表达能力和团队协作精神,能积极配合团队完成各项工作任务。"
],
"compound_skills": [
"新媒体平台运营能力: 具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力 理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力: 了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力 了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力: 了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力: 理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础: 具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力: 具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力: 了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生具备良好的学习能力与协作精神。在实习过程中我积极配合导师完成IP内容的撰写与平台内容运营能够胜任初步的文案编写、社群互动与活动物料整理等任务。面对多任务并行的运营节奏我能合理安排时间保证工作效率。虽然经验尚浅但我对品牌运营充满热情愿意持续学习快速适应新任务为团队创造更多价值。"
}
},
{
"position": "品牌公关",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目 ",
"position": "品牌公关助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助整理“唐小驼”“镜灵”等主IP角色的设定文案与视觉资料参与品牌宣传内容的校对与归档确保对外传播统一性\n参与撰写《西市密码》《唐小驼的丝路日志》等内容宣传资料简介用于B站、抖音等平台投稿与推送\n配合执行跨界联名项目如“冰峰饮料胡旋舞罐”与“小米手环镜灵守护版”的宣传活动整理新闻通稿与传播口径文案\n参与用户运营工作协助在“幻夜工坊”共创平台中整理用户投稿内容回复评论并策划互动话题提升粉丝活跃度\n跟随导师参与舆情监控实操学习关键词预警设置与科普内容生成流程辅助整理文化敏感内容的外部应对资料。"
},
"core_skills": [
"熟练使用PS、AI、Figma 等设计软件,协助完成品牌海报、社媒宣传图与联动项目周边图稿制作,具备基础视觉规范意识;",
"掌握 PPT与Word文档排版技能能够协助输出对外传播提案与活动执行方案文案与视觉排布兼顾表达与清晰度",
"熟悉B站、抖音、小红书等主流内容平台的运营逻辑了解视频发布流程与封面优化要点能配合完成内容发布与基础的粉丝互动管理",
"具备品牌文案撰写与润色能力参与IP故事设定、角色简介及传播文案编辑能初步完成短文案创作并结合平台调性优化语感",
"熟悉品牌联动项目的传播流程,了解跨品牌公关协同节奏;",
"了解社群与私域用户运营策略,包括管理平台评论区、回复用户留言、策划话题方向,具备基础运营思维;",
"能使用Excel、WPS表格工具进行用户数据整理、内容发布记录表更新、传播节点排期等日常运营支持任务"
],
"compound_skills": [
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是视觉传播设计与制作专业的大专应届生在“长安幻夜”文创IP项目实习过程中深入参与了品牌传播、内容撰写与用户运营等多项任务。面对真实品牌传播场景我认真听取导师指导主动提出改进意见逐步提升了协作能力与内容表达水平。虽然仍在学习阶段但我对品牌公关工作充满热情具备基础的视觉审美、平台理解与文案表达能力希望能在贵公司继续积累经验、发挥价值。"
}
},
{
"position": "品牌推广专员",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目 ",
"position": "品牌推广专员 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助完成项目主IP“唐小驼”及其角色矩阵的用户价值提炼工作整理文物背景与角色设定资料用于撰写品牌宣传文案与视觉传播参考\n配合团队策划并发布B站纪录片、抖音短视频等内容参与素材搜集与脚本润色协助提升内容点击率与用户互动量\n执行跨界联名产品的线上宣传任务包括微博图文排版、小程序宣传语设计、镜灵手环表盘上线预热等操作保障品牌调性一致性\n参与用户分层画像制定协助分析Z世代用户浏览行为与转化路径整理阶段性数据报告支持精准投放优化\n协助完成AR线下体验区的品牌物料制作、游客引导文案撰写与现场传播活动执行提升IP现场传播影响力与参与感。"
},
"core_skills": [
"熟悉使用 Photoshop 进行宣传海报与社交媒体图文设计,能够根据品牌风格进行基础的视觉排版与美化,提升宣传内容的视觉吸引力;",
"掌握 Excel 与 WPS 表格的使用方法,具备整理数据、制作基础数据图表与分析报告的能力,曾用于整理用户画像与浏览行为数据;",
"能够使用剪映、达芬奇、PR等视频编辑软件协助完成宣传视频的基础剪辑、转场、字幕添加与音乐同步提升内容传播效果",
"熟悉抖音、小红书、B站等主流新媒体平台的发布流程与内容机制了解热点运营规律具备话题参与与内容运营的基础意识",
"具备初步的文案撰写能力,能结合品牌调性与目标人群,撰写风格多样的推广文案,如宣传语、小程序介绍与微博推文等;",
"了解品牌联名产品推广流程,曾协助完成联名产品上线前的多平台宣传准备,包括图文素材设计、文案输出及线上预热策略执行。"
],
"compound_skills": [
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生具备良好的学习能力与跨团队沟通意识。在“长安幻夜”项目中我始终以助理角色积极参与到文创IP的推广与内容策划工作中注重细节、执行到位能根据指导快速完成任务。通过实际项目的参与我对品牌运营、新媒体内容策划及用户传播路径有了初步认识也更明确了自己的职业兴趣方向。虽然经验尚浅但我始终保持主动学习和适应变化的心态渴望在岗位中不断成长努力为团队贡献力量。"
}
},
{
"position": "ip运营",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营 ",
"position": "IP运营 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助整理敦煌元素素材资料库包括壁画图案、造型符号与故事文本配合IP内容的视觉规范制定与分类管理\n参与品牌社交媒体内容策划与发布执行如小红书、微博等平台日常图文与短视频素材整理保障传播节奏与品牌调性统一\n协助执行KOL与异业品牌的联名合作前期准备工作如联动档期确认、素材提供、权益文案初稿撰写等\n配合开展品牌用户社群的基础运营任务包括社群日常维护、用户反馈整理及文化内容分享文案的撰写\n协助组织线下品牌巡展与设计大赛活动参与资料准备、现场执行及观众互动等具体事务增强用户文化认同与品牌记忆。"
},
"core_skills": [
"熟悉使用PS、AI、剪映、达芬奇等新媒体编辑工具能够独立完成品牌图文内容的视觉排版与短视频的剪辑、音频编辑、字幕添加等基础操作具备良好的内容美感与风格统一能力",
"掌握小红书、微博、抖音等主流社交平台的内容发布规则与运营机制,能够根据不同平台用户特征制定传播节奏与内容策略,提升品牌曝光与互动效率;",
"具备IP联名企划协同能力参与品牌与KOL、异业品牌合作过程了解从前期沟通、档期协调、文案撰写到素材提交的完整流程能够胜任相关执行支持任务",
"掌握基础的 Photoshop图像处理技能可进行图片尺寸裁剪、亮度调整、简单排版与风格统一处理用于社群运营或平台内容发布场景",
"具有 内容文案撰写能力,能围绕品牌调性和用户兴趣撰写适配的文化类、产品类文案,已独立完成多条图文与社群运营稿件,风格自然,传播性好。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专毕业生在敦煌文创品牌项目实习期间深入参与了品牌IP运营的多个环节对文化IP素材管理、内容策划与社群运营有了系统性的理解和实践经验。实习过程中我始终保持细致、主动的工作态度擅长沟通协调、善于学习新工具。尽管经验尚浅但我对文创行业充满兴趣具备持续学习与快速成长的能力期待未来能在IP运营方向持续深入发展。"
}
},
{
"position": "IP运营总监助理",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营 ",
"position": "IP运营经理助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助IP运营经理整理品牌在抖音、小红书、B站等平台的内容发布计划按“敦煌文化+日常生活”主题策划内容板块包括节气系列、壁画故事、文创新品展示等累计提交选题方案15+条;\n参与短视频内容制作在剪映中完成视频剪辑、字幕添加与背景音乐设置配合完成“飞天元素开箱”“敦煌壁画变装”等热门话题视频上线实现单条视频播放量破5万\n参与“敦煌印象”社群维护工作负责更新社群话题内容、回复用户留言与问题反馈并协助开展“敦煌文化日打卡挑战”活动社群互动率提升30%\n配合整理项目各平台内容数据包括播放量、完播率、转发评论等并协助制作每周数据简报为后续选题优化与传播节奏调整提供支持\n协助完成“敦煌×某影视IP”联名产品企划案的初稿撰写工作参与概念文案拟定与素材搜集支持品牌在年轻圈层中的破圈营销实践\n整理项目资料并分析5家竞品的传播策略、联名设计与用户评价定期更新“IP运营参考资料库”为团队提供选题与内容创作参考依据。"
},
"core_skills": [
"**新媒体账号运营基础:** 熟悉新媒体平台如抖音、快手、小红书、B站等内容发布与后台操作流程理解账号定位与内容矩阵搭建逻辑。",
"**创意内容策划与执行能力:** 具备基础的创意选题挖掘能力了解短视频脚本结构掌握基础的拍摄构图与剪辑软件如剪映、Premiere基础操作使用技能。",
"**数据分析意识与应用:** 掌握基础数据分析方法,能够理解并初步解读账号数据(播放量、互动率等),运用数据辅助内容优化决策。",
"**社群互动与用户维护:** 具备基础的社群管理知识,了解用户互动技巧,能协助策划简单的线上活动以提升用户参与度。",
"**沟通协调与团队协作:** 具备良好的沟通表达能力,学习过项目协作知识,能够在指导下有效进行跨部门或团队内的信息传递与任务协作。",
"**行业信息收集与学习能力:** 掌握基础市场调研方法,具备主动关注行业动态和竞品信息的意识,并具备快速学习新知识、新工具的能力。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专在读学生曾在文创品牌运营项目中担任IP运营经理助理全面参与了内容策划、短视频制作、社群互动与数据分析等任务。实习期间我具备良好的执行力与责任感能主动完成任务并积极提出改进建议。在与内容团队的协作中我逐步锻炼了自己的沟通能力与新媒体敏感度。虽然经验尚浅但我热爱IP运营工作乐于学习新趋势新工具希望能在贵公司进一步深化专业能力成长为一名真正有影响力的运营人。"
}
},
{
"position": "文创产品设计师助理",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目 ",
"position": "文创产品设计师助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助主设计师进行“水墨苏乡”主题视觉元素的图像处理与文化语义归类,使用 Photoshop 对采集的江南水乡图像进行图层拆解与结构化归纳,提取“马头墙、小桥、窗棂、屋檐”等造型语汇,用于后续概念设计参考;\n使用 Rhino 对整套“新文房四宝”产品进行3D建模包括笔架窗棂结构、笔搁屋檐线条、镇纸小桥拱形、砚台小舟轮廓等器物确保建模结果在尺寸结构上具备装配逻辑和可加工性\n使用 KeyShot 对各款器物建模成果进行材质与光照渲染,展示“竹木/陶瓷/金属”多种材质搭配效果,用于评审会展示与用户调研材料;\n使用 AutoCAD 绘制产品结构平面图与关键尺寸标注图,重点完成笔搁凹槽尺寸、砚台出墨区斜率、镇纸重心分布等人机关键结构的二维表达;\n运用 Illustrator 参与绘制初步产品概念草图与器物功能图示,协助完成“功能+结构+文化元素”之间的逻辑表达文件,用于概念提案阶段汇报;\n使用 Figma 协助制作产品陈列组合的用户引导图,完成“组合即场景”状态下的摆放路径、限位点与安全区域说明图,提升用户理解与复现准确率。"
},
"core_skills": [
"文创产品全流程设计能力: 熟悉文创产品从概念挖掘、方案构思、设计执行到质量把控的基础流程,具备将创意转化为具体产品方案的能力。",
"专业设计软件操作: 初步掌握Photoshop, Illustrator, InDesign等软件进行图形设计、插画绘制及排版了解基础3D建模软件Rhino / SketchUp / Blender用于产品造型设计。",
"包装与印刷工艺知识: 熟悉包装设计规范及常用材料特性(如纸张、特种纸、环保材料),了解基础印刷工艺(四色印刷、专色、烫金/银、UV、击凸、压凹对设计实现的影响能配合跟进打样与生产环节。",
"市场调研与用户洞察基础: 掌握基础的定性/定量市场调研方法(如问卷设计、竞品分析、桌面研究),具备初步的消费者需求分析能力,能将调研结果辅助设计决策。",
"平面视觉传达设计: 具备品牌视觉元素应用能力,能完成海报、宣传物料、活动视觉等平面设计任务,确保设计符合品牌调性。",
"高效协作与沟通能力: 理解跨部门协作(如与产品、供应链、市场部门)的重要性,具备清晰表达设计理念、有效接收反馈并协作推进项目落地的沟通技巧。",
"快速学习与流程优化意识: 具备强烈的学习意愿和快速吸收新知识的能力,关注设计流程效率,有意识总结项目经验并乐于参与优化标准化工作方法。",
"创意发散与审美能力: 拥有活跃的创意思维和扎实的美学基础,能够持续输出符合市场趋势与文化内涵的创意设计方案。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,热爱文化与设计融合的表达方式。在“水墨苏乡”文创项目中,我系统接触了从文化图像分析、三维建模到产品展示的全流程任务,能熟练运用多款设计软件支持团队工作,并具备良好的视觉表达与图纸制作能力。实习期间,我积极配合导师完成任务,善于沟通反馈,能够快速理解设计意图并落实为具体输出。虽然目前仍处于学习阶段,但我具备较强的执行能力与持续学习意愿,期待在贵公司继续提升并贡献价值。"
}
},
{
"position": "品牌公关管培生",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营 ",
"position": "品牌公关助理 ",
"time_period": "XXXX时间 ",
"company": "某某公司 ",
"description": "协助整理敦煌文创品牌传播资料,包括壁画元素图样、传统文化故事文案、活动摄影素材等,按主题分类存档,用于宣传内容制作与媒体对接;\n参与撰写敦煌文化相关的传播内容初稿如传统节日故事、文创产品介绍文案等配合团队打磨语言风格贴合品牌调性\n支持“敦煌文化进校园”系列推广活动筹备协助准备活动所需物料、宣传折页与展示品确保布展工作有序完成\n跟进合作高校与文化平台的对接事项记录沟通要点整理合作执行清单配合品牌负责人进行进度汇总与反馈追踪\n整理用户留言与问卷反馈中涉及产品建议、文化认同等内容协助公关团队分析用户兴趣偏好为后续传播优化提供参考\n参与维护“敦煌文化月”专题活动的公关资料包制作包括PPT汇报模板、媒体发稿清单、问答话术草案等提升对外传播的专业度。"
},
"core_skills": [
"基础传播策略制定能力:能够根据客户需求或产品特性,协助制定简单的传播方案和执行计划,支持项目运营。",
"文案策划与撰写技能:擅长策划和撰写品牌传播文章、媒体稿件及创意文案,包括行业观察和热点结合内容。",
"项目执行与时间管理能力:能按时保质完成传播任务,协助控制预算和成本,确保项目及时交付。",
"行业热点分析与内容规划能力:熟悉追踪行业动态和热点,并能系统规划媒体合作、专访等内容发布。",
"团队协作与沟通能力:具备团队合作精神,支持客户对接和项目总结,有效参与小组工作。",
"创意传播策划基础:能参与创意文案的策划与执行,结合产品特性设计传播内容。",
"公关传播计划参与能力:协助制定阶段性公关计划,支持全年策略的落地执行。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专毕业生,在实习期间担任品牌公关助理,参与敦煌文创项目的内容策划、短视频剪辑与社群运营等多个环节,积累了丰富的一线实操经验。我善于学习与总结,能够结合用户反馈与数据分析,不断优化内容表现。在实际工作中具备较强的执行力与沟通协作能力,能够快速融入团队,完成多项跨平台工作任务。希望能在贵公司的新媒体或品牌运营岗位中继续深耕成长。"
}
}
]

332
resume_updates_cleaned.json Normal file
View File

@@ -0,0 +1,332 @@
[
{
"position": "露营地运营专员",
"studentInfo": {
"project_experience": {
"project_name": "轻奢露营市集玩乐活动运营项目",
"position": "露营地运营专员",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助整理《活动总述》《区域规划图》与《应急与安全方案》等前期资料,参与六大功能区规划讨论,初步熟悉露营地场景布局与功能设计逻辑;\n参与KV主视觉海报、倒计时物料与招募话术的内容校对与素材归档辅助完成社群渠道报名表的发布与数据登记\n在布置阶段协助场地标识、签到区、导视系统及打卡区域的布设工作配合布置市集摊位、帐篷区及照明装饰保证视觉统一与体验顺畅\n活动当天负责签到引导、票务核验、手环发放及礼品包分发协助游客入场分流与体验区问询保障人流动线与秩序稳定\n参与“帐篷搭建赛”“森林音乐会”“星空影院”等活动的流程协助与舞台支持协助主持人控场并负责节目表的时间提示与衔接\n协助运营组整理现场视频/照片素材,参与“云相册”上线与素材初筛,配合后期剪辑团队完成线上传播内容初步编排;\n活动结束后协助物资回收、摊位清理及满意度问卷收集并参与复盘会议内容整理输出基础版运营反馈报告。"
},
"core_skills": [
"掌握营地日常运营全流程管理包括接待流程优化、设施巡检维护及运营数据统计分析能力能独立运用Office办公软件完成经营报表制作与可视化呈现",
"具备线上线下活动落地执行经验,熟悉场景搭建、活动动线规划与现场摄影直播技术操作,能熟练操作无人机航拍、手持云台等设备完成多媒体素材采集",
"精通数字化营地管理工具应用包括OTA渠道管理后台如携程商旅、美团商家端、微信群控工具、自媒体运营平台抖音企业号、小红书专业号的数据分析与内容发布",
"具备团队管理与标准化建设能力,熟悉服务业人员排班调度、绩效考核方案设计,能通过钉钉/企业微信等协同工具实现跨部门任务分配与进度管控",
"擅长用户社群运营与私域流量转化具备客户需求分析、会员体系搭建及精准营销活动策划能力熟练使用SCRM系统进行客户分层管理与精准触达",
"掌握露营行业趋势分析与竞品调研方法论,能通过行业垂直平台(如露营天下、户外资料网)持续更新运营策略,具备基础商业计划书撰写与营收模型构建能力"
],
"compound_skills": [
"活动执行与现场管理能力: 了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力: 具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"新媒体平台运营能力: 具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"智慧文旅应用能力: 了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。",
"服务体验优化和资源协同能力: 理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"文化IP策划与品牌传播能力 理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力 了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力: 了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"产品营销基础: 具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,在露营地运营项目中担任助理角色,接触了从活动前期策划到现场执行、再到后期传播的全流程,对文旅活动的实际运作有了较为清晰的认识。在项目中,我能够主动承担任务、及时响应需求、配合团队完成细节工作。虽然经验尚浅,但我有较强的责任感与适应能力,愿意从基层做起,逐步积累经验,努力成长为一名综合型的运营人才。"
}
},
{
"position": "文创产品设计师",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目",
"position": "文创产品设计师助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助主设计师进行“水墨苏乡”主题视觉元素的图像处理与文化语义归类,使用 Photoshop 对采集的江南水乡图像进行图层拆解与结构化归纳,提取“马头墙、小桥、窗棂、屋檐”等造型语汇,用于后续概念设计参考;\n使用 Rhino 对整套“新文房四宝”产品进行3D建模包括笔架窗棂结构、笔搁屋檐线条、镇纸小桥拱形、砚台小舟轮廓等器物确保建模结果在尺寸结构上具备装配逻辑和可加工性\n使用 KeyShot 对各款器物建模成果进行材质与光照渲染,展示“竹木/陶瓷/金属”多种材质搭配效果,用于评审会展示与用户调研材料;\n使用 AutoCAD 绘制产品结构平面图与关键尺寸标注图,重点完成笔搁凹槽尺寸、砚台出墨区斜率、镇纸重心分布等人机关键结构的二维表达;\n运用 Illustrator 参与绘制初步产品概念草图与器物功能图示,协助完成“功能+结构+文化元素”之间的逻辑表达文件,用于概念提案阶段汇报;\n使用 Figma 协助制作产品陈列组合的用户引导图,完成“组合即场景”状态下的摆放路径、限位点与安全区域说明图,提升用户理解与复现准确率。"
},
"core_skills": [
"文创产品全流程设计能力: 熟悉文创产品从概念挖掘、方案构思、设计执行到质量把控的基础流程,具备将创意转化为具体产品方案的能力。",
"专业设计软件操作: 初步掌握Photoshop, Illustrator, InDesign等软件进行图形设计、插画绘制及排版了解基础3D建模软件Rhino / SketchUp / Blender用于产品造型设计。",
"包装与印刷工艺知识: 熟悉包装设计规范及常用材料特性(如纸张、特种纸、环保材料),了解基础印刷工艺(四色印刷、专色、烫金/银、UV、击凸、压凹对设计实现的影响能配合跟进打样与生产环节。",
"市场调研与用户洞察基础: 掌握基础的定性/定量市场调研方法(如问卷设计、竞品分析、桌面研究),具备初步的消费者需求分析能力,能将调研结果辅助设计决策。",
"平面视觉传达设计: 具备品牌视觉元素应用能力,能完成海报、宣传物料、活动视觉等平面设计任务,确保设计符合品牌调性。",
"高效协作与沟通能力: 理解跨部门协作(如与产品、供应链、市场部门)的重要性,具备清晰表达设计理念、有效接收反馈并协作推进项目落地的沟通技巧。",
"快速学习与流程优化意识: 具备强烈的学习意愿和快速吸收新知识的能力,关注设计流程效率,有意识总结项目经验并乐于参与优化标准化工作方法。",
"创意发散与审美能力: 拥有活跃的创意思维和扎实的美学基础,能够持续输出符合市场趋势与文化内涵的创意设计方案。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,热爱文化与设计融合的表达方式。在“水墨苏乡”文创项目中,我系统接触了从文化图像分析、三维建模到产品展示的全流程任务,能熟练运用多款设计软件支持团队工作,并具备良好的视觉表达与图纸制作能力。实习期间,我积极配合导师完成任务,善于沟通反馈,能够快速理解设计意图并落实为具体输出。虽然目前仍处于学习阶段,但我具备较强的执行能力与持续学习意愿,期待在贵公司继续提升并贡献价值。"
}
},
{
"position": "文创产品策划师",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目",
"position": "文创产品策划师助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "参与江南建筑意象调研,通过图片资料收集与用户访谈协助构建“马头墙、小桥、窗棂”等视觉元素清单,完成《文化元素映射表》初稿;\n协助产品策划师完成“新文房四宝”概念模型的语义解读工作整理各器物功能定义与使用场景文案用于支持初期设计逻辑说明\n配合工程人员完成不同材质组合样品的数据记录与对比包括竹木、陶瓷、金属等材料的热胀冷缩差异、装配公差与手感测试结果\n协助撰写《用户陈列与功能使用观察报告》参与家庭书房场景下的使用试验记录承托角度、稳定性及用户反馈形成优化建议表\n参与终端品牌包装提案的草稿整理与信息审核工作协助准备品牌叙事文本、器物摆放图示及包装结构可持续性材料说明。"
},
"core_skills": [
"能够基于品牌调性进行深度挖掘,独立创作具有文化内涵和情感共鸣的产品故事、命名方案及核心立意文案。",
"理解品牌定位的基本原则,并能将定位转化为具体的产品概念和传播语言。",
"熟悉文创产品从需求分析(含客户需求调研)、市场/品类选品研究、创意构思与方案策划、设计方向沟通指导到打样跟进的关键流程。",
"掌握 Adobe Photoshop (PS) 和 Adobe Illustrator (AI) 的基础操作(如图像处理、基础排版、查看设计稿),能够有效理解设计师工作并与设计师进行专业沟通,准确传达策划意图和反馈意见。",
"具备基础的客户访谈与信息收集技巧,能够协助进行客户公司背景及产品需求的调研分析。",
"能清晰整理需求要点并参与内部讨论或辅助准备面向客户的提案材料PPT/文档),学习将客户需求转化为具体的策划方向。",
"熟练运用 Microsoft Excel 进行市场数据(如竞品信息、用户偏好、品类趋势等)的收集、整理和基础分析(如数据透视表、图表制作)。",
"理解产品开发中与设计师、采购、生产等环节协作的重要性,具备良好的书面和口头沟通能力,确保信息准确传递。",
"了解常见文创产品的 基础生产工艺流程(如印刷、包装、常见材质特性)和 成本构成要素,能够协助跟进打样过程,理解设计落地的基本限制与可能性。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专生,在校期间积极参与实训项目,曾在“水墨苏乡”文创设计项目中担任策划师助理,协助完成从文化调研、概念提炼到用户测试等多个环节的任务。实习过程中,我具备较强的信息归纳与整理能力,善于从细节中发现优化点,并能在多方沟通中保持良好的协作态度。虽然我仍在学习阶段,但我热爱文化创意行业,具备持续学习与思考的能力,希望能在贵公司获得深入实践与成长的机会。"
}
},
{
"position": "品牌策划运营专员",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目",
"position": "品牌运营专员",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助梳理项目IP的角色人设与传播语料参与撰写“唐小驼”“镜灵”等角色的品牌故事文案用于宣传视频、短视频脚本及产品包装文案等传播渠道\n配合完成项目在B站与抖音平台的账号内容更新与粉丝互动包括视频上传、回复评论、整理热门话题标签增强用户粘性\n协助进行联名产品的线上活动策划与宣传物料制作如“胡旋舞”饮料联名的H5页面内容策划、“镜灵守护”手环表盘文案配图整理支持品牌曝光\n参与UGC共创平台“幻夜工坊”的日常用户运营任务包括用户投稿内容审核、优秀作品推送素材整理、月度创作榜单初筛等提高用户参与感\n协助整理多平台运营数据如小程序访问量、盲盒销售情况、文创IP关键词搜索热度等按周输出简易数据看板并提出初步优化建议支持团队运营决策。"
},
"core_skills": [
"基础内容运营能力: 掌握微信公众号、小程序、抖音、小红书等新媒体平台的基础运维与操作。",
"文案撰写与编辑: 初步具备良好的文字功底,能够协助撰写新闻稿件、活动简报及日常社交媒体文案。",
"宣传海报设计:熟悉使用 Photoshop制作基础画报宣传图能完成活动物料与社交平台配图初稿设计",
"活动执行支持: 了解市场推广活动执行流程,能有效协助活动落地与现场支持,并具备基础活动数据跟踪意识。",
"办公软件熟练应用: 精通Word、Excel、PPT等办公软件能高效处理文档、数据整理及制作基础演示材料。",
"项目事务跟进能力: 具备较强的责任心与细致度,能有效跟进项目执行进度,协助完成材料整理、申报及基础沟通协调工作。",
"信息收集与整理: 擅长收集行业信息、媒体动态及竞品资料,并能进行有效归纳整理。",
"团队协作与沟通: 具备良好的沟通表达能力和团队协作精神,能积极配合团队完成各项工作任务。"
],
"compound_skills": [
"新媒体平台运营能力: 具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力 理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力: 了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力 了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力: 了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力: 理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础: 具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力: 具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力: 了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生具备良好的学习能力与协作精神。在实习过程中我积极配合导师完成IP内容的撰写与平台内容运营能够胜任初步的文案编写、社群互动与活动物料整理等任务。面对多任务并行的运营节奏我能合理安排时间保证工作效率。虽然经验尚浅但我对品牌运营充满热情愿意持续学习快速适应新任务为团队创造更多价值。"
}
},
{
"position": "品牌公关",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目",
"position": "品牌公关助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助整理“唐小驼”“镜灵”等主IP角色的设定文案与视觉资料参与品牌宣传内容的校对与归档确保对外传播统一性\n参与撰写《西市密码》《唐小驼的丝路日志》等内容宣传资料简介用于B站、抖音等平台投稿与推送\n配合执行跨界联名项目如“冰峰饮料胡旋舞罐”与“小米手环镜灵守护版”的宣传活动整理新闻通稿与传播口径文案\n参与用户运营工作协助在“幻夜工坊”共创平台中整理用户投稿内容回复评论并策划互动话题提升粉丝活跃度\n跟随导师参与舆情监控实操学习关键词预警设置与科普内容生成流程辅助整理文化敏感内容的外部应对资料。"
},
"core_skills": [
"熟练使用PS、AI、Figma 等设计软件,协助完成品牌海报、社媒宣传图与联动项目周边图稿制作,具备基础视觉规范意识;",
"掌握 PPT与Word文档排版技能能够协助输出对外传播提案与活动执行方案文案与视觉排布兼顾表达与清晰度",
"熟悉B站、抖音、小红书等主流内容平台的运营逻辑了解视频发布流程与封面优化要点能配合完成内容发布与基础的粉丝互动管理",
"具备品牌文案撰写与润色能力参与IP故事设定、角色简介及传播文案编辑能初步完成短文案创作并结合平台调性优化语感",
"熟悉品牌联动项目的传播流程,了解跨品牌公关协同节奏;",
"了解社群与私域用户运营策略,包括管理平台评论区、回复用户留言、策划话题方向,具备基础运营思维;",
"能使用Excel、WPS表格工具进行用户数据整理、内容发布记录表更新、传播节点排期等日常运营支持任务"
],
"compound_skills": [
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是视觉传播设计与制作专业的大专应届生在“长安幻夜”文创IP项目实习过程中深入参与了品牌传播、内容撰写与用户运营等多项任务。面对真实品牌传播场景我认真听取导师指导主动提出改进意见逐步提升了协作能力与内容表达水平。虽然仍在学习阶段但我对品牌公关工作充满热情具备基础的视觉审美、平台理解与文案表达能力希望能在贵公司继续积累经验、发挥价值。"
}
},
{
"position": "品牌推广专员",
"studentInfo": {
"project_experience": {
"project_name": "“长安幻夜”文创IP运营与品牌建设项目",
"position": "品牌推广专员",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助完成项目主IP“唐小驼”及其角色矩阵的用户价值提炼工作整理文物背景与角色设定资料用于撰写品牌宣传文案与视觉传播参考\n配合团队策划并发布B站纪录片、抖音短视频等内容参与素材搜集与脚本润色协助提升内容点击率与用户互动量\n执行跨界联名产品的线上宣传任务包括微博图文排版、小程序宣传语设计、镜灵手环表盘上线预热等操作保障品牌调性一致性\n参与用户分层画像制定协助分析Z世代用户浏览行为与转化路径整理阶段性数据报告支持精准投放优化\n协助完成AR线下体验区的品牌物料制作、游客引导文案撰写与现场传播活动执行提升IP现场传播影响力与参与感。"
},
"core_skills": [
"熟悉使用 Photoshop 进行宣传海报与社交媒体图文设计,能够根据品牌风格进行基础的视觉排版与美化,提升宣传内容的视觉吸引力;",
"掌握 Excel 与 WPS 表格的使用方法,具备整理数据、制作基础数据图表与分析报告的能力,曾用于整理用户画像与浏览行为数据;",
"能够使用剪映、达芬奇、PR等视频编辑软件协助完成宣传视频的基础剪辑、转场、字幕添加与音乐同步提升内容传播效果",
"熟悉抖音、小红书、B站等主流新媒体平台的发布流程与内容机制了解热点运营规律具备话题参与与内容运营的基础意识",
"具备初步的文案撰写能力,能结合品牌调性与目标人群,撰写风格多样的推广文案,如宣传语、小程序介绍与微博推文等;",
"了解品牌联名产品推广流程,曾协助完成联名产品上线前的多平台宣传准备,包括图文素材设计、文案输出及线上预热策略执行。"
],
"compound_skills": [
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生具备良好的学习能力与跨团队沟通意识。在“长安幻夜”项目中我始终以助理角色积极参与到文创IP的推广与内容策划工作中注重细节、执行到位能根据指导快速完成任务。通过实际项目的参与我对品牌运营、新媒体内容策划及用户传播路径有了初步认识也更明确了自己的职业兴趣方向。虽然经验尚浅但我始终保持主动学习和适应变化的心态渴望在岗位中不断成长努力为团队贡献力量。"
}
},
{
"position": "ip运营",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营",
"position": "IP运营",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助整理敦煌元素素材资料库包括壁画图案、造型符号与故事文本配合IP内容的视觉规范制定与分类管理\n参与品牌社交媒体内容策划与发布执行如小红书、微博等平台日常图文与短视频素材整理保障传播节奏与品牌调性统一\n协助执行KOL与异业品牌的联名合作前期准备工作如联动档期确认、素材提供、权益文案初稿撰写等\n配合开展品牌用户社群的基础运营任务包括社群日常维护、用户反馈整理及文化内容分享文案的撰写\n协助组织线下品牌巡展与设计大赛活动参与资料准备、现场执行及观众互动等具体事务增强用户文化认同与品牌记忆。"
},
"core_skills": [
"熟悉使用PS、AI、剪映、达芬奇等新媒体编辑工具能够独立完成品牌图文内容的视觉排版与短视频的剪辑、音频编辑、字幕添加等基础操作具备良好的内容美感与风格统一能力",
"掌握小红书、微博、抖音等主流社交平台的内容发布规则与运营机制,能够根据不同平台用户特征制定传播节奏与内容策略,提升品牌曝光与互动效率;",
"具备IP联名企划协同能力参与品牌与KOL、异业品牌合作过程了解从前期沟通、档期协调、文案撰写到素材提交的完整流程能够胜任相关执行支持任务",
"掌握基础的 Photoshop图像处理技能可进行图片尺寸裁剪、亮度调整、简单排版与风格统一处理用于社群运营或平台内容发布场景",
"具有 内容文案撰写能力,能围绕品牌调性和用户兴趣撰写适配的文化类、产品类文案,已独立完成多条图文与社群运营稿件,风格自然,传播性好。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专毕业生在敦煌文创品牌项目实习期间深入参与了品牌IP运营的多个环节对文化IP素材管理、内容策划与社群运营有了系统性的理解和实践经验。实习过程中我始终保持细致、主动的工作态度擅长沟通协调、善于学习新工具。尽管经验尚浅但我对文创行业充满兴趣具备持续学习与快速成长的能力期待未来能在IP运营方向持续深入发展。"
}
},
{
"position": "IP运营总监助理",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营",
"position": "IP运营经理助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助IP运营经理整理品牌在抖音、小红书、B站等平台的内容发布计划按“敦煌文化+日常生活”主题策划内容板块包括节气系列、壁画故事、文创新品展示等累计提交选题方案15+条;\n参与短视频内容制作在剪映中完成视频剪辑、字幕添加与背景音乐设置配合完成“飞天元素开箱”“敦煌壁画变装”等热门话题视频上线实现单条视频播放量破5万\n参与“敦煌印象”社群维护工作负责更新社群话题内容、回复用户留言与问题反馈并协助开展“敦煌文化日打卡挑战”活动社群互动率提升30%\n配合整理项目各平台内容数据包括播放量、完播率、转发评论等并协助制作每周数据简报为后续选题优化与传播节奏调整提供支持\n协助完成“敦煌×某影视IP”联名产品企划案的初稿撰写工作参与概念文案拟定与素材搜集支持品牌在年轻圈层中的破圈营销实践\n整理项目资料并分析5家竞品的传播策略、联名设计与用户评价定期更新“IP运营参考资料库”为团队提供选题与内容创作参考依据。"
},
"core_skills": [
"**新媒体账号运营基础:** 熟悉新媒体平台如抖音、快手、小红书、B站等内容发布与后台操作流程理解账号定位与内容矩阵搭建逻辑。",
"**创意内容策划与执行能力:** 具备基础的创意选题挖掘能力了解短视频脚本结构掌握基础的拍摄构图与剪辑软件如剪映、Premiere基础操作使用技能。",
"**数据分析意识与应用:** 掌握基础数据分析方法,能够理解并初步解读账号数据(播放量、互动率等),运用数据辅助内容优化决策。",
"**社群互动与用户维护:** 具备基础的社群管理知识,了解用户互动技巧,能协助策划简单的线上活动以提升用户参与度。",
"**沟通协调与团队协作:** 具备良好的沟通表达能力,学习过项目协作知识,能够在指导下有效进行跨部门或团队内的信息传递与任务协作。",
"**行业信息收集与学习能力:** 掌握基础市场调研方法,具备主动关注行业动态和竞品信息的意识,并具备快速学习新知识、新工具的能力。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专在读学生曾在文创品牌运营项目中担任IP运营经理助理全面参与了内容策划、短视频制作、社群互动与数据分析等任务。实习期间我具备良好的执行力与责任感能主动完成任务并积极提出改进建议。在与内容团队的协作中我逐步锻炼了自己的沟通能力与新媒体敏感度。虽然经验尚浅但我热爱IP运营工作乐于学习新趋势新工具希望能在贵公司进一步深化专业能力成长为一名真正有影响力的运营人。"
}
},
{
"position": "文创产品设计师助理",
"studentInfo": {
"project_experience": {
"project_name": "“水墨苏乡”文化创意产品设计与量产落地项目",
"position": "文创产品设计师助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助主设计师进行“水墨苏乡”主题视觉元素的图像处理与文化语义归类,使用 Photoshop 对采集的江南水乡图像进行图层拆解与结构化归纳,提取“马头墙、小桥、窗棂、屋檐”等造型语汇,用于后续概念设计参考;\n使用 Rhino 对整套“新文房四宝”产品进行3D建模包括笔架窗棂结构、笔搁屋檐线条、镇纸小桥拱形、砚台小舟轮廓等器物确保建模结果在尺寸结构上具备装配逻辑和可加工性\n使用 KeyShot 对各款器物建模成果进行材质与光照渲染,展示“竹木/陶瓷/金属”多种材质搭配效果,用于评审会展示与用户调研材料;\n使用 AutoCAD 绘制产品结构平面图与关键尺寸标注图,重点完成笔搁凹槽尺寸、砚台出墨区斜率、镇纸重心分布等人机关键结构的二维表达;\n运用 Illustrator 参与绘制初步产品概念草图与器物功能图示,协助完成“功能+结构+文化元素”之间的逻辑表达文件,用于概念提案阶段汇报;\n使用 Figma 协助制作产品陈列组合的用户引导图,完成“组合即场景”状态下的摆放路径、限位点与安全区域说明图,提升用户理解与复现准确率。"
},
"core_skills": [
"文创产品全流程设计能力: 熟悉文创产品从概念挖掘、方案构思、设计执行到质量把控的基础流程,具备将创意转化为具体产品方案的能力。",
"专业设计软件操作: 初步掌握Photoshop, Illustrator, InDesign等软件进行图形设计、插画绘制及排版了解基础3D建模软件Rhino / SketchUp / Blender用于产品造型设计。",
"包装与印刷工艺知识: 熟悉包装设计规范及常用材料特性(如纸张、特种纸、环保材料),了解基础印刷工艺(四色印刷、专色、烫金/银、UV、击凸、压凹对设计实现的影响能配合跟进打样与生产环节。",
"市场调研与用户洞察基础: 掌握基础的定性/定量市场调研方法(如问卷设计、竞品分析、桌面研究),具备初步的消费者需求分析能力,能将调研结果辅助设计决策。",
"平面视觉传达设计: 具备品牌视觉元素应用能力,能完成海报、宣传物料、活动视觉等平面设计任务,确保设计符合品牌调性。",
"高效协作与沟通能力: 理解跨部门协作(如与产品、供应链、市场部门)的重要性,具备清晰表达设计理念、有效接收反馈并协作推进项目落地的沟通技巧。",
"快速学习与流程优化意识: 具备强烈的学习意愿和快速吸收新知识的能力,关注设计流程效率,有意识总结项目经验并乐于参与优化标准化工作方法。",
"创意发散与审美能力: 拥有活跃的创意思维和扎实的美学基础,能够持续输出符合市场趋势与文化内涵的创意设计方案。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名刚完成实习的大专毕业生,热爱文化与设计融合的表达方式。在“水墨苏乡”文创项目中,我系统接触了从文化图像分析、三维建模到产品展示的全流程任务,能熟练运用多款设计软件支持团队工作,并具备良好的视觉表达与图纸制作能力。实习期间,我积极配合导师完成任务,善于沟通反馈,能够快速理解设计意图并落实为具体输出。虽然目前仍处于学习阶段,但我具备较强的执行能力与持续学习意愿,期待在贵公司继续提升并贡献价值。"
}
},
{
"position": "品牌公关管培生",
"studentInfo": {
"project_experience": {
"project_name": "敦煌文创品牌策划与IP运营",
"position": "品牌公关助理",
"time_period": "XXXX时间",
"company": "某某公司",
"description": "协助整理敦煌文创品牌传播资料,包括壁画元素图样、传统文化故事文案、活动摄影素材等,按主题分类存档,用于宣传内容制作与媒体对接;\n参与撰写敦煌文化相关的传播内容初稿如传统节日故事、文创产品介绍文案等配合团队打磨语言风格贴合品牌调性\n支持“敦煌文化进校园”系列推广活动筹备协助准备活动所需物料、宣传折页与展示品确保布展工作有序完成\n跟进合作高校与文化平台的对接事项记录沟通要点整理合作执行清单配合品牌负责人进行进度汇总与反馈追踪\n整理用户留言与问卷反馈中涉及产品建议、文化认同等内容协助公关团队分析用户兴趣偏好为后续传播优化提供参考\n参与维护“敦煌文化月”专题活动的公关资料包制作包括PPT汇报模板、媒体发稿清单、问答话术草案等提升对外传播的专业度。"
},
"core_skills": [
"基础传播策略制定能力:能够根据客户需求或产品特性,协助制定简单的传播方案和执行计划,支持项目运营。",
"文案策划与撰写技能:擅长策划和撰写品牌传播文章、媒体稿件及创意文案,包括行业观察和热点结合内容。",
"项目执行与时间管理能力:能按时保质完成传播任务,协助控制预算和成本,确保项目及时交付。",
"行业热点分析与内容规划能力:熟悉追踪行业动态和热点,并能系统规划媒体合作、专访等内容发布。",
"团队协作与沟通能力:具备团队合作精神,支持客户对接和项目总结,有效参与小组工作。",
"创意传播策划基础:能参与创意文案的策划与执行,结合产品特性设计传播内容。",
"公关传播计划参与能力:协助制定阶段性公关计划,支持全年策略的落地执行。"
],
"compound_skills": [
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。"
],
"personal_summary": "我是一名大专毕业生,在实习期间担任品牌公关助理,参与敦煌文创项目的内容策划、短视频剪辑与社群运营等多个环节,积累了丰富的一线实操经验。我善于学习与总结,能够结合用户反馈与数据分析,不断优化内容表现。在实际工作中具备较强的执行力与沟通协作能力,能够快速融入团队,完成多项跨平台工作任务。希望能在贵公司的新媒体或品牌运营岗位中继续深耕成长。"
}
}
]

View File

@@ -0,0 +1,81 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
from datetime import datetime
# 定义等级排序
LEVEL_ORDER = {
'普通岗': 1,
'技术骨干岗': 2,
'储备干部岗': 3
}
def sort_positions(positions_str):
"""对适用岗位数组进行排序"""
# 匹配所有的岗位对象
pattern = r"\{\s*level:\s*['\"]([^'\"]+)['\"]\s*,\s*position:\s*['\"]([^'\"]+)['\"]\s*\}"
positions = []
for match in re.finditer(pattern, positions_str):
level = match.group(1)
position = match.group(2)
positions.append({'level': level, 'position': position})
# 按等级排序
positions.sort(key=lambda x: LEVEL_ORDER.get(x['level'], 999))
# 生成排序后的字符串
sorted_positions = [f"{{ level: '{p['level']}', position: '{p['position']}' }}" for p in positions]
return ', '.join(sorted_positions)
def update_project_library_mock():
file_path = 'src/mocks/projectLibraryMock.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_sorted'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 记录处理的项目数
count = 0
# 定义替换函数
def replace_positions(match):
nonlocal count
positions_str = match.group(1)
sorted_str = sort_positions(positions_str)
count += 1
return f"applicablePositions: [{sorted_str}]"
# 替换所有的applicablePositions
updated_content = re.sub(
r'applicablePositions:\s*\[(.*?)\]',
replace_positions,
content,
flags=re.DOTALL
)
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f"projectLibraryMock.js 更新完成,共排序了 {count} 个项目的适用岗位")
def main():
print("=" * 50)
print("开始对项目库中的适用岗位进行排序")
print("排序规则:普通岗 -> 技术骨干岗 -> 储备干部岗")
print("=" * 50)
update_project_library_mock()
print("\n" + "=" * 50)
print("排序完成!")
print("=" * 50)
if __name__ == "__main__":
main()

View File

@@ -47,7 +47,7 @@
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0;
margin: 10px 0;
position: relative;
.divider-line {
@@ -67,8 +67,46 @@
background-color: #fff;
position: relative;
z-index: 1;
display: flex;
align-items: center;
gap: 4px;
}
}
/* 可点击的分割线样式 */
.course-divider.clickable {
cursor: pointer;
transition: all 0.3s ease;
}
.course-divider.clickable:hover .divider-text {
color: #4080ff;
}
.course-divider.clickable:hover .divider-line {
border-color: #4080ff;
}
/* 分类容器缓动效果 */
.course-category-wrapper {
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: top;
}
.course-category-wrapper.expanded {
max-height: 2000px;
opacity: 1;
transform: scaleY(1);
margin-bottom: 0;
}
.course-category-wrapper.collapsed {
max-height: 0;
opacity: 0;
transform: scaleY(0);
margin-bottom: 0;
}
/* 自定义折叠面板元素 */
.course-list-item {

View File

@@ -1,5 +1,6 @@
import { useState, useEffect } from "react";
import { Collapse, Timeline, Spin } from "@arco-design/web-react";
import { IconDown, IconRight } from "@arco-design/web-react/icon";
import { getCourseLiveList } from "@/services/courseLive";
import "./index.css";
@@ -11,6 +12,12 @@ const CourseList = ({ className = "", onCourseClick }) => {
const [verticalCourseList, setVerticalCourseList] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedCourseId, setSelectedCourseId] = useState(null);
// 控制各分类的展开/收缩状态,默认全部展开
const [categoryExpanded, setCategoryExpanded] = useState({
'compound': true, // 复合能力课
'vertical': true // 垂直提升课
});
useEffect(() => {
fetchCourseList();
@@ -133,15 +140,21 @@ const CourseList = ({ className = "", onCourseClick }) => {
>
{/* 复合能力课分割线 */}
{compoundCourseList.length > 0 && (
<div className="course-divider">
<div
className="course-divider clickable"
onClick={() => setCategoryExpanded(prev => ({ ...prev, compound: !prev.compound }))}
>
<span className="divider-line"></span>
<span className="divider-text">复合能力课</span>
<span className="divider-text">
复合能力课
</span>
<span className="divider-line"></span>
</div>
)}
{/* 复合能力课部分 */}
{compoundCourseList.map((unit, index) => (
<div className={`course-category-wrapper ${!categoryExpanded.compound ? 'collapsed' : 'expanded'}`}>
{compoundCourseList.map((unit, index) => (
<CollapseItem
key={unit.unitId}
header={unit.unitName}
@@ -183,18 +196,25 @@ const CourseList = ({ className = "", onCourseClick }) => {
</Timeline>
</CollapseItem>
))}
</div>
{/* 垂直能力课分割线 */}
{verticalCourseList.length > 0 && (
<div className="course-divider">
<div
className="course-divider clickable"
onClick={() => setCategoryExpanded(prev => ({ ...prev, vertical: !prev.vertical }))}
>
<span className="divider-line"></span>
<span className="divider-text">垂直能力课</span>
<span className="divider-text">
垂直能力课
</span>
<span className="divider-line"></span>
</div>
)}
{/* 垂直能力课部分 */}
{verticalCourseList.map((unit, index) => {
<div className={`course-category-wrapper ${!categoryExpanded.vertical ? 'collapsed' : 'expanded'}`}>
{verticalCourseList.map((unit, index) => {
// 检查单元是否包含可试看课程
const hasPreviewCourse = unit.courses.some(course => course.canPreview);
@@ -274,6 +294,7 @@ const CourseList = ({ className = "", onCourseClick }) => {
</CollapseItem>
);
})}
</div>
</Collapse>
</div>
</div>

View File

@@ -197,7 +197,7 @@ export default ({ className = "", isLock = false, selectedCourse, teacherData, u
{displayCourse?.current && <div className="living-icon" />}
</div>
<span className="teacher-name">{currentTeacher?.name || ''}老师</span>
<span className="teacher-tag">{displayCourse?.unitName || unitName}</span>
<span className="teacher-tag">{displayCourse?.courseName || courseName || ''}</span>
<div className="living-data">
<div className="living-data-item">
<span>开始</span>

View File

@@ -43,6 +43,74 @@
width: 100%;
}
/*/* 分割线样式 */
.course-list-wrapper .course-list-content .course-list .course-divider {
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
margin: 10px 0;
position: relative;
}
.course-list-wrapper .course-list-content .course-list .course-divider .divider-line {
flex: 1;
height: 1px;
background: linear-gradient(90deg, transparent, #e5e6eb 20%, #e5e6eb 80%, transparent);
border-style: dashed;
border-width: 1px 0 0 0;
border-color: #e5e6eb;
}
.course-list-wrapper .course-list-content .course-list .course-divider .divider-text {
padding: 0 16px;
font-size: 14px;
font-weight: 500;
color: #86909c;
background-color: #fff;
position: relative;
z-index: 1;
display: flex;
align-items: center;
gap: 4px;
}
/* 可点击的分割线样式 */
.course-list-wrapper .course-list-content .course-list .course-divider.clickable {
cursor: pointer;
transition: all 0.3s ease;
}
.course-list-wrapper .course-list-content .course-list .course-divider.clickable:hover .divider-text {
color: #4080ff;
}
.course-list-wrapper .course-list-content .course-list .course-divider.clickable:hover .divider-line {
border-color: #4080ff;
}
/* 分类容器缓动效果 */
.course-list-wrapper .course-list-content .course-list .course-category-wrapper {
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: top;
}
.course-list-wrapper .course-list-content .course-list .course-category-wrapper.expanded {
max-height: 2000px;
opacity: 1;
transform: scaleY(1);
margin-bottom: 0;
}
.course-list-wrapper .course-list-content .course-list .course-category-wrapper.collapsed {
max-height: 0;
opacity: 0;
transform: scaleY(0);
margin-bottom: 0;
}
/* 自定义折叠面板元素 */
.course-list-wrapper .course-list-content .course-list .course-list-item {
width: 272px;

View File

@@ -1,14 +1,10 @@
import { useState, useEffect } from "react";
import { Collapse, Timeline, Spin } from "@arco-design/web-react";
import { IconDown, IconRight } from "@arco-design/web-react/icon";
import { getPublicCourseLiveList } from "@/services/courseLive";
import "./index.css";
// 公共课单元海报数据
const unitPosters = {
"终生学习系统": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6sRee.jpg", // AI课 -> sRee
"企业高管公开课": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6CiPN.jpg", // 公共课 -> CiPN
"营销能力课": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6zwRv.jpg" // 营销课 -> zwRv
};
// 单元海报数据将从服务器返回的数据中获取
const TimelineItem = Timeline.Item;
const CollapseItem = Collapse.Item;
@@ -17,6 +13,13 @@ const PublicCourseList = ({ className = "", onCourseClick }) => {
const [courseLiveList, setCourseLiveList] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedCourseId, setSelectedCourseId] = useState(null);
// 控制各分类的展开/收缩状态,默认全部展开
const [categoryExpanded, setCategoryExpanded] = useState({
'ai': true, // 终生学习系统
'public': true, // 企业高管公开课
'marketing': true // 营销能力课
});
useEffect(() => {
fetchCourseList();
@@ -95,54 +98,143 @@ const PublicCourseList = ({ className = "", onCourseClick }) => {
expandIconPosition="right"
defaultActiveKey={[]}
>
{courseLiveList.map((unit, index) => (
<CollapseItem
key={unit.unitId}
header={unit.unitName}
name={String(index + 1)}
className="course-list-item"
>
<Timeline>
{unit.courses.map((course) => (
<TimelineItem
key={course.courseId}
dot={getDotIcon(course)}
lineType="dashed"
{courseLiveList.map((unit, index) => {
// 判断当前单元属于哪个分类
const isAIUnit = [
"AI 入门与工具环境",
"RAG 与检索增强",
"AI 自动化与任务编排",
"AI 项目开发与前端交互",
"AI 大模型与核心原理",
"AI 行业应用与综合实战"
].includes(unit.unitName);
const isPublicUnit = [
"沟通与协作能力",
"问题解决与思维能力",
"职场基础与个人发展",
"职业发展与管理技能"
].includes(unit.unitName);
const isMarketingUnit = [
"必备营销技能",
"自我营销课"
].includes(unit.unitName);
// 判断是否需要显示分割线
// 终生学习系统第一个AI单元前显示
const showAIDivider = isAIUnit && index === 0;
// 企业高管公开课:第一个企业高管单元前显示(前一个不是企业高管单元)
const showPublicDivider = isPublicUnit && index > 0 &&
!["沟通与协作能力", "问题解决与思维能力", "职场基础与个人发展", "职业发展与管理技能"]
.includes(courseLiveList[index - 1]?.unitName);
// 营销能力课:第一个营销单元前显示(前一个不是营销单元)
const showMarketingDivider = isMarketingUnit && index > 0 &&
!["必备营销技能", "自我营销课"]
.includes(courseLiveList[index - 1]?.unitName);
return (
<div key={unit.unitId}>
{/* 终生学习系统分割线 */}
{showAIDivider && (
<div
className="course-divider clickable"
onClick={() => setCategoryExpanded(prev => ({ ...prev, ai: !prev.ai }))}
>
<div
className={`time-line-item ${getCourseStatus(course)} ${selectedCourseId === course.courseId ? 'selected' : ''}`}
onClick={() => {
setSelectedCourseId(course.courseId);
// 调试日志
console.log('点击课程单元:', unit.unitName);
console.log('匹配的海报URL:', unitPosters[unit.unitName]);
onCourseClick && onCourseClick({
...course,
unitName: unit.unitName,
unitPoster: unitPosters[unit.unitName] || unitPosters["终生学习系统"] || "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6sRee.jpg"
});
}}
style={{ cursor: 'pointer' }}
>
<p style={{
overflow: 'visible',
textOverflow: 'unset',
whiteSpace: 'normal',
wordBreak: 'break-word'
}}>
{course.courseName}
</p>
<div className="time-line-item-info">
<span>{course.teacherName}</span>
<span className="course-date">{course.date}</span>
</div>
</div>
</TimelineItem>
))}
</Timeline>
</CollapseItem>
))}
<span className="divider-line"></span>
<span className="divider-text">
终生学习系统
</span>
<span className="divider-line"></span>
</div>
)}
{/* 企业高管公开课分割线 */}
{showPublicDivider && (
<div
className="course-divider clickable"
onClick={() => setCategoryExpanded(prev => ({ ...prev, public: !prev.public }))}
>
<span className="divider-line"></span>
<span className="divider-text">
企业高管公开课
</span>
<span className="divider-line"></span>
</div>
)}
{/* 营销能力课分割线 */}
{showMarketingDivider && (
<div
className="course-divider clickable"
onClick={() => setCategoryExpanded(prev => ({ ...prev, marketing: !prev.marketing }))}
>
<span className="divider-line"></span>
<span className="divider-text">
营销能力课
</span>
<span className="divider-line"></span>
</div>
)}
{/* 根据分类的展开状态决定是否显示单元 */}
<div
className={`course-category-wrapper ${
(isAIUnit && !categoryExpanded.ai) ||
(isPublicUnit && !categoryExpanded.public) ||
(isMarketingUnit && !categoryExpanded.marketing)
? 'collapsed' : 'expanded'
}`}
>
<CollapseItem
key={unit.unitId}
header={unit.unitName}
name={String(index + 1)}
className="course-list-item"
>
<Timeline>
{unit.courses.map((course) => (
<TimelineItem
key={course.courseId}
dot={getDotIcon(course)}
lineType="dashed"
>
<div
className={`time-line-item ${getCourseStatus(course)} ${selectedCourseId === course.courseId ? 'selected' : ''}`}
onClick={() => {
setSelectedCourseId(course.courseId);
onCourseClick && onCourseClick({
...course,
unitName: unit.unitName,
unitPoster: unit.unitPoster || "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6sRee.jpg"
});
}}
style={{ cursor: 'pointer' }}
>
<p style={{
overflow: 'visible',
textOverflow: 'unset',
whiteSpace: 'normal',
wordBreak: 'break-word'
}}>
{course.courseName}
</p>
<div className="time-line-item-info">
<span>{course.teacherName}</span>
<span className="course-date">{course.date}</span>
</div>
</div>
</TimelineItem>
))}
</Timeline>
</CollapseItem>
</div>
</div>
);
})}
</Collapse>
</div>
</div>

View File

@@ -648,7 +648,7 @@
"任职要求": "1.具备丰富的酒店/民宿客房行业管理经验客房主管履历2年及以上有高端酒店/民宿领域领域工作经验者可优先录用。\n2.具备良好的沟通能力和团队管理能。\n3.对工作细致细心有较强的责任心和服务意识。\n4.能有效处理突发情况,保证客房服务的连续性。\n5.与其他部门协同工作,完成民宿接待工作",
"公司介绍": "米拉夏朵成立于2018年以“缔造城市微度假理想生活”为使命深耕长三角精品度假产业。现运营上海迪士尼/海昌海洋公园周边的五大主题民宿筹建中的安吉竹海度假村即将成为浙北文旅新地标。旗下项目连续斩获「中国十大必睡星宿」「上海市五星级乡村民宿」「长三角精品民宿TOP10」等20+行业殊荣。\n\n【品牌实力】\n√ 精准布局流量入口依托上海两大千万级流量景区打造“15分钟度假生活圈”\n√ 沉浸式场景设计每座建筑融合在地文化与童话美学客房平均溢价率超行业35%\n\n【团队基因】\n90后海归主理人领衔集结资深酒店管理精英、新锐空间设计师、文旅策划专家组成的跨领域战队。扁平化管理模式下每位成员都是价值创造者。\n\n【加入我们你将获得】\n• 参与长三角文旅产业升级的黄金机遇,接触民宿与度假村双赛道运营;\n• 合伙人孵化计划,优秀者可获门店股权激励及项目分红;\n• 年度带薪度假体验特权5天+专属福利包);\n• 迪士尼门票、安吉茶园采茶体验等员工权益;\n• 定期行业培训与跨界交流机会(如设计、文旅、电商模块)。\n\n【寻找这样的你】\n如果你不仅是执行者更是创造者既能用数据驱动运营又能用情怀打磨体验渴望在诗与远方中实现商业价值欢迎加入米拉夏朵我们将为你提供百万级项目操盘机会与行业顶配资源共同书写中国度假产业的新篇章。\n\n—— 让每个日常,都有抵达远方的可能 ——",
"岗位标签": "实习",
"岗位相关标签": "专业相关岗位",
"岗位相关标签": "专业相关岗位",
"福利标签": [
"五险一金",
"带薪年假",

View File

@@ -660,7 +660,7 @@
"任职要求": "1. 具备丰富的酒店/民宿客房行业管理经验客房主管履历2年及以上有高端酒店/民宿领域领域工作经验者可优先录用。\n2. 具备良好的沟通能力和团队管理能。\n3. 对工作细致细心有较强的责任心和服务意识。\n4. 能有效处理突发情况,保证客房服务的连续性。\n5. 与其他部门协同工作,完成民宿接待工作。",
"公司介绍": "米拉夏朵成立于2018年以“缔造城市微度假理想生活”为使命深耕长三角精品度假产业。现运营上海迪士尼/海昌海洋公园周边的五大主题民宿筹建中的安吉竹海度假村即将成为浙北文旅新地标。旗下项目连续斩获「中国十大必睡星宿」「上海市五星级乡村民宿」「长三角精品民宿TOP10」等20+行业殊荣。\n\n【品牌实力】\n√ 精准布局流量入口依托上海两大千万级流量景区打造“15分钟度假生活圈”\n√ 沉浸式场景设计每座建筑融合在地文化与童话美学客房平均溢价率超行业35%\n\n【团队基因】\n90后海归主理人领衔集结资深酒店管理精英、新锐空间设计师、文旅策划专家组成的跨领域战队。扁平化管理模式下每位成员都是价值创造者。\n\n【加入我们你将获得】\n• 参与长三角文旅产业升级的黄金机遇,接触民宿与度假村双赛道运营;\n• 合伙人孵化计划,优秀者可获门店股权激励及项目分红;\n• 年度带薪度假体验特权5天+专属福利包);\n• 迪士尼门票、安吉茶园采茶体验等员工权益;\n• 定期行业培训与跨界交流机会(如设计、文旅、电商模块)。\n\n【寻找这样的你】\n如果你不仅是执行者更是创造者既能用数据驱动运营又能用情怀打磨体验渴望在诗与远方中实现商业价值欢迎加入米拉夏朵我们将为你提供百万级项目操盘机会与行业顶配资源共同书写中国度假产业的新篇章。\n\n—— 让每个日常,都有抵达远方的可能 ——",
"岗位标签": "实习",
"岗位相关标签": "专业相关岗位",
"岗位相关标签": "专业相关岗位",
"福利标签": [
"五险一金",
"带薪年假",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,266 @@
{
"code": 200,
"message": "操作成功",
"data": {
"high": {
"name": "储备干部岗",
"list": [
{
"record_id": "recuzDi0lXYCA0",
"position_name": "民宿管家",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im65lI.jpeg"
},
{
"record_id": "recuzDi0lXza7O",
"position_name": "民宿客房管家",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imoVv6.jpeg"
},
{
"record_id": "recuzVoIzaXUqc",
"position_name": "民宿运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imlAwW.jpeg"
},
{
"record_id": "recuzDi0lXJQ5u",
"position_name": "酒店餐饮主管",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imTKuC.jpeg"
},
{
"record_id": "recuzVoIzaMhKk",
"position_name": "酒店运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imUf1N.jpeg"
},
{
"record_id": "recuzVoIzakyIc",
"position_name": "客房经理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPGOiZ8J13S.jpeg"
},
{
"record_id": "recuzVoIzaZMmW",
"position_name": "酒店大堂副理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPGOiZ85boC.jpeg"
},
{
"record_id": "recuzVoIza7JA5",
"position_name": "餐厅运营经理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imDPFP.jpeg"
},
{
"record_id": "recuzDi0lXi4bv",
"position_name": "品牌公关",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im9Sra.jpeg"
},
{
"record_id": "recuzDi0lXkX5u",
"position_name": "艺人经纪人",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuQIuAUMPgcx.jpeg"
},
{
"record_id": "recuzDi0lXn5dv",
"position_name": "演出执行经理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuQIuHUH07Ia.jpeg"
}
]
},
"middle": {
"name": "技术骨干岗",
"list": [
{
"record_id": "recuFZJhP8rNao",
"position_name": "赛事经纪",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPGOiZ8uICB.jpeg"
},
{
"record_id": "recuzDi0lXtaB3",
"position_name": "景区运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPGOiZ80asf.jpeg"
},
{
"record_id": "recuIZG3KIM5C5",
"position_name": "活动策划师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imXS9c.jpeg"
},
{
"record_id": "recuIZG7I3fy6w",
"position_name": "活动执行",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imyYok.jpeg"
},
{
"record_id": "recuzDi0lXAT6U",
"position_name": "场馆运营人员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imt2TC.jpeg"
},
{
"record_id": "recuRgmhftZcHa",
"position_name": "露营地运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imRFOD.jpeg"
},
{
"record_id": "recuFZJhP8hm76",
"position_name": "宠物店店长",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imzXzv.jpeg"
},
{
"record_id": "recuzJ1ZVuwnPv",
"position_name": "宠物营养师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imdfAp.jpeg"
},
{
"record_id": "recuIZKwO9ixGh",
"position_name": "SEO专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2iml2IU.jpeg"
},
{
"record_id": "recuzDi0lX7glV",
"position_name": "SEM专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imnfVv.jpeg"
},
{
"record_id": "recuzDi0lXyBDV",
"position_name": "文创产品设计师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imizTB.jpeg"
},
{
"record_id": "recuRgmlK4Pj7L",
"position_name": "文创产品策划师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imjSEA.jpeg"
},
{
"record_id": "recuFZJhP8hP1X",
"position_name": "会展策划师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imOdyu.jpeg"
},
{
"record_id": "recuzVoIzaxqAd",
"position_name": "会展营销",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imYg13.jpeg"
},
{
"record_id": "recuFZJhP8yJi4",
"position_name": "漫展策划师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im9Ecg.jpeg"
},
{
"record_id": "recuRgmO7ra6GB",
"position_name": "品牌策划运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imPi00.jpeg"
},
{
"record_id": "recuzDi0lXQCWG",
"position_name": "品牌推广专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imTJYD.jpeg"
},
{
"record_id": "recuzDi0lXedcK",
"position_name": "社群运营",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imvheR.jpeg"
},
{
"record_id": "recuzVoIzaHWP9",
"position_name": "ip运营",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imDp1Z.jpeg"
},
{
"record_id": "recuFc94HfoZHy",
"position_name": "赛事礼仪",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im6YlW.jpeg"
},
{
"record_id": "recuFZJ4YLutP7",
"position_name": "赛事编辑",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im1JEV.jpeg"
},
{
"record_id": "recuzDi0lXh3P4",
"position_name": "新媒体运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imbZSu.jpeg"
},
{
"record_id": "recuFZJhP80n5d",
"position_name": "二次元周边店店长",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imWiVD.jpeg"
},
{
"record_id": "recuzDi0lXzexM",
"position_name": "旅游规划师",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2im0xT7.jpeg"
},
{
"record_id": "recuzDi0lXXv4U",
"position_name": "旅游计调专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imqBs9.jpeg"
},
{
"record_id": "recuTPacKm3d50",
"position_name": "IP运营总监助理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuTL5CPsNiYe.jpeg"
}
]
},
"ordinary": {
"name": "普通岗",
"list": [
{
"record_id": "recuFZJhP8plco",
"position_name": "二次元周边选品专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imqaAh.jpeg"
},
{
"record_id": "recuRgloZcfNcO",
"position_name": "二次元周边店店员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFP8c21CSJ.jpeg"
},
{
"record_id": "recuRgmXAXrTA8",
"position_name": "会展执行助理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imZ1Bt.jpeg"
},
{
"record_id": "recuzDi0lXFOur",
"position_name": "会展讲解员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imXoJH.jpeg"
},
{
"record_id": "recuRgmV8M0qkD",
"position_name": "商业会展执行专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imjOOd.jpeg"
},
{
"record_id": "recuzVoIzafaiF",
"position_name": "直播中控",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imcqPK.jpeg"
},
{
"record_id": "recuzVoIzazez6",
"position_name": "直播助理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imof01.jpeg"
},
{
"record_id": "recuzDi0lXsd2r",
"position_name": "网络运营专员",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuPFY2imy8Dg.jpeg"
},
{
"record_id": "recuTPacKmTFN8",
"position_name": "文创产品设计师助理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuTL5CPsiABJ.jpeg"
},
{
"record_id": "recuTPacKmIYRA",
"position_name": "品牌公关管培生",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuTL5CPsaZas.jpeg"
},
{
"record_id": "recuTPacKm0jSg",
"position_name": "文旅运营总监助理",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuTL5CPswT5x.jpeg"
},
{
"record_id": "recuTPacKmzBcS",
"position_name": "文旅项目投资拓展管培生",
"img": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/butler_position_avatar/recuTL5CPs5hKs.jpeg"
}
]
}
}
}

View File

@@ -2701,7 +2701,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",
@@ -8714,7 +8714,7 @@ mockData.profileOverview = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1544,7 +1544,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1621,7 +1621,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1437,7 +1437,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1425,7 +1425,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1480,7 +1480,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1694,7 +1694,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1904,7 +1904,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

File diff suppressed because it is too large Load Diff

View File

@@ -2431,7 +2431,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1159,7 +1159,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1159,7 +1159,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -2701,7 +2701,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

View File

@@ -1149,7 +1149,7 @@ export const mockData = {
interviews: [
{
id: 1,
company: "求职面试初体验",
company: "面试初体验",
position: "自我介绍练习",
date: "2023-09-15",
time: "14:30",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,220 +1,265 @@
import { useEffect } from "react";
import Portal from "@/components/Portal";
import { IconCalendarClock, IconCheck, IconClockCircle } from "@arco-design/web-react/icon";
const EventDetailModal = ({ isOpen, event, onClose }) => {
// ESC键关闭模态框
useEffect(() => {
const handleEscKey = (e) => {
if (e.key === "Escape" && isOpen) {
onClose();
}
};
if (isOpen) {
document.addEventListener("keydown", handleEscKey);
}
return () => {
document.removeEventListener("keydown", handleEscKey);
};
}, [isOpen, onClose]);
// 如果未打开或无事件数据,不渲染
if (!isOpen || !event) {
return null;
}
// 事件类型映射
const eventTypeMap = {
'compound-skill': '复合技能课',
'vertical-skill': '垂直技能课',
'public-course': '公开课',
'one-on-one': '1v1规划',
'interview': '线下面试模拟',
'class': '课',
'meeting': '会议',
'lab': '实验',
'exam': '考试',
};
// 事件类型颜色映射
const eventTypeColorMap = {
'compound-skill': { bg: '#667eea', light: '#e0e7ff' },
'vertical-skill': { bg: '#22c55e', light: '#dcfce7' },
'public-course': { bg: '#f59e0b', light: '#fef3c7' },
'one-on-one': { bg: '#ec4899', light: '#fce7f3' },
'interview': { bg: '#3b82f6', light: '#dbeafe' },
'class': { bg: '#667eea', light: '#e0e7ff' },
'meeting': { bg: '#f093fb', light: '#fae8ff' },
'lab': { bg: '#fa709a', light: '#fce7f3' },
'exam': { bg: '#ff6b6b', light: '#fee2e2' },
};
// 处理遮罩层点击
const handleOverlayClick = (e) => {
if (e.target === e.currentTarget) {
onClose();
}
};
// 处理关闭按钮点击
const handleCloseClick = () => {
onClose();
};
// 格式化时间显示
const formatTime = (timeStr) => {
if (!timeStr) return '';
// 处理多种格式: "2024-09-18 09:00:00" 或 "2024-09-18 09:00" 或 "09:00:00" 或 "09:00"
const parts = timeStr.toString().split(' ');
let time = '';
if (parts.length > 1) {
// 格式如 "2024-09-18 09:00:00" 或 "2024-09-18 09:00"
time = parts[1];
} else {
// 格式如 "09:00:00" 或 "09:00"
time = parts[0];
}
// 确保时间存在且格式正确
if (!time || time === 'undefined') {
return '00:00';
}
// 只显示小时和分钟 (前5个字符)
return time.substring(0, 5);
};
// 格式化日期
const formatDate = (date) => {
if (!date) return '';
const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' };
return date.toLocaleDateString('zh-CN', options);
};
// 判断是否为多事件模式(点击日期时显示当天所有事件)
const isMultiEventMode = event.events && Array.isArray(event.events);
const events = isMultiEventMode ? event.events : [event];
const displayDate = isMultiEventMode ? formatDate(event.date) : '';
// 获取事件状态 - 所有事项都显示为已完成
const getEventStatus = (eventItem) => {
return { text: '已完成', icon: <IconCheck />, color: '#52c41a' };
};
return (
<Portal className="event-detail-portal">
<div className="event-detail-overlay" onClick={handleOverlayClick}>
<div className="event-detail-modal-new">
{/* 模态框头部 */}
<div className="event-detail-header-new">
<h3 className="event-detail-title-new">
{isMultiEventMode ? '日程详情' : '事件详情'}
</h3>
<button
className="event-detail-close-new"
onClick={handleCloseClick}
type="button"
aria-label="关闭"
>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
</svg>
</button>
</div>
{/* 日期显示(多事件模式) */}
{isMultiEventMode && (
<div className="event-detail-date-header">
<IconCalendarClock style={{ fontSize: 20, color: '#3b82f6' }} />
<span>{displayDate}</span>
</div>
)}
{/* 模态框内容 */}
<div className="event-detail-content-new">
{events.length === 0 ? (
<div className="event-empty-state">
<IconCalendarClock style={{ fontSize: 48, color: '#c3c5c9', marginBottom: 16 }} />
<p style={{ fontSize: 16, color: '#86909c', margin: 0 }}>当日无事项</p>
</div>
) : (
<div className="event-list-container">
{events.map((eventItem, index) => {
const status = getEventStatus(eventItem);
const typeColor = eventTypeColorMap[eventItem.type] || { bg: '#667eea', light: '#e0e7ff' };
return (
<div key={eventItem.id || index} className="event-card-new">
<div className="event-card-header">
<div className="event-type-indicator" style={{ backgroundColor: typeColor.bg }}></div>
<div className="event-card-title">
<h4>{eventItem.title}</h4>
<span className="event-type-tag" style={{
backgroundColor: typeColor.light,
color: typeColor.bg
}}>
{eventTypeMap[eventItem.type] || eventItem.type}
</span>
</div>
</div>
<div className="event-card-body">
<div className="event-info-row">
<IconClockCircle style={{ fontSize: 16, color: '#8c8c8c' }} />
<span className="event-time">
{formatTime(eventItem.startTime)} - {formatTime(eventItem.endTime)}
</span>
</div>
<div className="event-info-row">
<div className="event-status" style={{ color: status.color }}>
{status.icon}
<span>{status.text}</span>
</div>
</div>
{/* 企业高管公开课添加线下参与标签 */}
{eventItem.type === 'public-course' && (
<div className="event-info-row" style={{ marginTop: '8px' }}>
<div style={{
padding: '4px 12px',
backgroundColor: '#f0f9ff',
color: '#0ea5e9',
borderRadius: '4px',
fontSize: '12px',
fontWeight: '500',
display: 'inline-flex',
alignItems: 'center',
gap: '4px'
}}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
</svg>
可报名线下参与
</div>
</div>
)}
{eventItem.description && (
<div className="event-description">
{eventItem.description}
</div>
)}
</div>
</div>
);
})}
</div>
)}
</div>
</div>
</div>
</Portal>
);
};
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import Portal from "@/components/Portal";
import { IconCalendarClock, IconCheck, IconClockCircle } from "@arco-design/web-react/icon";
const EventDetailModal = ({ isOpen, event, onClose }) => {
const navigate = useNavigate();
// ESC键关闭模态框
useEffect(() => {
const handleEscKey = (e) => {
if (e.key === "Escape" && isOpen) {
onClose();
}
};
if (isOpen) {
document.addEventListener("keydown", handleEscKey);
}
return () => {
document.removeEventListener("keydown", handleEscKey);
};
}, [isOpen, onClose]);
// 如果未打开或无事件数据,不渲染
if (!isOpen || !event) {
return null;
}
// 事件类型映射
const eventTypeMap = {
'compound-skill': '复合技能课',
'vertical-skill': '垂直技能课',
'public-course': '公开课',
'one-on-one': '1v1规划',
'interview': '线下面试模拟',
'class': '课程',
'meeting': '会议',
'lab': '实验',
'exam': '考试',
};
// 事件类型颜色映射
const eventTypeColorMap = {
'compound-skill': { bg: '#667eea', light: '#e0e7ff' },
'vertical-skill': { bg: '#22c55e', light: '#dcfce7' },
'public-course': { bg: '#f59e0b', light: '#fef3c7' },
'one-on-one': { bg: '#ec4899', light: '#fce7f3' },
'interview': { bg: '#3b82f6', light: '#dbeafe' },
'class': { bg: '#667eea', light: '#e0e7ff' },
'meeting': { bg: '#f093fb', light: '#fae8ff' },
'lab': { bg: '#fa709a', light: '#fce7f3' },
'exam': { bg: '#ff6b6b', light: '#fee2e2' },
};
// 处理遮罩层点击
const handleOverlayClick = (e) => {
if (e.target === e.currentTarget) {
onClose();
}
};
// 处理关闭按钮点击
const handleCloseClick = () => {
onClose();
};
// 格式化时间显示
const formatTime = (timeStr) => {
if (!timeStr) return '';
// 处理多种格式: "2024-09-18 09:00:00" 或 "2024-09-18 09:00" 或 "09:00:00" 或 "09:00"
const parts = timeStr.toString().split(' ');
let time = '';
if (parts.length > 1) {
// 格式如 "2024-09-18 09:00:00" 或 "2024-09-18 09:00"
time = parts[1];
} else {
// 格式如 "09:00:00" 或 "09:00"
time = parts[0];
}
// 确保时间存在且格式正确
if (!time || time === 'undefined') {
return '00:00';
}
// 只显示小时和分钟 (前5个字符)
return time.substring(0, 5);
};
// 格式化日期
const formatDate = (date) => {
if (!date) return '';
const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' };
return date.toLocaleDateString('zh-CN', options);
};
// 判断是否为多事件模式(点击日期时显示当天所有事件)
const isMultiEventMode = event.events && Array.isArray(event.events);
const events = isMultiEventMode ? event.events : [event];
const displayDate = isMultiEventMode ? formatDate(event.date) : '';
// 获取事件状态 - 所有事项都显示为已完成
const getEventStatus = (eventItem) => {
return { text: '已完成', icon: <IconCheck />, color: '#52c41a' };
};
// 处理课程点击 - 跳转到对应的课程页面
const handleCourseClick = (eventItem) => {
// 构建URL参数
const params = new URLSearchParams();
if (eventItem.id) {
params.append('courseId', eventItem.id);
}
if (eventItem.title) {
params.append('courseTitle', eventItem.title);
}
// 根据课程类型跳转到不同页面
switch(eventItem.type) {
case 'compound-skill':
case 'vertical-skill':
// 复合技能课/垂直技能课 - 跳转到课程直播间
navigate(`/live?${params.toString()}`);
break;
case 'public-course':
// 公开课包括AI课、企业高管公开课、营销课 - 跳转到公共课直播间
navigate(`/public-courses?${params.toString()}`);
break;
case 'one-on-one':
// 1v1规划 - 跳转到定制求职策略页面
navigate('/job-strategy');
break;
case 'interview':
// 线下面试模拟 - 不跳转,仅关闭弹窗
break;
default:
// 其他类型暂不跳转
break;
}
// 关闭弹窗
onClose();
};
return (
<Portal className="event-detail-portal">
<div className="event-detail-overlay" onClick={handleOverlayClick}>
<div className="event-detail-modal-new">
{/* 模态框头部 */}
<div className="event-detail-header-new">
<h3 className="event-detail-title-new">
{isMultiEventMode ? '日程详情' : '课程详情'}
</h3>
<button
className="event-detail-close-new"
onClick={handleCloseClick}
type="button"
aria-label="关闭"
>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
</svg>
</button>
</div>
{/* 日期显示(多事件模式) */}
{isMultiEventMode && (
<div className="event-detail-date-header">
<IconCalendarClock style={{ fontSize: 20, color: '#3b82f6' }} />
<span>{displayDate}</span>
</div>
)}
{/* 模态框内容 */}
<div className="event-detail-content-new">
{events.length === 0 ? (
<div className="event-empty-state">
<IconCalendarClock style={{ fontSize: 48, color: '#c3c5c9', marginBottom: 16 }} />
<p style={{ fontSize: 16, color: '#86909c', margin: 0 }}>当日无事项</p>
</div>
) : (
<div className="event-list-container">
{events.map((eventItem, index) => {
const status = getEventStatus(eventItem);
const typeColor = eventTypeColorMap[eventItem.type] || { bg: '#667eea', light: '#e0e7ff' };
return (
<div
key={eventItem.id || index}
className={`event-card-new ${eventItem.type !== 'interview' ? 'clickable-course' : ''}`}
onClick={eventItem.type !== 'interview' ? () => handleCourseClick(eventItem) : undefined}
style={{ cursor: eventItem.type !== 'interview' ? 'pointer' : 'default' }}
>
<div className="event-card-header">
<div className="event-type-indicator" style={{ backgroundColor: typeColor.bg }}></div>
<div className="event-card-title">
<h4>{eventItem.title}</h4>
<span className="event-type-tag" style={{
backgroundColor: typeColor.light,
color: typeColor.bg
}}>
{eventTypeMap[eventItem.type] || eventItem.type}
</span>
</div>
</div>
<div className="event-card-body">
<div className="event-info-row">
<IconClockCircle style={{ fontSize: 16, color: '#8c8c8c' }} />
<span className="event-time">
{formatTime(eventItem.startTime)} - {formatTime(eventItem.endTime)}
</span>
</div>
<div className="event-info-row">
<div className="event-status" style={{ color: status.color }}>
{status.icon}
<span>{status.text}</span>
</div>
</div>
{/* 企业高管公开课添加线下参与标签 */}
{eventItem.type === 'public-course' && (
<div className="event-info-row" style={{ marginTop: '8px' }}>
<div style={{
padding: '4px 12px',
backgroundColor: '#f0f9ff',
color: '#0ea5e9',
borderRadius: '4px',
fontSize: '12px',
fontWeight: '500',
display: 'inline-flex',
alignItems: 'center',
gap: '4px'
}}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
</svg>
可报名线下参与
</div>
</div>
)}
{eventItem.description && (
<div className="event-description">
{eventItem.description}
</div>
)}
</div>
</div>
);
})}
</div>
)}
</div>
</div>
</div>
</Portal>
);
};
export default EventDetailModal;

View File

@@ -662,6 +662,19 @@
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
/* 可点击的课程卡片样式 */
.event-card-new.clickable-course {
cursor: pointer;
transition: all 0.2s ease;
}
.event-card-new.clickable-course:hover {
background: #f3f4f6;
border-color: #4080ff;
box-shadow: 0 4px 12px rgba(64, 128, 255, 0.15);
transform: translateY(-2px);
}
/* 事件卡片头部 */
.event-card-header {
display: flex;

View File

@@ -277,25 +277,11 @@
.job-info-modal-content-position-info-companyInfo {
width: 100%;
box-sizing: border-box;
padding: 20px;
border-radius: 12px;
background: linear-gradient(135deg, #ffffff 0%, #f7f8fa 100%);
margin: 8px 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(102, 126, 234, 0.1);
position: relative;
overflow: visible;
min-height: auto;
&:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
}
padding: 16px;
border-radius: 8px;
background-color: #fff;
margin: 10px 0;
border: 1px solid #e5e6eb;
> p {
width: 100%;
@@ -304,47 +290,42 @@
.description-title,
.requirements-title,
.companyInfo-title {
font-size: 16px;
font-size: 18px;
font-weight: 600;
line-height: 24px;
line-height: 28px;
color: #1d2129;
margin-bottom: 16px;
padding-left: 12px;
position: relative;
margin-bottom: 12px;
display: flex;
align-items: center;
&:before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 16px;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
border-radius: 2px;
.title-icon {
width: 20px;
height: 20px;
margin-right: 8px;
object-fit: contain;
}
}
.description-content {
font-size: 14px;
font-weight: 400;
line-height: 22px;
line-height: 24px;
color: #4e5969;
text-align: left;
.description-item {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
margin-bottom: 8px;
text-align: left;
.description-number {
display: inline-block;
min-width: 24px;
min-width: 20px;
font-size: 14px;
font-weight: 600;
color: #667eea;
margin-right: 8px;
font-weight: 500;
color: #1d2129;
margin-right: 6px;
text-align: left;
}
@@ -352,7 +333,7 @@
flex: 1;
font-size: 14px;
font-weight: 400;
line-height: 22px;
line-height: 24px;
color: #4e5969;
text-align: left;
}
@@ -368,16 +349,9 @@
font-weight: 400;
line-height: 24px;
color: #4e5969;
.company-paragraph {
margin-bottom: 12px;
text-indent: 2em;
text-align: justify;
&:last-child {
margin-bottom: 0;
}
}
text-align: left;
white-space: pre-wrap;
word-break: break-word;
}
.requirements-content {
width: 100%;
@@ -386,16 +360,16 @@
.requirements-item {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
margin-bottom: 8px;
text-align: left;
.requirement-number {
display: inline-block;
min-width: 24px;
min-width: 20px;
font-size: 14px;
font-weight: 600;
color: #667eea;
margin-right: 8px;
font-weight: 500;
color: #1d2129;
margin-right: 6px;
text-align: left;
}
@@ -403,7 +377,7 @@
flex: 1;
font-size: 14px;
font-weight: 400;
line-height: 22px;
line-height: 24px;
color: #4e5969;
text-align: left;
}

View File

@@ -269,7 +269,10 @@ export default ({ visible, onClose, data, directToResume = false, hideDeliverBut
)}
{data?.details?.description && (
<div className="job-info-modal-content-position-info-description">
<p className="description-title">岗位描述</p>
<p className="description-title">
<img className="title-icon" src="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/teach_sys_icon/recuW0XRVB1bpV.png" alt="" />
岗位描述
</p>
<div className="description-content">
{data?.details?.description.split(/\d+\.\s*/).filter(item => item.trim()).map((item, index) => (
<div key={index} className="description-item">
@@ -282,7 +285,10 @@ export default ({ visible, onClose, data, directToResume = false, hideDeliverBut
)}
{(data?.details?.requirements?.length > 0 || data?.details?.requirementsText) && (
<div className="job-info-modal-content-position-info-requirements">
<p className="requirements-title">岗位要求</p>
<p className="requirements-title">
<img className="title-icon" src="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/teach_sys_icon/recuW0XRVB1bpV.png" alt="" />
岗位要求
</p>
<div className="requirements-content">
{data?.details?.requirements ? (
data?.details?.requirements?.map((item, index) => (
@@ -304,7 +310,10 @@ export default ({ visible, onClose, data, directToResume = false, hideDeliverBut
)}
{data?.details?.companyInfo && (
<div className="job-info-modal-content-position-info-companyInfo">
<p className="companyInfo-title">公司介绍</p>
<p className="companyInfo-title">
<img className="title-icon" src="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/teach_sys_icon/recuW0XRVB1bpV.png" alt="" />
公司介绍
</p>
<div className="companyInfo-content">
{data?.details?.companyInfo.split('\n').map((paragraph, index) => (
<p key={index} className="company-paragraph">

View File

@@ -38,7 +38,12 @@ const Dashboard = () => {
// 根据选中日期筛选任务
const getTasksForDate = (date) => {
if (!dashboardData?.tasks?.allTasks) return [];
console.log("getTasksForDate called with date:", date);
console.log("dashboardData.tasks:", dashboardData?.tasks);
if (!dashboardData?.tasks?.allTasks) {
console.log("No allTasks found in dashboardData");
return [];
}
// Check if date is valid before calling getTime
if (!date || isNaN(date.getTime())) {
console.warn("Invalid date provided to getTasksForDate:", date);

View File

@@ -59,7 +59,7 @@ const ExpertSupportPage = () => {
{
id: 1,
type: "user",
content: "您好,我在使用TypeScript时遇到了一些泛型定义的问题",
content: "您好,我遇到了一些问题",
time: "2025-01-08 16:45",
avatar: "👤",
},
@@ -67,10 +67,10 @@ const ExpertSupportPage = () => {
id: 2,
type: "expert",
content:
"您好我是王开发专家很高兴为您解答TypeScript相关问题。请详细描述一下您遇到的具体问题。",
"你好我是多多ai智能问答小助手有什么问题就来问我吧",
time: "2025-01-08 16:46",
avatar: "👨‍💻",
expertName: "王开发专家",
expertName: "多多机器人",
},
{
id: 3,

View File

@@ -41,10 +41,30 @@
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
flex-wrap: nowrap;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 1px solid #f2f3f5;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
height: 6px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
background: #c9cdd4;
border-radius: 3px;
&:hover {
background: #86909c;
}
}
.unit-nav-item {
padding: 5px 14px;

View File

@@ -10,6 +10,7 @@ const HomeworkPage = () => {
const { homework } = mockData;
const scrollContainerRef = useRef(null);
const verticalScrollContainerRef = useRef(null);
const unitNavRefs = useRef({});
const [showIframe, setShowIframe] = useState(false);
const [selectedUnits, setSelectedUnits] = useState({
1: "全部", // 复合能力课的选中单元
@@ -27,7 +28,9 @@ const HomeworkPage = () => {
// 如果显示iframe不初始化滚动
if (showIframe) return;
const containers = [scrollContainerRef.current, verticalScrollContainerRef.current].filter(Boolean);
// 收集所有需要横向滚动的容器
const unitNavContainers = Object.values(unitNavRefs.current).filter(Boolean);
const containers = [scrollContainerRef.current, verticalScrollContainerRef.current, ...unitNavContainers].filter(Boolean);
if (containers.length === 0) return;
const animationIds = new Map();
@@ -177,7 +180,10 @@ const HomeworkPage = () => {
<p className="homework-page-content-list-title">{item.name}</p>
</div>
{item.units && (
<div className="homework-page-unit-nav">
<div
className="homework-page-unit-nav"
ref={el => unitNavRefs.current[item.id] = el}
>
<span
className={`unit-nav-item ${selectedUnits[item.id] === "全部" ? "active" : ""}`}
onClick={() => setSelectedUnits({...selectedUnits, [item.id]: "全部"})}

View File

@@ -4,11 +4,11 @@ import ScoreChart from "../ScoreChart";
import RadarChart from "../RadarChart";
import "./index.css";
export default ({ selectedItem = "求职面试初体验" }) => {
export default ({ selectedItem = "面试初体验" }) => {
// 根据选中项目获取对应的视频URL
const getVideoUrl = () => {
switch(selectedItem) {
case "求职面试初体验":
case "面试初体验":
return "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/video/teach_sys/interview_simulation/3years_ago.mov";
case "未来的自己":
return "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/video/teach_sys/interview_simulation/3years_later.mov";
@@ -146,7 +146,7 @@ export default ({ selectedItem = "求职面试初体验" }) => {
};
} else {
return {
totalScore: 14, // 根据JSON计算的真实总分 (求职面试初体验)
totalScore: 14, // 根据JSON计算的真实总分 (面试初体验)
professionalScore: 7, // (2+1+1+1+1+1)/6*10*0.6 = 7
performanceScore: 7, // (2+1+2+2)/4*10*0.4 = 7
radarData: [2, 1, 1, 1, 1, 1], // 六项专业能力指标来自JSON
@@ -177,7 +177,7 @@ export default ({ selectedItem = "求职面试初体验" }) => {
// 判断是否应该显示评价内容
const shouldShowEvaluation = () => {
return selectedItem === "求职面试初体验" ||
return selectedItem === "面试初体验" ||
selectedItem === "未来的自己" ||
selectedItem === "第一次线下面试模拟" ||
selectedItem === "第二次线下面试模拟" ||
@@ -331,9 +331,10 @@ export default ({ selectedItem = "求职面试初体验" }) => {
{ name: "仪表与职场礼仪", max: 10 },
{ name: "时间管理与条理性", max: 10 },
]}
lineClolr="#FFE4D9"
areaColor="#FFD4C1"
areaBorderColor="#FFB89A"
lineClolr="#E8F5E9"
areaColor="#C8E6C9"
areaBorderColor="#66BB6A"
isGreenTheme={true}
/>
</div>
</div>

View File

@@ -6,7 +6,7 @@ import "./index.css";
const TimelineItem = Timeline.Item;
export default ({ onItemSelect }) => {
const [selectedItem, setSelectedItem] = useState("求职面试初体验");
const [selectedItem, setSelectedItem] = useState("面试初体验");
const handleItemClick = (itemName) => {
setSelectedItem(itemName);
@@ -29,16 +29,16 @@ export default ({ onItemSelect }) => {
<TimelineItem
lineType="dashed"
dot={
<div className={`time-line-dot-icon ${selectedItem === "求职面试初体验" ? "time-line-dot-icon-active" : ""}`} />
<div className={`time-line-dot-icon ${selectedItem === "面试初体验" ? "time-line-dot-icon-active" : ""}`} />
}
>
<div
className={`time-line-item ${selectedItem === "求职面试初体验" ? "time-line-item-active" : ""}`}
onClick={() => handleItemClick("求职面试初体验")}
className={`time-line-item ${selectedItem === "面试初体验" ? "time-line-item-active" : ""}`}
onClick={() => handleItemClick("面试初体验")}
style={{ cursor: "pointer" }}
>
<p>
求职面试初体验
面试初体验
<span style={{
marginLeft: '8px',
padding: '2px 8px',

View File

@@ -4,7 +4,7 @@ import InterviewRating from "./components/InterviewRating";
import "./index.css";
const InterviewSimulationPage = () => {
const [selectedItem, setSelectedItem] = useState("求职面试初体验");
const [selectedItem, setSelectedItem] = useState("面试初体验");
return (
<div className="interview-simulation-page">

View File

@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react";
import { Modal, Message } from "@arco-design/web-react";
import { Modal, Message, Tooltip } from "@arco-design/web-react";
import { useNavigate, useLocation } from "react-router-dom";
import {
DndContext,
@@ -344,9 +344,51 @@ export default ({ locked = false }) => {
<div className="target-position-wrapper">
<div className="target-position-content">
<div className="batch-icon">
<span>第一批次</span>
<span>批次</span>
<span>第三批次</span>
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
批次
<Tooltip content="通过培训后能直接上岗的岗位,入职成功率最高。">
<span style={{ fontSize: '12px',
color: '#ffffff',
backgroundColor: '#4080ff',
borderRadius: '50%',
width: '16px',
height: '16px',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold' }}>?</span>
</Tooltip>
</span>
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
第二批次
<Tooltip content="需积累一定工作经验后可争取的晋升岗位方向。">
<span style={{ fontSize: '12px',
color: '#ffffff',
backgroundColor: '#4080ff',
borderRadius: '50%',
width: '16px',
height: '16px',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold' }}>?</span>
</Tooltip>
</span>
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
第三批次
<Tooltip content="需长期经验和能力沉淀,可作为学员的终极职业目标。">
<span style={{ fontSize: '12px',
color: '#ffffff',
backgroundColor: '#4080ff',
borderRadius: '50%',
width: '16px',
height: '16px',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold' }}>?</span>
</Tooltip>
</span>
</div>
{/* 第一批次 */}

View File

@@ -41,7 +41,7 @@ const JobStrategyDetailPage = () => {
onClick={() => setActiveItem("1")}
>
<span className="nav-icon target-icon"></span>
<span className="nav-text">优先目标岗位</span>
<span className="nav-text">目标岗位优先级</span>
</div>
<div
className={`nav-item ${activeItem === "2" ? "item-active" : ""}`}

View File

@@ -7,7 +7,7 @@ const JobStrategyPage = () => {
<div className="job-strategy-page">
<CoursesVideoPlayer
isLock
backgroundImage="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW8VeXQDVI2.jpg"
backgroundImage="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWolCCOlOCz.jpg"
/>
<LiveSummary showBtn />
</div>

View File

@@ -1,4 +1,5 @@
import { useState } from "react";
import { useState, useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import CoursesVideoPlayer from "@/components/CoursesVideoPlayer";
import CourseList from "@/components/CourseList";
import { mockData } from "@/data/mockData";
@@ -6,6 +7,29 @@ import "./index.css";
const LivePage = () => {
const [selectedCourse, setSelectedCourse] = useState(null);
const [searchParams] = useSearchParams();
// 检查URL参数如果有courseId或courseTitle则自动打开对应课程
useEffect(() => {
const courseId = searchParams.get('courseId');
const courseTitle = searchParams.get('courseTitle');
if (courseId || courseTitle) {
// 查找对应的课程
const allCourses = [
...(mockData.compoundSkillCourses || []),
...(mockData.verticalSkillCourses || [])
];
const targetCourse = allCourses.find(course =>
course.id === courseId || course.title === courseTitle
);
if (targetCourse) {
setSelectedCourse(targetCourse);
}
}
}, [searchParams]);
const handleCourseClick = (course) => {
setSelectedCourse(course);

View File

@@ -18,24 +18,6 @@ const Portfolio = () => {
return (
<div className="user-portfolio-page">
<button
onClick={handleRefresh}
style={{
position: "absolute",
top: "10px",
right: "10px",
zIndex: 1000,
padding: "8px 16px",
backgroundColor: "#3491fa",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
fontSize: "14px"
}}
>
刷新页面
</button>
{iframeSrc && (
<iframe
key={iframeSrc} // 使用key强制重新渲染iframe

View File

@@ -126,6 +126,7 @@
width: 210px;
height: 82px;
background-color: #f7f8fa;
transition: all 0.3s ease;
border-radius: 8px;
padding: 16px;
box-sizing: border-box;
@@ -137,6 +138,13 @@
cursor: pointer;
flex-shrink: 0;
&:hover {
background-color: #f2f3f5;
border-color: #4080ff;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
> span {
font-size: 12px;
line-height: 20px;

View File

@@ -1,4 +1,5 @@
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import Modal from "@/components/Modal";
import PDFICON from "@/assets/images/Common/pdf_icon.png";
import FileIcon from "@/components/FileIcon";
@@ -7,6 +8,7 @@ import ImagePreviewModal from "../ImagePreviewModal";
import "./index.css";
export default ({ visible, onClose, data }) => {
const navigate = useNavigate();
const [previewVisible, setPreviewVisible] = useState(false);
const [previewIndex, setPreviewIndex] = useState(0);
@@ -14,6 +16,14 @@ export default ({ visible, onClose, data }) => {
onClose();
};
// 处理岗位点击,跳转到简历与面试题页面
const handlePositionClick = (positionName) => {
// 关闭当前模态框
onClose();
// 跳转到简历与面试题页面,并传递岗位名称参数
navigate('/resume-interview', { state: { selectedPosition: positionName } });
};
// 处理图片点击预览
const handleImageClick = (index) => {
setPreviewIndex(index);
@@ -91,7 +101,12 @@ export default ({ visible, onClose, data }) => {
<p className="project-cases-modal-item-title">适用岗位</p>
<ul className="project-cases-modal-horizontal-list">
{data?.applicablePositions?.map((pos, index) => (
<li key={index} className="high-count-list-item">
<li
key={index}
className="high-count-list-item"
onClick={() => handlePositionClick(pos.position)}
style={{ cursor: 'pointer' }}
>
<span className={pos.level === '普通岗' ? 'low' : pos.level === '技术骨干岗' ? 'medium' : 'high'}>
{pos.level}
</span>
@@ -108,23 +123,72 @@ export default ({ visible, onClose, data }) => {
{/* 对应单元 */}
<li className="project-cases-modal-item">
<p className="project-cases-modal-item-title">对应单元</p>
<ul className="project-cases-modal-horizontal-list">
{data?.units?.map((unit, index) => (
<li key={index} className="class-list-item">
<div className="class-list-item-title">
<i />
<span>{unit}</span>
</div>
</li>
)) || (
<li className="class-list-item">
<div className="class-list-item-title">
<i />
<span>暂无对应单元信息</span>
</div>
</li>
)}
</ul>
{/* 复合能力课 */}
<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">
<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) && (
<li className="class-list-item">
<div className="class-list-item-title">
<i />
<span>暂无复合能力课信息</span>
</div>
</li>
)}
</ul>
</div>
{/* 垂直能力课 */}
<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">
<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) && (
<li className="class-list-item">
<div className="class-list-item-title">
<i />
<span>暂无垂直能力课信息</span>
</div>
</li>
)}
</ul>
</div>
</li>
{/* 项目整体流程介绍 - Markdown格式 */}
<li className="project-cases-modal-item">

View File

@@ -0,0 +1,301 @@
/*/* 全局样式控制弹窗容器 */
.upload-modal.arco-modal-wrapper {
.arco-modal {
width: 720px !important;
max-width: 90vw;
}
}
/* 强制控制 Arco Modal 外层容器为横向矩形 */
body {
[data-focus-lock-disabled="false"] {
.arco-modal-wrapper {
.arco-modal {
width: 960px !important;
max-width: 90vw;
height: auto !important;
}
}
}
}
/*/* 针对上传弹窗的特定样式 */
.arco-modal-wrapper:has(.upload-modal-content) {
.arco-modal {
width: 720px !important;
height: auto !important;
max-width: 90vw;
}
}
.upload-modal {
.arco-modal {
/* 横向矩形布局 - 16:9 比例 */
width: 720px !important;
.arco-modal-content {
height: 420px;
max-height: 420px;
display: flex;
flex-direction: column;
}
}
.arco-modal-header {
border-bottom: 1px solid #e5e6eb;
padding: 20px 24px;
flex-shrink: 0;
}
.arco-modal-title {
font-size: 18px;
font-weight: 600;
color: #1d2129;
}
.arco-modal-body {
padding: 0;
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.upload-modal-content {
height: 100%;
display: flex;
flex-direction: column;
.upload-header {
padding: 24px 24px 20px;
background: linear-gradient(180deg, #f7f8fa 0%, #ffffff 100%);
h3 {
font-size: 16px;
font-weight: 600;
color: #1d2129;
margin-bottom: 8px;
}
p {
font-size: 14px;
color: #86909c;
}
}
.upload-area {
margin: 20px 24px;
flex: 1;
max-height: 150px;
min-height: 120px;
border: 2px dashed #e5e6eb;
border-radius: 12px;
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
background: linear-gradient(to bottom, #fafafa, #f5f5f5);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg,
transparent 48%,
rgba(22, 93, 255, 0.03) 49%,
rgba(22, 93, 255, 0.03) 51%,
transparent 52%
);
background-size: 20px 20px;
opacity: 0;
transition: opacity 0.3s ease;
}
&:hover {
border-color: #165dff;
background-color: #f0f7ff;
&::before {
opacity: 1;
}
.upload-icon {
color: #165dff;
}
}
&.dragging {
border-color: #165dff;
background-color: #e8f4ff;
&::before {
opacity: 1;
}
}
&.has-file {
border-color: #00b42a;
background-color: #ffffff;
border-style: solid;
}
.upload-placeholder {
width: 100%;
height: 100%;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
.upload-icon {
font-size: 48px;
color: #c9cdd4;
}
.upload-text {
font-size: 16px;
color: #4e5969;
font-weight: 500;
margin: 0;
}
.upload-hint {
font-size: 14px;
color: #86909c;
margin: 0;
}
}
.uploaded-file-display {
width: 100%;
padding: 15px 24px;
display: flex;
align-items: center;
gap: 16px;
.file-icon-wrapper {
width: 48px;
height: 48px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
.file-icon {
font-size: 24px;
color: #ffffff;
}
}
.file-info {
flex: 1;
min-width: 0;
.file-name {
font-size: 15px;
color: #1d2129;
font-weight: 500;
margin-bottom: 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.file-meta {
display: flex;
align-items: center;
gap: 12px;
font-size: 13px;
.file-size {
color: #86909c;
}
.file-status {
color: #00b42a;
padding: 2px 8px;
background: #f0ffef;
border-radius: 4px;
font-size: 12px;
}
}
}
.remove-file-btn {
width: 32px;
height: 32px;
border: none;
background: #f2f3f5;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
color: #86909c;
&:hover {
background: #ff4d4f;
color: #ffffff;
}
svg {
font-size: 16px;
}
}
}
}
}
.arco-modal-footer {
border-top: 1px solid #e5e6eb;
padding: 16px 24px;
flex-shrink: 0;
background: linear-gradient(to bottom, #ffffff, #fafafa);
.arco-btn {
min-width: 100px;
height: 36px;
font-size: 14px;
font-weight: 500;
border-radius: 6px;
transition: all 0.3s ease;
&.arco-btn-default {
background: #ffffff;
border: 1px solid #e5e6eb;
color: #4e5969;
&:hover {
background: #f7f8fa;
border-color: #c9cdd4;
color: #1d2129;
}
}
&.arco-btn-primary {
background: linear-gradient(135deg, #165dff 0%, #3c7eff 100%);
border: none;
color: #ffffff;
box-shadow: 0 2px 8px rgba(22, 93, 255, 0.2);
&:hover {
background: linear-gradient(135deg, #1450db 0%, #3673ff 100%);
box-shadow: 0 4px 12px rgba(22, 93, 255, 0.3);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
box-shadow: 0 2px 6px rgba(22, 93, 255, 0.2);
}
}
}
}
}

View File

@@ -0,0 +1,161 @@
import { useState, useRef } from "react";
import { Modal } from "@arco-design/web-react";
import { IconUpload, IconFile, IconDelete } from "@arco-design/web-react/icon";
import toast from "@/components/Toast";
import "./index.css";
const UploadModal = ({ visible, onClose }) => {
const [isDragging, setIsDragging] = useState(false);
const [uploadedFile, setUploadedFile] = useState(null);
const fileInputRef = useRef(null);
const handleDragOver = (e) => {
e.preventDefault();
setIsDragging(true);
};
const handleDragLeave = (e) => {
e.preventDefault();
setIsDragging(false);
};
const handleDrop = (e) => {
e.preventDefault();
setIsDragging(false);
const files = e.dataTransfer.files;
if (files.length > 0) {
handleFileSelect(files[0]);
}
};
const handleFileSelect = (file) => {
// 验证文件类型
const allowedTypes = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain',
'text/markdown',
'text/x-markdown'
];
const allowedExtensions = ['.pdf', '.doc', '.docx', '.txt', '.md', '.markdown'];
const fileExtension = file.name.toLowerCase().match(/\.[^.]+$/)?.[0];
if (!allowedTypes.includes(file.type) && !allowedExtensions.includes(fileExtension)) {
toast.error("请上传 PDF、Word、Markdown 或 TXT 格式的文件");
return;
}
// 验证文件大小限制为10MB
if (file.size > 10 * 1024 * 1024) {
toast.error("文件大小不能超过10MB");
return;
}
setUploadedFile(file);
toast.success(`文件 ${file.name} 已选择`);
};
const handleFileInputChange = (e) => {
const file = e.target.files[0];
if (file) {
handleFileSelect(file);
}
};
const handleUploadClick = () => {
fileInputRef.current?.click();
};
const handleSubmit = () => {
if (!uploadedFile) {
toast.error("请先选择要上传的文件");
return;
}
// 这里可以添加实际的上传逻辑
toast.success("文件上传成功");
setUploadedFile(null);
onClose();
};
const handleCancel = () => {
setUploadedFile(null);
onClose();
};
return (
<Modal
title={false}
visible={visible}
onOk={handleSubmit}
onCancel={handleCancel}
okText="确认上传"
cancelText="取消"
style={{ width: '720px' }}
width={720}
className="upload-modal"
width={960}
maskClosable={false}
>
<div className="upload-modal-content">
<div className="upload-header">
<h3>选择文件上传</h3>
<p>请选择您的项目文档进行上传支持批量上传多个文件</p>
</div>
<div
className={`upload-area ${isDragging ? 'dragging' : ''} ${uploadedFile ? 'has-file' : ''}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
onClick={handleUploadClick}
>
<input
ref={fileInputRef}
type="file"
accept=".pdf,.doc,.docx,.txt,.md,.markdown"
onChange={handleFileInputChange}
style={{ display: 'none' }}
/>
{uploadedFile ? (
<div className="uploaded-file-display">
<div className="file-icon-wrapper">
<IconFile className="file-icon" />
</div>
<div className="file-info">
<p className="file-name">{uploadedFile.name}</p>
<p className="file-meta">
<span className="file-size">
{(uploadedFile.size / 1024 / 1024).toFixed(2)} MB
</span>
<span className="file-status">准备上传</span>
</p>
</div>
<button
className="remove-file-btn"
onClick={(e) => {
e.stopPropagation();
setUploadedFile(null);
}}
>
<IconDelete />
</button>
</div>
) : (
<div className="upload-placeholder">
<IconUpload className="upload-icon" />
<p className="upload-text">点击选择文件或将文件拖拽至此处</p>
<p className="upload-hint">支持 PDFWordMarkdownTXT 格式单个文件不超过 10MB</p>
</div>
)}
</div>
</div>
</Modal>
);
};
export default UploadModal;

View File

@@ -14,18 +14,50 @@
padding: 20px;
overflow: hidden;
.project-library-title {
/* 项目库头部样式 */
.project-library-header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 20px;
border-bottom: 1px solid #e5e6eb;
padding-bottom: 10px;
.upload-button {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background-color: #f7f8fa;
border: 1px solid #e5e6eb;
border-radius: 6px;
color: #86909c;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
svg {
font-size: 16px;
}
&:hover {
background-color: #e8f4ff;
border-color: #165dff;
color: #165dff;
}
}
}
.project-library-title {
width: auto;
height: 42px;
font-size: 20px;
font-weight: 600;
line-height: 30px;
margin-bottom: 20px;
color: #1d2129;
flex-shrink: 0;
position: relative;
border-bottom: 1px solid #e5e6eb;
padding-bottom: 10px;
&::after {
content: "";
@@ -40,6 +72,37 @@
}
}
/* 项目分类导航栏样式 */
.project-category-nav {
display: flex;
gap: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #e5e6eb;
padding-bottom: 15px;
.category-item {
padding: 8px 16px;
border-radius: 20px;
background-color: #f7f8fa;
color: #86909c;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
white-space: nowrap;
&:hover {
background-color: #e8f4ff;
color: #165dff;
}
&.active {
background-color: #165dff;
color: #ffffff;
}
}
}
.project-library-search-area {
width: 100%;
height: 36px;
@@ -157,8 +220,8 @@
}
}
}
.my-project-library {
.my-project-library {
margin-top: 20px;
.project-library-empty {
@@ -237,7 +300,33 @@
color: #1d4ed8 !important;
}
}
}
/* 全局控制上传弹窗的外层容器为横向矩形 */
:global([data-focus-lock-disabled="false"]) {
:global(.arco-modal-wrapper) {
:global(.arco-modal) {
width: 720px !important;
max-width: 90vw !important;
}
}
}
/* 确保上传弹窗是横向矩形 */
:global(.arco-modal-wrapper) {
&:has(.upload-modal-content) {
:global(.arco-modal) {
width: 720px !important;
max-width: 90vw !important;
height: auto !important;
:global(.arco-modal-content) {
height: 420px !important;
max-height: 420px !important;
}
}
}
}
}
}
}

View File

@@ -1,9 +1,11 @@
import { useState } from "react";
import { useState, useMemo } from "react";
import { Tooltip } from "@arco-design/web-react";
import toast from "@/components/Toast";
import InfiniteScroll from "@/components/InfiniteScroll";
import ProjectCasesModal from "./components/ProjectCasesModal";
import UploadModal from "./components/UploadModal";
import { getProjectsList, getProjectsdetail } from "@/services/projectLibrary";
import { IconUpload } from "@arco-design/web-react/icon";
// 我的项目库数据
const myProjectsData = [
{
@@ -91,7 +93,7 @@ import "./index.css";
const PAGE_SIZE = 10;
const ProjectLibrary = () => {
const ProjectLibraryPage = () => {
// 处理我的项目数据
const processMyProjects = () => {
const projects = [];
@@ -201,8 +203,19 @@ const ProjectLibrary = () => {
useState(false);
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const [selectedCategory, setSelectedCategory] = useState("全部");
const [uploadModalVisible, setUploadModalVisible] = useState(false);
// 项目分类基于数据中的direction字段
const categories = ["全部", "项目经营管理", "商业活动策划", "文化服务"];
// 根据分类过滤项目
const filteredProjects = useMemo(() => {
if (selectedCategory === "全部") {
return projectList;
}
return projectList.filter(project => project.direction === selectedCategory);
}, [selectedCategory, projectList]);
const handleProjectClick = async (item) => {
// 如果是我的普通项目,不允许点击
@@ -261,13 +274,26 @@ const ProjectLibrary = () => {
<div className="project-library-page">
<div className="project-library-wrapper">
<p className="project-library-title">文旅班级项目库</p>
{/* 项目分类导航栏 */}
<div className="project-category-nav">
{categories.map((category) => (
<span
key={category}
className={`category-item ${selectedCategory === category ? 'active' : ''}`}
onClick={() => setSelectedCategory(category)}
>
{category}
</span>
))}
</div>
<InfiniteScroll
loadMore={fetchProjects}
hasMore={hasMore}
empty={projectList.length === 0}
className="project-library-list"
>
{projectList.map((item) => (
{filteredProjects.map((item) => (
<li className="project-library-item" key={item.id}>
<p className="project-library-item-title">{item.description}</p>
<div>
@@ -281,7 +307,16 @@ const ProjectLibrary = () => {
{/* 我的项目库板块 */}
<div className="project-library-wrapper my-project-library">
<p className="project-library-title">我完成的项目库</p>
<div className="project-library-header">
<p className="project-library-title">我完成的项目库</p>
<button
className="upload-button"
onClick={() => setUploadModalVisible(true)}
>
<IconUpload />
<span>上传</span>
</button>
</div>
<div className="project-library-list">
{/* 可点击的特殊项目 */}
{clickableProjects.map((item) => (
@@ -322,8 +357,13 @@ const ProjectLibrary = () => {
visible={projectCasesModalVisible}
onClose={handleCloseModal}
/>
<UploadModal
visible={uploadModalVisible}
onClose={() => setUploadModalVisible(false)}
/>
</div>
);
};
export default ProjectLibrary;
export default ProjectLibraryPage;

View File

@@ -1,4 +1,5 @@
import { useState } from "react";
import { useState, useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import CoursesVideoPlayer from "@/components/CoursesVideoPlayer";
import PublicCourseList from "@/components/PublicCourseList";
import { mockData } from "@/data/mockData";
@@ -7,6 +8,25 @@ import "./index.css";
const PublicCourses = () => {
// 默认不选中任何课程,显示黑屏状态
const [selectedCourse, setSelectedCourse] = useState(null);
const [searchParams] = useSearchParams();
// 检查URL参数如果有courseId则自动打开对应课程
useEffect(() => {
const courseId = searchParams.get('courseId');
const courseTitle = searchParams.get('courseTitle');
if (courseId || courseTitle) {
// 查找对应的课程
const publicCourses = mockData.publicCourses || [];
const targetCourse = publicCourses.find(course =>
course.id === courseId || course.title === courseTitle
);
if (targetCourse) {
setSelectedCourse(targetCourse);
}
}
}, [searchParams]);
const handleCourseClick = (course) => {
setSelectedCourse(course);

View File

@@ -1,4 +1,5 @@
import { useRef, useState, useEffect } from "react";
import { useLocation } from "react-router-dom";
import { Spin, Empty } from "@arco-design/web-react";
import toast from "@/components/Toast";
import InterviewQuestionsModal from "./components/InterviewQuestionsModal";
@@ -14,6 +15,7 @@ import QuestionIcon from "@/assets/images/ResumeInterviewPage/question_icon2.png
import "./index.css";
const ResumeInterviewPage = () => {
const location = useLocation();
const [activeIndustry, setActiveIndustry] = useState("frontend");
const [interviewModalVisible, setInterviewModalVisible] = useState(false);
const [resumeModalVisible, setResumeModalVisible] = useState(false);
@@ -117,6 +119,7 @@ const ResumeInterviewPage = () => {
title: position.title,
content: selectedTemplate?.content || selectedTemplate?.oldContent || null,
studentResume: pageData.myResume,
selectedTemplate: selectedTemplate, // 添加整个模板数据包括studentInfo
};
setResumeModalData(resumeData);
@@ -161,6 +164,31 @@ const ResumeInterviewPage = () => {
fetchPageData();
}, []);
// 处理从项目库页面传递过来的岗位参数
useEffect(() => {
if (location.state?.selectedPosition && pageData) {
const positionName = location.state.selectedPosition;
// 遍历所有行业查找对应的岗位
for (const industry of pageData.industries) {
const position = industry.positions?.find(p => p.title === positionName);
if (position) {
// 找到岗位后,自动打开简历详情
handlePositionClick(position, industry);
// 滚动到对应的行业区域
setActiveIndustry(industry.id);
setTimeout(() => {
sectionsRef.current[industry.id]?.scrollIntoView({
behavior: "smooth",
block: "start",
});
}, 100);
break;
}
}
}
}, [location.state, pageData]);
// 监听滚动位置更新导航状态
useEffect(() => {
if (!pageData?.industries) return;

View File

@@ -67,6 +67,14 @@ export default [
key: "course",
showMenu: true,
routes: [
{
path: "/career-tree",
name: "就业管家知识树",
element: <CareerTreePage />,
default: "recuUY59K6SkoO",
active: "recuUY59l98AZg",
showMenuItem: true,
},
{
path: "/public-courses",
name: "公共课直播间",
@@ -83,22 +91,29 @@ export default [
active: "recuUY5abx7Arx",
showMenuItem: true,
},
{
path: "/career-tree",
name: "就业管家知识树",
element: <CareerTreePage />,
default: "recuUY59K6SkoO",
active: "recuUY59l98AZg",
showMenuItem: true,
},
{
path: "/homework",
name: "课作业",
name: "课作业",
element: <HomeworkPage />,
default: "recuUY5bpDGGa2",
active: "recuUY5aZHbzCC",
showMenuItem: true,
},
{
path: "/expert-support",
name: "专家支持中心",
element: <ExpertSupportPage />,
default: "recuUY5hQnbcBY",
active: "recuUY5hsxnmk6",
showMenuItem: true,
},
],
},
{
name: "求职",
key: "job",
showMenu: true,
routes: [
{
path: "/job-strategy",
name: "定制求职策略",
@@ -121,21 +136,6 @@ export default [
active: "recuUY5fQqg5MD",
showMenuItem: true,
},
],
},
{
name: "资源",
key: "resource",
showMenu: true,
routes: [
{
path: "/expert-support",
name: "专家支持中心",
element: <ExpertSupportPage />,
default: "recuUY5hQnbcBY",
active: "recuUY5hsxnmk6",
showMenuItem: true,
},
{
path: "/company-jobs",
name: "企业内推岗位",
@@ -150,9 +150,16 @@ export default [
element: <CompanyJobsListPage />,
showMenu: false,
},
],
},
{
name: "资源",
key: "resource",
showMenu: true,
routes: [
{
path: "/resume-interview",
name: "我的简历与面试",
name: "简历与面试",
element: <ResumeInterviewPage />,
default: "recuUY5dTT3xbx",
active: "recuUY5dvQEYlx",

174
update_job_levels.py Normal file
View File

@@ -0,0 +1,174 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
import re
from datetime import datetime
# 读取岗位等级数据
def load_job_levels():
with open('网页未导入数据/文旅产业/岗位等级.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建岗位名称到等级的映射
job_levels_map = {}
for item in data:
job_name = item['❌岗位名称']
level = item['前端查询名称']
job_levels_map[job_name] = level
return job_levels_map
# 更新resumeInterviewMock.js文件
def update_resume_interview_mock(job_levels_map):
file_path = 'src/mocks/resumeInterviewMock.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 更新内容
updated_count = 0
lines = content.split('\n')
new_lines = []
for line in lines:
# 查找position_name字段
if 'position_name:' in line:
# 提取岗位名称
match = re.search(r'position_name:\s*["\']([^"\']+)["\']', line)
if match:
position_name = match.group(1)
if position_name in job_levels_map:
# 找到对应的等级
level = job_levels_map[position_name]
# 查找下一个position_level字段并更新
for i in range(len(lines)):
if lines[i] == line:
# 向后查找position_level
for j in range(i+1, min(i+10, len(lines))):
if 'position_level:' in lines[j]:
old_line = lines[j]
lines[j] = re.sub(
r'position_level:\s*["\'][^"\']*["\']',
f'position_level: "{level}"',
lines[j]
)
if old_line != lines[j]:
updated_count += 1
print(f"更新: {position_name} -> {level}")
break
break
new_lines.append(line)
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
print(f"resumeInterviewMock.js 更新完成,共更新 {updated_count}")
# 更新companyJobsNew.json文件
def update_company_jobs(job_levels_map):
file_path = 'src/data/companyJobsNew.json'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
with open(backup_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"已备份: {backup_path}")
# 更新数据
updated_count = 0
for company in data:
if 'jobs' in company:
for job in company['jobs']:
if 'positionName' in job and job['positionName'] in job_levels_map:
old_level = job.get('jobLevel', '')
new_level = job_levels_map[job['positionName']]
job['jobLevel'] = new_level
if old_level != new_level:
updated_count += 1
print(f"更新: {job['positionName']} -> {new_level}")
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"companyJobsNew.json 更新完成,共更新 {updated_count}")
# 更新mockData.js中的项目库数据
def update_mock_data_projects(job_levels_map):
file_path = 'src/data/mockData.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_job_levels'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 更新项目库中的relatedPositions字段
updated_count = 0
lines = content.split('\n')
for i, line in enumerate(lines):
if 'relatedPositions:' in line or 'targetPositions:' in line:
# 查找数组内容
j = i
while j < len(lines) and ']' not in lines[j]:
j += 1
# 提取并更新数组内容
for k in range(i, j+1):
for job_name, level in job_levels_map.items():
if f'"{job_name}"' in lines[k] or f"'{job_name}'" in lines[k]:
# 检查是否需要添加等级信息(如果还没有的话)
# 这里我们只是确保岗位名称正确,等级信息在其他地方维护
updated_count += 1
print(f"mockData.js 项目库数据检查完成,确认了 {updated_count} 个岗位引用")
# 主函数
def main():
print("=" * 50)
print("开始更新岗位等级数据")
print("=" * 50)
# 加载岗位等级映射
job_levels_map = load_job_levels()
print(f"已加载 {len(job_levels_map)} 个岗位等级映射")
# 显示等级分布
level_counts = {}
for level in job_levels_map.values():
level_counts[level] = level_counts.get(level, 0) + 1
print("\n岗位等级分布:")
for level, count in level_counts.items():
print(f" {level}: {count} 个岗位")
print("\n" + "=" * 50)
# 更新各个文件
print("\n1. 更新简历面试题数据...")
update_resume_interview_mock(job_levels_map)
print("\n2. 更新公司岗位数据...")
update_company_jobs(job_levels_map)
print("\n3. 检查项目库数据...")
update_mock_data_projects(job_levels_map)
print("\n" + "=" * 50)
print("所有更新完成!")
print("=" * 50)
if __name__ == "__main__":
main()

200
update_job_levels_v2.py Normal file
View File

@@ -0,0 +1,200 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
import re
from datetime import datetime
# 读取岗位等级数据
def load_job_levels():
with open('网页未导入数据/文旅产业/岗位等级.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建岗位名称到等级的映射
job_levels_map = {}
for item in data:
job_name = item['❌岗位名称']
level = item['前端查询名称']
job_levels_map[job_name] = level
return job_levels_map
# 更新resumeInterviewMock.js文件 - 添加level字段
def update_resume_interview_mock(job_levels_map):
file_path = 'src/mocks/resumeInterviewMock.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_levels'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 更新内容
updated_count = 0
lines = content.split('\n')
new_lines = []
i = 0
while i < len(lines):
line = lines[i]
new_lines.append(line)
# 查找title字段
if 'title:' in line and 'positions' not in line:
# 提取岗位名称
match = re.search(r'title:\s*["\']([^"\']+)["\']', line)
if match:
position_name = match.group(1)
if position_name in job_levels_map:
level = job_levels_map[position_name]
# 检查下一行是否已经有level字段
has_level = False
for j in range(i+1, min(i+5, len(lines))):
if 'level:' in lines[j]:
has_level = True
# 更新现有的level字段
lines[j] = re.sub(
r'level:\s*["\'][^"\']*["\']',
f'level: "{level}"',
lines[j]
)
updated_count += 1
print(f"更新: {position_name} -> {level}")
break
# 如果没有level字段添加一个
if not has_level:
# 在title后面添加level字段
indent = len(line) - len(line.lstrip())
new_level_line = ' ' * indent + f'level: "{level}",'
# 找到合适的位置插入在title之后
new_lines.append(new_level_line)
updated_count += 1
print(f"添加: {position_name} -> {level}")
i += 1
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(new_lines))
print(f"resumeInterviewMock.js 更新完成,共更新 {updated_count}")
# 更新companyJobsNew.json文件
def update_company_jobs(job_levels_map):
file_path = 'src/data/companyJobsNew.json'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_levels'
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
with open(backup_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"已备份: {backup_path}")
# 更新数据
updated_count = 0
added_count = 0
for company in data:
if 'jobs' in company:
for job in company['jobs']:
position_name = job.get('positionName', '')
if position_name in job_levels_map:
new_level = job_levels_map[position_name]
if 'jobLevel' in job:
old_level = job['jobLevel']
if old_level != new_level:
job['jobLevel'] = new_level
updated_count += 1
print(f"更新: {position_name}: {old_level} -> {new_level}")
else:
job['jobLevel'] = new_level
added_count += 1
print(f"添加: {position_name} -> {new_level}")
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"companyJobsNew.json 更新完成,更新 {updated_count} 处,新增 {added_count}")
# 检查mockData.js中的项目库数据
def check_mock_data_projects(job_levels_map):
file_path = 'src/data/mockData.js'
print("检查mockData.js中的项目库数据...")
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 查找所有引用的岗位
found_positions = set()
# 查找relatedPositions和targetPositions中的岗位
pattern = r'["\']([^"\']+)["\']'
# 查找包含positions的行
lines = content.split('\n')
for i, line in enumerate(lines):
if 'relatedPositions:' in line or 'targetPositions:' in line:
# 查找数组内容
j = i
bracket_count = 0
in_array = False
while j < len(lines):
if '[' in lines[j]:
in_array = True
bracket_count += lines[j].count('[')
if in_array:
matches = re.findall(pattern, lines[j])
for match in matches:
if match in job_levels_map:
found_positions.add(match)
bracket_count -= lines[j].count(']')
if in_array and bracket_count <= 0:
break
j += 1
print(f"在项目库中找到 {len(found_positions)} 个不同的岗位引用:")
for pos in sorted(found_positions):
print(f" - {pos}: {job_levels_map[pos]}")
# 主函数
def main():
print("=" * 50)
print("开始更新岗位等级数据 V2")
print("=" * 50)
# 加载岗位等级映射
job_levels_map = load_job_levels()
print(f"已加载 {len(job_levels_map)} 个岗位等级映射")
# 显示等级分布
level_counts = {}
for level in job_levels_map.values():
level_counts[level] = level_counts.get(level, 0) + 1
print("\n岗位等级分布:")
for level, count in level_counts.items():
print(f" {level}: {count} 个岗位")
print("\n" + "=" * 50)
# 更新各个文件
print("\n1. 更新简历面试题数据...")
update_resume_interview_mock(job_levels_map)
print("\n2. 更新公司岗位数据...")
update_company_jobs(job_levels_map)
print("\n3. 检查项目库数据...")
check_mock_data_projects(job_levels_map)
print("\n" + "=" * 50)
print("所有更新完成!")
print("=" * 50)
if __name__ == "__main__":
main()

101
update_joblevel_json.py Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
from datetime import datetime
# 读取岗位等级数据
def load_job_levels():
with open('网页未导入数据/文旅产业/岗位等级.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建岗位名称到等级的映射
job_levels_map = {}
for item in data:
job_name = item['❌岗位名称']
level = item['前端查询名称']
job_levels_map[job_name] = level
return job_levels_map
# 读取当前的joblevel.json
def load_current_joblevel():
with open('src/data/joblevel.json', 'r', encoding='utf-8') as f:
return json.load(f)
# 重新整理joblevel.json
def reorganize_joblevel():
# 备份原文件
backup_path = f'src/data/joblevel.json.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
with open('src/data/joblevel.json', 'r', encoding='utf-8') as f:
original_data = json.load(f)
with open(backup_path, 'w', encoding='utf-8') as f:
json.dump(original_data, f, ensure_ascii=False, indent=4)
print(f"已备份: {backup_path}")
# 加载岗位等级映射
job_levels_map = load_job_levels()
# 收集所有岗位信息
all_positions = []
for level_key, level_data in original_data['data'].items():
for position in level_data['list']:
all_positions.append(position)
# 按新的等级重新分组
new_data = {
"code": 200,
"message": "操作成功",
"data": {
"high": {
"name": "储备干部岗",
"list": []
},
"middle": {
"name": "技术骨干岗",
"list": []
},
"ordinary": {
"name": "普通岗",
"list": []
}
}
}
# 分配岗位到正确的等级
unmatched_positions = []
for position in all_positions:
position_name = position['position_name']
if position_name in job_levels_map:
level = job_levels_map[position_name]
if level == "储备干部岗":
new_data['data']['high']['list'].append(position)
elif level == "技术骨干岗":
new_data['data']['middle']['list'].append(position)
elif level == "普通岗":
new_data['data']['ordinary']['list'].append(position)
print(f"分配: {position_name} -> {level}")
else:
# 对于未匹配的岗位,保持原有等级或默认为普通岗
unmatched_positions.append(position)
print(f"未找到匹配: {position_name}")
# 将未匹配的岗位添加到普通岗
for position in unmatched_positions:
new_data['data']['ordinary']['list'].append(position)
print(f"默认分配到普通岗: {position['position_name']}")
# 写回文件
with open('src/data/joblevel.json', 'w', encoding='utf-8') as f:
json.dump(new_data, f, ensure_ascii=False, indent=4)
# 统计结果
print("\n" + "=" * 50)
print("重新整理完成!")
print(f"储备干部岗: {len(new_data['data']['high']['list'])} 个岗位")
print(f"技术骨干岗: {len(new_data['data']['middle']['list'])} 个岗位")
print(f"普通岗: {len(new_data['data']['ordinary']['list'])} 个岗位")
print("=" * 50)
if __name__ == "__main__":
reorganize_joblevel()

85
update_missing_fields.py Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取清理后的数据
with open('resume_updates_cleaned.json', 'r', encoding='utf-8') as f:
updates = json.load(f)
# 读取resumeInterviewMock.js
with open('src/mocks/resumeInterviewMock.js', 'r', encoding='utf-8') as f:
content = f.read()
print("开始更新缺失的project_experience字段...")
# 需要更新project_experience的岗位
positions_to_update = [
'文创产品设计师',
'文创产品策划师',
'文创产品设计师助理',
'品牌策划运营专员',
'品牌公关',
'品牌推广专员',
'ip运营',
'IP运营总监助理',
'品牌公关管培生'
]
for position in positions_to_update:
update_data = next((u for u in updates if u['position'] == position), None)
if not update_data:
print(f"⚠ 未找到{position}的更新数据")
continue
# 准备project_experience数据
project_exp = update_data['studentInfo']['project_experience']
# 查找该岗位的studentInfo位置
# 使用更精确的模式匹配
pattern = rf'(position:\s*"{re.escape(position)}"[^}}]*?studentInfo:\s*{{)'
match = re.search(pattern, content, re.DOTALL)
if match:
# 找到studentInfo开始位置
start_pos = match.end()
# 找到对应的结束大括号
brace_count = 1
end_pos = start_pos
while brace_count > 0 and end_pos < len(content):
if content[end_pos] == '{':
brace_count += 1
elif content[end_pos] == '}':
brace_count -= 1
end_pos += 1
# 获取当前的studentInfo内容
student_info_content = content[start_pos:end_pos-1]
# 检查是否有project_experience: null
if 'project_experience: null' in student_info_content:
# 构建新的project_experience
new_project_exp = f'''project_experience: {{
project_name: "{project_exp['project_name']}",
position: "{project_exp['position']}",
time_period: "{project_exp['time_period']}",
company: "{project_exp['company']}",
description: `{project_exp['description']}`
}}'''
# 替换project_experience: null
new_content = student_info_content.replace('project_experience: null', new_project_exp)
# 更新content
content = content[:start_pos] + new_content + content[end_pos-1:]
print(f"{position} project_experience已更新")
else:
print(f" {position} 已有project_experience或结构异常")
# 保存更新后的文件
with open('src/mocks/resumeInterviewMock.js', 'w', encoding='utf-8') as f:
f.write(content)
print("\n✓ 所有project_experience更新完成")

View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
from datetime import datetime
# 读取岗位等级数据
def load_job_levels():
with open('网页未导入数据/文旅产业/岗位等级.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建岗位名称到等级的映射
job_levels_map = {}
for item in data:
job_name = item['❌岗位名称']
level = item['前端查询名称']
job_levels_map[job_name] = level
return job_levels_map
# 更新projectLibraryMock.js文件中的applicablePositions
def update_project_library_mock(job_levels_map):
file_path = 'src/mocks/projectLibraryMock.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_levels'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 定义一个函数来更新单个applicablePositions数组
def update_positions_array(match):
positions_str = match.group(1)
# 匹配所有的岗位对象
pattern = r"\{\s*level:\s*['\"]([^'\"]+)['\"]\s*,\s*position:\s*['\"]([^'\"]+)['\"]\s*\}"
updated_positions = []
for pos_match in re.finditer(pattern, positions_str):
old_level = pos_match.group(1)
position_name = pos_match.group(2)
# 查找正确的等级
if position_name in job_levels_map:
new_level = job_levels_map[position_name]
updated_positions.append(f"{{ level: '{new_level}', position: '{position_name}' }}")
if old_level != new_level:
print(f" 更新: {position_name}: {old_level} -> {new_level}")
else:
# 保持原样
updated_positions.append(f"{{ level: '{old_level}', position: '{position_name}' }}")
print(f" 未找到匹配: {position_name}")
return f"applicablePositions: [{', '.join(updated_positions)}]"
# 更新所有的applicablePositions
updated_content = re.sub(
r'applicablePositions:\s*\[(.*?)\]',
update_positions_array,
content,
flags=re.DOTALL
)
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write(updated_content)
print(f"projectLibraryMock.js 更新完成")
# 主函数
def main():
print("=" * 50)
print("开始更新项目库中的岗位等级数据")
print("=" * 50)
# 加载岗位等级映射
job_levels_map = load_job_levels()
print(f"已加载 {len(job_levels_map)} 个岗位等级映射\n")
# 更新文件
print("更新项目库Mock数据...")
update_project_library_mock(job_levels_map)
print("\n" + "=" * 50)
print("所有更新完成!")
print("=" * 50)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,153 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
from datetime import datetime
# 读取岗位等级数据
def load_job_levels():
with open('网页未导入数据/文旅产业/岗位等级.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建岗位名称到等级的映射
job_levels_map = {}
for item in data:
job_name = item['❌岗位名称']
level = item['前端查询名称']
job_levels_map[job_name] = level
return job_levels_map
# 读取项目案例适用岗位映射
def load_project_positions_mapping():
with open('网页未导入数据/文旅产业/项目案例适用岗位.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 创建项目名称到岗位列表的映射
mapping = {}
for item in data:
project_name = item['案例名称']
positions = item['岗位名称_文旅']
mapping[project_name] = positions
return mapping
# 定义等级排序
LEVEL_ORDER = {
'普通岗': 1,
'技术骨干岗': 2,
'储备干部岗': 3
}
# 生成适用岗位数组字符串
def generate_positions_array(positions, job_levels_map):
# 创建岗位对象列表
position_objects = []
for position in positions:
if position in job_levels_map:
level = job_levels_map[position]
position_objects.append({
'level': level,
'position': position,
'order': LEVEL_ORDER.get(level, 999)
})
else:
print(f" 警告: 未找到岗位 '{position}' 的等级信息")
# 按等级排序
position_objects.sort(key=lambda x: x['order'])
# 生成字符串
positions_str = ', '.join([
f"{{ level: '{p['level']}', position: '{p['position']}' }}"
for p in position_objects
])
return f"[{positions_str}]"
# 更新projectLibraryMock.js文件
def update_project_library_mock(project_mapping, job_levels_map):
file_path = 'src/mocks/projectLibraryMock.js'
# 备份文件
backup_path = f'{file_path}.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}_remapped'
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"已备份: {backup_path}")
# 项目名称映射(因为代码中的名称可能略有不同)
name_variations = {
'id: 1': '舟山某民宿180天提升入住率项目',
'id: 2': '希尔顿欢朋酒店经营管理与服务一体化优化项目',
'id: 3': '长安汽车新款车型线下推广活动',
'id: 4': '春风 450MT新品上市营销活动策划项目',
'id: 5': '敦煌文创品牌策划与IP运营',
'id: 6': '"长安幻夜"文创IP运营与品牌建设项目',
'id: 7': '2024年深圳国际家具展策划项目',
'id: 8': '2024 合肥国际 3C 电子产业博览会策划项目',
'id: 9': '盐城第九届 ICGC 动漫嘉年华漫展策划项目',
'id: 10': '某地森林湿地自然景区多平台新媒体运营方案',
'id: 11': '漓江畔水墨居度假酒店新媒体直播运营方案',
'id: 12': '某自驾游平台SEO/SEM全流程优化项目',
'id: 13': '环渤海经济圈城市足球冠军赛策划与执行项目',
'id: 14': '某歌手2025公益演唱会策划与执行项目',
'id: 15': '贵州黔东南非遗文化探索之旅线路设计项目',
'id: 16': '某宠物生活馆经营改善项目',
'id: 17': '"水墨苏乡"文化创意产品设计与量产落地项目',
'id: 18': '谷子店开店与经营管理',
'id: 19': '轻奢露营市集玩乐活动运营项目',
'id: 20': '中国科学院武汉植物园生态科普与文旅运营项目'
}
updated_count = 0
# 对每个项目进行处理
for id_pattern, project_name in name_variations.items():
if project_name in project_mapping:
positions = project_mapping[project_name]
new_positions_str = generate_positions_array(positions, job_levels_map)
# 查找并替换该项目的applicablePositions
# 使用更精确的正则表达式来定位特定项目
pattern = rf'({id_pattern}.*?applicablePositions:\s*)\[[^\]]*\]'
def replace_func(match):
nonlocal updated_count
updated_count += 1
print(f"\n更新项目 {project_name}:")
print(f" 新岗位: {positions}")
return match.group(1) + new_positions_str
content = re.sub(pattern, replace_func, content, flags=re.DOTALL)
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"\nprojectLibraryMock.js 更新完成,共更新了 {updated_count} 个项目")
# 主函数
def main():
print("=" * 50)
print("根据项目案例适用岗位.json重新匹配适用岗位")
print("=" * 50)
# 加载数据
job_levels_map = load_job_levels()
print(f"已加载 {len(job_levels_map)} 个岗位等级映射")
project_mapping = load_project_positions_mapping()
print(f"已加载 {len(project_mapping)} 个项目岗位映射\n")
# 更新文件
update_project_library_mock(project_mapping, job_levels_map)
print("\n" + "=" * 50)
print("所有更新完成!")
print("=" * 50)
if __name__ == "__main__":
main()

91
update_resume_data.py Normal file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
# 读取提取的数据
with open('extracted_resume_data.json', 'r', encoding='utf-8') as f:
extracted_data = json.load(f)
def parse_resume_content(content):
"""解析简历内容,提取项目经历、核心能力、复合能力和个人总结"""
# 提取项目信息
project_name = re.search(r'项目名称:(.+?)(?:\n|$)', content)
position = re.search(r'实习岗位:(.+?)(?:\n|$)', content)
time_period = re.search(r'实习时间:(.+?)(?:\n|$)', content)
company = re.search(r'实习单位:(.+?)(?:\n|$)', content)
# 提取岗位职责
duties_match = re.search(r'(?:岗位职责|项目职责)[\s]*\n((?:\d+\..+?(?=\n#|\n\n|\Z))+)', content, re.DOTALL)
if duties_match:
duties_text = duties_match.group(1).strip()
# 提取所有职责项并合并
duties_items = re.findall(r'\d+\.\s*(.+?)(?=\d+\.|$)', duties_text, re.DOTALL)
description = '\n'.join([d.strip().replace('\n', '') for d in duties_items if d])
else:
description = ""
# 提取核心能力
core_skills_match = re.search(r'核心能力[\s]*\n((?:\d+\..+?(?=\n#|\n\n|\Z))+)', content, re.DOTALL)
core_skills = []
if core_skills_match:
skills_text = core_skills_match.group(1).strip()
# 分割并清理每个技能项
core_skills = re.findall(r'\d+\.\s*(.+?)(?=\d+\.|$)', skills_text, re.DOTALL)
core_skills = [s.strip().replace('\n', '').replace(' ', ' ') for s in core_skills if s]
# 提取复合能力
compound_skills_match = re.search(r'复合能力[\s]*\n((?:\d+\..+?(?=\n#|\Z))+)', content, re.DOTALL)
compound_skills = []
if compound_skills_match:
skills_text = compound_skills_match.group(1)
# 提取每个复合能力(格式:数字. 能力名称:描述)
compound_skills = re.findall(r'\d+\.\s*(.+?)(?=\d+\.|$)', skills_text, re.DOTALL)
compound_skills = [s.strip().replace('\n', '') for s in compound_skills if s]
# 提取个人总结/评价
personal_summary_match = re.search(r'(?:个人总结|个人评价)[\s]*\n(.+?)(?:\Z)', content, re.DOTALL)
personal_summary = personal_summary_match.group(1).strip() if personal_summary_match else ""
return {
'project_experience': {
'project_name': project_name.group(1) if project_name else "",
'position': position.group(1) if position else "",
'time_period': time_period.group(1) if time_period else "",
'company': company.group(1) if company else "",
'description': description
},
'core_skills': core_skills,
'compound_skills': compound_skills,
'personal_summary': personal_summary
}
# 生成JavaScript代码更新
updates = []
for position_name, data in extracted_data.items():
content = data.get('简历内容', '')
if content:
student_info = parse_resume_content(content)
# 格式化为JavaScript对象
js_obj = {
'position': position_name,
'studentInfo': student_info
}
updates.append(js_obj)
# 保存为JSON供后续处理
with open('resume_updates.json', 'w', encoding='utf-8') as f:
json.dump(updates, f, ensure_ascii=False, indent=2)
print(f"成功处理 {len(updates)} 个岗位的数据")
print("已保存到 resume_updates.json")
# 显示第一个更新作为示例
if updates:
print("\n示例数据(第一个岗位):")
print(json.dumps(updates[0], ensure_ascii=False, indent=2)[:1000])

62
verify_data.js Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env node
import { resumeInterviewMockData } from './src/mocks/resumeInterviewMock.js';
const positionsToCheck = [
'民宿管家',
'民宿客房管家',
'民宿运营专员',
'露营地运营专员',
'新媒体运营专员',
'文创产品设计师',
'文创产品策划师',
'文创产品设计师助理',
'品牌策划运营专员',
'品牌公关',
'品牌推广专员',
'ip运营',
'IP运营总监助理',
'品牌公关管培生'
];
console.log('验证简历数据完整性...\n');
console.log('=' .repeat(60));
// 检查每个行业
for (const industry of resumeInterviewMockData.industries) {
const templates = resumeInterviewMockData.resumeTemplates[industry.name] || [];
for (const position of industry.positions) {
if (!positionsToCheck.includes(position.title)) continue;
// 查找对应的模板
const template = templates.find(t => t.position === position.title);
console.log(`\n岗位: ${position.title}`);
console.log(`行业: ${industry.name}`);
if (!template) {
console.log('❌ 未找到简历模板');
continue;
}
// 检查content
const hasContent = !!(template.content?.original || template.content?.modified);
console.log(`- content: ${hasContent ? '✅' : '❌'}`);
// 检查studentInfo
const hasStudentInfo = !!template.studentInfo;
console.log(`- studentInfo: ${hasStudentInfo ? '✅' : '❌'}`);
if (hasStudentInfo) {
const info = template.studentInfo;
console.log(` - project_experience: ${info.project_experience ? '✅' : '❌'}`);
console.log(` - core_skills: ${info.core_skills ? '✅' : '❌'}`);
console.log(` - compound_skills: ${info.compound_skills ? '✅' : '❌'}`);
console.log(` - personal_summary: ${info.personal_summary ? '✅' : '❌'}`);
}
}
}
console.log('\n' + '=' .repeat(60));
console.log('验证完成!');

View File

@@ -0,0 +1,202 @@
[
{
"课程名称": "AI 学习路径与课程总览",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "AI 工具与环境初始化",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "常见 AI 工具对比与选择方法",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "AI 辅助思维导图与可视化工具实践",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "Obsidian × AI双向链接与模板应用",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "Notion × AI数据库与多视角管理",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "DuoduoNote × AI多源视频高效采集",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "AI 辅助卡片化写作与引用规范",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "API × AI 自动同步Notion/Obsidian",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "AI 驱动的日程与任务管理",
"单元": "AI 入门与工具环境"
},
{
"课程名称": "RAG 与 AI 知识增强全景",
"单元": "RAG 与检索增强"
},
{
"课程名称": "向量检索与阈值调优Embedding 技术)",
"单元": "RAG 与检索增强"
},
{
"课程名称": "AI 混合检索:关键词 × 向量",
"单元": "RAG 与检索增强"
},
{
"课程名称": "AI 重排与结果融合",
"单元": "RAG 与检索增强"
},
{
"课程名称": "AI 评测集构建与标注规范",
"单元": "RAG 与检索增强"
},
{
"课程名称": "AI 离线评测与迭代优化",
"单元": "RAG 与检索增强"
},
{
"课程名称": "RAG 接入 AI 第二大脑",
"单元": "RAG 与检索增强"
},
{
"课程名称": "AI 自动化思维:从事件风暴到数据流",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "AI 错误处理与补偿机制",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "AI 定时任务与数据抓取管线",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "Dify多工具 AI Agent 编排",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "Dify × AI 应用评测与灰度发布",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "MCP 工具集入门与 AI 场景",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "MCP × AI 自动化融合案例",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "AI 驱动的低代码平台实战Zapier / Make",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "Agent 自动化:多任务协作与调度",
"单元": "AI 自动化与任务编排"
},
{
"课程名称": "AI 项目骨架与协作Trea/Claude/Copilot",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI Agent 前端交互(对话与工具状态)",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "RAG × AI 前端展示(可引用回答)",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "前端触发 AI 自动化Webhook 应用)",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI 应用部署与安全Vercel/Netlify",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI 性能优化与可访问性保障",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI 项目演示脚本与讲解录制",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI 应用问题排查与日志分析",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "项目协作与版本控制GitHub / GitLab × AI",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "数据可视化与仪表盘Superset / PowerBI × AI",
"单元": "AI 项目开发与前端交互"
},
{
"课程名称": "AI大模型原理解析",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "提示工程高级策略",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "模型微调方法",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "AI DevOps 与 MLOps",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "向量数据库深度实践",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "AI 安全与对抗样本",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "AI 成本优化与算力管理",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "AutoML 与 AutoAgent",
"单元": "AI 大模型与核心原理"
},
{
"课程名称": "AI × 教育的应用",
"单元": "AI 行业应用与综合实战"
},
{
"课程名称": "AI × 金融的应用",
"单元": "AI 行业应用与综合实战"
},
{
"课程名称": "AI × 医疗的应用",
"单元": "AI 行业应用与综合实战"
},
{
"课程名称": "AI × 制造业的应用",
"单元": "AI 行业应用与综合实战"
},
{
"课程名称": "端到端 AI 应用开发",
"单元": "AI 行业应用与综合实战"
},
{
"课程名称": "企业级 RAG 应用实战",
"单元": "AI 行业应用与综合实战"
}
]

View File

@@ -6,11 +6,11 @@
### 项目名称2024年深圳国际家具展策划项目
### (二)实习岗位:会展执行助理
### (二)实习岗位:会展策划师助理
### 实习时间2024.09-2024.10
### 实习时间2023.09-2023.11
### (四)实习单位:某某公司
### (四)实习单位:深圳市华奥展览服务有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:会展策划师助理
### 实习时间2024.09-2024.10
### 实习时间2023.09-2023.11
### (四)实习单位:某某公司
### (四)实习单位:深圳市华奥展览服务有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:会展讲解员
### 实习时间2024.09-2024.10
### 实习时间2023.09-2023.11
### (四)实习单位:某某公司
### (四)实习单位:深圳市华奥展览服务有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:文旅运营总监助理
### (三)实习单位:某某公司
### (三)实习单位:2024.02-2024.03
### (四)实习时间:XXXX时间
### (四)实习时间:湖北视界文旅数字科技有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:旅游规划助理
### 实习时间2024.09-2024.10
### 实习时间2024.05-2024.07
### (四)实习单位:某某公司
### (四)实习单位:上海好拾光旅游咨询有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:旅游计调助理
### 实习时间2024.09-2024.10
### 实习时间2024.05-2024.07
### (四)实习单位:某某公司
### (四)实习单位:上海好拾光旅游咨询有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:景区运营助理
### (三)实习时间:XXXX时间
### (三)实习时间:2023.12-2024.02
### (四)实习单位:某某公司
### (四)实习单位:湖北视界文旅数字科技有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:活动执行助理
### (三)实习时间:XXXX时间
### (三)实习时间:2024.04-2024.06
### (四)实习单位:某某公司
### (四)实习单位:四川西行驿站文化传播有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:活动策划是助理
### (三)实习时间:XXXX时间
### (三)实习时间:2024.06-2024.07
### (四)实习单位:某某公司
### (四)实习单位:浙江春风动力股份有限公司
### (五)岗位职责:

View File

@@ -8,9 +8,9 @@
### (二)实习岗位:漫展策划师助理
### (三)实习时间:XXXX时间
### (三)实习时间:2023.10-2024.12
### (四)实习单位:某某公司
### (四)实习单位:盐城东拓国际会展服务有限公司
### (五)岗位职责:

View File

@@ -0,0 +1,50 @@
[
{
"课程名称": "如何进行有效的沟通与表达",
"单元名称": "沟通与协作能力"
},
{
"课程名称": "高效团队协作与跨部门合作技巧",
"单元名称": "沟通与协作能力"
},
{
"课程名称": "问题解决与批判性思维的培养",
"单元名称": "问题解决与思维能力"
},
{
"课程名称": "创新思维与数字化转型中的机会",
"单元名称": "问题解决与思维能力"
},
{
"课程名称": "企业文化与职场适应",
"单元名称": "职场基础与个人发展"
},
{
"课程名称": "在企业中如何进行自我管理与自主学习",
"单元名称": "职场基础与个人发展"
},
{
"课程名称": "情商管理与压力应对",
"单元名称": "职场基础与个人发展"
},
{
"课程名称": "个人品牌与网络形象管理",
"单元名称": "职场基础与个人发展"
},
{
"课程名称": "如何利用AI工具在企业中升职加薪",
"单元名称": "职业发展与管理技能"
},
{
"课程名称": "目标管理与绩效提升的系统方法",
"单元名称": "职业发展与管理技能"
},
{
"课程名称": "职场领导力与影响力的初步养成",
"单元名称": "职业发展与管理技能"
},
{
"课程名称": "长期职业规划与可持续发展之路",
"单元名称": "职业发展与管理技能"
}
]

View File

@@ -0,0 +1,50 @@
[
{
"单元": "AI 入门与工具环境",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6sRee.jpg"
},
{
"单元": "RAG 与检索增强",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6zwRv.jpeg"
},
{
"单元": "AI 自动化与任务编排",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW7gMz6CiPN.jpeg"
},
{
"单元": "AI 项目开发与前端交互",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuW8VeXQDVI2.jpeg"
},
{
"单元": "AI 大模型与核心原理",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWnTJ2VZpoL.jpeg"
},
{
"单元": "AI 行业应用与综合实战",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWokg39Rmbf.jpeg"
},
{
"单元": "必备营销技能",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWokGcLVoRh.jpg"
},
{
"单元": "自我营销课",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWokT3zxfhR.jpeg"
},
{
"单元": "沟通与协作能力",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWolCj6ffh5.jpeg"
},
{
"单元": "问题解决与思维能力",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWolCCOVTt1.jpg"
},
{
"单元": "职场基础与个人发展",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWolCCOM6l0.jpeg"
},
{
"单元": "职业发展与管理技能",
"url": "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/public_bg/recuWolCCOlOCz.jpg"
}
]

Some files were not shown because too many files have changed in this diff Show More