Преглед изворни кода

使用简历附件生成在线简历

lifanagju_citu пре 4 месеци
родитељ
комит
13d800e8d2

+ 2 - 2
pagesA/resume/index.vue

@@ -5,7 +5,7 @@
       <uni-card v-for="(item, index) in bioList" :key="index" :is-shadow="true" :border='false' shadow="0px 0px 3px 1px rgba(0,0,0,0.1)">
         <view class="d-flex align-center">
           <view v-if="props.resumeAnalysis" class="ss-m-r-15">
-            <radio :value="index" :checked="index === checkedIndex" @tap="radioChange(index)" />
+            <radio :value="index" color="#00897B" :checked="index === checkedIndex" @tap="radioChange(index)" />
           </view>
           <view @click="preview(item.url)"  style="flex: 1;">
             <view class="font-size-14" style="font-weight: bold;">{{ item.title }}</view>
@@ -21,7 +21,7 @@
 			<image src="https://minio.citupro.com/dev/static/nodata.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
 		</view>
     <view class="bottom-sticky flex-column">
-      <!-- <button class="recomm-button" style="margin-bottom: 0;" :loading="analysisLoading" @click="handleResumeAnalysis">开始解析</button> -->
+      <button v-if="props.resumeAnalysis" class="recomm-button" style="margin-bottom: 0;" :loading="analysisLoading" @click="handleResumeAnalysis">开始解析</button>
       <button class="recomm-button" style="margin-bottom: 0;" @click="handleUpload">微信聊天文件上传</button>
       <view class="color-primary font-size-14 ss-m-b-25 ss-m-t-10" style="text-align: center;">上传文件大小不能超过20MB</view>
     </view>

+ 11 - 3
pagesA/resumeAnalysis/components/advantage.vue

