Parcourir la source

Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner-admin into dev

lifanagju_citu il y a 4 jours
Parent
commit
06b806a72c

+ 1 - 0
package.json

@@ -30,6 +30,7 @@
     "@form-create/designer": "^3.1.3",
     "@form-create/element-ui": "^3.1.24",
     "@iconify/iconify": "^3.1.1",
+    "@mendable/firecrawl-js": "1.19.1",
     "@videojs-player/vue": "^1.0.0",
     "@vueuse/core": "^10.9.0",
     "@wangeditor/editor": "^5.1.23",

+ 59 - 0
pnpm-lock.yaml

@@ -20,6 +20,9 @@ importers:
       '@iconify/iconify':
         specifier: ^3.1.1
         version: 3.1.1
+      '@mendable/firecrawl-js':
+        specifier: 1.19.1
+        version: 1.19.1(ws@8.18.2)
       '@videojs-player/vue':
         specifier: ^1.0.0
         version: 1.0.0(@types/video.js@7.3.58)(video.js@7.21.5)(vue@3.4.21(typescript@5.3.3))
@@ -1367,6 +1370,9 @@ packages:
   '@jridgewell/trace-mapping@0.3.25':
     resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
 
+  '@mendable/firecrawl-js@1.19.1':
+    resolution: {integrity: sha512-rtBnlF6oLJAxhH4YG8P72FernR1TvdI4J7uiSad2hOF7ZtbkzHkuNsa/10KUTPsmeQf8ESxiSQ1p7HMyEXuW9g==}
+
   '@nodelib/fs.scandir@2.1.5':
     resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
     engines: {node: '>= 8'}
@@ -3569,6 +3575,11 @@ packages:
     resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
     engines: {node: '>=0.10.0'}
 
+  isows@1.0.7:
+    resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==}
+    peerDependencies:
+      ws: '*'
+
   jackspeak@2.3.6:
     resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
     engines: {node: '>=14'}
@@ -4884,6 +4895,9 @@ packages:
     resolution: {integrity: sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==}
     engines: {node: '>= 0.4'}
 
+  typescript-event-target@1.1.1:
+    resolution: {integrity: sha512-dFSOFBKV6uwaloBCCUhxlD3Pr/P1a/tJdcmPrTXCHlEFD3faj0mztjcGn6VBAhQ0/Bdy8K3VWrrqwbt/ffsYsg==}
+
   typescript@5.3.3:
     resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
     engines: {node: '>=14.17'}
@@ -5225,6 +5239,18 @@ packages:
     resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
+  ws@8.18.2:
+    resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
+    engines: {node: '>=10.0.0'}
+    peerDependencies:
+      bufferutil: ^4.0.1
+      utf-8-validate: '>=5.0.2'
+    peerDependenciesMeta:
+      bufferutil:
+        optional: true
+      utf-8-validate:
+        optional: true
+
   xml-js@1.6.11:
     resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
     hasBin: true
@@ -5283,6 +5309,14 @@ packages:
     resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
     engines: {node: '>=12.20'}
 
+  zod-to-json-schema@3.24.5:
+    resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==}
+    peerDependencies:
+      zod: ^3.24.1
+
+  zod@3.24.4:
+    resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==}
+
   zrender@5.5.0:
     resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==}
 
@@ -6493,6 +6527,17 @@ snapshots:
       '@jridgewell/resolve-uri': 3.1.2
       '@jridgewell/sourcemap-codec': 1.4.15
 
+  '@mendable/firecrawl-js@1.19.1(ws@8.18.2)':
+    dependencies:
+      axios: 1.6.8
+      isows: 1.0.7(ws@8.18.2)
+      typescript-event-target: 1.1.1
+      zod: 3.24.4
+      zod-to-json-schema: 3.24.5(zod@3.24.4)
+    transitivePeerDependencies:
+      - debug
+      - ws
+
   '@nodelib/fs.scandir@2.1.5':
     dependencies:
       '@nodelib/fs.stat': 2.0.5
@@ -9035,6 +9080,10 @@ snapshots:
 
   isobject@3.0.1: {}
 
