|
|
@@ -4,42 +4,32 @@
|
|
|
<template #detail>
|
|
|
<a-form ref="formRef" :labelCol="labelCol" :wrapperCol="wrapperCol" class="antd-modal-form" name="ResumeInfoForm">
|
|
|
<a-row :gutter="24">
|
|
|
- <a-col :span="8">
|
|
|
- <a-form-item id="ResumeInfoForm-resumeName" label="简历名称" name="resumeName" v-bind="validateInfos.resumeName">
|
|
|
- <a-input v-model:value="formData.resumeName" allow-clear placeholder="请输入简历名称"></a-input>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="8">
|
|
|
- <a-form-item id="ResumeInfoForm-validDate" label="有效期" name="validDate" v-bind="validateInfos.validDate">
|
|
|
- <a-date-picker v-model:value="formData.validDate" allow-clear placeholder="请选择有效期" style="width: 100%" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="8">
|
|
|
- <a-form-item id="ResumeInfoForm-isPublic" label="是否公开" name="isPublic" v-bind="validateInfos.isPublic">
|
|
|
- <a-radio-group v-model:value="formData.isPublic">
|
|
|
- <a-radio value="1">是</a-radio>
|
|
|
- <a-radio value="0">否</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="8">
|
|
|
- <a-form-item id="ResumeInfoForm-isDefault" label="是否默认简历" name="isDefault" v-bind="validateInfos.isDefault">
|
|
|
- <a-radio-group v-model:value="formData.isDefault">
|
|
|
- <a-radio value="1">是</a-radio>
|
|
|
- <a-radio value="0">否</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
<a-divider orientation="left" orientation-margin="10px">求职意向</a-divider>
|
|
|
<!-- 求职意向字段(原子表数据合并入主表) -->
|
|
|
<a-col :span="8">
|
|
|
<a-form-item id="ResumeInfoForm-expectedIndustry" label="期望行业" name="expectedIndustry" v-bind="validateInfos.expectedIndustry">
|
|
|
- <a-input v-model:value="formData.expectedIndustry" allow-clear placeholder="请输入期望行业"></a-input>
|
|
|
+ <a-tree-select
|
|
|
+ v-model:value="expectedIndustryValueObj"
|
|
|
+ :tree-data="expectedIndustryTreeData"
|
|
|
+ placeholder="请选择期望行业"
|
|
|
+ allow-clear
|
|
|
+ label-in-value
|
|
|
+ @change="(val) => { formData.expectedIndustry = val?.value || ''; }"
|
|
|
+ />
|
|
|
</a-form-item>
|
|
|
</a-col>
|
|
|
<a-col :span="8">
|
|
|
<a-form-item id="ResumeInfoForm-expectedPosition" label="期望职位" name="expectedPosition" v-bind="validateInfos.expectedPosition">
|
|
|
- <a-input v-model:value="formData.expectedPosition" allow-clear placeholder="请输入期望职位"></a-input>
|
|
|
+ <a-tree-select
|
|
|
+ v-model:value="positionValueObj"
|
|
|
+ v-model:tree-expanded-keys="positionExpandedKeys"
|
|
|
+ :tree-data="positionTreeData"
|
|
|
+ :load-data="(node) => loadPositionChildren(node)"
|
|
|
+ placeholder="请选择期望职位"
|
|
|
+ allow-clear
|
|
|
+ label-in-value
|
|
|
+ @change="(val) => { formData.expectedPosition = val?.value || ''; }"
|
|
|
+ />
|
|
|
</a-form-item>
|
|
|
</a-col>
|
|
|
<a-col :span="8">
|
|
|
@@ -81,152 +71,174 @@
|
|
|
</a-form-item>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
+
|
|
|
<!-- 工作经历(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">工作经历</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="workExpTableRef"
|
|
|
- :columns="computedWorkExpColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openWorkExpModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="workExpColumns"
|
|
|
:dataSource="workExpData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
>
|
|
|
- <template #companyTypeSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="companyTypeOptions"
|
|
|
- :value="row.companyType"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择单位类型"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
- </template>
|
|
|
- <template #companySizeSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="companySizeOptions"
|
|
|
- :value="row.companySize"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择人员规模"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
+ <template #bodyCell="{ column, text, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'companyType'">
|
|
|
+ {{ getDictText('CompanyType', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.dataIndex === 'companySize'">
|
|
|
+ {{ getDictText('CompanySize', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.dataIndex === 'industry'">
|
|
|
+ {{ getDictText('EconomicIndustry', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.dataIndex === 'economyType'">
|
|
|
+ {{ getDictText('EconomicType', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openWorkExpModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeWorkExp(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
</template>
|
|
|
- </JVxeTable>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<!-- 教育经历(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">教育经历</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="educationTableRef"
|
|
|
- :columns="computedEducationColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openEducationModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="educationColumns"
|
|
|
:dataSource="educationData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
>
|
|
|
- <template #educationSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="educationOptions"
|
|
|
- :value="row.education"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择学历"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
- </template>
|
|
|
- <template #degreeSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="degreeOptions"
|
|
|
- :value="row.degree"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择学位"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
+ <template #bodyCell="{ column, text, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'education'">
|
|
|
+ {{ getDictText('Education', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.dataIndex === 'degree'">
|
|
|
+ {{ getDictText('Degree', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.dataIndex === 'eduSystem'">
|
|
|
+ {{ getDictText('EduSystem', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openEducationModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeEducation(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
</template>
|
|
|
- <template #eduSystemSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="eduSystemOptions"
|
|
|
- :value="row.eduSystem"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择学制"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </JVxeTable>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<!-- 培训经历(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">培训经历</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="trainingTableRef"
|
|
|
- :columns="computedTrainingColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openTrainingModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="trainingColumns"
|
|
|
:dataSource="trainingData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
- />
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openTrainingModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeTraining(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<!-- 职业技能(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">职业技能</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="skillTableRef"
|
|
|
- :columns="computedSkillColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openSkillModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="skillColumns"
|
|
|
:dataSource="skillData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
>
|
|
|
- <template #skillLevelSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="skillLevelOptions"
|
|
|
- :value="row.skillLevel"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择技能等级"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
+ <template #bodyCell="{ column, text, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'skillLevel'">
|
|
|
+ {{ getDictText('SkillLevel', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openSkillModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeSkill(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
</template>
|
|
|
- </JVxeTable>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<!-- 职称情况(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">职称情况</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="titleTableRef"
|
|
|
- :columns="computedTitleColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openTitleModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="titleColumns"
|
|
|
:dataSource="titleData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
>
|
|
|
- <template #titleLevelSlot="{ row, triggerChange }">
|
|
|
- <a-select
|
|
|
- :bordered="false"
|
|
|
- :options="titleLevelOptions"
|
|
|
- :value="row.level"
|
|
|
- allow-clear
|
|
|
- placeholder="请选择职称级别"
|
|
|
- style="width: 100%"
|
|
|
- @change="(val) => triggerChange(val)"
|
|
|
- />
|
|
|
+ <template #bodyCell="{ column, text, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'level'">
|
|
|
+ {{ getDictText('TitleLevel', text) }}
|
|
|
+ </template>
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openTitleModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeTitle(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
</template>
|
|
|
- </JVxeTable>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<a-divider orientation="left" orientation-margin="0px">其他证书</a-divider>
|
|
|
<a-row :gutter="24">
|
|
|
<a-col :span="24">
|
|
|
@@ -242,35 +254,74 @@
|
|
|
</a-form-item>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
+
|
|
|
<!-- 获奖情况(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">获奖情况</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="awardTableRef"
|
|
|
- :columns="computedAwardColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openAwardModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="awardColumns"
|
|
|
:dataSource="awardData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
- />
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openAwardModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeAward(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+
|
|
|
<!-- 留学经历(子表) -->
|
|
|
<a-divider orientation="left" orientation-margin="0px">留学经历</a-divider>
|
|
|
- <JVxeTable
|
|
|
- ref="studyAbroadTableRef"
|
|
|
- :columns="computedStudyAbroadColumns"
|
|
|
+ <div style="text-align: right; margin-bottom: 8px;">
|
|
|
+ <a-button v-if="!disabled" type="primary" size="small" @click="openStudyAbroadModal()">
|
|
|
+ <template #icon><plus-outlined /></template>
|
|
|
+ 新增
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <a-table
|
|
|
+ :columns="studyAbroadColumns"
|
|
|
:dataSource="studyAbroadData.dataSource"
|
|
|
- :height="250"
|
|
|
- keepSource
|
|
|
- rowNumber
|
|
|
- rowSelection
|
|
|
- stripe
|
|
|
- toolbar
|
|
|
- />
|
|
|
+ :pagination="false"
|
|
|
+ bordered
|
|
|
+ size="small"
|
|
|
+ rowKey="id"
|
|
|
+ style="margin-bottom: 24px"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index }">
|
|
|
+ <template v-if="column.dataIndex === 'action' && !disabled">
|
|
|
+ <a @click="openStudyAbroadModal(record, index)">编辑</a>
|
|
|
+ <a-divider type="vertical" />
|
|
|
+ <a-popconfirm title="确定删除吗?" @confirm="removeStudyAbroad(index)">
|
|
|
+ <a style="color: #ff4d4f">删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
</a-form>
|
|
|
</template>
|
|
|
</JFormContainer>
|
|
|
+
|
|
|
+ <!-- 子表新增/编辑弹窗 -->
|
|
|
+ <ResumeWorkExpModal ref="workExpModalRef" @success="onWorkExpSuccess" />
|
|
|
+ <ResumeEducationModal ref="educationModalRef" @success="onEducationSuccess" />
|
|
|
+ <ResumeTrainingModal ref="trainingModalRef" @success="onTrainingSuccess" />
|
|
|
+ <ResumeSkillModal ref="skillModalRef" @success="onSkillSuccess" />
|
|
|
+ <ResumeTitleModal ref="titleModalRef" @success="onTitleSuccess" />
|
|
|
+ <ResumeAwardModal ref="awardModalRef" @success="onAwardSuccess" />
|
|
|
+ <ResumeStudyAbroadModal ref="studyAbroadModalRef" @success="onStudyAbroadSuccess" />
|
|
|
</a-spin>
|
|
|
</template>
|
|
|
|
|
|
@@ -278,21 +329,22 @@
|
|
|
import { computed, defineExpose, nextTick, reactive, ref } from 'vue';
|
|
|
import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
import { useDict } from '/@/hooks/dictionary/useDict';
|
|
|
+ import { defHttp } from '/@/utils/http/axios';
|
|
|
import { getDateByPicker, getValueType } from '/@/utils';
|
|
|
import { editResume, queryResumeById, saveResume } from '../ResumeInfo.api';
|
|
|
import dayjs from 'dayjs';
|
|
|
- import {
|
|
|
- awardColumns,
|
|
|
- educationColumns,
|
|
|
- skillColumns,
|
|
|
- studyAbroadColumns,
|
|
|
- titleColumns,
|
|
|
- trainingColumns,
|
|
|
- workExpColumns,
|
|
|
- } from '../ResumeInfo.data';
|
|
|
- import { JVxeColumn } from '/@/components/jeecg/JVxeTable/types';
|
|
|
import { Form } from 'ant-design-vue';
|
|
|
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
|
|
+ import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
+
|
|
|
+ // 子表弹窗组件
|
|
|
+ import ResumeWorkExpModal from './ResumeWorkExpModal.vue';
|
|
|
+ import ResumeEducationModal from './ResumeEducationModal.vue';
|
|
|
+ import ResumeTrainingModal from './ResumeTrainingModal.vue';
|
|
|
+ import ResumeSkillModal from './ResumeSkillModal.vue';
|
|
|
+ import ResumeTitleModal from './ResumeTitleModal.vue';
|
|
|
+ import ResumeAwardModal from './ResumeAwardModal.vue';
|
|
|
+ import ResumeStudyAbroadModal from './ResumeStudyAbroadModal.vue';
|
|
|
|
|
|
const props = defineProps({
|
|
|
formDisabled: { type: Boolean, default: false },
|
|
|
@@ -336,24 +388,96 @@
|
|
|
const fieldPickers = reactive({});
|
|
|
|
|
|
// 预加载字典数据
|
|
|
- const { getDictOptions } = useDict(['WorkNature', 'CompanyType', 'CompanySize', 'Education', 'Degree', 'EduSystem', 'SkillLevel', 'TitleLevel']);
|
|
|
+ const { getDictOptions, getDictText } = useDict(['WorkNature', 'CompanyType', 'CompanySize', 'Education', 'Degree', 'EduSystem', 'SkillLevel', 'TitleLevel', 'EconomicIndustry', 'EconomicType']);
|
|
|
const workNatureOptions = computed(() => getDictOptions('WorkNature'));
|
|
|
- const companyTypeOptions = computed(() => getDictOptions('CompanyType'));
|
|
|
- const companySizeOptions = computed(() => getDictOptions('CompanySize'));
|
|
|
- const educationOptions = computed(() => getDictOptions('Education'));
|
|
|
- const degreeOptions = computed(() => getDictOptions('Degree'));
|
|
|
- const eduSystemOptions = computed(() => getDictOptions('EduSystem'));
|
|
|
- const skillLevelOptions = computed(() => getDictOptions('SkillLevel'));
|
|
|
- const titleLevelOptions = computed(() => getDictOptions('TitleLevel'));
|
|
|
-
|
|
|
- const workExpTableRef = ref();
|
|
|
- const educationTableRef = ref();
|
|
|
- const trainingTableRef = ref();
|
|
|
- const skillTableRef = ref();
|
|
|
- const titleTableRef = ref();
|
|
|
- const awardTableRef = ref();
|
|
|
- const studyAbroadTableRef = ref();
|
|
|
|
|
|
+ // ---------- 树形字典:期望行业 (EconomicIndustry) ----------
|
|
|
+ const expectedIndustryTreeData = ref<any[]>([]);
|
|
|
+ const expectedIndustryValueObj = ref<any>(undefined);
|
|
|
+
|
|
|
+ // ---------- 树形字典:期望职位 (ZYFL) ----------
|
|
|
+ const positionTreeData = ref<any[]>([]);
|
|
|
+ const positionValueObj = ref<any>(undefined);
|
|
|
+ const positionExpandedKeys = ref<string[]>([]);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从 getDictTree 接口加载树形字典完整数据
|
|
|
+ * 后端返回格式: { label, value, children }
|
|
|
+ * 映射为 a-tree-select 识别的: { key, title, value, isLeaf, children }
|
|
|
+ */
|
|
|
+ async function loadTreeData(dictionaryCode: string) {
|
|
|
+ const res = await defHttp.get({ url: '/system/dictionary/getDictTree', params: { dictionaryCode } }, { isTransformResponse: false });
|
|
|
+ if (res.success && res.result) {
|
|
|
+ return res.result.map((item) => treeNodeMapper(item));
|
|
|
+ }
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 递归映射树节点:从后端 {label, value, children} 转为 {key, title, value, isLeaf, children} */
|
|
|
+ function treeNodeMapper(node: any): any {
|
|
|
+ return {
|
|
|
+ key: String(node.value),
|
|
|
+ title: node.label,
|
|
|
+ value: String(node.value),
|
|
|
+ isLeaf: !node.children || node.children.length === 0,
|
|
|
+ children: node.children?.length ? node.children.map((child) => treeNodeMapper(child)) : undefined,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 在树形字典数据中递归查找 value 对应的 label */
|
|
|
+ function findTreeNodeLabel(tree: any[], value: string): string | undefined {
|
|
|
+ for (const node of tree) {
|
|
|
+ if (node.value === value) return node.title;
|
|
|
+ if (node.children) {
|
|
|
+ const found = findTreeNodeLabel(node.children, value);
|
|
|
+ if (found) return found;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return undefined;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载期望职位(ZYFL)树形字典根节点(懒加载,数据量2000+)
|
|
|
+ */
|
|
|
+ async function loadPositionRootNodes() {
|
|
|
+ const res = await defHttp.get({
|
|
|
+ url: '/system/dictionary/getDictTreeChildren',
|
|
|
+ params: { dictionaryCode: 'ZYFL', parentCode: '' },
|
|
|
+ }, { isTransformResponse: false });
|
|
|
+ if (res.success && res.result) {
|
|
|
+ return res.result.map((item) => ({
|
|
|
+ key: item.key,
|
|
|
+ title: item.title,
|
|
|
+ value: item.key,
|
|
|
+ isLeaf: item.leaf,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 懒加载期望职位(ZYFL)子节点(展开时按需加载下一级)
|
|
|
+ */
|
|
|
+ async function loadPositionChildren(treeNode) {
|
|
|
+ if (treeNode.dataRef.children) return Promise.resolve();
|
|
|
+ const res = await defHttp.get({
|
|
|
+ url: '/system/dictionary/getDictTreeChildren',
|
|
|
+ params: { dictionaryCode: 'ZYFL', parentCode: treeNode.value },
|
|
|
+ }, { isTransformResponse: false });
|
|
|
+ if (res.success && res.result) {
|
|
|
+ const children = res.result.map((item) => ({
|
|
|
+ key: item.key,
|
|
|
+ title: item.title,
|
|
|
+ value: item.key,
|
|
|
+ isLeaf: item.leaf,
|
|
|
+ }));
|
|
|
+ treeNode.dataRef.children = children;
|
|
|
+ positionTreeData.value = [...positionTreeData.value];
|
|
|
+ }
|
|
|
+ return Promise.resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 子表数据源
|
|
|
const workExpData = reactive({ dataSource: [] });
|
|
|
const educationData = reactive({ dataSource: [] });
|
|
|
const trainingData = reactive({ dataSource: [] });
|
|
|
@@ -362,6 +486,24 @@
|
|
|
const awardData = reactive({ dataSource: [] });
|
|
|
const studyAbroadData = reactive({ dataSource: [] });
|
|
|
|
|
|
+ // 编辑时记录当前操作的行索引
|
|
|
+ const editingWorkExpIndex = ref<number | null>(null);
|
|
|
+ const editingEducationIndex = ref<number | null>(null);
|
|
|
+ const editingTrainingIndex = ref<number | null>(null);
|
|
|
+ const editingSkillIndex = ref<number | null>(null);
|
|
|
+ const editingTitleIndex = ref<number | null>(null);
|
|
|
+ const editingAwardIndex = ref<number | null>(null);
|
|
|
+ const editingStudyAbroadIndex = ref<number | null>(null);
|
|
|
+
|
|
|
+ // 子表弹窗引用
|
|
|
+ const workExpModalRef = ref();
|
|
|
+ const educationModalRef = ref();
|
|
|
+ const trainingModalRef = ref();
|
|
|
+ const skillModalRef = ref();
|
|
|
+ const titleModalRef = ref();
|
|
|
+ const awardModalRef = ref();
|
|
|
+ const studyAbroadModalRef = ref();
|
|
|
+
|
|
|
const disabled = computed(() => {
|
|
|
if (props.formBpm === true) {
|
|
|
if (props.formData.disabled === false) {
|
|
|
@@ -373,33 +515,230 @@
|
|
|
return props.formDisabled;
|
|
|
});
|
|
|
|
|
|
- function applyDisabled(columns: JVxeColumn[]): JVxeColumn[] {
|
|
|
- if (!disabled.value) return columns;
|
|
|
- return columns.map((col) => ({ ...col, disabled: true }));
|
|
|
- }
|
|
|
-
|
|
|
- const computedWorkExpColumns = computed(() => applyDisabled(workExpColumns));
|
|
|
- const computedEducationColumns = computed(() => applyDisabled(educationColumns));
|
|
|
- const computedTrainingColumns = computed(() => applyDisabled(trainingColumns));
|
|
|
- const computedSkillColumns = computed(() => applyDisabled(skillColumns));
|
|
|
- const computedTitleColumns = computed(() => applyDisabled(titleColumns));
|
|
|
- const computedAwardColumns = computed(() => applyDisabled(awardColumns));
|
|
|
- const computedStudyAbroadColumns = computed(() => applyDisabled(studyAbroadColumns));
|
|
|
-
|
|
|
- function convertDateFields(list: any[], dateKeys: string[]): any[] {
|
|
|
- if (!list || list.length === 0) return list;
|
|
|
- return list.map((item) => {
|
|
|
- const newItem = { ...item };
|
|
|
- dateKeys.forEach((key) => {
|
|
|
- if (newItem[key] && typeof newItem[key] === 'string') {
|
|
|
- newItem[key] = dayjs(newItem[key]);
|
|
|
- }
|
|
|
- });
|
|
|
- return newItem;
|
|
|
- });
|
|
|
+ // ---------- 表格列定义 ----------
|
|
|
+ const workExpColumns = [
|
|
|
+ { title: '工作单位', dataIndex: 'companyName', width: 180 },
|
|
|
+ { title: '所在职位', dataIndex: 'position', width: 150 },
|
|
|
+ { title: '开始时间', dataIndex: 'startDate', width: 120 },
|
|
|
+ { title: '结束时间', dataIndex: 'endDate', width: 120 },
|
|
|
+ { title: '所属行业', dataIndex: 'industry', width: 150 },
|
|
|
+ { title: '单位类型', dataIndex: 'companyType', width: 120 },
|
|
|
+ { title: '经济类型', dataIndex: 'economyType', width: 120 },
|
|
|
+ { title: '人员规模', dataIndex: 'companySize', width: 120 },
|
|
|
+ { title: '工作职责', dataIndex: 'workResponsibility', width: 200 },
|
|
|
+ { title: '工作业绩', dataIndex: 'workAchievement', width: 200 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const educationColumns = [
|
|
|
+ { title: '开始时间', dataIndex: 'startDate', width: 120 },
|
|
|
+ { title: '结束时间', dataIndex: 'endDate', width: 120 },
|
|
|
+ { title: '毕业院校', dataIndex: 'schoolName', width: 180 },
|
|
|
+ { title: '所学专业', dataIndex: 'major', width: 150 },
|
|
|
+ { title: '学历', dataIndex: 'education', width: 100 },
|
|
|
+ { title: '学位', dataIndex: 'degree', width: 100 },
|
|
|
+ { title: '学制', dataIndex: 'eduSystem', width: 100 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const trainingColumns = [
|
|
|
+ { title: '培训机构', dataIndex: 'trainingInstitution', width: 180 },
|
|
|
+ { title: '培训课程', dataIndex: 'trainingCourse', width: 150 },
|
|
|
+ { title: '开始时间', dataIndex: 'startDate', width: 120 },
|
|
|
+ { title: '结束时间', dataIndex: 'endDate', width: 120 },
|
|
|
+ { title: '资格证书号', dataIndex: 'certificateNo', width: 180 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const skillColumns = [
|
|
|
+ { title: '职业名称', dataIndex: 'professionName', width: 180 },
|
|
|
+ { title: '工种/职业方向', dataIndex: 'workType', width: 150 },
|
|
|
+ { title: '技能等级', dataIndex: 'skillLevel', width: 120 },
|
|
|
+ { title: '发证日期', dataIndex: 'issueDate', width: 120 },
|
|
|
+ { title: '发证机构', dataIndex: 'issueOrganization', width: 180 },
|
|
|
+ { title: '证书编号', dataIndex: 'certificateNo', width: 180 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const titleColumns = [
|
|
|
+ { title: '职称名称', dataIndex: 'titleName', width: 180 },
|
|
|
+ { title: '专业', dataIndex: 'profession', width: 150 },
|
|
|
+ { title: '级别', dataIndex: 'level', width: 100 },
|
|
|
+ { title: '发证日期', dataIndex: 'issueDate', width: 120 },
|
|
|
+ { title: '发证单位', dataIndex: 'issueUnit', width: 180 },
|
|
|
+ { title: '证书编号', dataIndex: 'certificateNo', width: 180 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const awardColumns = [
|
|
|
+ { title: '证书名称', dataIndex: 'certificateName', width: 180 },
|
|
|
+ { title: '发证日期', dataIndex: 'issueDate', width: 120 },
|
|
|
+ { title: '颁奖机构', dataIndex: 'awardOrganization', width: 180 },
|
|
|
+ { title: '角色', dataIndex: 'role', width: 100 },
|
|
|
+ { title: '成果名称', dataIndex: 'achievementName', width: 180 },
|
|
|
+ { title: '成果说明', dataIndex: 'achievementDesc', width: 200 },
|
|
|
+ { title: '其他说明', dataIndex: 'otherDesc', width: 200 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const studyAbroadColumns = [
|
|
|
+ { title: '院校名称', dataIndex: 'schoolName', width: 180 },
|
|
|
+ { title: '国家或地区', dataIndex: 'countryRegion', width: 120 },
|
|
|
+ { title: '留学专业', dataIndex: 'major', width: 150 },
|
|
|
+ { title: '是否毕业', dataIndex: 'isGraduated', width: 100 },
|
|
|
+ { title: '开始时间', dataIndex: 'startDate', width: 120 },
|
|
|
+ { title: '结束时间', dataIndex: 'endDate', width: 120 },
|
|
|
+ { title: '海外学历认证书编号', dataIndex: 'diplomaCertNo', width: 200 },
|
|
|
+ { title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ // ---------- 子表操作:新增/编辑/删除 ----------
|
|
|
+ let tempIdCounter = 0;
|
|
|
+ function genId(): string {
|
|
|
+ return '__temp_' + ++tempIdCounter;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 工作经历
|
|
|
+ function openWorkExpModal(record?: any, index?: number) {
|
|
|
+ editingWorkExpIndex.value = index !== undefined ? index : null;
|
|
|
+ workExpModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onWorkExpSuccess(data: any) {
|
|
|
+ if (editingWorkExpIndex.value !== null) {
|
|
|
+ workExpData.dataSource[editingWorkExpIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ workExpData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ workExpData.dataSource = [...workExpData.dataSource];
|
|
|
+ }
|
|
|
+ function removeWorkExp(index: number) {
|
|
|
+ workExpData.dataSource.splice(index, 1);
|
|
|
+ workExpData.dataSource = [...workExpData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 教育经历
|
|
|
+ function openEducationModal(record?: any, index?: number) {
|
|
|
+ editingEducationIndex.value = index !== undefined ? index : null;
|
|
|
+ educationModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onEducationSuccess(data: any) {
|
|
|
+ if (editingEducationIndex.value !== null) {
|
|
|
+ educationData.dataSource[editingEducationIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ educationData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ educationData.dataSource = [...educationData.dataSource];
|
|
|
+ }
|
|
|
+ function removeEducation(index: number) {
|
|
|
+ educationData.dataSource.splice(index, 1);
|
|
|
+ educationData.dataSource = [...educationData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 培训经历
|
|
|
+ function openTrainingModal(record?: any, index?: number) {
|
|
|
+ editingTrainingIndex.value = index !== undefined ? index : null;
|
|
|
+ trainingModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onTrainingSuccess(data: any) {
|
|
|
+ if (editingTrainingIndex.value !== null) {
|
|
|
+ trainingData.dataSource[editingTrainingIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ trainingData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ trainingData.dataSource = [...trainingData.dataSource];
|
|
|
+ }
|
|
|
+ function removeTraining(index: number) {
|
|
|
+ trainingData.dataSource.splice(index, 1);
|
|
|
+ trainingData.dataSource = [...trainingData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 职业技能
|
|
|
+ function openSkillModal(record?: any, index?: number) {
|
|
|
+ editingSkillIndex.value = index !== undefined ? index : null;
|
|
|
+ skillModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onSkillSuccess(data: any) {
|
|
|
+ if (editingSkillIndex.value !== null) {
|
|
|
+ skillData.dataSource[editingSkillIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ skillData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ skillData.dataSource = [...skillData.dataSource];
|
|
|
+ }
|
|
|
+ function removeSkill(index: number) {
|
|
|
+ skillData.dataSource.splice(index, 1);
|
|
|
+ skillData.dataSource = [...skillData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 职称情况
|
|
|
+ function openTitleModal(record?: any, index?: number) {
|
|
|
+ editingTitleIndex.value = index !== undefined ? index : null;
|
|
|
+ titleModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onTitleSuccess(data: any) {
|
|
|
+ if (editingTitleIndex.value !== null) {
|
|
|
+ titleData.dataSource[editingTitleIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ titleData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ titleData.dataSource = [...titleData.dataSource];
|
|
|
+ }
|
|
|
+ function removeTitle(index: number) {
|
|
|
+ titleData.dataSource.splice(index, 1);
|
|
|
+ titleData.dataSource = [...titleData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获奖情况
|
|
|
+ function openAwardModal(record?: any, index?: number) {
|
|
|
+ editingAwardIndex.value = index !== undefined ? index : null;
|
|
|
+ awardModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onAwardSuccess(data: any) {
|
|
|
+ if (editingAwardIndex.value !== null) {
|
|
|
+ awardData.dataSource[editingAwardIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ awardData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ awardData.dataSource = [...awardData.dataSource];
|
|
|
+ }
|
|
|
+ function removeAward(index: number) {
|
|
|
+ awardData.dataSource.splice(index, 1);
|
|
|
+ awardData.dataSource = [...awardData.dataSource];
|
|
|
}
|
|
|
|
|
|
- function add(personalId) {
|
|
|
+ // 留学经历
|
|
|
+ function openStudyAbroadModal(record?: any, index?: number) {
|
|
|
+ editingStudyAbroadIndex.value = index !== undefined ? index : null;
|
|
|
+ studyAbroadModalRef.value?.open(record);
|
|
|
+ }
|
|
|
+ function onStudyAbroadSuccess(data: any) {
|
|
|
+ if (editingStudyAbroadIndex.value !== null) {
|
|
|
+ studyAbroadData.dataSource[editingStudyAbroadIndex.value] = data;
|
|
|
+ } else {
|
|
|
+ data.id = genId();
|
|
|
+ studyAbroadData.dataSource.push(data);
|
|
|
+ }
|
|
|
+ studyAbroadData.dataSource = [...studyAbroadData.dataSource];
|
|
|
+ }
|
|
|
+ function removeStudyAbroad(index: number) {
|
|
|
+ studyAbroadData.dataSource.splice(index, 1);
|
|
|
+ studyAbroadData.dataSource = [...studyAbroadData.dataSource];
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------- 主表操作 ----------
|
|
|
+ async function add(personalId) {
|
|
|
+ // 加载树形字典数据:期望行业全量加载,期望职位懒加载
|
|
|
+ expectedIndustryTreeData.value = await loadTreeData('EconomicIndustry');
|
|
|
+ expectedIndustryValueObj.value = undefined;
|
|
|
+ positionTreeData.value = await loadPositionRootNodes();
|
|
|
+ positionValueObj.value = undefined;
|
|
|
+ positionExpandedKeys.value = [];
|
|
|
edit({ personalId });
|
|
|
}
|
|
|
|
|
|
@@ -407,6 +746,10 @@
|
|
|
await nextTick();
|
|
|
resetFields();
|
|
|
resetSubTables();
|
|
|
+ // 重置树形字典状态
|
|
|
+ expectedIndustryValueObj.value = undefined;
|
|
|
+ positionValueObj.value = undefined;
|
|
|
+ positionExpandedKeys.value = [];
|
|
|
if (record.id) {
|
|
|
confirmLoading.value = true;
|
|
|
try {
|
|
|
@@ -422,13 +765,31 @@
|
|
|
tmpData.validDate = dayjs(tmpData.validDate);
|
|
|
}
|
|
|
Object.assign(formData, tmpData);
|
|
|
- workExpData.dataSource = convertDateFields(res.resumeWorkExpList || [], ['startDate', 'endDate']);
|
|
|
- educationData.dataSource = convertDateFields(res.resumeEducationList || [], ['startDate', 'endDate']);
|
|
|
- trainingData.dataSource = convertDateFields(res.resumeTrainingList || [], ['startDate', 'endDate']);
|
|
|
- skillData.dataSource = convertDateFields(res.resumeSkillList || [], ['issueDate']);
|
|
|
- titleData.dataSource = convertDateFields(res.resumeTitleList || [], ['issueDate']);
|
|
|
- awardData.dataSource = convertDateFields(res.resumeAwardList || [], ['issueDate']);
|
|
|
- studyAbroadData.dataSource = convertDateFields(res.resumeStudyAbroadList || [], ['startDate', 'endDate']);
|
|
|
+ // 加载树形字典数据:期望行业全量加载,期望职位懒加载
|
|
|
+ expectedIndustryTreeData.value = await loadTreeData('EconomicIndustry');
|
|
|
+ positionTreeData.value = await loadPositionRootNodes();
|
|
|
+ // 期望行业:从已加载的树数据中查找 label 回显
|
|
|
+ if (tmpData.expectedIndustry) {
|
|
|
+ const label = findTreeNodeLabel(expectedIndustryTreeData.value, tmpData.expectedIndustry) || tmpData.expectedIndustry;
|
|
|
+ expectedIndustryValueObj.value = { value: tmpData.expectedIndustry, label };
|
|
|
+ }
|
|
|
+ // 期望职位:调 API 获取字典项名称用于编辑回显
|
|
|
+ if (tmpData.expectedPosition) {
|
|
|
+ const apiRes = await defHttp.get({
|
|
|
+ url: `/system/dictionary/loadDictItem/ZYFL`,
|
|
|
+ params: { key: tmpData.expectedPosition },
|
|
|
+ }, { isTransformResponse: false });
|
|
|
+ const label = apiRes.success && apiRes.result?.length ? apiRes.result[0] : tmpData.expectedPosition;
|
|
|
+ positionValueObj.value = { value: tmpData.expectedPosition, label };
|
|
|
+ }
|
|
|
+ // 直接用原始字符串数据,子表弹窗的 open() 会自行处理 string→dayjs 转换
|
|
|
+ workExpData.dataSource = res.resumeWorkExpList || [];
|
|
|
+ educationData.dataSource = res.resumeEducationList || [];
|
|
|
+ trainingData.dataSource = res.resumeTrainingList || [];
|
|
|
+ skillData.dataSource = res.resumeSkillList || [];
|
|
|
+ titleData.dataSource = res.resumeTitleList || [];
|
|
|
+ awardData.dataSource = res.resumeAwardList || [];
|
|
|
+ studyAbroadData.dataSource = res.resumeStudyAbroadList || [];
|
|
|
}
|
|
|
} finally {
|
|
|
confirmLoading.value = false;
|
|
|
@@ -475,13 +836,15 @@
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- const workExpList = workExpTableRef.value?.getTableData?.() || [];
|
|
|
- const educationList = educationTableRef.value?.getTableData?.() || [];
|
|
|
- const trainingList = trainingTableRef.value?.getTableData?.() || [];
|
|
|
- const skillList = skillTableRef.value?.getTableData?.() || [];
|
|
|
- const titleList = titleTableRef.value?.getTableData?.() || [];
|
|
|
- const awardList = awardTableRef.value?.getTableData?.() || [];
|
|
|
- const studyAbroadList = studyAbroadTableRef.value?.getTableData?.() || [];
|
|
|
+
|
|
|
+ // 从本地 dataSource 收集子表数据
|
|
|
+ const workExpList = [...workExpData.dataSource];
|
|
|
+ const educationList = [...educationData.dataSource];
|
|
|
+ const trainingList = [...trainingData.dataSource];
|
|
|
+ const skillList = [...skillData.dataSource];
|
|
|
+ const titleList = [...titleData.dataSource];
|
|
|
+ const awardList = [...awardData.dataSource];
|
|
|
+ const studyAbroadList = [...studyAbroadData.dataSource];
|
|
|
|
|
|
const dto = {
|
|
|
...model,
|