|
@@ -688,10 +688,10 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="question-actions">
|
|
|
- <!-- <el-button type="text" @click="editQuestion(chatQuestions.indexOf(element))">
|
|
|
+ <div class="question-actions" style="margin-top: 0px;">
|
|
|
+ <el-button type="text" @click="editQuestion(chatQuestions.indexOf(element))">
|
|
|
<el-icon><Edit /></el-icon>
|
|
|
- </el-button> -->
|
|
|
+ </el-button>
|
|
|
<el-button type="text" @click="deleteQuestion(chatQuestions.indexOf(element))">
|
|
|
<el-icon><Delete /></el-icon>
|
|
|
</el-button>
|
|
@@ -1049,7 +1049,7 @@
|
|
|
|
|
|
<!-- 在 template 中添加问题编辑弹框 -->
|
|
|
<el-dialog
|
|
|
- title="添加问题"
|
|
|
+ title="编辑问题"
|
|
|
v-model="showQuestionDialog"
|
|
|
width="500px"
|
|
|
:close-on-click-modal="false"
|
|
@@ -1058,56 +1058,137 @@
|
|
|
<div class="question-form">
|
|
|
<div class="form-item">
|
|
|
<div class="form-label">
|
|
|
- 标题<span class="required">*</span>
|
|
|
+ 题目内容<span class="required">*</span>
|
|
|
</div>
|
|
|
<el-input
|
|
|
- v-model="questionForm.title"
|
|
|
- placeholder="请输入标题"
|
|
|
- maxlength="15"
|
|
|
+ v-model="questionForm.content"
|
|
|
+ type="textarea"
|
|
|
+ rows="4"
|
|
|
+ placeholder="请描述一次你如何在紧迫的时间内完成一个复杂的后端开发任务的经历"
|
|
|
+ maxlength="300"
|
|
|
show-word-limit
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
<div class="form-item">
|
|
|
- <div class="form-label">考察能力</div>
|
|
|
+ <div class="form-label">胜任力标签</div>
|
|
|
<el-select
|
|
|
- v-model="questionForm.ability"
|
|
|
- placeholder="请选择考察能力"
|
|
|
+ v-model="questionForm.competencyTags"
|
|
|
+ placeholder="请选择胜任力标签"
|
|
|
class="full-width"
|
|
|
+ multiple
|
|
|
+ @change="handleCompetencyTagsChange"
|
|
|
>
|
|
|
- <el-option label="深入考察抗压能力" value="pressure" />
|
|
|
- <el-option label="候选人回答中包含一个详细的案例" value="case" />
|
|
|
- <el-option label="获取候选人明确的毕业院校和专业" value="education" />
|
|
|
+ <el-option
|
|
|
+ v-for="tag in competencyTagOptions"
|
|
|
+ :key="tag.value"
|
|
|
+ :label="tag.label"
|
|
|
+ :value="tag.value"
|
|
|
+ />
|
|
|
</el-select>
|
|
|
+ <div class="form-tip">选择胜任力标签和胜任力标签,可多选</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="form-item">
|
|
|
<div class="form-label">
|
|
|
- 面试内容<span class="required">*</span>
|
|
|
+ 胜任力配置
|
|
|
</div>
|
|
|
- <el-input
|
|
|
- v-model="questionForm.content"
|
|
|
- type="textarea"
|
|
|
- rows="4"
|
|
|
- placeholder="请输入面试内容"
|
|
|
- maxlength="300"
|
|
|
- show-word-limit
|
|
|
- />
|
|
|
+ <div class="competency-config">
|
|
|
+ <div class="config-row">
|
|
|
+ <span class="config-label">标签</span>
|
|
|
+ <span class="config-label">权重</span>
|
|
|
+ <span class="config-label">级别</span>
|
|
|
+ </div>
|
|
|
+ <div class="config-row">
|
|
|
+ <span class="tag-name">时间管理</span>
|
|
|
+ <el-input-number v-model="questionForm.weight" :min="0" :max="100" :step="1" controls-position="right" /> %
|
|
|
+ <el-input-number v-model="questionForm.level" :min="1" :max="5" :step="1" controls-position="right" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-tip">配置各个胜任力标签的权重,总和需要100%</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="form-item">
|
|
|
- <div class="form-label">对话目标</div>
|
|
|
- <el-input
|
|
|
- v-model="questionForm.target"
|
|
|
- type="textarea"
|
|
|
- rows="3"
|
|
|
- placeholder="输入你想在对话中达成的目标,示例:
|
|
|
-• 深入考察抗压能力
|
|
|
-• 候选人回答中包含一个详细的案例
|
|
|
-• 获取候选人明确的毕业院校和专业"
|
|
|
- maxlength="100"
|
|
|
- show-word-limit
|
|
|
+ <div class="form-label">题目形式</div>
|
|
|
+ <el-select
|
|
|
+ v-model="questionForm.type"
|
|
|
+ placeholder="开放问题"
|
|
|
+ class="full-width"
|
|
|
+ @change="handleQuestionTypeChange"
|
|
|
+ >
|
|
|
+ <el-option label="开放问题" value="open" />
|
|
|
+ <el-option label="单选题" value="single" />
|
|
|
+ <el-option label="多选题" value="multiple" />
|
|
|
+ <el-option label="填空题" value="fill" />
|
|
|
+ <el-option label="自言语" value="self" />
|
|
|
+ </el-select>
|
|
|
+ <div class="form-tip">选择题目的形式:开放问题、单选题、多选题、填空题、自言语</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="form-label">适用职位</div>
|
|
|
+ <el-select
|
|
|
+ v-model="questionForm.position"
|
|
|
+ placeholder="请选择适用职位类型"
|
|
|
+ class="full-width"
|
|
|
+ multiple
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="pos in positionOptions"
|
|
|
+ :key="pos.value"
|
|
|
+ :label="pos.label"
|
|
|
+ :value="pos.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <div class="form-tip">选择题目适用的职位类型,可多选</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="form-label">分类</div>
|
|
|
+ <el-select
|
|
|
+ v-model="questionForm.category"
|
|
|
+ placeholder="请选择题目分类"
|
|
|
+ class="full-width"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="cat in categoryOptions"
|
|
|
+ :key="cat.value"
|
|
|
+ :label="cat.label"
|
|
|
+ :value="cat.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <div class="form-tip">选择题目所属分类</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="form-label">标签</div>
|
|
|
+ <el-select
|
|
|
+ v-model="questionForm.tags"
|
|
|
+ placeholder="请选择标签"
|
|
|
+ class="full-width"
|
|
|
+ multiple
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="tag in tagOptions"
|
|
|
+ :key="tag.value"
|
|
|
+ :label="tag.label"
|
|
|
+ :value="tag.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <div class="form-tip">选择题目相关标签,可多选</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="form-label">建议时长(秒)</div>
|
|
|
+ <el-input-number
|
|
|
+ v-model="questionForm.suggestedDuration"
|
|
|
+ :min="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="请输入建议回答时长"
|
|
|
+ class="full-width"
|
|
|
/>
|
|
|
+ <div class="form-tip">建议回答题目的时长,单位为秒</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
@@ -2044,14 +2125,142 @@ const maxQuestions = ref(5); // 默认5个问题
|
|
|
// 在 script setup 部分添加以下响应式变量
|
|
|
const showQuestionDialog = ref(false); // 控制添加问题弹框显示
|
|
|
const questionForm = reactive({
|
|
|
- title: '', // 标题
|
|
|
- ability: '', // 考察能力
|
|
|
- content: '', // 面试内容
|
|
|
- target: '', // 对话目标
|
|
|
+ content: '', // 题目内容
|
|
|
+ competencyTags: [], // 胜任力标签
|
|
|
weight: 100, // 权重占比,默认100%
|
|
|
- maxAnswers: 1 // 最多回答次数,默认1次
|
|
|
+ level: 1, // 胜任力级别,默认1级
|
|
|
+ type: 'open', // 题目形式:开放问题/单选题/多选题/填空题/自言语
|
|
|
+ position: [], // 适用职位
|
|
|
+ category: '', // 分类
|
|
|
+ tags: [], // 标签
|
|
|
+ suggestedDuration: 60 // 建议时长,默认60秒
|
|
|
});
|
|
|
|
|
|
+// 胜任力标签选项
|
|
|
+const competencyTagOptions = ref([
|
|
|
+ { label: '时间管理', value: 'time_management' },
|
|
|
+ { label: '沟通能力', value: 'communication' },
|
|
|
+ { label: '团队协作', value: 'teamwork' },
|
|
|
+ { label: '问题解决', value: 'problem_solving' },
|
|
|
+ { label: '抗压能力', value: 'pressure_resistance' }
|
|
|
+]);
|
|
|
+
|
|
|
+// 职位类型选项
|
|
|
+const positionOptions = ref([
|
|
|
+ { label: '后端开发', value: 'backend' },
|
|
|
+ { label: '前端开发', value: 'frontend' },
|
|
|
+ { label: '产品经理', value: 'product_manager' },
|
|
|
+ { label: '项目经理', value: 'project_manager' },
|
|
|
+ { label: '测试工程师', value: 'test_engineer' }
|
|
|
+]);
|
|
|
+
|
|
|
+// 题目分类选项
|
|
|
+const categoryOptions = ref([
|
|
|
+ { label: '技术能力', value: 'tech' },
|
|
|
+ { label: '管理能力', value: 'management' },
|
|
|
+ { label: '沟通能力', value: 'communication' },
|
|
|
+ { label: '专业知识', value: 'professional' },
|
|
|
+ { label: '个人素质', value: 'personal' }
|
|
|
+]);
|
|
|
+
|
|
|
+// 标签选项
|
|
|
+const tagOptions = ref([
|
|
|
+ { label: '时间管理', value: 'time_management' },
|
|
|
+ { label: '压力处理', value: 'pressure_handling' },
|
|
|
+ { label: '团队合作', value: 'team_cooperation' },
|
|
|
+ { label: '问题分析', value: 'problem_analysis' },
|
|
|
+ { label: '创新思维', value: 'innovative_thinking' }
|
|
|
+]);
|
|
|
+
|
|
|
+// 重置问题表单
|
|
|
+const resetQuestionForm = () => {
|
|
|
+ Object.assign(questionForm, {
|
|
|
+ content: '',
|
|
|
+ competencyTags: [],
|
|
|
+ weight: 100,
|
|
|
+ level: 1,
|
|
|
+ type: 'open',
|
|
|
+ position: [],
|
|
|
+ category: '',
|
|
|
+ tags: [],
|
|
|
+ suggestedDuration: 60
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 取消添加问题
|
|
|
+const cancelAddQuestion = () => {
|
|
|
+ showQuestionDialog.value = false;
|
|
|
+ resetQuestionForm();
|
|
|
+};
|
|
|
+
|
|
|
+// 确认添加问题
|
|
|
+const confirmAddQuestion = async () => {
|
|
|
+ // 表单验证
|
|
|
+ if (!questionForm.content) {
|
|
|
+ ElMessage.error('请输入题目内容');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证胜任力配置
|
|
|
+ if (!validateCompetencyConfig()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证其他必填项
|
|
|
+ if (!questionForm.type) {
|
|
|
+ ElMessage.error('请选择题目形式');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (questionForm.position.length === 0) {
|
|
|
+ ElMessage.error('请选择适用职位');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!questionForm.category) {
|
|
|
+ ElMessage.error('请选择题目分类');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (questionForm.suggestedDuration <= 0) {
|
|
|
+ ElMessage.error('请设置有效的建议时长');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 创建新的问题对象
|
|
|
+ const newQuestion = {
|
|
|
+ content: questionForm.content,
|
|
|
+ competencyTags: questionForm.competencyTags,
|
|
|
+ weight: questionForm.weight,
|
|
|
+ level: questionForm.level,
|
|
|
+ type: questionForm.type,
|
|
|
+ position: questionForm.position,
|
|
|
+ category: questionForm.category,
|
|
|
+ tags: questionForm.tags,
|
|
|
+ suggestedDuration: questionForm.suggestedDuration
|
|
|
+ };
|
|
|
+
|
|
|
+ // TODO: 调用API保存问题
|
|
|
+ // const response = await api.saveQuestion(newQuestion);
|
|
|
+
|
|
|
+ // 关闭弹窗
|
|
|
+ showQuestionDialog.value = false;
|
|
|
+
|
|
|
+ // 重置表单
|
|
|
+ resetQuestionForm();
|
|
|
+
|
|
|
+ // 提示成功
|
|
|
+ ElMessage.success('问题添加成功');
|
|
|
+
|
|
|
+ // 刷新问题列表
|
|
|
+ // await loadQuestions();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('添加问题失败:', error);
|
|
|
+ ElMessage.error('添加问题失败,请重试');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
// 在 script setup 中添加以下响应式变量
|
|
|
const showDataCollectionDialog = ref(false); // 控制资料收集对话框显示
|
|
|
const dataCollectionForm = reactive({
|
|
@@ -2680,7 +2889,7 @@ const handleAddQuestion = () => {
|
|
|
showQuestionDialog.value = true;
|
|
|
};
|
|
|
|
|
|
-// 取消添加问题
|
|
|
+/* // 取消添加问题
|
|
|
const cancelAddQuestion = () => {
|
|
|
showQuestionDialog.value = false;
|
|
|
// 重置表单
|
|
@@ -2692,9 +2901,9 @@ const cancelAddQuestion = () => {
|
|
|
weight: 100,
|
|
|
maxAnswers: 1
|
|
|
});
|
|
|
-};
|
|
|
+}; */
|
|
|
|
|
|
-// 确认添加问题
|
|
|
+/* // 确认添加问题
|
|
|
const confirmAddQuestion = () => {
|
|
|
if (!questionForm.title || !questionForm.content) {
|
|
|
ElMessage.warning('请填写必填项');
|
|
@@ -2724,7 +2933,7 @@ const confirmAddQuestion = () => {
|
|
|
|
|
|
// 提示成功
|
|
|
ElMessage.success('问题添加成功');
|
|
|
-};
|
|
|
+}; */
|
|
|
|
|
|
// 导入问题处理方法
|
|
|
const handleImportQuestion = () => {
|
|
@@ -4606,6 +4815,58 @@ const handleAutoGenerate = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 处理胜任力标签变化
|
|
|
+const handleCompetencyTagsChange = (value: string[]) => {
|
|
|
+ questionForm.competencyTags = value;
|
|
|
+ // 如果只有一个标签,自动设置权重为100%
|
|
|
+ if (value.length === 1) {
|
|
|
+ questionForm.weight = 100;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 验证胜任力配置
|
|
|
+const validateCompetencyConfig = () => {
|
|
|
+ if (questionForm.competencyTags.length === 0) {
|
|
|
+ ElMessage.warning('请至少选择一个胜任力标签');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (questionForm.weight <= 0 || questionForm.weight > 100) {
|
|
|
+ ElMessage.warning('权重必须在1-100之间');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (questionForm.level < 1 || questionForm.level > 5) {
|
|
|
+ ElMessage.warning('级别必须在1-5之间');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+};
|
|
|
+
|
|
|
+// 处理题目形式变化
|
|
|
+const handleQuestionTypeChange = (value: string) => {
|
|
|
+ questionForm.type = value;
|
|
|
+ // 根据题目形式设置默认建议时长
|
|
|
+ switch (value) {
|
|
|
+ case 'open':
|
|
|
+ questionForm.suggestedDuration = 120; // 开放题默认2分钟
|
|
|
+ break;
|
|
|
+ case 'single':
|
|
|
+ case 'multiple':
|
|
|
+ questionForm.suggestedDuration = 60; // 选择题默认1分钟
|
|
|
+ break;
|
|
|
+ case 'fill':
|
|
|
+ questionForm.suggestedDuration = 30; // 填空题默认30秒
|
|
|
+ break;
|
|
|
+ case 'self':
|
|
|
+ questionForm.suggestedDuration = 180; // 自言语默认3分钟
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ questionForm.suggestedDuration = 60;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -5066,4 +5327,67 @@ const handleAutoGenerate = async () => {
|
|
|
align-items: center;
|
|
|
width: 80px; // 设置一个固定宽度
|
|
|
}
|
|
|
+
|
|
|
+.question-form {
|
|
|
+ .form-item {
|
|
|
+ margin-bottom: 20px;
|
|
|
+
|
|
|
+ .form-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ .required {
|
|
|
+ color: #f56c6c;
|
|
|
+ margin-left: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-tip {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #999;
|
|
|
+ margin-top: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .competency-config {
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 12px;
|
|
|
+
|
|
|
+ .config-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-label {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tag-name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-input-number {
|
|
|
+ flex: 1;
|
|
|
+ margin: 0 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .full-width {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|