+  isows@1.0.7(ws@8.18.2):
+    dependencies:
+      ws: 8.18.2
+
   jackspeak@2.3.6:
     dependencies:
       '@isaacs/cliui': 8.0.2
@@ -10413,6 +10462,8 @@ snapshots:
       typed-array-buffer: 1.0.2
       typed-array-byte-offset: 1.0.2
 
+  typescript-event-target@1.1.1: {}
+
   typescript@5.3.3: {}
 
   ufo@1.5.3: {}
@@ -10833,6 +10884,8 @@ snapshots:
       imurmurhash: 0.1.4
       signal-exit: 4.1.0
 
+  ws@8.18.2: {}
+
   xml-js@1.6.11:
     dependencies:
       sax: 1.3.0
@@ -10892,6 +10945,12 @@ snapshots:
 
   yocto-queue@1.0.0: {}
 
+  zod-to-json-schema@3.24.5(zod@3.24.4):
+    dependencies:
+      zod: 3.24.4
+
+  zod@3.24.4: {}
+
   zrender@5.5.0:
     dependencies:
       tslib: 2.3.0

+ 21 - 0
src/api/menduner/system/talentMap/search.ts

@@ -0,0 +1,21 @@
+import request from '@/config/axios'
+
+export const talentSearchApi = {
+	// 根据条件获取人才列表
+	getTalentList: async (data: any, signal: AbortSignal) => {
+		return await request.post({ 
+			url: `/api/parse/query-kg`,
+			data,
+			signal,
+			baseURL: import.meta.env.VITE_BASE_URL 
+		})
+	},
+
+	// 根据ID获取名片详情
+	getBusinessCardDetails: async (talent_id: number) => {
+		return await request.get({ 
+			url: `/api/parse/get-business-card/${talent_id}`, 
+			baseURL: import.meta.env.VITE_BASE_URL 
+		})
+	}
+}

+ 1 - 1
src/config/axios/service.ts

@@ -194,7 +194,7 @@ service.interceptors.response.use(
     } else if (message.includes('Request failed with status code')) {
       message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3)
     }
-    ElMessage.error(message)
+    if (message !== 'canceled') ElMessage.error(message)
     return Promise.reject(error)
   }
 )

+ 126 - 3
src/views/menduner/system/talentMap/components/webPageParsing.vue

@@ -13,7 +13,7 @@
 					class="!w-60vw"
 					type="textarea"
 					:rows="1"
-					placeholder="请输入需要爬取的页面,多个页面请用','隔开"
+					placeholder="请输入需要爬取的页面,多个页面请用 ',' 隔开"
 				/>
 			</el-form-item>
 			<el-form-item>
@@ -22,22 +22,145 @@
 		</el-form>
 	</ContentWrap>
 
+	<ContentWrap v-if="contents.length">
+		<el-row gutter="20">
+			<el-col v-for="(content, index) in contents" :key="index" :span="12">
+				<el-card class="!h-500px" v-loading="!content.data">
+					<template #header>
+						<div class="flex items-center justify-between">
+							<el-text class="flex-1" truncated>{{ content.url }}</el-text>
+							<div class="!w-85px">
+								<Icon icon="ep:view" size="25" class="ml-10px cursor-pointer" color="#409eff" @click="showPage(content)" />
+								<Icon icon="ep:refresh" size="25" class=" ml-18px cursor-pointer" color="#409eff" @click="handleReload(content)" />
+							</div>
+						</div>
+					</template>
+					<div v-if="content.data">
+						<template v-if="typeof content.data === 'string'">{{ content.data }}</template>
+            <el-tabs v-else v-model="content.tab">
+              <el-tab-pane v-for="(v, k) in content.data.data[0]" :key="k" :label="k" :name="k" class="overflow-y-auto !h-360px">
+								<template v-if="k === 'html'">
+									<div class="position-sticky float-right">
+										<el-button
+											type="primary"
+											class="cursor-pointer"
+											@click="content.showHtml = !content.showHtml"
+											:icon="SetUp"
+											circle
+										/>
+									</div>
+                  <pre v-if="!content.showHtml">{{ v }}</pre>
+                  <div v-else v-html="v"></div>
+                </template>
+                <pre v-else>{{ v }}</pre>
+							</el-tab-pane>
+            </el-tabs>
+          </div>
+				</el-card>
+			</el-col>
+		</el-row>
+	</ContentWrap>
+
+	<el-drawer
+		v-model="drawer"
+		class="!w-50vw"
+		:with-header="false"
+		:modal="true"
+	>
+		<iframe class="!w-100% !h-[calc(100vh-90px)]" :src="drawerUrl" frameborder="0"></iframe>
+		<el-divider class="!ma-0" />
+		<div class="position-sticky left-20px !h-50px lh-50px">
+			<el-button type="primary" class="!w-100px" @click="drawer = false; drawerUrl = ''">关 闭</el-button>
+		</div>
+	</el-drawer>
 </template>
 
 <script setup>
 defineOptions({ name: 'WebPageParsing' })
