Przeglądaj źródła

展示招聘会

lifanagju_citu 4 miesięcy temu
rodzic
commit
2fae1e7647

+ 40 - 0
api/jobFair.js

@@ -0,0 +1,40 @@
+import request from "@/utils/request"
+
+// 获得招聘会列表
+export const getJobFairList = (params) => {
+  return request({
+    url: '/app-api/menduner/system/job-fair/list',
+    method: 'GET',
+    params,
+    custom: {
+      showLoading: false,
+      auth: false
+    }
+  })
+}
+
+// 招聘会企业分页查询
+export const getJobFairEnterprisePage = (params) => {
+  return request({
+    url: '/app-api/menduner/system/job-fair/enterprise/page',
+    method: 'GET',
+    params,
+    custom: {
+      showLoading: false,
+      auth: false
+    }
+  })
+}
+
+// 根据企业id查询招聘会职位列表
+export const getJobFairEntJobPage = (params) => {
+  return request({
+    url: '/app-api/menduner/system/job-fair/detail/page',
+    method: 'GET',
+    params,
+    custom: {
+      showLoading: false,
+      auth: false
+    }
+  })
+}

+ 26 - 3
components/PositionList/index.vue

@@ -1,9 +1,22 @@
 <template>
   <view class="ss-m-x-20">
+    <!-- 招聘会 -->
+    <view v-if="props.showJobFair" class="ss-p-t-20" style="position: relative" @click="handleToJobFair">
+      <image
+        src="https://minio.menduner.com/dev/menduner/miniProgram/Grand-Mercure.jpg"
+        style="width: 100%; height: 100px; border-radius: 8px"
+      ></image>
+      <view
+        style="position: absolute; top: 20rpx; width: 100%; text-align: center; height: 100px; line-height: 100px; font-size: 46px; color: #fff; font-weight: bold;"
+      >
+        招 聘 会
+      </view>
+    </view>
+    <!-- 岗位列表 -->
     <view v-if="list.length > 0" class="ss-p-b-30 ss-p-t-20">
       <view v-for="(item, index) in list" :key="index" class="mList" :class="{ 'disable': item.job?.status === '1'}" @click="toDetail(item)">
         <!-- 职位信息 -->
-        <view class="list-shape">
+        <view class="list-shape" :style="`border-radius: ${props.showEntInfo ? '12px 12px 0 0' : '12px'};`">
           <!-- 职位 -->
           <view class="titleBox my-5">
             <view style="display: flex;align-items: center;">
@@ -50,10 +63,10 @@
               custom-style="background-color: #e2f0ef; color:#00897B; border-color:#e2f0ef;"
             />
           </view>
-          <view class="font-size-13 color-999 ss-m-t-10" style="text-align: end;">更新时间:{{ timesTampChange(item.job.updateTime, 'Y-M-D h:m') }}</view>
+          <view class="font-size-13 color-999 ss-m-t-10" :style="`text-align: ${props.updateTimeAlign};`">更新时间:{{ timesTampChange(item.job.updateTime, 'Y-M-D h:m') }}</view>
         </view>
         <!-- 企业信息 -->
-        <view class="sub-li-bottom">
+        <view v-if="props.showEntInfo" class="sub-li-bottom">
           <view class="avatarBox">
             <image class="enterAvatar ml" :src="item.enterprise?.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></image>
           </view>
@@ -81,6 +94,9 @@ import { formatName } from '@/utils/getText'
 
 const props = defineProps({
   list: { type: Array, default: () => [] },
+  showJobFair: { type: Boolean, default: false }, // 招聘会
+  showEntInfo: { type: Boolean, default: true },
+  updateTimeAlign: { type: String, default: 'end' },
   noMore: { type: Boolean, default: false },
   showWelfareTag: { type: Boolean, default: true }
 })
@@ -91,6 +107,13 @@ const toDetail = (item) =>{
   uni.navigateTo({ url })
 }
 
+//招聘会
+const handleToJobFair = () => {
+	uni.navigateTo({
+		url: '/pagesB/jobFair/index'
+	})
+}
+
 </script>
 
 <style scoped lang="scss">

+ 18 - 0
pages.json

@@ -300,6 +300,24 @@
 					"style": {
 						"navigationBarTitleText": "优选集团"
 					}
