|
@@ -42,18 +42,47 @@
|
|
<div class="detail-item">
|
|
<div class="detail-item">
|
|
<div class="detail-label">工作地点</div>
|
|
<div class="detail-label">工作地点</div>
|
|
<div class="detail-value" v-if="!isEditingLocation">
|
|
<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-button type="text" class="edit-title-btn" @click="startEditLocation">
|
|
<el-icon><Edit /></el-icon>
|
|
<el-icon><Edit /></el-icon>
|
|
</el-button>
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
<div class="title-edit-container" v-else>
|
|
<div class="title-edit-container" v-else>
|
|
- <el-input
|
|
|
|
|
|
+ <!-- <el-input
|
|
v-model="editingLocation"
|
|
v-model="editingLocation"
|
|
placeholder="请输入工作地点"
|
|
placeholder="请输入工作地点"
|
|
maxlength="50"
|
|
maxlength="50"
|
|
show-word-limit
|
|
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">
|
|
<div class="title-edit-actions">
|
|
<el-button size="small" @click="cancelEditLocation">取消</el-button>
|
|
<el-button size="small" @click="cancelEditLocation">取消</el-button>
|
|
<el-button size="small" type="primary" @click="saveLocation">保存</el-button>
|
|
<el-button size="small" type="primary" @click="saveLocation">保存</el-button>
|
|
@@ -191,7 +220,7 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
- <div class="detail-item">
|
|
|
|
|
|
+ <div class="detail-item" >
|
|
<div class="detail-label">职位要求</div>
|
|
<div class="detail-label">职位要求</div>
|
|
<div class="detail-value html-content" v-if="!isEditingRequirements" v-html="positionData.requirements"></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">
|
|
<el-button type="text" class="edit-title-btn" @click="startEditRequirements" v-if="!isEditingRequirements">
|
|
@@ -212,7 +241,7 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
-
|
|
|
|
|
|
+ <div style="width: 100%; border-bottom: 1px solid #e5e5e5;"></div>
|
|
<div class="detail-item">
|
|
<div class="detail-item">
|
|
<div class="detail-label">职位描述</div>
|
|
<div class="detail-label">职位描述</div>
|
|
<div class="detail-value html-content" v-if="!isEditingDescription" v-html="positionData.description"></div>
|
|
<div class="detail-value html-content" v-if="!isEditingDescription" v-html="positionData.description"></div>
|
|
@@ -296,7 +325,7 @@
|
|
<el-card class="status-card">
|
|
<el-card class="status-card">
|
|
<div class="section-title">
|
|
<div class="section-title">
|
|
<div class="section-line"></div>
|
|
<div class="section-line"></div>
|
|
- <span>职位用途</span>
|
|
|
|
|
|
+ <span>职位性质</span>
|
|
<el-button type="text" class="edit-btn" @click="handleEditUsage">编辑</el-button>
|
|
<el-button type="text" class="edit-btn" @click="handleEditUsage">编辑</el-button>
|
|
</div>
|
|
</div>
|
|
<div class="usage-content">
|
|
<div class="usage-content">
|
|
@@ -321,7 +350,7 @@
|
|
<div class="step-number">{{ index + 1 }}</div>
|
|
<div class="step-number">{{ index + 1 }}</div>
|
|
<div class="step-content">
|
|
<div class="step-content">
|
|
<div class="step-title">{{ step.name }}</div>
|
|
<div class="step-title">{{ step.name }}</div>
|
|
- <div class="step-desc">{{ step.description }}</div>
|
|
|
|
|
|
+ <!-- <div class="step-desc">{{ step.description }}</div> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@@ -714,7 +743,16 @@
|
|
</el-select>
|
|
</el-select>
|
|
</div>
|
|
</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>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</draggable>
|
|
</draggable>
|
|
@@ -750,7 +788,7 @@
|
|
<div class="section-header">请选择面试官形象</div>
|
|
<div class="section-header">请选择面试官形象</div>
|
|
<div style=" display: flex;align-items: flex-start;">
|
|
<div style=" display: flex;align-items: flex-start;">
|
|
<div style="width: 100px;height: 170px;background-color: #f2f2f2; margin-right: 30px;border-radius: 10px;">
|
|
<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>
|
|
<div>
|
|
<div class="interviewer-avatars">
|
|
<div class="interviewer-avatars">
|
|
@@ -769,7 +807,8 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</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="1" />
|
|
<el-option label="严厉" value="2" />
|
|
<el-option label="严厉" value="2" />
|
|
<el-option label="严谨" value="3" />
|
|
<el-option label="严谨" value="3" />
|
|
@@ -783,7 +822,7 @@
|
|
<div class="interview-settings">
|
|
<div class="interview-settings">
|
|
<div class="setting-item">
|
|
<div class="setting-item">
|
|
<div class="setting-label">「回答视频保留」</div>
|
|
<div class="setting-label">「回答视频保留」</div>
|
|
- <div class="setting-desc">当候选人不符合中断条件时,保留其回答视频</div>
|
|
|
|
|
|
+ <div class="setting-desc">选取后,将在报告中展示候选人的回答视频</div>
|
|
<el-switch
|
|
<el-switch
|
|
v-model="settings.keepVideo"
|
|
v-model="settings.keepVideo"
|
|
@change="(value: boolean) => handleSettingChange('keepVideo', value)"
|
|
@change="(value: boolean) => handleSettingChange('keepVideo', value)"
|
|
@@ -815,7 +854,7 @@
|
|
|
|
|
|
<div class="setting-item">
|
|
<div class="setting-item">
|
|
<div class="setting-label">「智慧追问」</div>
|
|
<div class="setting-label">「智慧追问」</div>
|
|
- <div class="setting-desc">当候选人给出特殊关键词时,系统将自动追问</div>
|
|
|
|
|
|
+ <div class="setting-desc">* 追问将结合候选人资料情况,综合分析发问</div>
|
|
<el-switch
|
|
<el-switch
|
|
v-model="settings.smartFollowUp"
|
|
v-model="settings.smartFollowUp"
|
|
@change="(value: boolean) => handleSettingChange('smartFollowUp', value)"
|
|
@change="(value: boolean) => handleSettingChange('smartFollowUp', value)"
|
|
@@ -1724,10 +1763,11 @@ import { GetList } from '../../questionBank/classList/api';
|
|
import { GetCompetencyList,GetQuestionList,GenerateQuestions,
|
|
import { GetCompetencyList,GetQuestionList,GenerateQuestions,
|
|
GetDraftList,SaveDraft,GetDigitalList,
|
|
GetDraftList,SaveDraft,GetDigitalList,
|
|
CreateConfig,GetConfig,UpdateConfig,AddDocument,
|
|
CreateConfig,GetConfig,UpdateConfig,AddDocument,
|
|
- GetOpeningSpeech,GetVideo,BatchBind,BatchUnbind } from './api';
|
|
|
|
|
|
+ GetOpeningSpeech,GetVideo,BatchBind,BatchUnbind,UpdateObj } from './api';
|
|
import draggable from 'vuedraggable';
|
|
import draggable from 'vuedraggable';
|
|
import { updateFieldConfig } from './utils';
|
|
import { updateFieldConfig } from './utils';
|
|
import type { ProfileFieldsConfig } from './types';
|
|
import type { ProfileFieldsConfig } from './types';
|
|
|
|
+import { getPCAData } from '../../../utils/pcaData';
|
|
|
|
|
|
// 添加 CompetencyTag 接口定义
|
|
// 添加 CompetencyTag 接口定义
|
|
interface CompetencyTag {
|
|
interface CompetencyTag {
|
|
@@ -1790,7 +1830,7 @@ const positionData = reactive({
|
|
job_category: '',
|
|
job_category: '',
|
|
job_type_display: '',
|
|
job_type_display: '',
|
|
city: '',
|
|
city: '',
|
|
- location: [],
|
|
|
|
|
|
+ location: [] as string[] | string, // 修改类型定义
|
|
location_str: '',
|
|
location_str: '',
|
|
address_detail: '',
|
|
address_detail: '',
|
|
benefits: [],
|
|
benefits: [],
|
|
@@ -1830,6 +1870,55 @@ const processStepOptions = [
|
|
{ label: '打字测试', value: 'typing_test' } */
|
|
{ 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);
|
|
const currentAddIndex = ref(-1);
|
|
// 是否显示选项菜单
|
|
// 是否显示选项菜单
|
|
@@ -2100,7 +2189,7 @@ const goBack = () => {
|
|
|
|
|
|
// 编辑职位
|
|
// 编辑职位
|
|
const handleEdit = () => {
|
|
const handleEdit = () => {
|
|
- router.push(`/position/edit/${positionId.value}`);
|
|
|
|
|
|
+ router.push(`/position/list`);
|
|
};
|
|
};
|
|
|
|
|
|
// 分享职位
|
|
// 分享职位
|
|
@@ -2945,7 +3034,36 @@ const editingLocation = ref('');
|
|
|
|
|
|
// 开始编辑工作地点
|
|
// 开始编辑工作地点
|
|
const startEditLocation = () => {
|
|
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;
|
|
isEditingLocation.value = true;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -2958,13 +3076,37 @@ const cancelEditLocation = () => {
|
|
const saveLocation = async () => {
|
|
const saveLocation = async () => {
|
|
try {
|
|
try {
|
|
const id = route.query.id;
|
|
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({
|
|
await api.UpdateObj({
|
|
id: id,
|
|
id: id,
|
|
- location: editingLocation.value.trim()
|
|
|
|
|
|
+ location: locationNames
|
|
});
|
|
});
|
|
|
|
|
|
// 更新本地数据
|
|
// 更新本地数据
|
|
- positionData.location = editingLocation.value.trim();
|
|
|
|
|
|
+ positionData.location = locationNames;
|
|
isEditingLocation.value = false;
|
|
isEditingLocation.value = false;
|
|
ElMessage.success('工作地点已更新');
|
|
ElMessage.success('工作地点已更新');
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -3343,7 +3485,7 @@ const addDimension = () => {
|
|
|
|
|
|
const settings = reactive({
|
|
const settings = reactive({
|
|
keepVideo: false,
|
|
keepVideo: false,
|
|
- interruptionMode: 'previous',
|
|
|
|
|
|
+ interruptionMode: '',
|
|
smartFollowUp: false
|
|
smartFollowUp: false
|
|
});
|
|
});
|
|
|
|
|
|
@@ -3372,7 +3514,7 @@ const interviewerAvatars = ref<InterviewerAvatar[]>([
|
|
]);
|
|
]);
|
|
|
|
|
|
const selectedInterviewer = ref(interviewerAvatars.value[0]);
|
|
const selectedInterviewer = ref(interviewerAvatars.value[0]);
|
|
-
|
|
|
|
|
|
+const interviewerAvatar = ref('');
|
|
// 添加面试官选择处理函数
|
|
// 添加面试官选择处理函数
|
|
const handleInterviewerSelect = (avatar: any) => {
|
|
const handleInterviewerSelect = (avatar: any) => {
|
|
// 更新选中的面试官
|
|
// 更新选中的面试官
|
|
@@ -3384,7 +3526,7 @@ const handleInterviewerSelect = (avatar: any) => {
|
|
name: avatar.name,
|
|
name: avatar.name,
|
|
avatar_url: avatar.avatar_url || avatar.image
|
|
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,
|
|
question_form_name: question.question_form_name,
|
|
scoring_reference: question.scoring_reference,
|
|
scoring_reference: question.scoring_reference,
|
|
question_form: question.question_form,
|
|
question_form: question.question_form,
|
|
|
|
+ is_required_correct: question.is_required_correct,
|
|
weight: 100, // 默认权重
|
|
weight: 100, // 默认权重
|
|
maxAnswers: 1, // 默认最多回答次数
|
|
maxAnswers: 1, // 默认最多回答次数
|
|
source: 'custom_selected' as const // 标识为自定义选择的题目
|
|
source: 'custom_selected' as const // 标识为自定义选择的题目
|
|
@@ -3963,7 +4106,7 @@ console.log(selectedQuestions.value);
|
|
selectedQuestions.value = [];
|
|
selectedQuestions.value = [];
|
|
questionSearchKeyword.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,
|
|
question_form_name: question.question_form_name,
|
|
scoring_reference: question.scoring_reference,
|
|
scoring_reference: question.scoring_reference,
|
|
question_form: question.question_form,
|
|
question_form: question.question_form,
|
|
|
|
+ is_required_correct: question.is_required_correct,
|
|
weight: 100,
|
|
weight: 100,
|
|
maxAnswers: 1,
|
|
maxAnswers: 1,
|
|
source: 'ai_generated' as const // 标识为AI生成的题目
|
|
source: 'ai_generated' as const // 标识为AI生成的题目
|