+import FirecrawlApp from '@mendable/firecrawl-js'
+import { SetUp } from '@element-plus/icons-vue'
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
 const loading = ref(false)
 const queryParams = reactive({
-	urls: 'https://mp.weixin.qq.com/s/gtCcUeXZUXkQi5CR25vjew'
+	urls: 'https://element.eleme.cn/#/zh-CN/component/installation'
 })
 const queryFormRef = ref()
+const contents = ref([])
+const drawer = ref(false)
+const drawerUrl = ref('')
+
+const showPage = (content) => {
+	drawer.value = true
+	drawerUrl.value = content.url
+}
+
+const handleReload = async (content) => {
+	content.data = null
+	const res = await handleData(queryParams.urls)
+	content.tab = 0
+	content.data = res
+}
+
+const handleData = async (url) => {
+	try {
+    const app = new FirecrawlApp({ apiKey: 'fc-85c1550c6db64ce4ae8f2d2cd2606e6f' })
+    const crawlResponse = await app.crawlUrl(url, {
+      limit: 100,
+      scrapeOptions: {
+        formats: ['markdown', 'html']
+      }
+    })
+    if (!crawlResponse.success) {
+      throw new Error(`Failed to crawl: ${crawlResponse.error}`)
+    }
+    return crawlResponse
+  } catch (error) {
+    return error.message
+  }
+}
+
+// const handleExecute = async () => {
+// 	if (!queryParams.urls) return
+// 	contents.value = []
+// 	const urls = queryParams.urls.split(',')
+
+// 	const run = async (url) => {
+// 	  contents.value.push({ url, tab: 'markdown', showHtml: false, data: null })
+// 		const res = await handleData(url)
+// 		contents.value[contents.value.length - 1] = { url, tab: 'markdown', showHtml: false, data: res }
+
+// 		if (contents.value.length < urls.length) {
+// 			await run(urls[contents.value.length])
+// 		}
+// 	}
+
+// 	await run(urls[contents.value.length])
+// }
 
 // 执行
 const handleExecute = async () => {
-	console.log(queryParams.urls, 'urls')
+	if (!queryParams.urls) return
+	contents.value = []
+	const urls = queryParams.urls.split(',').map(url => url.trim()).filter(url => url)
+	if (urls.length === 0) return
+
+	urls.forEach(url => {
+	  contents.value.push({ url, tab: 'markdown', showHtml: false, data: null })
+	})
+
+	const crawlPromises = urls.map(async (url, index) => {
+		const res = await handleData(url)
+		contents.value[index] = { ...contents.value[index], data: res }
+	})
+
+	try {
+		await Promise.all(crawlPromises)
+		console.log('All crawls completed:', contents.value); // 可在此处添加成功回调
+	} catch (error) {
+		console.error('爬取过程中发生错误:', error);
+	}
 }
 </script>

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

@@ -1,13 +1,13 @@
 <template>
   <div>
-		<el-tabs v-model="activeName" @tab-click="handleClick" type="border-card">
-			<el-tab-pane label="简历" name="resume">
+		<el-tabs v-model="activeName" type="border-card">
+			<el-tab-pane label="简历解析" name="resume">
 				<resumePage/>
 			</el-tab-pane>
-			<el-tab-pane label="名片" name="card">
+			<el-tab-pane label="名片解析" name="card">
 				<cardPage/>
 			</el-tab-pane>
