job.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <template>
  2. <div class="flex">
  3. <el-input
  4. v-model="queryParams.jobName"
  5. placeholder="职位名称(回车搜索)"
  6. class="!w-240px"
  7. clearable
  8. @keyup.enter="handleRefresh"
  9. @clear="handleRefresh"
  10. />
  11. <el-input
  12. v-model="queryParams.enterpriseName"
  13. placeholder="企业全称(回车搜索)"
  14. class="!w-240px mx-10px"
  15. clearable
  16. @keyup.enter="handleRefresh"
  17. @clear="handleRefresh"
  18. />
  19. <!-- <el-button @click="handleRefresh"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> -->
  20. <!-- <el-button @click="resetQuery" plain><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> -->
  21. <el-button type="success" @click="handleRefresh" plain><Icon icon="ep:refresh" class="mr-5px" /> 刷新</el-button>
  22. </div>
  23. <el-table v-loading="loading" :data="tableData" :stripe="true" class="m-t-20px">
  24. <el-table-column label="职位名称" align="center" prop="jobName">
  25. <template #default="{ row }">{{ formatName(row.jobName) }}</template>
  26. </el-table-column>
  27. <el-table-column label="企业全称" align="center" prop="enterpriseName">
  28. <template #default="{ row }">{{ formatName(row.enterpriseName) }}</template>
  29. </el-table-column>
  30. <el-table-column label="企业别称" align="center" prop="enterpriseAnotherName">
  31. <template #default="{ row }">{{ formatName(row.enterpriseAnotherName) }}</template>
  32. </el-table-column>
  33. <el-table-column
  34. label="发布时间"
  35. align="center"
  36. prop="createTime"
  37. :formatter="dateFormatter"
  38. :show-overflow-tooltip="true"
  39. width="180px"
  40. />
  41. <el-table-column label="操作" align="center">
  42. <template #default="scope">
  43. <el-button v-if="scope.row.jobId" link type="primary" @click="openDetail(scope.row)">职位详情</el-button>
  44. </template>
  45. </el-table-column>
  46. </el-table>
  47. <Pagination
  48. :total="total"
  49. v-model:page="queryParams.pageNo"
  50. v-model:limit="queryParams.pageSize"
  51. @pagination="getList"
  52. />
  53. <Dialog title="职位详情" v-model="dialogVisible" class="!w-60%">
  54. <el-descriptions :column="2" border>
  55. <el-descriptions-item label="职位名称">{{ formatName(itemData.name) }}</el-descriptions-item>
  56. <el-descriptions-item label="发布企业">{{ itemData.enterpriseName }}</el-descriptions-item>
  57. <el-descriptions-item label="职位类型">{{ itemData.positionName }}</el-descriptions-item>
  58. <el-descriptions-item label="地区">{{ !itemData.areaId ? '全国' : itemData.areaName }}</el-descriptions-item>
  59. <el-descriptions-item label="详细地址">{{ itemData.address }}</el-descriptions-item>
  60. <el-descriptions-item label="薪资">
  61. <span v-if="itemData.payFrom && itemData.payTo">
  62. {{ itemData.payFrom }} - {{ itemData.payTo }}/{{ payUnit.find(e => e.value === Number(itemData.payUnit))?.label }}
  63. </span>
  64. <span v-else>面议</span>
  65. </el-descriptions-item>
  66. <el-descriptions-item label="招聘类型">
  67. <dict-tag :type="DICT_TYPE.MENDUNER_JOB_TYPE" :value="itemData.type" />
  68. </el-descriptions-item>
  69. <el-descriptions-item label="学历要求">
  70. <dict-tag v-if="itemData.eduType" :type="DICT_TYPE.MENDUNER_EDUCATION_TYPE" :value="itemData.eduType" />
  71. <el-tag v-else>学历不限</el-tag>
  72. </el-descriptions-item>
  73. <el-descriptions-item label="工作经验">
  74. <dict-tag v-if="itemData.expType" :type="DICT_TYPE.MENDUNER_EXP_TYPE" :value="itemData.expType" />
  75. <el-tag v-else>经验不限</el-tag>
  76. </el-descriptions-item>
  77. <el-descriptions-item label="职位状态">
  78. <el-tag v-if="itemData.status === '99'" type="warning">待支付</el-tag>
  79. <dict-tag v-else :type="DICT_TYPE.MENDUNER_STATUS" :value="itemData.status" />
  80. </el-descriptions-item>
  81. <el-descriptions-item label="发布时间">{{ timesTampChange(itemData.createTime) }}</el-descriptions-item>
  82. <el-descriptions-item label="刷新时间">{{ timesTampChange(itemData.updateTime) }}</el-descriptions-item>
  83. </el-descriptions>
  84. <el-descriptions :column="1" border>
  85. <el-descriptions-item label="职位关键字">
  86. <el-tag type="primary" v-for="k in itemData.tagList" :key="k" class="m-r-5px">{{ k }}</el-tag>
  87. </el-descriptions-item>
  88. <el-descriptions-item label="岗位职责">
  89. <div v-html="cleanedHtml(itemData.content)"></div>
  90. </el-descriptions-item>
  91. <el-descriptions-item label="岗位要求">
  92. <div v-html="cleanedHtml(itemData.requirement)"></div>
  93. </el-descriptions-item>
  94. </el-descriptions>
  95. <template #footer>
  96. <el-button @click="dialogVisible = false; itemData = {}">取 消</el-button>
  97. </template>
  98. </Dialog>
  99. </template>
  100. <script setup>
  101. defineOptions({ name: 'EnterpriseUserList'})
  102. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  103. import { dealDictObjData } from '@/utils/transform/position'
  104. import { timesTampChange } from '@/utils/transform/date'
  105. import { formatName } from '@/utils'
  106. import { dateFormatter } from '@/utils/formatTime'
  107. import { JobFairManageApi } from '@/api/menduner/system/jobFair/manage'
  108. import { JobAdvertisedApi } from '@/api/menduner/system/job'
  109. const props = defineProps({
  110. fairId: String
  111. })
  112. const { t } = useI18n() // 国际化
  113. const message = useMessage() // 消息弹窗
  114. const loading = ref(false)
  115. const tableData = ref([])
  116. const total = ref(0)
  117. const queryParams = reactive({
  118. pageNo: 1,
  119. pageSize: 10,
  120. jobName: undefined,
  121. enterpriseName: undefined,
  122. jobFairId: props.fairId
  123. })
  124. const payUnit = getIntDictOptions(DICT_TYPE.MENDUNER_PAY_UNIT)
  125. const dialogVisible = ref(false)
  126. const itemData = ref({})
  127. // 职位列表
  128. const getList = async () => {
  129. loading.value = true
  130. try {
  131. const data = await JobFairManageApi.getJobFairEnterpriseJobs(queryParams)
  132. tableData.value = data.list
  133. total.value = data.total
  134. } finally {
  135. loading.value = false
  136. }
  137. }
  138. getList()
  139. const handleRefresh = () => {
  140. queryParams.pageNo = 1
  141. getList()
  142. }
  143. const resetQuery = () => {
  144. queryParams.jobName = undefined
  145. queryParams.enterpriseName = undefined
  146. handleRefresh()
  147. }
  148. // 富文本去除空格、换行、空标签
  149. const cleanedHtml = (text) => {
  150. let cleaned = text.replace(/\n/g, '</br>')
  151. cleaned = cleaned.replace(/\s+/g, ' ').trim()
  152. cleaned = cleaned.replace(/(^|\s+)<\/p>(\s*<p>|$)/g, '</p><p>').trim()
  153. cleaned = cleaned.replace(/<p>\s*(<br>)\s*<\/p>/g, '')
  154. cleaned = cleaned.replace(/<p>\s*(<\/br>)\s*<\/p>/g, '')
  155. return cleaned
  156. }
  157. // 职位详情
  158. const openDetail = async (item) => {
  159. try {
  160. const data = await JobAdvertisedApi.getJobAdvertised(item.jobId)
  161. itemData.value = {
  162. enterpriseName: formatName(item.enterpriseAnotherName || item.enterpriseName),
  163. ...dealDictObjData({}, data)
  164. }
  165. dialogVisible.value = true
  166. } catch {}
  167. }
  168. </script>
  169. <style scoped lang="scss">
  170. :deep(.el-descriptions__label.el-descriptions__cell.is-bordered-label) {
  171. width: 100px;
  172. }
  173. </style>