index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <div>
  3. <v-card elevation="5" class="pa-10">
  4. <TextInput
  5. v-model="content"
  6. :item="textItem"
  7. @enter="handleSearch"
  8. @appendInnerClick="handleSearch"
  9. ></TextInput>
  10. </v-card>
  11. <v-card elevation="5" class="mt-3">
  12. <CtTable
  13. :items="items"
  14. class="pa-3"
  15. :headers="headers"
  16. :loading="loading"
  17. :disable-sort="true"
  18. :elevation="0"
  19. :isTools="false"
  20. :noDataText="!content ? '请先输入您的描述信息定位人才' : '暂无数据'"
  21. :items-per-page="-1"
  22. height="calc(100vh - 400px)"
  23. :showFixedLastItem="true"
  24. itemKey="id"
  25. >
  26. <template #actions="{ item }">
  27. <v-btn variant="text" color="primary" @click.stop="handleAnnotation(item)">标注</v-btn>
  28. <v-btn variant="text" color="error" @click.stop="handleDisabled(item)">禁用</v-btn>
  29. <v-btn variant="text" color="#008970" @click.stop="handleEnable(item)">启用</v-btn>
  30. <v-btn variant="text" color="error" @click.stop="handleDelete(item)">删除</v-btn>
  31. </template>
  32. </CtTable>
  33. </v-card>
  34. <!-- 标注 -->
  35. <CtDialog :visible="showAnnotationDialog" title="人才标注" :footer="false" widthType="1" @close="showAnnotationDialog = false">
  36. <v-row>
  37. <v-col cols="4">
  38. <v-card elevation="3" class="pa-3" style="height: 100%">
  39. <p>名片</p>
  40. <p>门墩儿新任命</p>
  41. <p>门墩儿用户简历</p>
  42. </v-card>
  43. </v-col>
  44. <v-col cols="8">
  45. <v-card elevation="3" class="pa-3">
  46. <div class="base-info pa-3">
  47. <div class="d-flex align-center">
  48. <div v-for="(val, index) in talentInfoKeys" :key="index" class="common-width">
  49. <p v-ellipse-tooltip>{{ talentItem[val.key] }}</p>
  50. <p v-ellipse-tooltip>{{ talentItem[val.value] }}</p>
  51. </div>
  52. </div>
  53. <div class="d-flex align-center my-6">
  54. <div class="common-width">{{ talentItem.phone }}</div>
  55. <div class="common-width">{{ talentItem.email }}</div>
  56. </div>
  57. <div>{{ talentItem.address }}</div>
  58. </div>
  59. <div class="my-5">
  60. <p>自动标注</p>
  61. <v-chip
  62. v-for="(item, index) in talentItem.automaticDimensionTags" :key="index"
  63. class="chip mx-2 mt-4"
  64. label color="primary"
  65. >
  66. {{ item }}
  67. <v-icon size="18" color="primary" style="margin-left: 6px;" @click="closeClick(index, 'automaticDimensionTags')">mdi-close-circle</v-icon>
  68. </v-chip>
  69. </div>
  70. <div>
  71. <p>人工标注</p>
  72. <v-chip
  73. v-for="(item, index) in talentItem.manualAnnotationTags" :key="index"
  74. class="chip mx-2 mt-4 cursor-pointer"
  75. label color="primary"
  76. >
  77. {{ item.name }}
  78. <v-icon size="18" color="primary" style="margin-left: 6px;" @click="closeClick(item, 'manualAnnotationTags')">mdi-close-circle</v-icon>
  79. </v-chip>
  80. <div class="mt-5">
  81. <v-chip
  82. v-for="(item, index) in tagList" :key="index"
  83. class="chip mx-2 mt-4 cursor-pointer"
  84. label color="primary"
  85. :disabled="talentItem.manualAnnotationTags.includes(item)"
  86. @click="handleAdd(item)"
  87. >
  88. <v-icon icon="mdi-plus" start></v-icon>
  89. {{ item.name }}
  90. </v-chip>
  91. </div>
  92. </div>
  93. <v-divider class="mt-5"></v-divider>
  94. <div class="d-flex justify-space-evenly my-5">
  95. <v-btn width="120" color="warning" elevation="5" @click="handleClose">取 消</v-btn>
  96. <v-btn width="120" color="primary" elevation="5" @click="handleSave">保 存</v-btn>
  97. </div>
  98. </v-card>
  99. </v-col>
  100. </v-row>
  101. </CtDialog>
  102. </div>
  103. <Loading :visible="annotationLoading"></Loading>
  104. </template>
  105. <script setup>
  106. defineOptions({ name: 'NewTalentMapAnnotation' })
  107. import { ref } from 'vue'
  108. import { getLabelingList } from '@/api/recruit/enterprise/talentMap/labeling'
  109. import { getTalentTagList } from '@/api/recruit/enterprise/talentMap/tag'
  110. import Snackbar from '@/plugins/snackbar'
  111. import Confirm from '@/plugins/confirm'
  112. import { useI18n } from '@/hooks/web/useI18n'
  113. const { t } = useI18n()
  114. const loading = ref(false)
  115. const showAnnotationDialog = ref(false)
  116. const content = ref('查找所有在上海的五星级酒店担任总经理职位的人才')
  117. const items = ref([
  118. {
  119. "姓名": "张三",
  120. "邮箱": "zhang@example.com",
  121. "职位": "总经理",
  122. "酒店名称": "上海四季酒店"
  123. },
  124. {
  125. "姓名": "李四",
  126. "邮箱": "li@example.com",
  127. "职位": "执行总经理",
  128. "酒店名称": "上海浦东丽思卡尔顿酒店"
  129. }
  130. ])
  131. const headers = [
  132. { title: '姓名', key: '姓名', sortable: false },
  133. { title: '酒店名称', key: '酒店名称', sortable: false },
  134. { title: '职位', key: '职位', sortable: false },
  135. { title: '邮箱', key: '邮箱', sortable: false },
  136. { title: '操作', key: 'actions', sortable: false, align: 'center' }
  137. ]
  138. const textItem = ref({
  139. type: 'text',
  140. value: '',
  141. label: '请输入您的描述信息定位人才',
  142. placeholder: '回车开始人才匹配',
  143. clearable: true,
  144. hideDetails: true,
  145. appendInnerIcon: 'mdi-magnify'
  146. })
  147. const getList = async () => {
  148. loading.value = true
  149. try {
  150. const data = await getLabelingList({ query_requirement: content.value })
  151. console.log(data, '列表========')
  152. items.value = data || []
  153. } finally {
  154. loading.value = false
  155. }
  156. }
  157. getList()
  158. // 搜索
  159. const handleSearch = async () => {
  160. console.log('搜索', content.value)
  161. if (!content.value) return Snackbar.warning('请输入您的描述信息定位人才')
  162. getList()
  163. }
  164. // 标注
  165. const talentItem = ref({
  166. name: '张三',
  167. enName: 'Tom',
  168. postName: '总经理',
  169. enPostName: 'General Manager',
  170. inaugurationHotel: '南京洲际酒店',
  171. enInaugurationHotel: 'Nanjing InterContinental Hotel',
  172. groupName: '洲际集团',
  173. enGroupName: 'IHG',
  174. phone: '13800138000',
  175. email: 'zhangsan@163.com',
  176. address: '南京市人民路123号',
  177. automaticDimensionTags: ['富强', '民主', '文明', '和谐'],
  178. manualAnnotationTags: [],
  179. })
  180. const talentInfoKeys = [
  181. { key: 'name', value: 'enName' },
  182. { key: 'postName', value: 'enPostName' },
  183. { key: 'inaugurationHotel', value: 'enInaugurationHotel' },
  184. { key: 'groupName', value: 'enGroupName' },
  185. ]
  186. // 获取人才标签
  187. const tagList = ref([])
  188. const getTagList = async () => {
  189. annotationLoading.value = true
  190. try {
  191. const data = await getTalentTagList()
  192. tagList.value = data || []
  193. } finally {
  194. annotationLoading.value = false
  195. }
  196. }
  197. // 标注
  198. const annotationLoading = ref(false)
  199. const handleAnnotation = async (item) => {
  200. await getTagList()
  201. showAnnotationDialog.value = true
  202. }
  203. // 删除
  204. const closeClick = (index, dataKey) => {
  205. if (dataKey === 'manualAnnotationTags') {
  206. const dataIndex = talentItem.value[dataKey].findIndex((i) => i === index)
  207. if (dataIndex !== -1) index = dataIndex
  208. }
  209. talentItem.value[dataKey].splice(index, 1)
  210. }
  211. // 手动标注添加
  212. const handleAdd = (item) => {
  213. talentItem.value.manualAnnotationTags.push(item)
  214. }
  215. // 禁用
  216. const handleDisabled = (item) => {
  217. console.log(item, '禁用')
  218. Confirm(t('common.confirmTitle'), '是否确定禁用此人才数据?').then(async () => {
  219. Snackbar.success(t('common.operationSuccessful'))
  220. })
  221. }
  222. // 启用
  223. const handleEnable = (item) => {
  224. console.log(item, '启用')
  225. Confirm(t('common.confirmTitle'), '是否确定启用此人才数据?').then(async () => {
  226. Snackbar.success(t('common.operationSuccessful'))
  227. })
  228. }
  229. // 删除
  230. const handleDelete = (item) => {
  231. console.log(item, '删除')
  232. Confirm(t('common.confirmTitle'), '是否确定删除?').then(async () => {
  233. // await deleteInvoiceTitle(id)
  234. Snackbar.success(t('common.delMsg'))
  235. // getList()
  236. })
  237. }
  238. const handleClose = () => {
  239. showAnnotationDialog.value = false
  240. }
  241. const handleSave = async () => {
  242. handleClose()
  243. }
  244. </script>
  245. <style scoped lang="scss">
  246. .base-info {
  247. background-color: #f7f8fa;
  248. border-radius: 6px;
  249. }
  250. .common-width {
  251. width: 25%;
  252. max-width: 25%;
  253. }
  254. </style>