index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <template>
  2. <div :class="{'disable': info && info?.entitlement && !info?.entitlement?.hireJob}">
  3. <v-card class="card-box pa-5">
  4. <div class="d-flex justify-center mt-3">
  5. <TextUI :item="textItem" @enter="handleEnter" @appendInnerClick="handleEnter"></TextUI>
  6. </div>
  7. <div class="text-end">
  8. <v-btn prepend-icon="mdi-plus" color="primary" @click="handleAdd">{{ $t('position.newPositionsAdded') }}</v-btn>
  9. <v-btn :loading="exportLoading" prepend-icon="mdi-export-variant" color="primary" variant="tonal" class="ml-3" @click="handleExport">职位列表下载</v-btn>
  10. </div>
  11. <div class="mt-3">
  12. <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="handleChangeTab">
  13. <v-tab v-for="val in tabList" :key="val.value" :value="val.value"> {{ val.label }}</v-tab>
  14. </v-tabs>
  15. <v-window v-model="tab" class="mt-3">
  16. <v-window-item v-for="val in tabList" :key="val.value" :value="val.value">
  17. <PositionItem v-if="items.length" :tab="tab" :items="items" @refresh="handleRefresh"></PositionItem>
  18. </v-window-item>
  19. </v-window>
  20. <Empty v-if="!items.length" :message="loading ? '加载中...' : tipsText" :elevation="false"></Empty>
  21. <CtPagination
  22. v-else
  23. :total="total"
  24. :page="query.pageNo"
  25. :limit="query.pageSize"
  26. @handleChange="handleChangePage"
  27. ></CtPagination>
  28. </div>
  29. </v-card>
  30. </div>
  31. </template>
  32. <script setup>
  33. defineOptions({ name: 'enterprise-hire-position-list'})
  34. import { ref } from 'vue'
  35. import TextUI from '@/components/FormUI/TextInput'
  36. import PositionItem from './components/item.vue'
  37. import { useRouter } from 'vue-router'; const router = useRouter()
  38. import { getJobAdvertisedList, getJobAdvertisedExport } from '@/api/position'
  39. import { dealDictArrayData } from '@/utils/position'
  40. import { useI18n } from '@/hooks/web/useI18n'
  41. import { useUserStore } from '@/store/user'
  42. import download from '@/utils/download'
  43. import { getEnterprisePubJobTypePermission } from '@/api/recruit/enterprise/position'
  44. import Snackbar from '@/plugins/snackbar'
  45. const store = useUserStore()
  46. const { t } = useI18n()
  47. const total = ref(0)
  48. const tipsText = ref(t('common.noData'))
  49. const query = ref({
  50. pageSize: 10,
  51. pageNo: 1,
  52. status: 0, // 0招聘中 1已关闭
  53. hasExpiredData: false, // true 到期职位
  54. hire: true
  55. })
  56. const exportLoading = ref(false)
  57. const tab = ref(1)
  58. const tabList = [
  59. { label: '待发布', value: 0, status: 99 },
  60. { label: t('position.recruitmentInProgress'), value: 1, status: 0 },
  61. { label: t('position.closed'), value: 2, status: 1 },
  62. { label: t('position.expiredPosition'), value: 3 }
  63. ]
  64. const items = ref([])
  65. const textItem = ref({
  66. type: 'text',
  67. width: 600,
  68. value: '',
  69. label: '请输入职位名称',
  70. clearable: true,
  71. appendInnerIcon: 'mdi-magnify'
  72. })
  73. // 获取企业权益信息
  74. const info = ref(localStorage.getItem('entBaseInfo') ? JSON.parse(localStorage.getItem('entBaseInfo')) : {})
  75. store.$subscribe((mutation, state) => {
  76. if (Object.keys(state.entBaseInfo).length) info.value = state.entBaseInfo
  77. })
  78. const handleAdd = async () => {
  79. const data = await getEnterprisePubJobTypePermission()
  80. if (!data || !data.length) return Snackbar.warning('没有该操作权限,请联系平台管理员升级后再试')
  81. router.push('/recruit/enterprise/hirePosition/add')
  82. await store.getEnterpriseUserAccountInfo()
  83. }
  84. const handleExport = async () => {
  85. exportLoading.value = true
  86. try {
  87. const data = await getJobAdvertisedExport(query.value)
  88. download.excel(data, '众聘职位列表.xlsx')
  89. } finally {
  90. exportLoading.value = false
  91. }
  92. }
  93. const loading = ref(false)
  94. // 获取职位列表
  95. const getPositionList = async () => {
  96. items.value = []; total.value = 0
  97. loading.value = true
  98. if (tab.value !== 3) {
  99. query.value.status = tabList[tab.value].status
  100. query.value.hasExpiredData = false
  101. } else {
  102. query.value.hasExpiredData = true
  103. delete query.value.status
  104. }
  105. const { list, total: number } = await getJobAdvertisedList(query.value)
  106. if (!list.length) {
  107. if (query.value.name) tipsText.value = '暂无数据,请更换关键词后再试'
  108. }
  109. total.value = number
  110. items.value = list.length ? dealDictArrayData([], list) : []
  111. loading.value = false
  112. }
  113. getPositionList()
  114. const handleRefresh = (index) => {
  115. query.value.pageNo = 1
  116. if (index) tab.value = index
  117. getPositionList()
  118. }
  119. const handleChangeTab = () => {
  120. query.value.pageNo = 1
  121. getPositionList()
  122. }
  123. const handleChangePage = (index) => {
  124. query.value.pageNo = index
  125. getPositionList()
  126. }
  127. // 职位名称检索
  128. const handleEnter = (e) => {
  129. query.value.name = e
  130. query.value.pageNo = 1
  131. getPositionList()
  132. }
  133. </script>
  134. <style scoped lang="scss">
  135. .disable {
  136. position: relative;
  137. overflow: hidden;
  138. &::after {
  139. content: '很抱歉,您当前没有权限使用全员猎寻模块';
  140. position: absolute;
  141. display: flex;
  142. align-items: center;
  143. justify-content: center;
  144. font-size: 1.5em;
  145. font-family: 'MiSans-Bold';
  146. color: #fff;
  147. top: 0;
  148. border-radius: 12px;
  149. left: 0;
  150. width: 100%;
  151. height: 100%;
  152. background-color: rgba(0, 0, 0, 0.35);
  153. }
  154. }
  155. </style>