2 Commitit a58bd322ca ... f44b1b633b

Tekijä SHA1 Viesti Päivämäärä
  lifanagju_citu f44b1b633b Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner-admin into dev 3 päivää sitten
  lifanagju_citu 46e74c0f06 名片解析 3 päivää sitten

+ 10 - 1
src/api/menduner/system/talentMap/labeling.ts

@@ -41,5 +41,14 @@ export const talentLabelingApi = {
 			url: `/api/parse/business-cards/image/${image_path}`,
 			baseURL: import.meta.env.VITE_BASE_URL 
 		})
-	}
+	},
+
+  // 非结构化数据源 名片解析
+	businessCardParse: async (data: any) => {
+		return await request.upload({ 
+			url: `/api/parse/business-card-parse`,
+			baseURL: import.meta.env.VITE_BASE_URL,
+			data 
+		})
+	},
 }

+ 7 - 1
src/components/UploadFile/src/UploadImg.vue

@@ -12,6 +12,7 @@
       :multiple="false"
       :on-error="uploadError"
       :on-success="uploadSuccess"
+      :on-change="handleChange"
       :show-file-list="false"
     >
       <template v-if="modelValue">
@@ -96,7 +97,7 @@ const imagePreview = (imgUrl: string) => {
   })
 }
 
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'handleChange'])
 
 const deleteImg = () => {
   emit('update:modelValue', '')
@@ -140,6 +141,11 @@ const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
   } else return imgType.includes(rawFile.type as FileTypes) && imgSize
 }
 
+const handleChange = (file: any, fileList: any) => {
+  emit('handleChange', file?.raw, fileList)
+}
+
+
 // 图片上传成功提示
 const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
   message.success('上传成功')

+ 1 - 2
src/views/menduner/system/talentMap/components/ImageImportEdit.vue

@@ -1,6 +1,5 @@
 <template>
-  <div>
-	</div>
+  <div>ImageImportEdit</div>
 </template>
 
 <script setup>

+ 174 - 17
src/views/menduner/system/talentMap/components/card.vue

@@ -23,36 +23,72 @@
 
   <!-- 列表 -->
   <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true">
-      <el-table-column label="姓名(中)" align="center" prop="person.name_zh" fixed="left" />
-      <el-table-column label="姓名(英)" align="center" prop="person.name_en" />
-      <el-table-column label="职位" align="center" prop="person.title_en" />
-      <el-table-column label="酒店/公司" align="center" prop="person.hotel_zh" />
-      <el-table-column label="创建日期" align="center" prop="person.created_at" :formatter="dateFormatter2" />
-      <el-table-column label="状态" align="center" prop="person.status" />
+    <el-table v-loading="loading" :data="list" :stripe="true" height="550">
+      <el-table-column label="姓名(中)" align="center" prop="name_zh" fixed="left" />
+      <el-table-column label="姓名(英)" align="center" prop="name_en" />
+      <el-table-column label="职位" align="center" prop="title_en" />
+      <el-table-column label="酒店/公司" align="center" prop="hotel_zh" />
+      <el-table-column label="创建日期" align="center" prop="created_at" :formatter="dateFormatter2" />
+      <el-table-column label="状态" align="center" prop="status" />
       <el-table-column label="操作" align="center" fixed="right" min-width="110">
         <template #default="scope">
-          <el-button link type="primary" @click="handleEdit(scope.row.person.id)">编辑</el-button>
-          <el-button link type="danger" @click="handleDisable(scope.row.person.id)">禁用</el-button>
+          <el-button link type="primary" @click="handleEdit(scope.row.id)">编辑</el-button>
+          <el-button link type="danger" @click="handleDisable(scope.row.id)">禁用</el-button>
         </template>
       </el-table-column>
     </el-table>
     <!-- 分页 -->
     <Pagination
+      v-if="total"
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
       @pagination="getList"
     />
+    <!-- 上传 -->
+    <Dialog title="名片解析" v-model="openUploadImg" width="500">
+      <UploadImg v-model="filePath" :limit="1" @handle-change="uploadChange" height="150px" width="150px" style="margin: 20px auto; width: 150px;">
+        <template #tip>{{ filePath ? '' : '请上传名片' }}</template>
+      </UploadImg>
+      <template #footer>
+        <el-button @click="handleAnalysis" type="success" :disabled="analysisLoading" :loading="analysisLoading">{{ buttonValue ? '更 换' : '解 析' }}</el-button>
+        <el-button @click="openUploadImg = false">取 消</el-button>
+      </template>
+    </Dialog>
+    <!-- 解析回显 -->
+    <Dialog title="名片解析" v-model="showAnalysisTable" width="80%">
+      <div class="analysisInfoBox">
+        <div class="image">
+          <el-image style="width: 100%;" :src="filePath" :fit="fit" />
+        </div>
+        <div class="formBox">
+          <el-form
+            ref="formRef"
+            :model="formData"
+            label-width="100px"
+            v-loading="formLoading"
+          >
+            <el-form-item label="姓名" prop="name">
+              <el-input :disabled="formType === 'handle'" v-model="formData.name" placeholder="请输入姓名" />
+            </el-form-item>
+          </el-form>
+        </div>
+      </div>
+      <template #footer>
+        <!-- <el-button @click="changeImg" type="primary">更换名片</el-button> -->
+        <el-button @click="handleSave" type="success" :disabled="analysisLoading">更 新</el-button>
+        <el-button @click="showAnalysisTable = false">取 消</el-button>
+      </template>
+    </Dialog>
   </ContentWrap>
 </template>
 
 <script setup>
