Browse Source

修改问题

yangg 1 tháng trước cách đây
mục cha
commit
f88e6a232f

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
src/assets/pca-code.json


+ 30 - 0
src/utils/pcaData.ts

@@ -0,0 +1,30 @@
+import pcaData from '/@/assets/pca-code.json'
+
+export interface PCAreaItem {
+  code: string
+  name: string
+  children?: PCAreaItem[]
+}
+
+// 获取省市区数据
+export function getPCAData(): PCAreaItem[] {
+  return pcaData
+}
+
+// 根据区域编码获取完整的省市区名称
+export function getFullAreaName(codes: string[]): string {
+  if (!codes || codes.length === 0) return ''
+  
+  let result = ''
+  let currentLevel = pcaData as PCAreaItem[]
+  
+  for (const code of codes) {
+    const area = currentLevel.find((item: PCAreaItem) => item.code === code)
+    if (area) {
+      result += (result ? '/' : '') + area.name
+      currentLevel = area.children || []
+    }
+  }
+  
+  return result
+} 

+ 52 - 71
src/views/position/create/index.vue

@@ -68,7 +68,9 @@
             :options="locationOptions"
             :props="{ 
               expandTrigger: 'hover',
-              checkStrictly: false
+              checkStrictly: false,
+              value: 'code',
+              label: 'name'
             }"
             style="width: 100%"
             placeholder="请选择工作地点"
@@ -222,6 +224,7 @@ import type { FormInstance } from 'element-plus';
 import Quill from 'quill';
 import 'quill/dist/quill.snow.css'; // 引入样式
 import axios from 'axios';
+import { getPCAData } from '../../../utils/pcaData';
 
 const router = useRouter();
 const formRef = ref<FormInstance>();
@@ -233,13 +236,14 @@ interface CompetencyTag {
   description: string;
 }
 
