123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- <template>
- <!-- 搜索工作栏 -->
- <ContentWrap>
- <el-form
- class="-mb-15px"
- :model="queryParams"
- ref="queryFormRef"
- :inline="true"
- label-width="68px"
- >
- <el-form-item label="任务类型" prop="task_type">
- <el-select
- v-model="queryParams.task_type"
- placeholder="请选择类型"
- clearable
- class="!w-200px"
- @change="handleQuery"
- >
- <el-option v-for="(val, index) in taskType" :label="val.label" :value="val.value" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item label="任务状态" prop="task_status">
- <el-select
- v-model="queryParams.task_status"
- placeholder="请选择状态"
- clearable
- class="!w-200px"
- @change="handleQuery"
- >
- <el-option v-for="(val, index) in taskStatus" :label="val" :value="val" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button @click="handleQuery"><Icon icon="ep:search" /> 搜索</el-button>
- <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
- <el-button type="primary" plain @click="handleAdd">
- <Icon icon="ep:plus" class="mr-5px" /> 新增人才
- </el-button>
- </el-form-item>
- </el-form>
- </ContentWrap>
- <!-- 列表 -->
- <ContentWrap>
- <el-table v-loading="loading" :data="list" :stripe="true">
- <el-table-column label="任务名称" align="center" prop="task_name" />
- <el-table-column label="任务类型" align="center" prop="task_type" />
- <el-table-column label="任务状态" align="center" prop="task_status" />
- <el-table-column label="创建时间" align="center" prop="created_at" :formatter="dateFormatter" />
- <el-table-column label="更新时间" align="center" prop="updated_at" :formatter="dateFormatter" />
- <el-table-column label="操作" align="center" fixed="right" min-width="110">
- <template #default="scope">
- <el-button
- v-if="scope.row.task_status === '待解析'"
- link
- type="success"
- @click="handleAnalysis(scope.row)"
- >解析</el-button>
- <el-button
- v-if="scope.row.task_status === '成功' && scope.row.parse_result"
- link
- type="primary"
- @click="handleStore(scope.row)"
- >入库</el-button>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <Pagination
- :total="total"
- v-model:page="queryParams.page"
- v-model:limit="queryParams.per_page"
- @pagination="getList"
- />
- </ContentWrap>
- <!-- 选择来源 -->
- <Dialog title="新增" v-model="openSelect" width="550" @close="openSelect = false">
- <el-radio-group v-model="radioValue" size="large" class="radioBox">
- <el-radio
- v-for="item in radioList"
- :key="item.value"
- :value="item.value"
- >
- {{ item.label }}
- </el-radio>
- </el-radio-group>
- <template #footer>
- <el-button type="primary" @click="handleSelect">确 认</el-button>
- <el-button @click="openSelect = false">取 消</el-button>
- </template>
- </Dialog>
- <!-- 解析文件上传 -->
- <Dialog :title="radioObject[radioValue]" v-model="dialog_upload" :modalClose="false" :width="DialogWidth" @close="handleCancel">
- <div>
- <!-- 简历解析 -->
- <template v-if="radioValue === 'file'">
- <el-upload
- ref="uploadRef"
- v-model:file-list="fileList"
- :action="uploadUrl"
- :auto-upload="false"
- :data="fileData"
- :on-change="handleChange"
- :on-error="submitFormError"
- :on-exceed="handleExceed"
- :http-request="httpRequest"
- accept=".pdf"
- drag
- :limit="5"
- multiple
- class="flex-1"
- >
- <i class="el-icon-upload"></i>
- <div class="el-upload__text">仅允许导入PDF格式文件! 将文件拖到此处,或 <em>点击上传</em></div>
- <template #tip>
- <div class="el-upload__tip color-red">
- 提示:最多可上传5份简历({{ fileList.length }}/5)
- </div>
- </template>
- </el-upload>
- </template>
- <!-- 名片解析 -->
- <template v-if="radioValue === 'card'">
- <UploadImgs
- v-model="cardImgUrl"
- :uploadSuccessTip="false"
- :limit="10"
- @handle-change="cardUploadChange"
- height="150px" width="150px" style="margin: 20px auto; text-align: center;"
- >
- <template #tip>{{ cardImgUrl ? `${cardImgUrl.length}/10` : '请上传名片(最多可上传10张)' }}</template>
- </UploadImgs>
- </template>
- <!-- 杂项 -->
- <template v-if="radioValue === 'picture'">
- <div class="flex align-center">
- <UploadImg
- v-model="cardImgUrl"
- :uploadSuccessTip="false"
- @handle-change="val => cardUploadChange(val, '杂项')"
- height="150px" width="150px" style="margin: 20px auto; text-align: center;"
- >
- <template #tip>{{ cardImgUrl ? '' : '请上传图片' }}</template>
- </UploadImg>
- </div>
- </template>
- <!-- 网页解析 -->
- <template v-if="radioValue === 'web'">
- <webAnalysis
- @analysis="handleWebAnalysis"
- @reset="webOriginList = []"
- />
- </template>
- <!-- 网页解析 -->
- <template v-if="radioValue === 'menduner'">
- <Search ref="SearchRef" />
- </template>
- </div>
- <template #footer>
- <el-button @click="handleSubmit" type="success" :disabled="analysisLoading" :loading="analysisLoading">提 交</el-button>
- <el-button @click="handleCancel">取 消</el-button>
- </template>
- </Dialog>
- <StorePage ref="StorePageRef" @refresh="getList" />
- </template>
- <script setup>
- defineOptions({ name: 'TalentMapStoreIndex' })
- import { dateFormatter } from '@/utils/formatTime'
- import { talentLabelingApi } from '@/api/menduner/system/talentMap/labeling'
- import { TalentMap } from '@/api/menduner/system/talentMap'
- import Search from './components/search.vue'
- import webAnalysis from './components/webAnalysis.vue'
- import { useUpload } from '@/components/UploadFile/src/useUpload'
- import { commonApi } from '@/api/menduner/common'
- import { Base64 } from 'js-base64'
- import Info from '@/views/menduner/system/person/details/components/info.vue'
- import expExtend from '@/views/menduner/system/person/details/components/expExtend.vue'
- import Attachment from '@/views/menduner/system/person/details/components/attachment.vue'
- import { talentWebParsingApi } from '@/api/menduner/system/talentMap/webParsing'
- import { ElLoading } from 'element-plus'
- import StorePage from '@/views/menduner/system/talentMap/maintenance/gather/components/store.vue'
- import { talentGatherApi } from '@/api/menduner/system/talentMap/gather'
- const { uploadUrl, httpRequest } = useUpload()
- const message = useMessage() // 消息弹窗
- const { t } = useI18n() // 国际化
- const loading = ref(false) // 列表的加载中
- const list = ref([]) // 列表的数据
- const total = ref(0) // 列表的总页数
- const queryParams = reactive({
- page: 1,
- per_page: 10,
- task_type: undefined, // 任务类型
- task_status: undefined // 任务状态
- })
- const queryFormRef = ref() // 搜索的表单
- const dialog_upload = ref(false)
- const taskType = [
- { label: '名片', value: '名片' },
- { label: '简历', value: '简历' },
- { label: '门墩儿新任命', value: '新任命' },
- { label: '门墩儿招聘', value: '招聘' },
- { label: '杂项', value: '杂项' }
- ]
- const taskStatus = ['待解析', '成功']
- const itemData = ref({})
- const SearchRef = ref(null)
- /** 查询列表 */
- const getList = async () => {
- loading.value = true
- try {
- list.value = []
- const data = await talentGatherApi.getTaskList(queryParams)
- list.value = data.tasks ?? []
- total.value = data.pagination.total ?? 0
- } finally {
- loading.value = false
- }
- }
- /** 搜索按钮操作 */
- const handleQuery = () => {
- queryParams.page = 1
- getList()
- }
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value.resetFields()
- handleQuery()
- }
- // 网页解析-信息提取
- const webOriginList = ref([])
- const handleWebAnalysis = (list) => {
- webOriginList.value = list ?? []
- }
- // 入库
- const StorePageRef = ref(null)
- const handleStore = async (row) => {
- const { task_type, task_name, parse_result } = row
- // const { results } = parse_result
- // if (!results || !results.length) return message.warning('该任务无解析数据,无法入库')
- // StorePageRef.value.open(task_type, results, { summary, processed_time })
- // if (!row?.task_name) return message.warning('该任务无解析数据,无法入库')
- StorePageRef.value.open(task_type, parse_result)
- }
- // 任务解析
- const handleAnalysis = async ({ task_type, id, task_source, task_name }) => {
- if (!id) return
- await message.confirm('是否解析当前任务?')
- const loading = ElLoading.service({
- lock: true,
- text: '任务解析中...',
- background: 'rgba(0, 0, 0, 0.7)',
- })
- const params = {
- task_type,
- id,
- data: task_source.minio_paths_json
- }
- if (task_type === '杂项') params.process_type = 'table'
- if (task_type === '新任命') params.publish_time = '2025-07-23'
- // 招聘数据未返回,params.data设置为测试数据
- if (task_type === '招聘' && !params.data?.length) params.data = [{"id":"1843906600113389570","userId":"598525227328212992","name":"尹世丹","name_zh":"尹世丹"},{"id":"1942125259693166593","userId":"1942124499676893185","name":"陈梅","name_zh":"陈梅"}]
- try {
- const { results } = await talentGatherApi.taskAnalysis(params)
- message.success('解析成功')
- getList()
- StorePageRef.value.open(task_type, { results })
- } finally {
- loading.close()
- }
- }
- // 关闭上传弹窗
- const handleCancel = () => {
- dialog_upload.value = false
- analysisLoading.value = false
- cardUploadRow.value = []
- fileList.value = []
- }
- // 创建任务
- const handleCreateTask = async (query) => {
- try {
- await talentGatherApi.createTask(query)
- message.success('任务创建成功')
- getList()
- } finally {
- analysisLoading.value = false
- webOriginList.value = []
- handleCancel()
- }
- }
- // 新任命
- const handleCreateWebTask = async () => {
- if (!webOriginList.value || !webOriginList.value?.length) return message.warning('请输入新任命链接查看后再进行提交')
- analysisLoading.value = true
- const formData = new FormData()
- formData.append('task_type', '新任命')
- webOriginList.value.forEach(e => {
- formData.append('files', e.file)
- formData.append('publish_time', e.publish_time)
- })
- handleCreateTask(formData)
- }
- // 任务创建
- const analysisLoading = ref(false)
- const handleSubmit = async () => {
- const type = radioValue.value
- // 新任命
- if (type === 'web') return handleCreateWebTask()
- // 杂项、名片、简历
- if (['card', 'file', 'picture'].includes(type)) {
- const currentList = type === 'file' ? fileList.value : cardUploadRow.value
- if (!currentList || !currentList?.length) {
- message.warning(`请上传${type === 'file' ? '简历' : type === 'card' ? '名片' : '杂项'}`)
- return
- }
- analysisLoading.value = true
- const formData = new FormData()
- formData.append('task_type', type === 'file' ? '简历' : type === 'card' ? '名片' : '杂项')
- currentList.forEach(e => {
- formData.append('files', e.raw)
- })
- handleCreateTask(formData)
- }
-
- // 门墩儿招聘
- if (type === 'menduner') {
- const formData = new FormData()
- const list = SearchRef.value?.addList?.length ? SearchRef.value.addList : null
- if (!list) return message.warning('请先选择人员 !')
- formData.append('task_type', '招聘')
- formData.append('data', JSON.stringify(list))
- handleCreateTask(formData)
- }
- }
- // 简历解析
- const uploadRef = ref()
- const fileList = ref([])
- const fileData = ref({ path: '' })
- // 文件上传
- const handleChange = async (file) => {
- fileData.value.path = file.name
- unref(uploadRef)?.submit()
- }
- const submitFormError = () => {
- message.error('上传失败,请您重新上传!')
- }
- const handleExceed = () => {
- message.error('最多只能上传一个文件!')
- }
- // 名片解析
- const cardUploadRow = ref(null)
- const cardImgUrl = ref(null)
- const cardUploadChange = (file, type) => {
- cardUploadRow.value = type ? [{ raw: file }] : file
- }
- // 选择解析方式
- const DialogWidth = ref('500')
- const handleSelect = () => {
- openSelect.value = false
- itemData.value = {}
- DialogWidth.value = '500'
-
- const type = radioValue.value
- if (['card', 'web'].includes(type)) {
- DialogWidth.value = '800'
- }
- if (type === 'menduner') {
- DialogWidth.value = '1200'
- }
- dialog_upload.value = true
- }
- const openSelect = ref(false)
- const radioObject = { card: '名片', file: '简历', web: '门墩儿新任命', menduner: '门墩儿招聘', picture: '杂项' }
- const radioList = ref(Object.keys(radioObject).map(key => ({ value: key, label: radioObject[key]}) ))
- const defaultValue = radioList.value[0].value // 默认选中
- const radioValue = ref(defaultValue)
- // 新增解析
- const handleAdd = () => {
- webOriginList.value = []
- cardUploadRow.value = null
- cardImgUrl.value = null
- analysisLoading.value = false
- radioValue.value = defaultValue // 重置解析类型
- openSelect.value = true
- }
- /** 初始化 **/
- onMounted(() => {
- getList()
- })
- </script>
- <style lang="scss" scoped>
- .radioBox {
- margin: 40px 0;
- }
- :deep {
- .el-tag__content {
- display: flex;
- align-items: center;
- }
- }
- </style>
|