-import { TalentMap } from '@/api/menduner/system/talentMap'
 import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
+import { talentLabelingApi } from '@/api/menduner/system/talentMap/labeling'
 
 /** 人才地图 列表 */
-defineOptions({ name: 'TalentMap' })
+defineOptions({ name: 'TalentMapCard' })
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
@@ -77,9 +113,9 @@ const queryFormRef = ref() // 搜索的表单
 const getList = async () => {
   loading.value = true
   try {
-    const data = await TalentMap.getTalentMapInfoPage(queryParams)
-    list.value = data.list
-    total.value = data.total
+    const data = await talentLabelingApi.getCardList(queryParams)
+    list.value = data || []
+    // total.value = total || []
   } finally {
     loading.value = false
   }
@@ -110,19 +146,140 @@ const handleDisable = async (id) => {
     // 禁用的二次确认
     await message.delConfirm()
     // 发起禁用
-    await TalentMap.deleteTalentMap(id)
+    await talentLabelingApi.deleteTalentMap(id)
     message.success(t('common.delSuccess'))
     // 刷新列表
     await getList()
   } catch {}
 }
 
+const formQuery = ref({
+  id: undefined,
+  name: undefined,
+})
+
+const file = ref(null)
+const uploadChange = (raw) => {
+  file.value = raw
+}
+
+// 更换名片
+const changeImg = () => {
+  openUploadImg.value = true
+}
+
+// 更新
+const showAnalysisTable = ref(false)
+const formLoading = ref(false)
+const formRef = ref() // 表单 Ref
+const handleSave = () => {
+  if (!filePath.value) {
+    message.warning('ID获取异常')
+    return
+  }
+  try {
+    formLoading.value = true
+    Object.assign(this.itemData, this.formQuery)
+
+    message.success('更新成功!')
+  } catch (error) {
+    console.log('更新失败', error)
+  } finally {
+    formLoading.value = false
+  }
+}
+
+// 解析中
+const analysisLoading = ref(false)
+const filePath = ref(null)
+const itemData = ref({})
+const handleAnalysis = async () => {
+  if (!filePath.value) {
+    message.warning('请先上传名片!')
+    return
+  }
+  try {
+    analysisLoading.value = true
+    const query = new FormData()
+    query.append('image', file.value)
+    // const data = await talentLabelingApi.businessCardParse(query)
+    const data = {
+      address_en: "", 
+      address_zh: "苏州市吴中区木渎镇花苑东路726号3幢", 
+      affiliation_en: "", 
+      affiliation_zh: "", 
+      brand_en: "", 
+      brand_group: "", 
+      brand_zh: "", 
+      career_path: [
+        {
+          company_name: "苏州木渎古镇ROSSO酒店", 
+          current_date: null, 
+          position: "销售总监"
+        }
+      ], 
+      created_at: "2025-05-16 18:11:46", 
+      email: "cw928383712@163.com", 
+      hotel_en: "ROSSO Hotel Suzhou Mudu Ancient Town", 
+      hotel_zh: "苏州木渎古镇 ROSSO酒店", 
+      id: 38, 
+      image_path: "e0a5a36e8be643e5a2953cd384836bdb.jpg", 
+      mobile: "13073381364", 
+      name_en: "", 
+      name_zh: "陈玮", 
+      phone: "0512-66563999", 
+      postal_code_en: "", 
+      postal_code_zh: "", 
+      status: "active", 
+      title_en: "Sales Director", 
+      title_zh: "销售总监", 
+      updated_at: null, 
+      updated_by: "system"
+    }
+    itemData.value = { ...data }
+    Object.keys(formQuery.value).forEach(key => {
+      formQuery.value[key] = data[key] || null
+    })
+    openUploadImg.value = false
+    showAnalysisTable.value = true
+    message.success('名片解析成功')
+  } catch (error) {
+    console.log('解析失败', error)
+  } finally {
+    analysisLoading.value = false
+  }
+}
+
+// 新增
+const openUploadImg = ref(false)
+const buttonValue = ref(0)
 const handleAdd = () => {
-  // push({ name: 'TalentMapDetail', params: { id: 'add' } })
+  file.value = null
+  filePath.value = null
+  buttonValue.value = 0
+  openUploadImg.value = true
 }
 
 /** 初始化 **/
 onMounted(() => {
   getList()
 })
-</script>
+</script>
+
+<style lang="scss" scoped>
+.analysisInfoBox {
+  display: flex;
+  .image {
+    width: 52%;
+    max-height: 70vh;
+    padding-right: 12px;
+    overflow: auto;
+  }
+  .formBox {
+    flex: 1;
+    max-height: 70vh;
+    overflow: auto;
+    background-color: #f5f7f9;
+  }
+}
+</style>

+ 1 - 1
src/views/menduner/system/talentMap/index.vue

@@ -20,5 +20,5 @@ import resumePage from './components/resume.vue'
 import cardPage from './components/card.vue'
 import webPageParsing from './components/webPageParsing.vue'
 
-const activeName = ref('resume')
+const activeName = ref('card')
 </script>