-// 在 PositionFormData 接口中添加胜任力字段
+// 在 PositionFormData 接口中修改 location 字段类型
 interface PositionFormData {
   title: string;
   job_category: string;
   job_type_display: string;
   city: string;
-  location: string[];
+  location: string[]; // 存储选中的代码
+  location_names: string[]; // 存储选中的名称
   address_detail: string;
   benefits: string[];
   requirements: string;
@@ -257,16 +261,17 @@ interface PositionFormData {
   district: string;
   location_str?: string;
   status: number;
-  competency_tags: number[]; // 存储选中的胜任力标签ID
+  competency_tags: number[];
 }
 
-// 表单数据
+// 表单数据中添加 location_names 字段
 const formData = reactive<PositionFormData>({
   title: '',
   job_category: '',
   job_type_display: '',
   city: '',
   location: [],
+  location_names: [], // 新增字段
   address_detail: '',
   benefits: [],
   requirements: '',
@@ -311,61 +316,41 @@ let editor: any = null;
 let descEditor: any = null;
 
 // 工作地点选项
-const locationOptions = [
-  {
-    value: '上海市',
-    label: '上海市',
-    children: [
-      {
-        value: '浦东新区',
-        label: '浦东新区',
-        children: [
-          { value: '张江', label: '张江' },
-          { value: '金桥', label: '金桥' },
-          { value: '陆家嘴', label: '陆家嘴' }
-        ]
-      },
-      {
-        value: '徐汇区',
-        label: '徐汇区',
-        children: [
-          { value: '漕河泾', label: '漕河泾' },
-          { value: '徐家汇', label: '徐家汇' }
-        ]
-      },
-    ]
-  },
-  {
-    value: '北京市',
-    label: '北京市',
-    children: [
-      {
-        value: '海淀区',
-        label: '海淀区',
-        children: [
-          { value: '中关村', label: '中关村' },
-          { value: '上地', label: '上地' }
-        ]
-      },
-      {
-        value: '朝阳区',
-        label: '朝阳区',
-        children: [
-          { value: 'CBD', label: 'CBD' },
-          { value: '望京', label: '望京' }
-        ]
-      },
-    ]
-  },
-];
+const locationOptions = getPCAData();
 
-// 处理地点选择变化
+// 修改处理地点选择变化的函数
 const handleLocationChange = (value: any) => {
   console.log('地址选择变化:', value);
   if (value && Array.isArray(value) && value.length > 0) {
-    formData.province = value[0];
-    formData.city = value[1] || '';
-    formData.district = value[2] || '';
+    const [provinceCode, cityCode, districtCode] = value;
+    const province = locationOptions.find(p => p.code === provinceCode);
+    let city, district;
+
+    if (province && province.children) {
+      city = province.children.find(c => c.code === cityCode);
+      if (city && city.children) {
+        district = city.children.find(d => d.code === districtCode);
+      }
+    }
+
+    // 保存名称
+    formData.location_names = [
+      province?.name || '',
+      city?.name || '',
+      district?.name || ''
+    ].filter(Boolean);
+
+    // 更新各个字段
+    formData.province = province?.name || '';
+    formData.city = city?.name || '';
+    formData.district = district?.name || '';
+    formData.location_str = formData.location_names.join('/');
+  } else {
+    formData.location_names = [];
+    formData.province = '';
+    formData.city = '';
+    formData.district = '';
+    formData.location_str = '';
   }
 };
 
@@ -483,7 +468,7 @@ const goBack = () => {
   router.push('/position/list');
 };
 
-// 提交表单
+// 修改提交表单函数
 const submitForm = async () => {
   if (!formRef.value) return;
   
@@ -504,23 +489,19 @@ const submitForm = async () => {
       try {
         const formToSubmit = { ...formData };
         
-        // 处理地址信息
-        if (Array.isArray(formToSubmit.location) && formToSubmit.location.length > 0) {
-          formToSubmit.province = formToSubmit.location[0];
-          formToSubmit.city = formToSubmit.location[1] || '';
-          formToSubmit.district = formToSubmit.location[2] || '';
-          // 使用location_str字段存储字符串形式的位置
-          formToSubmit.location_str = formToSubmit.location.join(' ');
+        // 处理地址信息 - 只提交名称
+        if (formToSubmit.location_names.length > 0) {
+          formToSubmit.province = formToSubmit.location_names[0];
+          formToSubmit.city = formToSubmit.location_names[1] || '';
+          formToSubmit.district = formToSubmit.location_names[2] || '';
+          formToSubmit.location = formToSubmit.location_names; // 使用名称数组替换代码数组
+          formToSubmit.location_str = formToSubmit.location_names.join('/');
         }
         
-        // 处理胜任力标签数据
-        const apiData = {
-          ...formToSubmit,
-          competency_tags: formToSubmit.competency_tags,
-          // ... other fields
-        };
+        // 删除多余的字段
+        delete formToSubmit.location_names;
         
-        const response = await api.AddObj(apiData);
+        const response = await api.AddObj(formToSubmit);
         ElMessage.success('职位添加成功');
         router.push(`/position/detail?id=${response.data.id}`);
       } catch (error) {

+ 8 - 0
src/views/position/detail/api.ts

@@ -130,6 +130,14 @@ export function BatchUnbind(obj: AddReq) {
     });
 }
  */
+/* 更新为红线题 */
+export function UpdateObj(obj: EditReq) {
+	return request({
+		url: "/api/system/interview_question/update",/* + obj.id+'/' */
+		method: 'put',
+		data: {...obj,tenant_id: '1'},
+	});
+}
 export function GetcategoryList(query: UserPageQuery) {
 	return request({
 		url: '/api/system/question_category/list',

+ 165 - 21
src/views/position/detail/index.vue

@@ -42,18 +42,47 @@
         <div class="detail-item">
           <div class="detail-label">工作地点</div>
           <div class="detail-value" v-if="!isEditingLocation">
-            {{ positionData.location || '暂无' }}
+            {{ 
+              (() => {
+                if (!positionData.location) return '暂无';
+                if (Array.isArray(positionData.location)) return positionData.location.join(',');
+                if (typeof positionData.location === 'string') {
+                  try {
+                    // 移除方括号并分割字符串
+                    const cleanStr = positionData.location.replace(/[\[\]']/g, '');
+                    return cleanStr.split(',').map(item => item.trim()).join(',');
+                  } catch (e) {
+                    return positionData.location;
+                  }
+                }
+                return positionData.location;
+              })()
+            }}
             <el-button type="text" class="edit-title-btn" @click="startEditLocation">
               <el-icon><Edit /></el-icon>
             </el-button>
           </div>
           <div class="title-edit-container" v-else>
-            <el-input 
+            <!-- <el-input 
               v-model="editingLocation" 
               placeholder="请输入工作地点" 
               maxlength="50"
               show-word-limit
-            />
+            /> -->
+            <el-cascader
+            v-model="editingLocation"
+            :options="locationOptions"
+            :props="{ 
+              expandTrigger: 'hover',
+              checkStrictly: false,
+              value: 'code',
+              label: 'name'
+            }"
+            style="width: 100%"
+            placeholder="请选择工作地点"
+            clearable
+            @change="handleLocationChange"
+          />
             <div class="title-edit-actions">
               <el-button size="small" @click="cancelEditLocation">取消</el-button>
               <el-button size="small" type="primary" @click="saveLocation">保存</el-button>
@@ -191,7 +220,7 @@
           </div>
         </div>
            
-        <div class="detail-item">
+        <div class="detail-item" >
           <div class="detail-label">职位要求</div>
           <div class="detail-value html-content" v-if="!isEditingRequirements" v-html="positionData.requirements"></div>
           <el-button type="text" class="edit-title-btn" @click="startEditRequirements" v-if="!isEditingRequirements">
@@ -212,7 +241,7 @@
             </div>
           </div>
         </div>
-        
+        <div style="width: 100%; border-bottom: 1px solid #e5e5e5;"></div>
         <div class="detail-item">
           <div class="detail-label">职位描述</div>
           <div class="detail-value html-content" v-if="!isEditingDescription" v-html="positionData.description"></div>
@@ -296,7 +325,7 @@
         <el-card class="status-card">
           <div class="section-title">
             <div class="section-line"></div>
-            <span>职位用途</span>
+            <span>职位性质</span>
             <el-button type="text" class="edit-btn" @click="handleEditUsage">编辑</el-button>
           </div>
           <div class="usage-content">
@@ -321,7 +350,7 @@
               <div class="step-number">{{ index + 1 }}</div>
               <div class="step-content">
                 <div class="step-title">{{ step.name }}</div>
-                <div class="step-desc">{{ step.description }}</div>
+                <!-- <div class="step-desc">{{ step.description }}</div> -->
               </div>
             </div>
           </div>
@@ -714,7 +743,16 @@
                           </el-select>
                         </div>
                        
+                    </div>
+                    <div class="question-actions" v-if="element.question_form==1">
+                      <div class="answer-limit">
+                        <span class="answer-label">是否为红线题:</span>
+                        <el-select v-model="element.is_required_correct" @change="handleIsRequiredCorrectChange(element.id,element.is_required_correct)" size="small" placeholder="请选择">
+                          <el-option label="是" :value="true" />
+                          <el-option label="否" :value="false" />
+                        </el-select>
                       </div>
+                    </div>
                   </div>
                 </template>
               </draggable>
@@ -750,7 +788,7 @@
             <div class="section-header">请选择面试官形象</div>
             <div style="    display: flex;align-items: flex-start;">
               <div style="width: 100px;height: 170px;background-color: #f2f2f2; margin-right: 30px;border-radius: 10px;">
-                
+                <img v-if="interviewerAvatar" :src="interviewerAvatar" alt="" style="width: 100%;height: 100%;">
               </div>
               <div>
                  <div class="interviewer-avatars">
@@ -769,7 +807,8 @@
                     </div>
                   </div>
                 </div>
-                <div>追问风格:  <el-select v-model="settings.interruptionMode" placeholder="请选择">
+                <div>追问风格:  
+                  <el-select v-model="settings.interruptionMode" placeholder="请选择">
                     <el-option label="温和" value="1" />
                     <el-option label="严厉" value="2" />
                     <el-option label="严谨" value="3" />
@@ -783,7 +822,7 @@
             <div class="interview-settings">
               <div class="setting-item">
                 <div class="setting-label">「回答视频保留」</div>
-                 <div class="setting-desc">当候选人不符合中断条件时,保留其回答视频</div>
+                 <div class="setting-desc">选取后,将在报告中展示候选人的回答视频</div>
                 <el-switch 
                   v-model="settings.keepVideo" 
                   @change="(value: boolean) => handleSettingChange('keepVideo', value)"
@@ -815,7 +854,7 @@
 
               <div class="setting-item">
                 <div class="setting-label">「智慧追问」</div>
-                <div class="setting-desc">当候选人给出特殊关键词时,系统将自动追问</div>
+                <div class="setting-desc">* 追问将结合候选人资料情况,综合分析发问</div>
                 <el-switch 
                   v-model="settings.smartFollowUp" 
                   @change="(value: boolean) => handleSettingChange('smartFollowUp', value)"
@@ -1724,10 +1763,11 @@ import { GetList } from '../../questionBank/classList/api';
 import { GetCompetencyList,GetQuestionList,GenerateQuestions,
   GetDraftList,SaveDraft,GetDigitalList,
   CreateConfig,GetConfig,UpdateConfig,AddDocument,
-  GetOpeningSpeech,GetVideo,BatchBind,BatchUnbind } from './api';
+  GetOpeningSpeech,GetVideo,BatchBind,BatchUnbind,UpdateObj } from './api';
 import draggable from 'vuedraggable';
 import { updateFieldConfig } from './utils';
 import type { ProfileFieldsConfig } from './types';
+import { getPCAData } from '../../../utils/pcaData';
 
 // 添加 CompetencyTag 接口定义
 interface CompetencyTag {
@@ -1790,7 +1830,7 @@ const positionData = reactive({
   job_category: '',
   job_type_display: '',
   city: '',
-  location: [],
+  location: [] as string[] | string, // 修改类型定义
   location_str: '',
   address_detail: '',
   benefits: [],
@@ -1830,6 +1870,55 @@ const processStepOptions = [
   { label: '打字测试', value: 'typing_test' } */
 ];
 
+/* 工作地点 */
+// 工作地点选项
+const locationOptions = getPCAData();
+
+// 修改处理地点选择变化的函数
+const handleLocationChange = (value: any) => {
+  console.log('地址选择变化:', value);
+  if (value && Array.isArray(value) && value.length > 0) {
+    const [provinceCode, cityCode, districtCode] = value;
+    const province = locationOptions.find(p => p.code === provinceCode);
+    let city, district;
+
+    if (province && province.children) {
+      city = province.children.find(c => c.code === cityCode);
+      if (city && city.children) {
+        district = city.children.find(d => d.code === districtCode);
+      }
+    }
+
+   /*  // 保存名称
+    formData.location_names = [
+      province?.name || '',
+      city?.name || '',
+      district?.name || ''
+    ].filter(Boolean);
+
+    // 更新各个字段
+    formData.province = province?.name || '';
+    formData.city = city?.name || '';
+    formData.district = district?.name || '';
+    formData.location_str = formData.location_names.join('/'); */
+  } else {
+  /*   formData.location_names = [];
+    formData.province = '';
+    formData.city = '';
+    formData.district = '';
+    formData.location_str = ''; */
+  }
+};
+
+const handleIsRequiredCorrectChange = (id: number, value: boolean) => {
+    UpdateObj({
+        id: id,
+        is_required_correct: value
+    }).then((res:any) => {
+        console.log('res', res);
+    })
+};
+
 // 当前选择的添加位置
 const currentAddIndex = ref(-1);
 // 是否显示选项菜单
@@ -2100,7 +2189,7 @@ const goBack = () => {
 
 // 编辑职位
 const handleEdit = () => {
-  router.push(`/position/edit/${positionId.value}`);
+  router.push(`/position/list`);
 };
 
 // 分享职位
@@ -2945,7 +3034,36 @@ const editingLocation = ref('');
 
 // 开始编辑工作地点
 const startEditLocation = () => {
-  editingLocation.value = positionData.location || '';
+  if (!positionData.location) {
+    editingLocation.value = '';
+  } else if (Array.isArray(positionData.location)) {
+    editingLocation.value = positionData.location;
+  } else if (typeof positionData.location === 'string') {
+    try {
+      // 移除方括号和单引号,并分割成数组
+      const cleanStr = positionData.location.replace(/[\[\]']/g, '');
+      const locationArray = cleanStr.split(',').map(item => item.trim());
+      // 根据地址数据查找对应的code
+      const province = locationOptions.find(p => p.name === locationArray[0]);
+      let city, district;
+      
+      if (province && province.children) {
+        city = province.children.find(c => c.name === locationArray[1]);
+        if (city && city.children) {
+          district = city.children.find(d => d.name === locationArray[2]);
+        }
+      }
+
+      editingLocation.value = [
+        province?.code,
+        city?.code,
+        district?.code
+      ].filter(Boolean);
+    } catch (e) {
+      console.error('解析地址失败:', e);
+      editingLocation.value = '';
+    }
+  }
   isEditingLocation.value = true;
 };
 
@@ -2958,13 +3076,37 @@ const cancelEditLocation = () => {
 const saveLocation = async () => {
   try {
     const id = route.query.id;
+    // 获取选中地址的名称
+    const locationNames = [];
+    if (editingLocation.value && Array.isArray(editingLocation.value)) {
+      const [provinceCode, cityCode, districtCode] = editingLocation.value;
+      const province = locationOptions.find(p => p.code === provinceCode);
+      let city, district;
+
+      if (province) {
+        locationNames.push(province.name);
+        if (province.children) {
+          city = province.children.find(c => c.code === cityCode);
+          if (city) {
+            locationNames.push(city.name);
+            if (city.children) {
+              district = city.children.find(d => d.code === districtCode);
+              if (district) {
+                locationNames.push(district.name);
+              }
+            }
+          }
+        }
+      }
+    }
+
     await api.UpdateObj({
       id: id,
-      location: editingLocation.value.trim()
+      location: locationNames
     });
     
     // 更新本地数据
-    positionData.location = editingLocation.value.trim();
+    positionData.location = locationNames;
     isEditingLocation.value = false;
     ElMessage.success('工作地点已更新');
   } catch (error) {
@@ -3343,7 +3485,7 @@ const addDimension = () => {
 
 const settings = reactive({
   keepVideo: false,
-  interruptionMode: 'previous',
+  interruptionMode: '',
   smartFollowUp: false
 });
 
@@ -3372,7 +3514,7 @@ const interviewerAvatars = ref<InterviewerAvatar[]>([
 ]);
 
 const selectedInterviewer = ref(interviewerAvatars.value[0]);
-
+const interviewerAvatar = ref('');
 // 添加面试官选择处理函数
 const handleInterviewerSelect = (avatar: any) => {
   // 更新选中的面试官
@@ -3384,7 +3526,7 @@ const handleInterviewerSelect = (avatar: any) => {
     name: avatar.name,
     avatar_url: avatar.avatar_url || avatar.image
   });
-  
+  interviewerAvatar.value = avatar.avatar_url;
   // 可以在这里添加其他处理逻辑
   // 比如:保存到后端、触发其他事件等
   
@@ -3951,6 +4093,7 @@ console.log(selectedQuestions.value);
     question_form_name: question.question_form_name,
     scoring_reference: question.scoring_reference,
     question_form: question.question_form,
+    is_required_correct: question.is_required_correct,
     weight: 100, // 默认权重
     maxAnswers: 1, // 默认最多回答次数
     source: 'custom_selected' as const // 标识为自定义选择的题目
@@ -3963,7 +4106,7 @@ console.log(selectedQuestions.value);
   selectedQuestions.value = [];
   questionSearchKeyword.value = '';
   
-  ElMessage.success(`已添加${selectedQuestions.value.length}个题目`);
+/*   ElMessage.success(`已添加${selectedQuestions.value.length}个题目`); */
 };
 
 // 字段配置数据
@@ -4441,6 +4584,7 @@ const handleAutoGenerate = async () => {
           question_form_name: question.question_form_name,
           scoring_reference: question.scoring_reference,
           question_form: question.question_form,
+          is_required_correct: question.is_required_correct,
           weight: 100,
           maxAnswers: 1,
           source: 'ai_generated' as const // 标识为AI生成的题目

+ 10 - 0
src/views/position/list/crud.tsx

@@ -414,6 +414,16 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 					column: {
 						minWidth: 120,
 						formatter: ({ row }) => {
+							if (typeof row.location === 'string' && row.location.startsWith('[')) {
+								try {
+									// 解析字符串形式的数组
+									const locationArray = JSON.parse(row.location.replace(/'/g, '"'));
+									return locationArray.join(' ');
+								} catch (e) {
+									console.error('解析location失败:', e);
+									return row.location;
+								}
+							}
 							if (Array.isArray(row.location)) {
 								return row.location.join(' ');
 							}

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác