|
@@ -0,0 +1,180 @@
|
|
|
|
+<template>
|
|
|
|
+ <Dialog title="人才标注" v-model="dialogVisible" class="!w-90%">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="8">
|
|
|
|
+ <div>
|
|
|
|
+ <p :class="{'cursor-pointer': previewUrl}" :style="{'color': previewUrl ? '#2d8cf0' : ''}">
|
|
|
|
+ 名片
|
|
|
|
+ <Icon v-if="previewUrl" :size="20" icon="ep:zoom-out" />
|
|
|
|
+ </p>
|
|
|
|
+ <img v-if="previewUrl" width="100%" class="cursor-pointer" :src="previewUrl" />
|
|
|
|
+ <p class="mb-3" :class="{'mt-3': !previewUrl}">门墩儿新任命</p>
|
|
|
|
+ <p>门墩儿用户简历</p>
|
|
|
|
+ </div>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="16">
|
|
|
|
+ <div>
|
|
|
|
+ <div class="base-info">
|
|
|
|
+ <div class="mb-15px">
|
|
|
|
+ {{ talentItem.name_zh }}
|
|
|
|
+ <span v-if="talentItem.name_en">({{ talentItem.name_en }})</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex align-center">
|
|
|
|
+ <div v-for="(val, index) in talentInfoKeys" :key="index" class="common-width info-item">
|
|
|
|
+ <p>{{ talentItem[val.key] }}</p>
|
|
|
|
+ <p>{{ talentItem[val.value] }}</p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex align-center my-24px">
|
|
|
|
+ <div class="common-width pr-12px">{{ talentItem.mobile }}</div>
|
|
|
|
+ <div class="flex-1">{{ talentItem.email }}</div>
|
|
|
|
+ </div>
|
|
|
|
+ <div>{{ talentItem.address_zh }}</div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="my-5">
|
|
|
|
+ <p>人才标签</p>
|
|
|
|
+ <div v-if="talentSelectedTags?.length" class="mt-4 px-3 pb-3" style="border: 1px dashed #67c23a; border-radius: 4px;">
|
|
|
|
+ <el-tag
|
|
|
|
+ v-for="(item, index) in talentSelectedTags"
|
|
|
|
+ :key="index"
|
|
|
|
+ closable
|
|
|
|
+ size="large"
|
|
|
|
+ type="success"
|
|
|
|
+ class="mr-14px mt-14px"
|
|
|
|
+ @close="closeClick(item)"
|
|
|
|
+ >
|
|
|
|
+ {{ item.name }}
|
|
|
|
+ </el-tag>
|
|
|
|
+ </div>
|
|
|
|
+ <div :class="{'mt-5': talentSelectedTags?.length > 0}">
|
|
|
|
+ <el-tag
|
|
|
|
+ v-for="(item, index) in tagList" :key="index"
|
|
|
|
+ size="large"
|
|
|
|
+ type="primary"
|
|
|
|
+ class="mr-14px mt-14px"
|
|
|
|
+ :class="{'cursor-pointer': !talentSelectedTags.find(k => k.name === item.name)}"
|
|
|
|
+ :effect="talentSelectedTags.find(k => k.name === item.name) ? 'info' : 'default'"
|
|
|
|
+ @click="handleAdd(item)"
|
|
|
|
+ >
|
|
|
|
+ + {{ item.name }}
|
|
|
|
+ </el-tag>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ <template #footer>
|
|
|
|
+ <el-button @click="submitForm" type="primary" :disabled="loading">确 定</el-button>
|
|
|
|
+ <el-button @click="dialogVisible = false">取 消</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </Dialog>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import { talentLabelingApi } from '@/api/menduner/system/talentMap/labeling'
|
|
|
|
+import { talentTagApi } from '@/api/menduner/system/talentMap/tag'
|
|
|
|
+
|
|
|
|
+const message = useMessage() // 消息弹窗
|
|
|
|
+const loading = ref(false)
|
|
|
|
+const dialogVisible = ref(false) // 弹窗的是否展示
|
|
|
|
+const talentItem = ref({})
|
|
|
|
+const previewUrl = ref<string>()
|
|
|
|
+const talentSelectedTags = ref([])
|
|
|
|
+const tagList = ref([])
|
|
|
|
+const talentInfoKeys = [
|
|
|
|
+ { key: 'title_zh', value: 'title_en' },
|
|
|
|
+ { key: 'hotel_zh', value: 'hotel_en' },
|
|
|
|
+ { key: 'brand_zh', value: 'brand_en' },
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+// 获取人才标签
|
|
|
|
+const getTagList = async () => {
|
|
|
|
+ loading.value = true
|
|
|
|
+ try {
|
|
|
|
+ const data = await talentTagApi.getTalentTagList()
|
|
|
|
+ tagList.value = data || []
|
|
|
|
+ } finally {
|
|
|
|
+ loading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/** 打开弹窗 */
|
|
|
|
+const open = async (data: any) => {
|
|
|
|
+ dialogVisible.value = true
|
|
|
|
+ talentItem.value = data
|
|
|
|
+
|
|
|
|
+ // 获取所有人才标签
|
|
|
|
+ await getTagList()
|
|
|
|
+
|
|
|
|
+ // 获取名片预览
|
|
|
|
+ if (data.image_path) {
|
|
|
|
+ const result = await talentLabelingApi.getTalentCardByImagePath(data.image_path)
|
|
|
|
+ previewUrl.value = URL.createObjectURL(result)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取人才标签
|
|
|
|
+ const tagData = await talentLabelingApi.getTalentTagById(data.id)
|
|
|
|
+ talentSelectedTags.value = tagData ? tagData.map((i) => {
|
|
|
|
+ return { id: i.talent, name: i.tag }
|
|
|
|
+ }) : []
|
|
|
|
+}
|
|
|
|
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
|
+
|
|
|
|
+// 标签删除
|
|
|
|
+const closeClick = (item) => {
|
|
|
|
+ const index = talentSelectedTags.value.findIndex((i) => i === item)
|
|
|
|
+ if (index !== -1) talentSelectedTags.value.splice(index, 1)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 标签添加
|
|
|
|
+const handleAdd = (item: any) => {
|
|
|
|
+ talentSelectedTags.value.push(item)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/** 提交表单 */
|
|
|
|
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
|
|
|
+const submitForm = async () => {
|
|
|
|
+ if (!talentSelectedTags.value || !talentSelectedTags.value.length) return message.warning('请选择要更新的人才标签')
|
|
|
|
+
|
|
|
|
+ loading.value = true
|
|
|
|
+ const tags = talentSelectedTags.value.map(e => {
|
|
|
|
+ return { talent: talentItem.value.id, tag: e.name }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 提交请求
|
|
|
|
+ try {
|
|
|
|
+ await talentLabelingApi.updateTalentTags(tags)
|
|
|
|
+ dialogVisible.value = false
|
|
|
|
+ // 发送操作成功的事件
|
|
|
|
+ emit('success')
|
|
|
|
+ } finally {
|
|
|
|
+ loading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.base-info {
|
|
|
|
+ background-color: #f7f8fa;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ padding: 15px;
|
|
|
|
+}
|
|
|
|
+.common-width {
|
|
|
|
+ width: 33.3%;
|
|
|
|
+ max-width: 33.3%;
|
|
|
|
+}
|
|
|
|
+.info-item {
|
|
|
|
+ padding-right: 12px;
|
|
|
|
+ &:nth-child(3n) {
|
|
|
|
+ padding-right: 0;
|
|
|
|
+ }
|
|
|
|
+ p {
|
|
|
|
+ height: 24px;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+.active {
|
|
|
|
+ color: var(--v-primary-base);
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+</style>
|