@@ -22,6 +22,10 @@ const props = defineProps({
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: String,
     default: ''
@@ -47,9 +51,13 @@ const rules = {
 }
 
 const submit = async () => {
-  const valid = await unref(form).validate()
-  if (!valid) return { id: props.id, data: null}
-  return { id: props.id, data: formData.value.advantage}
+  try {
+    const valid = await unref(form).validate()
+    // if (!valid) return { id: props.id, data: null}
+    return { id: props.id, data: { content: formData.value.advantage }}
+  } catch (error) {
+    return { text: props.text }
+  }
 }
 
 defineExpose({

+ 4 - 0
pagesA/resumeAnalysis/components/avatarEdit.vue

@@ -24,6 +24,10 @@ const props = defineProps({
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: String,
     default: ''

+ 31 - 20
pagesA/resumeAnalysis/components/baseInfoEdit.vue

@@ -49,6 +49,7 @@ import { cloneDeep } from 'lodash-es'
 import { emailRequired } from '@/utils/validate'
 import { dictObj } from '@/utils/position.js'
 import { userStore } from '@/store/user'
+import { removeEmptyProperties } from "@/utils/index"
 // import { saveBaseInfo, updatePersonAvatar } from '@/api/user'
 // import { uploadFile } from '@/api/file'
 import { ref, watch, unref } from 'vue'
@@ -57,6 +58,10 @@ const props = defineProps({
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: Object,
     default: () => ({})
@@ -68,31 +73,33 @@ const sexData = ref([])
 const map = { text: 'label', value: 'value' }
 const useUserStore = userStore()
 
-const formData = ref({})
+const formData = ref({
+  name: '',
+  sex: '',
+  regId: '',
+  birthday: '1985-05-01',
+  phone: '',
+  email: '',
+  eduType: '',
+  firstWorkTime: '',
+  expType: '',
+  jobType: '',
+  jobStatus: '',
+  maritalStatus: '',
+  areaId: ''
+})
 const getInfo = (data) => {
   data.phone = data.phone || useUserStore?.baseInfo?.phone
-  formData.value = cloneDeep(data) || {
-    name: '',
-    sex: '',
-    regId: '',
-    birthday: '1985-05-01',
-    phone: '',
-    email: '',
-    eduType: '',
-    firstWorkTime: '',
-    expType: '',
-    jobType: '',
-    jobStatus: '',
-    maritalStatus: '',
-    areaId: ''
-  }
+  Object.keys(formData.value).forEach(key => formData.value[key] = data[key])
+  debugger
 }
 
 watch(
   () => props.data,
   (newVal) => {
     if (newVal && Object.keys(newVal)) {
-      getInfo(newVal)
+      const data = removeEmptyProperties(newVal)
+      getInfo(data)
     }
   },
   { immediate: true },
@@ -131,9 +138,13 @@ const rules = {
 
 
 const submit = async () => {
-  const valid = await unref(form).validate()
-  if (!valid) return { id: props.id, data: null}
-  return { id: props.id, data: formData.value}
+  try {
+    const valid = await unref(form).validate()
+    // if (!valid) return { id: props.id, data: null}
+    return { id: props.id, data: formData.value}
+  } catch (error) {
+    return { text: props.text }
+  }
 }
 
 defineExpose({

+ 16 - 7
pagesA/resumeAnalysis/components/educationExp.vue

@@ -35,11 +35,16 @@ import { cloneDeep } from 'lodash-es'
 import { ref, watch, unref } from 'vue'
 import { dictObj } from '@/utils/position.js'
 import { convertYearMonthToTimestamp, timesTampChange } from '@/utils/date.js'
+import { removeEmptyProperties } from "@/utils/index"
 const props = defineProps({
   id: {
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: Object,
     default: () => ({})
@@ -75,7 +80,8 @@ watch(
   () => props.data,
   (newVal) => {
     if (newVal && Object.keys(newVal)) {
-      getInfo(newVal)
+      const data = removeEmptyProperties(newVal)
+      getInfo(data)
     }
   },
   { immediate: true },
@@ -122,12 +128,15 @@ const handleSearchMajor = (e) => {
 }
 
 const submit = async () => {
-  const valid = await unref(form).validate()
-  if (!valid) return { id: props.id, data: null}
-  //
-  const startTime = convertYearMonthToTimestamp(formData.value.startTime)
-  const endTime = convertYearMonthToTimestamp(formData.value.endTime)
-  return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  try {
+    const valid = await unref(form).validate()
+    // if (!valid) return { id: props.id, data: null}
+    const startTime = convertYearMonthToTimestamp(formData.value.startTime)
+    const endTime = convertYearMonthToTimestamp(formData.value.endTime)
+    return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  } catch (error) {
+    return { text: props.text }
+  }
 }
 
 defineExpose({

+ 16 - 7
pagesA/resumeAnalysis/components/trainingExperience.vue

@@ -28,11 +28,16 @@
 import { cloneDeep } from 'lodash-es'
 import { ref, watch, unref } from 'vue'
 import { convertYearMonthToTimestamp, timesTampChange } from '@/utils/date.js'
+import { removeEmptyProperties } from "@/utils/index"
 const props = defineProps({
   id: {
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: Object,
     default: () => ({})
@@ -60,7 +65,8 @@ watch(
   () => props.data,
   (newVal) => {
     if (newVal && Object.keys(newVal)) {
-      getInfo(newVal)
+      const data = removeEmptyProperties(newVal)
+      getInfo(data)
     }
   },
   { immediate: true },
@@ -82,12 +88,15 @@ const rules = {
 }
 
 const submit = async () => {
-  const valid = await unref(form).validate()
-  if (!valid) return { id: props.id, data: null}
-  //
-  const startTime = convertYearMonthToTimestamp(formData.value.startTime)
-  const endTime = convertYearMonthToTimestamp(formData.value.endTime)
-  return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  try {
+    const valid = await unref(form).validate()
+    // if (!valid) return { id: props.id, data: null}
+    const startTime = convertYearMonthToTimestamp(formData.value.startTime)
+    const endTime = convertYearMonthToTimestamp(formData.value.endTime)
+    return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  } catch (error) {
+    return { text: props.text }
+  }
 }
 
 defineExpose({

+ 18 - 8
pagesA/resumeAnalysis/components/workExperience.vue

@@ -32,11 +32,16 @@ import { cloneDeep } from 'lodash-es'
 import { ref, watch, unref } from 'vue'
 import { getDict } from '@/hooks/useDictionaries.js'
 import { convertYearMonthToTimestamp, timesTampChange } from '@/utils/date.js'
+import { removeEmptyProperties } from "@/utils/index"
 const props = defineProps({
   id: {
     type: String,
     default: ''
   },
+  text: {
+    type: String,
+    default: ''
+  },
   data: {
     type: Object,
     default: () => ({})
@@ -77,7 +82,8 @@ watch(
   () => props.data,
   (newVal) => {
     if (newVal && Object.keys(newVal)) {
-      getInfo(newVal)
+      const data = removeEmptyProperties(newVal)
+      getInfo(data)
     }
   },
   { immediate: true },
@@ -125,13 +131,17 @@ const handleChangeSofar = (e) => {
 }
 
 const submit = async () => {
-  const valid = await unref(form).validate()
-  if (!valid) return { id: props.id, data: null}
-  if (!formData.value.endTime && !sofar.value.length) return uni.showToast({ icon: 'none', title: '请选择工作经历的结束时间' })
-  //
-  const startTime = convertYearMonthToTimestamp(formData.value.startTime)
-  const endTime = sofar.value.length ? null : convertYearMonthToTimestamp(formData.value.endTime)
-  return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  try {
+    const valid = await unref(form).validate()
+    // if (!valid) return { id: props.id, data: null}
+    if (!formData.value.endTime && !sofar.value.length) return uni.showToast({ icon: 'none', title: '请选择工作经历的结束时间' })
+    //
+    const startTime = convertYearMonthToTimestamp(formData.value.startTime)
+    const endTime = sofar.value.length ? null : convertYearMonthToTimestamp(formData.value.endTime)
+    return { id: props.id, data: { ...formData.value, startTime, endTime }}
+  } catch (error) {
+    return { text: props.text }
+  }
 }
 
 defineExpose({

+ 15 - 17
pagesA/resumeAnalysis/index.vue

@@ -1,4 +1,4 @@
-<!--  -->
+<!-- 简历附件解析 -->
 <template>
   <view>
     <!-- 选择简历 -->
@@ -10,12 +10,12 @@
           <template v-slot:right>
             <view v-if="item.path !== 'baseInfoEdit'" style="color: #e64340;" @click="del(item)">删除</view>
           </template>
-          <avatarEdit v-if="item.path === 'avatarEdit'" ref="componentRef" :id="item.id" :data="item.data" />
-          <baseInfoEdit v-if="item.path === 'baseInfoEdit'" ref="componentRef" :id="item.id" :data="item.data" />
-          <advantageEdit v-if="item.path === 'advantageEdit'" ref="componentRef" :id="item.id" :data="item.data" />
-          <educationEdit v-if="item.path === 'educationEdit'" ref="componentRef" :id="item.id" :data="item.data" />
-          <workExperienceEdit v-if="item.path === 'workExperienceEdit'" ref="componentRef" :id="item.id" :data="item.data" />
-          <trainingExperienceEdit v-if="item.path === 'trainingExperienceEdit'" ref="componentRef" :id="item.id" :data="item.data" />
+          <avatarEdit v-if="item.path === 'avatarEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
+          <baseInfoEdit v-if="item.path === 'baseInfoEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
+          <advantageEdit v-if="item.path === 'advantageEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
+          <educationEdit v-if="item.path === 'educationEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
+          <workExperienceEdit v-if="item.path === 'workExperienceEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
+          <trainingExperienceEdit v-if="item.path === 'trainingExperienceEdit'" ref="componentRef" :id="item.id"  :text="item.text" :data="item.data" />
         </uni-section>
       </uni-card>
       <!-- 保存 -->
@@ -56,7 +56,7 @@ import advantageEdit from './components/advantage.vue'
 import educationEdit from './components/educationExp.vue'
 import workExperienceEdit from './components/workExperience.vue'
 import trainingExperienceEdit from './components/trainingExperience.vue'
-// import { data } from './testData.js'
+import { resumeParser2Data } from './testData.js'
 
 const step = ref(1)
 
@@ -136,11 +136,10 @@ const handleAnalysis = async (url) => {
   if (!url) return
   loading.value = true
   step.value = 3
-  // const baseUrl = envObj.previewUrl
-  // fileUrl.value = !url.includes('.pdf') ?  `${baseUrl}/onlinePreview?url=${encodeURIComponent(Base64.encode(url))}` : url
   try {
-    const res = await resumeParser2({ fileUrl: url })
-    result.value = res?.data || {}
+    // const res = await resumeParser2({ fileUrl: url })
+    // result.value = res?.data || {}
+    result.value = resumeParser2Data
     await transformToLIst(result.value)
     step.value = 2
   } catch (error) {
@@ -160,7 +159,7 @@ const handleResumeAnalysis = (url) => {
 
 const componentRef = ref()
 const getValue = async () => {
-  let id = ''
+  let text = ''
   let data = {}
   for (let index = 0; index < componentRef.value.length; index++) {
     const e = componentRef.value[index]
@@ -168,12 +167,11 @@ const getValue = async () => {
     if (query && query.data) {
       data[query.id] = query.data
     } else {
-      id = id ? id : query.id
+      if (!text) text = query.text
     }
   }
-  console.log('id:', id)
-  if (id) {
-    uni.showToast({ icon: 'none', title: '请填写完整后提交!' })
+  if (text) {
+    uni.showToast({ icon: 'none', title: `请完整填写 ${text} 后提交!` })
     return
   }
   // 处理data

+ 1 - 1
pagesA/resumeAnalysis/testData.js

@@ -1,4 +1,4 @@
-export const data = {
+export const resumeParser2Data = {
   "person": {
       "id": null,
       "userId": null,

+ 3 - 3
pagesA/resumeOnline/index.vue

@@ -280,9 +280,9 @@ function handleTo (str, id) {
   uni.navigateTo({ url: id ? `/pagesA/resumeOnline/${str}?id=${id}` : `/pagesA/resumeOnline/${str}` })
 }
 
-// function handleToResumeAnalysis () {
-//   uni.navigateTo({ url: '/pagesA/resumeAnalysis/index' })
-// }
+function handleToResumeAnalysis () {
+  uni.navigateTo({ url: '/pagesA/resumeAnalysis/index' })
+}
 
 // 获取基础信息
 function getBaseInfo () {

+ 11 - 11
unpackage/dist/cache/.vite/deps/_metadata.json

@@ -1,55 +1,55 @@
 {
-  "hash": "4e51a6e8",
+  "hash": "268e6389",
   "configHash": "fe45daba",
-  "lockfileHash": "ae20d0a2",
-  "browserHash": "d323c82a",
+  "lockfileHash": "063b1730",
+  "browserHash": "f98f1617",
   "optimized": {
     "pinia-plugin-persistedstate": {
       "src": "../../../../../node_modules/pinia-plugin-persistedstate/dist/index.js",
       "file": "pinia-plugin-persistedstate.js",
-      "fileHash": "a6b7a0cc",
+      "fileHash": "16eaaa42",
       "needsInterop": false
     },
     "luch-request": {
       "src": "../../../../../node_modules/luch-request/src/lib/luch-request.js",
       "file": "luch-request.js",
-      "fileHash": "8b38c832",
+      "fileHash": "9e908f8f",
       "needsInterop": false
     },
     "qs": {
       "src": "../../../../../node_modules/qs/lib/index.js",
       "file": "qs.js",
-      "fileHash": "97b521b9",
+      "fileHash": "bca5af64",
       "needsInterop": true
     },
     "js-sha256": {
       "src": "../../../../../node_modules/js-sha256/src/sha256.js",
       "file": "js-sha256.js",
-      "fileHash": "d5456d1a",
+      "fileHash": "068c1f17",
       "needsInterop": true
     },
     "js-base64": {
       "src": "../../../../../node_modules/js-base64/base64.mjs",
       "file": "js-base64.js",
-      "fileHash": "c6c345a4",
+      "fileHash": "c3a102c1",
       "needsInterop": false
     },
     "wukongimjssdk": {
       "src": "../../../../../node_modules/wukongimjssdk/lib/wukongimjssdk.esm.js",
       "file": "wukongimjssdk.js",
-      "fileHash": "661a449c",
+      "fileHash": "31d04fbc",
       "needsInterop": false
     },
     "dayjs": {
       "src": "../../../../../node_modules/dayjs/dayjs.min.js",
       "file": "dayjs.js",
-      "fileHash": "ce3d9f8d",
+      "fileHash": "d4ca863f",
       "needsInterop": true
     },
     "lodash-es": {
       "src": "../../../../../node_modules/lodash-es/lodash.js",
       "file": "lodash-es.js",
-      "fileHash": "2b4fbfbe",
+      "fileHash": "0187f4b7",
       "needsInterop": false
     }
   },

+ 6 - 0
utils/index.js

@@ -161,3 +161,9 @@ export const generateUUID = (len = 32, firstU = true, radix = null) => { // 商
   return uuid.join('');
 }
 
+// 过滤对象空属性
+export const removeEmptyProperties = (obj) => {
+  return Object.fromEntries(
+    Object.entries(obj).filter(([key, value]) => value !== null && value !== undefined && value !== '' && (Array.isArray(value) ? value.length > 0 : true))
+  )
+}