-			<el-tab-pane label="网页" name="webpage">
+			<el-tab-pane label="网页解析" name="webpage">
 				<webPageParsing/>
 			</el-tab-pane>
 		</el-tabs>

+ 3 - 3
src/views/menduner/system/talentMap/labeling/LabelingForm.vue

@@ -66,7 +66,7 @@
   </Dialog>
 </template>
 
-<script setup lang="ts">
+<script setup>
 import { talentLabelingApi } from '@/api/menduner/system/talentMap/labeling'
 import { talentTagApi } from '@/api/menduner/system/talentMap/tag'
 
@@ -90,7 +90,7 @@ const getTagList = async () => {
 }
 
 /** 打开弹窗 */
-const open = async (data: any) => {
+const open = async (data) => {
 	previewUrl.value = null
   dialogVisible.value = true
 	talentItem.value = data
@@ -119,7 +119,7 @@ const closeClick = (item) => {
 }
 
 // 标签添加
-const handleAdd = (item: any) => {
+const handleAdd = (item) => {
 	talentSelectedTags.value.push(item)
 }
 

+ 8 - 27
src/views/menduner/system/talentMap/labeling/index.vue

@@ -45,7 +45,6 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" row-key="id">
-      <el-table-column label="ID" align="center" prop="id" />
       <el-table-column label="姓名" align="center" prop="name_zh" />
       <el-table-column label="职位" align="center" prop="title_zh" :show-overflow-tooltip="true" />
       <el-table-column label="酒店" align="center" prop="hotel_zh" :show-overflow-tooltip="true" />
@@ -59,29 +58,9 @@
       <el-table-column label="创建时间" align="center" prop="created_at" width="180" />
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm(scope.row)"
-          >
-            标注
-          </el-button>
-          <el-button
-            v-if="scope.row.status === 'active'"
-            link
-            type="danger"
-            @click="handleAction(scope.row.id, 'inactive')"
-          >
-            禁用
-          </el-button>
-          <el-button
-            v-if="scope.row.status === 'inactive'"
-            link
-            type="success"
-            @click="handleAction(scope.row.id, 'active')"
-          >
-            启用
-          </el-button>
+          <el-button link type="primary" @click="openForm(scope.row)">标注</el-button>
+          <el-button v-if="scope.row.status === 'active'" link type="danger" @click="handleAction(scope.row.id, 'inactive')">禁用</el-button>
+          <el-button v-if="scope.row.status === 'inactive'" link type="success" @click="handleAction(scope.row.id, 'active')">启用</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -125,13 +104,15 @@ const openForm = (data: any) => {
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  getList()
+  message.warning('建设中...')
+  // getList()
 }
 
 /** 重置按钮操作 */
 const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  handleQuery()
+  message.warning('建设中...')
+  // queryFormRef.value.resetFields()
+  // handleQuery()
 }
 
 /** 禁用、启用按钮操作 */

+ 183 - 0
src/views/menduner/system/talentMap/search/index.vue

@@ -0,0 +1,183 @@
+<template>
+  <ContentWrap>
+    <div class="box flex items-center justify-center decoration-column transition-duration-500" :class="{ active: isSearch }">
+      <div class="!w-75%">
+        <el-input
+          v-model.trim="searchValue"
+          size="large"
+					clearable
+          placeholder="请输入您的描述信息定位人才"
+          @keydown.enter="handleSearch"
+					@clear="handleSearch('clear')"
+        >
+					<template #append>
+						<el-button :icon="Search" @click="handleSearch" />
+					</template>
+				</el-input>
+      </div>
+    </div>
+  </ContentWrap>
+	
+  <ContentWrap v-if="isSearch">
+    <el-table
+      v-loading="loading"
+      :data="list"
+      :stripe="true"
+      row-key="pg_id"
+    >
+      <el-table-column label="中文名" align="left" prop="name_zh" />
+      <el-table-column label="英文名" align="left" prop="name_en" />
+      <el-table-column label="联系电话" align="center" prop="mobile" />
+      <el-table-column label="电子邮箱" align="center" prop="email" />
+      <el-table-column label="更新时间" align="center" prop="updated_at" />
+      <el-table-column label="操作" align="left">
+        <template #default="scope">
+          <el-button link type="primary" @click="handleDetails(scope.row.pg_id)">详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </ContentWrap>
+
+	<el-drawer
+		v-model="drawer"
+		class="!w-50vw"
+		:with-header="false"
+	>
+		<div v-loading="detailsLoading">
+			<div v-if="detail && Object.keys(detail).length > 0">
+				<div class="mb-30px" v-if="previewUrl">
+					<div class="el-descriptions__header el-descriptions__title">名片</div>
+					<div class="text-center w-100% cursor-pointer">
+						<el-image :src="previewUrl" class="w-300px h-500px" :preview-src-list="[previewUrl]" />
+					</div>
+				</div>
+
+				<el-descriptions title="基本信息" :column="1" border>
+					<el-descriptions-item label="中文名">{{ detail.name_zh }}</el-descriptions-item>
+					<el-descriptions-item label="英文名">{{ detail.name_en }}</el-descriptions-item>
+					<el-descriptions-item label="职位/头衔(中)">{{ detail.title_zh }}</el-descriptions-item>
+					<el-descriptions-item label="职位/头衔(英)">{{ detail.title_en }}</el-descriptions-item>
+					<el-descriptions-item label="手机号码">{{ detail.mobile }}</el-descriptions-item>
+					<el-descriptions-item label="电子邮箱">{{ detail.email }}</el-descriptions-item>
+					<el-descriptions-item label="酒店/公司名称(中)">{{ detail.hotel_zh }}</el-descriptions-item>
+					<el-descriptions-item label="酒店/公司名称(英)">{{ detail.hotel_eh }}</el-descriptions-item>
+					<el-descriptions-item label="地址(中)">{{ detail.address_zh }}</el-descriptions-item>
+					<el-descriptions-item label="地址(英)">{{ detail.address_en }}</el-descriptions-item>
+					<el-descriptions-item label="邮政编码(中)">{{ detail.postal_code_zh }}</el-descriptions-item>
+					<el-descriptions-item label="邮政编码(英)">{{ detail.postal_code_en }}</el-descriptions-item>
+					<el-descriptions-item label="品牌名称(中)">{{ detail.brand_zh }}</el-descriptions-item>
+					<el-descriptions-item label="品牌名称(英)">{{ detail.brand_en }}</el-descriptions-item>
+					<el-descriptions-item label="隶属关系(中)">{{ detail.affiliation_zh }}</el-descriptions-item>
+					<el-descriptions-item label="隶属关系(英)">{{ detail.affiliation_en }}</el-descriptions-item>
+					<el-descriptions-item label="品牌组合">{{ detail.brand_group }}</el-descriptions-item>
+					<el-descriptions-item label="固定电话">{{ detail.phone }}</el-descriptions-item>
+					<el-descriptions-item label="创建时间">{{ detail.created_at }}</el-descriptions-item>
+					<el-descriptions-item label="更新时间">{{ detail.updated_at }}</el-descriptions-item>
+					<el-descriptions-item label="状态">
+						<el-tag :type="detail.status === 'active' ? 'primary' : 'danger'">
+							{{ detail.status === 'active' ? '已启用' : '已禁用' }}
+						</el-tag>
+					</el-descriptions-item>
+				</el-descriptions>
+
+				<div class="mt-30px career">
+					<div class="el-descriptions__header el-descriptions__title">职业轨迹</div>
+					<el-table :data="detail.career_path" border>
+						<el-table-column prop="company_name" label="酒店名称" />
+						<el-table-column prop="position" label="职位名称" />
+						<el-table-column prop="current_date" label="日期" />
+					</el-table>
+				</div>
+			</div>
+			<el-empty v-else description="暂无详细信息,去查看其他人的信息吧~" />
+		</div>
+	</el-drawer>
+
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { talentSearchApi } from '@/api/menduner/system/talentMap/search'
+import { talentLabelingApi } from '@/api/menduner/system/talentMap/labeling'
+
+const message = useMessage() // 消息弹窗
+const searchValue = ref(null)
+const formRef = ref()
+const loading = ref(false)
+const list = ref([])
+const abortController = ref(null)
+
+const drawer = ref(false)
+const detailsLoading = ref(false)
+const detail = ref({})
+const previewUrl = ref(null)
+const handleDetails = async (id) => {
+	if (!id) return
+
+	drawer.value = true
+	detailsLoading.value = true
+	try {
+    const result = await talentSearchApi.getBusinessCardDetails(id)
+    detail.value = result || {}
+
+    // 获取名片预览
+    if (result?.image_path) {
+      const data = await talentLabelingApi.getTalentCardByImagePath(result.image_path)
+      previewUrl.value = URL.createObjectURL(data)
+    }
+  } finally {
+		detailsLoading.value = false
+	}
+}
+
+const getList = async () => {
+	loading.value = true
+	try {
+		abortController.value = new AbortController()
+		const signal = abortController.value.signal
+		const data = await talentSearchApi.getTalentList({ query_requirement: searchValue.value }, signal)
+		if (!data || !data.length) {
+			message.warning('暂无数据,请更换查询条件后再试')
+			list.value = []
+			isSearch.value = false
+			return
+		}
+		list.value = data
+	} finally {
+		loading.value = false
+	}
+}
+
+const isSearch = ref(false)
+const handleSearch = (type='search') => {
+	if (type === 'clear') {
+		list.value = []
+		isSearch.value = false
+		if (abortController.value) {
+      abortController.value.abort() 
+      abortController.value = null
+    }
+		return
+	}
+	isSearch.value = true
+	if (!searchValue.value) return message.warning('请输入查询条件')
+	getList()
+}
+</script>
+
+<style scoped lang="scss">
+.box {
+  min-height: 500px;
+  &.active {
+    min-height: unset;
+  }
+}
+:deep {
+	.career {
+		.el-table th.el-table__cell {
+			background-color: #f5f7fa;
+		}
+	}
+}
+</style>

+ 2 - 1
src/views/menduner/system/talentMap/tag/TagForm.vue

@@ -43,7 +43,7 @@ const message = useMessage() // 消息弹窗
 
 const statusOptions = [
 	{ label: '启用', value: 'active' },
-	{ label: '禁用', value: 'disable' },
+	{ label: '禁用', value: 'inactive' },
 ]
 
 const dialogVisible = ref(false) // 弹窗的是否展示
@@ -73,6 +73,7 @@ const open = async (type: string, data?: any) => {
   // 修改时,设置数据
   if (data && Object.keys(data).length) {
     formData.value = data
+    if (data.status === 'disable') formData.value.status = 'inactive'
   }
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗

+ 12 - 21
src/views/menduner/system/talentMap/tag/index.vue

@@ -72,20 +72,8 @@
       <el-table-column label="更新时间" align="center" prop="time" width="180" />
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm('update', scope.row)"
-          >
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-          >
-            删除
-          </el-button>
+          <el-button link type="primary" @click="openForm('update', scope.row)">编辑</el-button>
+          <el-button link type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -94,7 +82,8 @@
   <!-- 表单弹窗:添加/修改 -->
   <TagForm ref="formRef" @success="getList" />
 </template>
-<script setup lang="ts" name="Tag">
+
+<script setup>
 import { talentTagApi } from '@/api/menduner/system/talentMap/tag'
 import TagForm from './TagForm.vue'
 
@@ -108,7 +97,7 @@ const queryParams = reactive({
 const queryFormRef = ref() // 搜索的表单
 const statusOptions = [
 	{ label: '启用', value: 'active' },
-	{ label: '禁用', value: 'disable' },
+	{ label: '禁用', value: 'inactive' },
 ]
 
 const message = useMessage() // 消息弹窗
@@ -127,23 +116,25 @@ const getList = async () => {
 
 /** 添加/修改操作 */
 const formRef = ref()
-const openForm = (type: string, data?: any) => {
+const openForm = (type, data) => {
   formRef.value.open(type, data)
 }
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  getList()
+  // getList()
+  message.warning('建设中...')
 }
 
 /** 重置按钮操作 */
 const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  handleQuery()
+  // queryFormRef.value.resetFields()
+  // handleQuery()
+  message.warning('建设中...')
 }
 
 /** 删除按钮操作 */
-const handleDelete = async (id: number) => {
+const handleDelete = async (id) => {
   try {
     // 删除的二次确认
     await message.delConfirm()