+				},
+				{
+					"path": "jobFair/index",
+					"style": {
+						"navigationBarTitleText": "招聘会"
+					}
+				},
+				{
+					"path": "jobFair/enterprises",
+					"style": {
+						"navigationBarTitleText": "招聘会/企业"
+					}
+				},
+				{
+					"path": "jobFair/positions",
+					"style": {
+						"navigationBarTitleText": "招聘会/岗位"
+					}
 				}
 			]
 		}

+ 1 - 1
pages/index/position.vue

@@ -35,7 +35,7 @@
             <view class="white-bgc px-10 stickFilter">
             <FilterList :list="filterList" idValue="label" @change="handleSearch"></FilterList>
           </view>
-          <PositionList :list="positionListData" :noMore="false"></PositionList>
+          <PositionList :list="positionListData" :noMore="false" :showJobFair="true"></PositionList>
           <uni-load-more :status="more" />
         </view>
       </scroll-view>

+ 254 - 0
pagesB/jobFair/enterprises.vue

@@ -0,0 +1,254 @@
+<!-- 招聘会/企业 -->
+<template>
+  <view>
+    <view class="box defaultBgc">
+      <scroll-view class="scrollBox" :scroll-y="true" :scroll-top="scrollTop" @scrolltolower="loadingMore" @scroll="onScroll" style="position:relative;">
+        <view>
+          <!-- 顶部 -->
+          <view class="white-bgc stick ss-p-t-10 ss-p-b-10">
+            <view class="titleBox">
+              <view class="title">招聘会企业</view>
+              <view class="jobFairName">{{ jobFairName }}</view>
+            </view>
+            <!-- 搜索条 -->
+            <view style="position: relative;">
+              <uni-search-bar
+                v-model="query.keyword"
+                placeholder="输入公司关键字"
+                cancelButton="none"
+                :focus="false"
+                bgColor="#fff"
+                @confirm="onSearch($event.value)"
+                @clear="query.keyword = ''; onSearch()"
+              >
+              </uni-search-bar>
+              <button class="search-btn" @tap.stop="onSearch">搜索</button>
+            </view>
+          </view>
+          <view v-if="listData?.length" class="listDataBox">
+            <uni-card v-for="val in listData" :key="val.id" @click="toDetail(val)" :is-shadow="true" :border='false' shadow="0px 0px 3px 1px rgba(0,0,0,0.1)">
+              <view class="d-flex align-center ss-m-30" @click="null">
+                <image class="enterAvatar" :src="val.logoUrl ? val.logoUrl : 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></image>
+                <view class="ss-m-l-20" style="flex: 1;">
+                  <view class="font-size-16 enterpriseName">{{ formatName(val.anotherName || val.name) }}</view>
+                  <view class="ss-m-t-5">
+                    <span class="color-999">{{ val?.industryName || '' }}</span>
+                    <span class="divider tag-gap1" v-if="val?.industryName && val?.scaleName"> | </span>
+                    <span class="color-999">{{ val?.scaleName || '' }}</span>
+                  </view>
+                  <view class="ss-m-t-10" style="overflow: hidden;height: 48px;">
+                    <uni-tag 
+                      v-for="(tag,i) in val?.welfareList || []"
+                      :key="i"
+                      class="ss-m-r-5"
+                      :text="tag"
+                      inverted="false"
+                      size="mini"
+                      custom-style="background-color: #ececec; color: #666; border-color: #ececec; display: inline-block;"
+                    />
+                  </view>
+                </view>
+              </view>
+              <view class="jobCount">{{ val.jobCount }}个在线职位招聘中</view>
+            </uni-card>
+            <uni-load-more :status="more" />
+          </view>
+          <view v-else class="nodata-img-parent">
+            <image src="https://minio.citupro.com/dev/static/nodata.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
+          </view>
+        </view>
+      </scroll-view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, reactive } from 'vue'
+import { dealDictArrayData } from '@/utils/position'
+import { getJobFairEnterprisePage } from '@/api/jobFair'
+import { formatName } from '@/utils/getText'
+import { onLoad } from '@dcloudio/uni-app'
+
+const more = ref('more')
+const listData = ref([])
+const query = reactive({
+  pageSize: 20, 
+  pageNo: 1,
+  keyword: '',
+  jobFairId: undefined,
+})
+
+const jobFairName = ref('')
+
+onLoad(async (options) => {
+  jobFairName.value = options.jobFairName
+  if (options?.jobFairId) {
+    query.jobFairId = options.jobFairId
+    getData()
+	}
+})
+
+const getData = async () => {
+  if (!query.jobFairId) {
+    uni.showToast({ title: '进去招聘会失败!', icon: 'none', duration: 2000 })
+    return
+  }
+  try {
+    const res = await getJobFairEnterprisePage(query)
+    const list = res?.data?.list || []
+    listData.value = listData.value.concat(dealDictArrayData([], list))
+    if (listData.value?.length === +res?.data?.total) {
+      more.value = 'noMore'
+      return
+    }
+  } catch (error) {
+    query.pageNo--
+    more.value = 'more'
+  }
+}
+
+const scrollTop = ref(0)
+const old = ref({
+  scrollTop: 0
+})
+const onScroll = (e) =>{
+  old.value.scrollTop = e.detail.scrollTop
+}
+
+const onSearch = () => {
+  query.pageNo = 1
+  listData.value = []
+  getData()
+}
+
+// 加载更多
+const loadingMore = () => {
+  more.value = 'loading'
+  query.pageNo++
+  getData()
+}
+
+// const goBack = () => {
+// 	uni.navigateTo({
+// 		url: '/pagesB/jobFair/index'
+// 	})
+// }
+
+const toDetail = (item) =>{
+  if (!item?.id || !(item?.jobFairId ?? query.jobFairId)) return
+  const url = `/pagesB/jobFair/positions?jobFairId=${query.jobFairId || item.jobFairId}&enterpriseId=${item.id}&jobFairName=${item.anotherName}`
+  uni.navigateTo({ url })
+}
+
+</script>
+
+<style scoped lang="scss">
+.stick {
+  z-index: 1;
+  position: sticky;
+  top: 0;
+}
+.stickFilter {
+  z-index: 1;
+  position: sticky;
+  box-shadow: 0px 10rpx 12rpx 0px rgba(195, 195, 195, .25);
+  top: 120rpx;
+}
+.px-0 { padding-left: 0 !important; padding-right: 0 !important; }
+.pb-10 {
+  padding-bottom: 10px;
+}
+.pb-20 { padding-bottom: 20px; }
+.px-5 { padding-left: 5px; padding-right: 5px; }
+.px-10 { padding-left: 10px; padding-right: 10px; }
+.mx-10 { margin-left: 10px; margin-right: 10px }
+.mx-20 { margin-left: 20px; margin-right: 20px; }
+.mb-10 { margin-bottom: 10px; }
+.box {
+  height: 100vh;
+  overflow: hidden;
+  // padding-bottom: 120rpx;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+}
+.listDataBox {
+  padding-bottom: 120rpx;
+}
+.scrollBox{
+  flex: 1;
+  height: 0 !important;
+  padding-bottom: 24rpx;
+  box-sizing: border-box;
+}
+:deep(.uni-searchbar__box) {
+  width: calc(100% - 105px);
+  height: 40px !important;
+  border: 1px solid #00897B;
+  padding-right: 20px;
+  flex: none;
+}
+.search-btn {
+  position: absolute;
+  right: 11px;
+  top: 10px;
+  width: 110px;
+  height: 40px;
+  font-size: 16px;
+  background-color: #00897B;
+  color: #fff;
+  border-radius: 0 5px 5px 0;
+  z-index: 9;
+}
+.goBack {
+  width: 110px;
+  height: 32px;
+  font-size: 13px;
+  background-color: #00897B;
+  color: #fff;
+  // border-radius: 0 5px 5px 0;
+  z-index: 9;
+}
+:deep(.picker-view) {
+  padding-bottom: 80px !important;
+}
+
+.jobCount {
+  height: 40px;
+  line-height: 40px;
+  color: #fff;
+  text-align: center;
+  font-size: 15px;
+  background: linear-gradient(to right, #12ebb0, #427daa);
+}
+
+:deep(.uni-card) {
+  padding: 0 !important;
+  .uni-card__content {
+    padding: 0 !important;
+  }
+}
+
+.enterpriseName {
+  color: #404040;
+  font-weight: 700;
+}
+.enterAvatar {
+  width: 60px;
+  height: 60px;
+  // border-radius: 50%;
+  margin: auto;
+}
+.titleBox {
+  text-align: center;
+  padding: 0 20rpx 15px;
+  .title {
+    font-size: 20px;
+    font-weight: 600;
+    margin-bottom: 12px;
+  }
+  .jobFairName {
+    color: var( --v-primary-base);
+  }
+}
+</style>

+ 48 - 0
pagesB/jobFair/index.vue

@@ -0,0 +1,48 @@
+<!-- 招聘会 -->
+<template>
+  <view style="padding-bottom: 30px; ">
+    <view v-if="items.length">
+      <uni-card v-for="val in items" :key="val.id">
+        <image class="ss-m-t-10" :src="val.headImg" mode="widthFix" style="width: 100%; height: auto;"></image>
+        <view class="ss-m-t-20">活动时间:{{ timesTampChange(val.startTime, 'Y-M-D') }}至{{ timesTampChange(val.endTime, 'Y-M-D') }}</view>
+        <button class="ss-m-t-20 ss-m-b-10 main-button-color" type="primary" @tap="handleToJobFairEnterprises(val)">查看详情</button>
+      </uni-card>
+    </view>
+    <view v-else class="nodata-img-parent">
+      <image src="https://minio.citupro.com/dev/static/nodata.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
+    </view>
+  </view>
+</template>
+<script setup>
+import { ref }  from 'vue'
+import { getJobFairList } from '@/api/jobFair'
+import { timesTampChange } from '@/utils/date'
+
+const items = ref([])
+
+// 获得招聘会列表
+const getList = async () => {
+  const res = await getJobFairList()
+  items.value = res?.data || []
+  // items.value = [...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value, ...items.value]
+}
+getList()
+
+//招聘会
+const handleToJobFairEnterprises = (val) => {
+  if (!val?.id) {
+    uni.showToast({ title: '进去招聘会失败!', icon: 'none' })
+  }
+	let text = val.title ? val.title.replace(/<[^>]+>/g, ' ') : '' // 去掉所有 HTML 标签
+	text = text ? text.replace(/\s+/g, ' ').trim() : '' // 去掉多余的空格
+	uni.navigateTo({
+		url: `/pagesB/jobFair/enterprises?jobFairId=${val.id}&jobFairName=${text}`
+	})
+}
+
+</script>
+<style lang="scss" scoped>
+.line {
+  border-top: 1px solid #ccc;
+}
+</style>

+ 210 - 0
pagesB/jobFair/positions.vue

@@ -0,0 +1,210 @@
+<!-- 招聘会/企业详情 -->
+<template>
+  <view>
+    <view class="box">
+      <scroll-view class="scrollBox" :scroll-y="true" :scroll-top="scrollTop" @scrolltolower="loadingMore" @scroll="onScroll" style="position:relative;">
+        <view>
+          <!-- 顶部 -->
+          <view class="white-bgc stick ss-p-t-10">
+            <view class="titleBox">
+              <view class="title">招聘职位</view>
+              <view class="entName">{{ entName }}</view>
+            </view>
+          </view>
+          <view v-if="listData?.length" class="listDataBox defaultBgc">
+			      <PositionList class="pb-10" :list="listData" :noMore="false" :showEntInfo="false" updateTimeAlign="left"></PositionList>
+            <uni-load-more :status="more" />
+          </view>
+          <view v-else class="nodata-img-parent">
+            <image src="https://minio.citupro.com/dev/static/nodata.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
+          </view>
+        </view>
+      </scroll-view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { onLoad } from '@dcloudio/uni-app'
+import { ref, reactive } from 'vue'
+import { dealDictObjData } from '@/utils/position'
+import { getJobFairEntJobPage } from '@/api/jobFair'
+import PositionList from '@/components/PositionList'
+
+const more = ref('more')
+const listData = ref([])
+const query = reactive({
+  pageSize: 20, 
+  pageNo: 1,
+  jobFairId: undefined,
+  enterpriseId: undefined,
+})
+
+const entName = ref('')
+
+onLoad(async (options) => {
+  entName.value = options.entName
+  if (options?.jobFairId) {
+    query.jobFairId = options.jobFairId
+    query.enterpriseId = options.enterpriseId
+    getData()
+	}
+})
+
+const getData = async () => {
+  if (!query.jobFairId) {
+    uni.showToast({ title: '获取企业岗位失败,请重试!', icon: 'none', duration: 2000 })
+    return
+  }
+  try {
+    const res = await getJobFairEntJobPage(query)
+    const list = res?.data?.list || []
+    list.forEach(e => {
+      e.job = dealDictObjData({}, e)
+    })
+    listData.value = listData.value.concat(list)
+    if (listData.value?.length === +res?.data?.total) {
+      more.value = 'noMore'
+      return
+    }
+  } catch (error) {
+    query.pageNo--
+    more.value = 'more'
+  }
+}
+
+const scrollTop = ref(0)
+const old = ref({
+  scrollTop: 0
+})
+const onScroll = (e) =>{
+  old.value.scrollTop = e.detail.scrollTop
+}
+
+// 加载更多
+const loadingMore = () => {
+  more.value = 'loading'
+  query.pageNo++
+  getData()
+}
+
+// const goBack = () => {
+// 	uni.navigateTo({
+// 		url: '/pagesB/jobFair/index'
+// 	})
+// }
+
+</script>
+
+<style scoped lang="scss">
+.stick {
+  z-index: 1;
+  position: sticky;
+  top: 0;
+}
+.stickFilter {
+  z-index: 1;
+  position: sticky;
+  box-shadow: 0px 10rpx 12rpx 0px rgba(195, 195, 195, .25);
+  top: 120rpx;
+}
+.px-0 { padding-left: 0 !important; padding-right: 0 !important; }
+.pb-10 {
+  padding-bottom: 10px;
+}
+.pb-20 { padding-bottom: 20px; }
+.px-5 { padding-left: 5px; padding-right: 5px; }
+.px-10 { padding-left: 10px; padding-right: 10px; }
+.mx-10 { margin-left: 10px; margin-right: 10px }
+.mx-20 { margin-left: 20px; margin-right: 20px; }
+.mb-10 { margin-bottom: 10px; }
+.box {
+  height: 100vh;
+  overflow: hidden;
+  // padding-bottom: 120rpx;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+}
+.listDataBox {
+  padding: 1px 0 120rpx;
+  // padding-bottom: 120rpx;
+  margin: 0 30rpx;
+}
+.scrollBox{
+  flex: 1;
+  height: 0 !important;
+  padding-bottom: 24rpx;
+  box-sizing: border-box;
+}
+:deep(.uni-searchbar__box) {
+  width: calc(100% - 105px);
+  height: 40px !important;
+  border: 1px solid #00897B;
+  padding-right: 20px;
+  flex: none;
+}
+.search-btn {
+  position: absolute;
+  right: 11px;
+  top: 10px;
+  width: 110px;
+  height: 40px;
+  font-size: 16px;
+  background-color: #00897B;
+  color: #fff;
+  border-radius: 0 5px 5px 0;
+  z-index: 9;
+}
+.goBack {
+  width: 110px;
+  height: 32px;
+  font-size: 13px;
+  background-color: #00897B;
+  color: #fff;
+  // border-radius: 0 5px 5px 0;
+  z-index: 9;
+}
+:deep(.picker-view) {
+  padding-bottom: 80px !important;
+}
+
+.jobCount {
+  height: 40px;
+  line-height: 40px;
+  color: #fff;
+  text-align: center;
+  font-size: 15px;
+  background: linear-gradient(to right, #12ebb0, #427daa);
+}
+
+:deep(.uni-card) {
+  padding: 0 !important;
+  .uni-card__content {
+    padding: 0 !important;
+  }
+}
+
+.enterpriseName {
+  color: #404040;
+  font-weight: 700;
+}
+.enterAvatar {
+  width: 60px;
+  height: 60px;
+  // border-radius: 50%;
+  margin: auto;
+}
+.titleBox {
+  text-align: center;
+  padding: 0 20rpx 15px;
+  .title {
+    font-size: 20px;
+    font-weight: 600;
+    margin-bottom: 12px;
+  }
+  .entName {
+    color: var( --v-primary-base);
+  }
+}
+</style>

+ 5 - 0
static/style/index.scss

@@ -432,6 +432,11 @@
 	color: #fff;
 }
 
+.main-button-color {
+	background-color: #00897B !important;
+	color: #fff;
+}
+
 .commonBtnStyle {
   width: 45vw;
   height: 44px;