yangg пре 1 дан
родитељ
комит
8aff1ee3c3

+ 3 - 2
.env.development

@@ -6,9 +6,10 @@ ENV = 'development'
 # 本地环境接口地址 121.36.251.245
 
 
-VITE_API_URL = 'http://192.168.100.115:8083'
-# VITE_API_URL = 'https://backend.qicai321.com'
+#VITE_API_URL = 'http://192.168.100.115:8083'
+VITE_API_URL = 'https://backend.qicai321.com'
 VITE_API_WX_URL='https://api.weixin.qq.com/'
 VITE_API_URL_MINLONG='http://117.185.80.170:7861'
 # 是否启用按钮权限
 VITE_PM_ENABLED = true
+

+ 2 - 2
src/views/JobApplication/list/crud.tsx

@@ -253,7 +253,7 @@ export const createCrudOptions = function ({ crudExpose, context}: CreateCrudOpt
 							const selection = context.selectedRows || [];
 							
 							if (!selection || selection.length === 0) {
-								warningMessage('请先选择要操作的数据');
+								warningMessage('请先选择要操作的候选人');
 								return;
 							}
 							// 打开批量修改状态对话框
@@ -272,7 +272,7 @@ export const createCrudOptions = function ({ crudExpose, context}: CreateCrudOpt
 							const selection = context.selectedRows || [];
 							
 							if (!selection || selection.length === 0) {
-								warningMessage('请先选择要操作的数据');
+								warningMessage('请先选择要操作的候选人');
 								return;
 							}
 

+ 103 - 20
src/views/position/detail/index.vue

@@ -1382,6 +1382,14 @@
           </div>
           <div class="form-tip">添加选项并设置正确答案,单选题只能有一个正确答案,多选题可以有多个正确答案</div>
         </div>
+        <div class="form-item" v-if="questionForm.question_form==6">
+          <div class="form-label">填空答案模板</div>
+          <BlankAnswerEditor
+            :model-value="questionForm.blank_answer_template || []"
+            :question="questionForm.content"
+            :readonly="true"
+          />
+        </div>
         <div v-if="questionForm.question_form === 3">
           <div class="form-label">题目图片</div>
           <img :src="questionForm.question_image_url" alt="">
@@ -2235,7 +2243,7 @@
         </div> -->
         <span class="dialog-footer">
           <el-button @click="handleQuestionSelectPreview">预览已选</el-button>
-          <el-button @click="cancelQuestionSelect">取消</el-button>
+         <!--  <el-button @click="cancelQuestionSelect">取消</el-button> -->
           <el-button type="primary" @click="confirmSelect" style="background-color: #ed7d31;border-color: #ed7d31;">确定</el-button>
         </span>
       </template>
@@ -2456,6 +2464,7 @@ import { updateFieldConfig } from './utils';
 import type { ProfileFieldsConfig } from './types';
 import { getPCAData } from '../../../utils/pcaData';
 import QuestionBankForm from '../../questionBank/list/components/QuestionBankForm.vue';
+import BlankAnswerEditor from '../../questionBank/list/components/BlankAnswerEditor.vue';
 import * as questionBankApi from '../../questionBank/list/api';
 import TreeList from './treeList.vue';
 import { GetDocumentTree, GetCategoryList, GetTagList,DeleteDocumentCategory } from '../../questionBank/positionList/api';
@@ -2564,7 +2573,8 @@ const recruitmentProcess = reactive([
   { id: 5, name: '资料收集', description: '资料收集', active: true, type: 'data_collection',visible:true },
   { id: 2, name: 'AI考察', description: 'AI考察', active: true, type: 'ai_video',visible:true },
   { id: 8, name: '综合素质考察', description: '综合素质考察', active: true, type: 'common_sense',visible:true },
-  { id: 9, name: '心理问题', description: '心理问题', active: true, type: 'psychological_problem',visible:true },
+  { id: 9, name: '心理测试', description: '心理测试', active: true, type: 'psychological_problem',visible:true },
+  { id: 10, name: '肢体检测', description: '肢体检测', active: true, type: 'posture_check', visible: true }, //, enable_posture_check: true
   { id: 7, name: '候选人提问', description: '时长5分钟,最多3个问题', active: true, type: 'candidate_questions', visible:true,
     config: {
       title: '候选人提问',
@@ -2580,7 +2590,7 @@ const recruitmentProcess = reactive([
       ]
     }
   },
-
+ 
  
  /*  { id: 1, name: '待核验', description: '待核验', active: true, type: 'pending_verification' }, */
   { id: 3, name: '已通过', description: '已通过', active: true, type: 'passed',visible:true },
@@ -2598,9 +2608,9 @@ const processStepOptions = [
     { label: '资料收集', value: 'data_collection' },
   { label: 'AI考察', value: 'ai_video' },
   { label: '综合素质考察', value: 'common_sense' },
-  { label: '心理问题', value: 'psychological_problem' },
+  { label: '心理测试', value: 'psychological_problem' },
   { label: '候选人提问', value: 'candidate_questions' },
-  { label: '肢体检测', value: 'body_detection' },  // 新增肢体检测选项
+  { label: '肢体检测', value: 'posture_check' },  // 新增肢体检测选项
   /* { label: 'AI实时对话', value: 'ai_chat' },*/
   /* { label: '代码测试', value: 'code_test' },
   { label: '打字测试', value: 'typing_test' } */
@@ -2742,8 +2752,8 @@ const handleQuestionSelectPreview = async () => {
     const response = await GetSelectedApplications({
       page: 1,
       limit: 100,
-      job_id: 22,
-      question_form: 0
+      job_id: route.query.id,
+     
     });
     if (response.data && response.data.items) {
       selectedApplications.value = response.data.items;
@@ -2901,7 +2911,8 @@ const questionForm = reactive({
   tags: [], // 标签
   suggestedDuration: 60, // 建议时长,默认60秒
   scoring_reference: '', // 评分标准
-  question_image_url: '' // 题目图片
+  question_image_url: '', // 题目图片
+  blank_answer_template: []
 });
 
 // 定义胜任力标签类型
@@ -2956,7 +2967,8 @@ const resetQuestionForm = () => {
     tags: [],
     suggestedDuration: 60,
     scoring_reference: '',
-    question_image_url: ''
+    question_image_url: '',
+    blank_answer_template: []
   });
 };
 
@@ -3112,7 +3124,18 @@ const confirmResumeCollection = () => {
   
   // 添加到流程中
   recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
-  console.log(recruitmentProcess);
+
+    UpdateConfig({
+      id: getConfigId.value,
+      require_resume_upload: true // 删除综合素质考察时,将enable_scoring_questions设置为false
+    }).then((res:any) => {
+      if(res.code == 2000) {
+        recruitmentProcess[0].visible = true;
+        // ElMessage.success('新增成功');
+      } else {
+        ElMessage.error('删除失败');
+      }
+    })
   // 关闭弹窗
   showResumeCollectionDialog.value = false;
   
@@ -3309,7 +3332,21 @@ const deleteProcessStep = (step: any,index: number) => {
       }
     })
   }
+  if(step.type=='posture_check'){
+    UpdateConfig({
+      id: getConfigId.value,
+      enable_posture_check: false
+    }).then((res:any) => {
+      if(res.code == 2000) {
+        ElMessage.success('删除成功');
+        return
+      } else {
+        ElMessage.error('删除失败');
+      }
+    })
+  }
   recruitmentProcess.splice(index, 1);
+  console.log('recruitmentProcess',recruitmentProcess);
 };
 
 // 在特定位置添加流程步骤
@@ -3434,7 +3471,7 @@ const addSelectedStepType = async (type: string, label: string) => {
  
   }
 
-  // 添加心理问题类型的处理
+  // 添加心理测试类型的处理
   if (type === 'psychological_problem') {
     UpdateConfig({
       id: getConfigId.value,
@@ -3459,13 +3496,17 @@ const addSelectedStepType = async (type: string, label: string) => {
   }
 
   if(type=='resume_collection'){
+  
+  }
+//肢体检测
+  if(type==='posture_check'){
     UpdateConfig({
       id: getConfigId.value,
-      require_resume_upload: true // 删除综合素质考察时,将enable_scoring_questions设置为false
+      enable_posture_check: true
     }).then((res:any) => {
       if(res.code == 2000) {
-        recruitmentProcess[0].visible = true;
-        // ElMessage.success('新增成功');
+        console.log('recruitmentProcess',recruitmentProcess);
+        recruitmentProcess[5].visible = true;
       } else {
         ElMessage.error('删除失败');
       }
@@ -3524,6 +3565,12 @@ const addSelectedStepType = async (type: string, label: string) => {
     showOptionsMenu.value = false;
     return;
   }
+  //添加肢体检测
+  if(type==='posture_check'){
+    // showPostureCheckConfig();
+    showOptionsMenu.value = false;
+   
+  }
   
   // 添加代码测试类型的处理
   if (type === 'code_test') {
@@ -4127,7 +4174,7 @@ const editQuestion = (index: number) => {
             scoring_reference:res.data.scoring_reference,
             competency_tag_info:res.data.competency_tag_info,
             competency_tags:res.data.competency_tags,
-            options:res.data.options.map((item:any)=>{
+            options:res.data.options?.map((item:any)=>{
               return {
                 text:item.option_text,
                 is_correct:item.is_correct,
@@ -4137,7 +4184,8 @@ const editQuestion = (index: number) => {
             enable_follow_up:res.data.enable_follow_up,
             maxAnswers:res.data.maxAnswers,
             weight:res.data.weight,
-            question_image_url:res.data.question_image_url
+            question_image_url:res.data.question_image_url,
+            blank_answer_template: res.data.blank_answer_template || []
           }
           Object.assign(questionForm, data);
         }
@@ -4256,6 +4304,7 @@ const initializeConfigState = async () => {
           config.data.question_form_switches.enable_image_choice ||
           config.data.question_form_switches.enable_fill_blank;
           recruitmentProcess[4].visible = config.data.question_form_switches.enable_scoring_questions;
+          recruitmentProcess[5].visible = config.data.enable_posture_check;
         
         
         // 可以在这里添加其他配置状态的同步
@@ -4957,6 +5006,39 @@ const editAIVideo = async (step: AIVideoStep) => {
           return item;
         });
       }
+      // 新增:获取选定的申请数据
+      const selectedApplicationsResponse = await GetSelectedApplications({
+       
+        job_id: route.query.id,
+        page: 1,
+        limit: 50
+      });
+      // 处理获取的申请数据并合并到 chatQuestions
+      if (selectedApplicationsResponse && selectedApplicationsResponse.data) {
+        const selectedApplications = selectedApplicationsResponse.data.items
+          .filter((app: any) => app.question_form !== 4 && app.question_form !== 5) // 过滤掉 question_form == 4 的项
+          .map((app: any) => {
+            
+            app.content=app.question, // 假设这里是申请内容
+            app.title=app.question, // 假设这里是申请标题
+            app.source='selected_application',
+            app.id=app.question_id
+              return app
+            
+          });
+        
+          // 合并数据并过滤掉重复的问题
+          const existingQuestionIds = new Set(chatQuestions.value.map((item: any) => item.content)); // 创建一个集合,存储现有问题的 ID
+
+          const uniqueSelectedApplications = selectedApplications.filter((app: any) => {
+            // 只保留那些不在现有问题集合中的申请
+            return !existingQuestionIds.has(app.content);
+          });
+
+        // 合并数据
+        chatQuestions.value = [...chatQuestions.value, ...uniqueSelectedApplications];
+        console.log('chatQuestions', chatQuestions.value);
+      }
 
       // 首先尝试获取已有的职位标签
       const existingTags = await GetPositionTags({position_id:route.query.id,page:1,limit:50});
@@ -5029,7 +5111,7 @@ const editAIVideo = async (step: AIVideoStep) => {
     })
     
   }
-  if(step.name === '心理问题'){
+  if(step.name === '心理测试'){
     GetQuestionList({page:1,limit:30,question_form:4}).then((res:any)=>{
       if(res.data){
         questionListQuery.question_form=4
@@ -5751,8 +5833,9 @@ const fetchQuestionList = async () => {
     };
     const response = await GetQuestionList(params);
     if (response && response.data) {
+      console.log(response.data);
       questionList.value = response.data.items;
-      totalQuestions.value = response.data.total;
+      totalQuestions2.value = response.data.total;
     }
   } catch (error) {
     console.error('获取题目列表失败:', error);
@@ -6704,7 +6787,7 @@ const saveBodyDetectionConfig = async () => {
     // TODO: 调用API保存配置
     await saveProcessConfig({
       position_id: route.params.id,
-      process_type: 'body_detection',
+      process_type: 'posture_check',
       config: bodyDetectionConfig.value
     })
     ElMessage.success('配置保存成功')
@@ -6719,7 +6802,7 @@ const saveBodyDetectionConfig = async () => {
 const handleProcessConfig = (type: string) => {
   switch (type) {
     // ... existing code ...
-    case 'body_detection':
+    case 'posture_check':
       openBodyDetectionConfig()
       break
     // ... existing code ...

+ 9 - 2
src/views/questionBank/list/components/BlankAnswerEditor.vue

@@ -15,6 +15,7 @@
         <el-input 
           v-model="blank.correct_answer" 
           placeholder="请输入正确答案" 
+          :disabled="readonly"
           style="flex: 1; margin: 0 10px;"
         />
         <el-input-number
@@ -24,6 +25,7 @@
           :step="1"
           :precision="0"
           :controls="false"
+          :disabled="readonly"
           style="width: 120px;"
           placeholder="分值"
         />
@@ -47,13 +49,16 @@ interface BlankAnswer {
 interface Props {
   modelValue: BlankAnswer[];
   question: string;
+  readonly?: boolean;
 }
 
 interface Emits {
   (e: 'update:modelValue', value: BlankAnswer[]): void;
 }
 
-const props = defineProps<Props>();
+const props = withDefaults(defineProps<Props>(), {
+  readonly: false
+});
 const emit = defineEmits<Emits>();
 
 const blankAnswers = ref<BlankAnswer[]>([...props.modelValue]);
@@ -65,6 +70,7 @@ const blankCount = computed(() => {
 
 // 监听数据变化
 watch(() => blankAnswers.value, (newVal) => {
+  if (props.readonly) return;
   if (JSON.stringify(newVal) !== JSON.stringify(props.modelValue)) {
     emit('update:modelValue', newVal);
   }
@@ -79,6 +85,7 @@ watch(() => props.modelValue, (newVal) => {
 
 // 监听题目变化,自动调整填空数量
 watch(() => props.question, (newQuestion) => {
+  if (props.readonly) return;
   const newBlankCount = (newQuestion || '').split('___').length - 1;
   
   if (newBlankCount > 0 && blankAnswers.value.length !== newBlankCount) {
@@ -95,7 +102,7 @@ watch(() => props.question, (newQuestion) => {
 });
 
 // 初始化填空模板
-if (blankAnswers.value.length === 0) {
+if (!props.readonly && blankAnswers.value.length === 0) {
   blankAnswers.value = [{ blank_index: 1, correct_answer: '', score: 5 }];
 }
 </script>

+ 2 - 2
src/views/questionBank/list/components/QuestionBankForm.vue

@@ -174,7 +174,7 @@
       </el-form-item>
 
       <!-- 红线问题 (仅单选题和多选题显示) -->
-      <el-form-item 
+    <!--   <el-form-item 
         v-if="formData.question_form === 1 || formData.question_form === 2"
         label="红线问题"
       >
@@ -182,7 +182,7 @@
           <el-option label="否" :value="false" />
           <el-option label="是" :value="true" />
         </el-select>
-      </el-form-item>
+      </el-form-item> -->
 
       <!-- 系统题目 -->
       <el-form-item label="系统题目">

+ 14 - 3
src/views/questionBank/positionList/components/editor.vue

@@ -204,7 +204,13 @@
         </el-select>
         <div class="form-tip">选择题目相关标签,可多选</div>
       </div>
-
+      <div class="form-item" v-if="questionForm.question_form === 1">
+        <div class="form-label">是否为红线题</div>
+        <el-select v-model="questionForm.is_required_correct" placeholder="请选择是否为红线问题" style="width: 100%;">
+          <el-option label="否" :value="false" />
+          <el-option label="是" :value="true" />
+        </el-select>
+      </div>
       <div class="form-item">
         <div class="form-label">建议时长(秒)</div>
         <el-input-number 
@@ -280,6 +286,7 @@ interface QuestionForm {
   question_form: number
   suggestedDuration: number
   scoring_reference: string
+  is_required_correct: Boolean
 }
 
 // 对话框显示状态
@@ -314,6 +321,7 @@ const fetchQuestionDetail = async (id: string | number) => {
       questionForm.question_form = questionData.question_form;
       questionForm.suggestedDuration = questionData.recommended_duration || 0;
       questionForm.scoring_reference = questionData.scoring_reference || '';
+      questionForm.is_required_correct=questionData.is_required_correct
       
       // 更新胜任力标签选择
       competencyTagsValue.value = competencyTags.map((tag: any) => tag.id);
@@ -394,7 +402,8 @@ const questionForm = reactive<QuestionForm>({
   options: [],
   question_form: 0,
   suggestedDuration: 0,
-  scoring_reference: ''
+  scoring_reference: '',
+  is_required_correct:false
 })
 
 // 胜任力标签相关
@@ -534,6 +543,7 @@ const resetForm = () => {
   questionForm.options = []
   questionForm.suggestedDuration = 0
   questionForm.scoring_reference = ''
+  questionForm.is_required_correct=false
   competencyTagsValue.value = []
 }
 
@@ -556,7 +566,8 @@ const confirmAddQuestion = async () => {
       competency_tags: questionForm.competency_tags,
       options: questionForm.options,
       recommended_duration: questionForm.suggestedDuration,
-      scoring_reference: questionForm.scoring_reference
+      scoring_reference: questionForm.scoring_reference,
+      is_required_correct:questionForm.is_required_correct
     };
 /*     console.log(questionForm)
 return */

+ 22 - 4
src/views/questionBank/positionList/crud.tsx

@@ -19,11 +19,13 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 			...query,
 			limit: 100,
 			tenant_id: Session.get('tenant_id'),
-			
 			question_category: (query.form && query.form.category) || query.category || '',
 			question_tags: (query.form && query.form.tag) || query.tag || '',
 		};
 
+		// 缓存搜索参数
+		sessionStorage.setItem('cacheSearchData', JSON.stringify(baseParams));
+
 		// 根据是否有tag或category来选择不同的接口和参数
 		if (baseParams.question_category || baseParams.question_tags) {
 			if(baseParams.question_category==5){
@@ -124,9 +126,25 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					search: {
 						size: 'small', // 设置查询按钮大小为small
 					},
-					reset: {
-						size: 'small', // 设置重置按钮大小为small
-					}
+											reset: {
+							size: 'small', // 设置重置按钮大小为small
+							click: () => {
+								// 从sessionStorage获取缓存的搜索参数
+								const cacheSearchData = sessionStorage.getItem('cacheSearchData');
+								if (cacheSearchData) {
+									const searchParams = JSON.parse(cacheSearchData);
+									// 只保留 job_id 和 question_form 参数
+									const resetParams = {
+										job_id: searchParams.job_id || searchParams.form?.job_id,
+										question_form: searchParams.question_form
+									};
+									// 执行搜索
+									crudExpose.doSearch({
+										form: resetParams
+									});
+								}
+							}
+						}
 				},
 				onSearch: (params: any) => {
 				},