ソースを参照

岗位信息管理

lizeyu 11 ヶ月 前
コミット
141e70eb64

+ 2 - 2
h5app/src/api/post/index.ts

@@ -1,11 +1,11 @@
 import {request} from '@/utils/request';
 
-export function getPostList() {
+export function getPostList(params: any) {
     return request<any>(
         {
             url: 'companyService/post/getList',
             method: 'get',
-            params: {pageIndex:1,pageSize:10000},
+            params: params,
         },
         { isNew: true },
     );

+ 43 - 0
h5app/src/api/recommendmgt/index.ts

@@ -0,0 +1,43 @@
+import {request} from "@/utils/request";
+
+
+export function addRecommend(data: any) {
+    return request(
+        {
+            url: 'jobusermgr/recommendmgt/addRecommend',
+            method: 'post',
+            data: data,
+        },
+        {
+            isNew: true,
+            successMsg: '提交成功!',
+            errorMsg: '提交失败!'
+        },
+    );
+}
+
+export function getRecommendCompanyPostList(params: any) {
+    return request<object>(
+        {
+            url: "jobusermgr/recommendmgt/getRecommendCompanyPostList",
+            method: 'get',
+            params: params,
+        },
+        {
+            isNew: true,
+        },
+    );
+}
+
+export function getRecommendJobList(params: any) {
+    return request<any>(
+        {
+            url: "jobusermgr/recommendmgt/getRecommendJobList",
+            method: 'get',
+            params: params,
+        },
+        {
+            isNew: true,
+        },
+    );
+}

BIN
h5app/src/assets/icon/gwxxgl.png


+ 8 - 0
h5app/src/router/index.ts

@@ -64,6 +64,14 @@ const routes: Array<RouteRecordRaw> = [
                 path: 'tabMain/company/editPost',
                 component: () => import('@/views/pages/company/editPost.vue')
             },
+            {
+                path: 'tabMain/post/list',
+                component: () => import('@/views/pages/post/list.vue')
+            },
+            {
+                path: 'tabMain/post/recommendJob',
+                component: () => import('@/views/pages/post/recommendJob.vue')
+            },
             {
                 path: 'tabMain/post/recommend',
                 component: () => import('@/views/pages/post/recommend.vue')

+ 398 - 0
h5app/src/views/pages/post/edit.vue

@@ -0,0 +1,398 @@
+<template>
+  <ion-page  class="list-page">
+    <ion-header class="header-theme2">
+      <ion-toolbar>
+        <ion-buttons slot="start">
+          <ion-icon :icon="arrowBackOutline" @click="back"></ion-icon>
+        </ion-buttons>
+        <ion-title>
+          岗位信息收集
+        </ion-title>
+      </ion-toolbar>
+    </ion-header>
+    <ion-content>
+      <form autocomplete="off">
+        <ion-list>
+          <ion-item>
+            <div class="panel-title2">
+              <div class="item-flag"></div>
+              基础信息
+            </div>
+          </ion-item>
+          <ion-label class="title-item">岗位名称<span class="danger">*</span></ion-label>
+          <ion-item mode="md" :class="[v$.dataModel.postName.$error?'ion-invalid':'ion-valid']">
+            <ion-input placeholder="请输入岗位名称" label-placement="stacked" :clear-input="true"
+                       v-model="dataModel.postName" class="custom">
+            </ion-input>
+            <ion-note slot="error">请输入岗位名称</ion-note>
+          </ion-item>
+          <ion-label class="title-item">招聘数量(人)<span class="danger">*</span></ion-label>
+          <ion-item mode="md" :class="[v$.dataModel.recruitCount.$error?'ion-invalid':'ion-valid']">
+            <ion-input type="number" placeholder="请输入招聘数量" label-placement="stacked" :clear-input="true"
+                       v-model="dataModel.recruitCount" class="custom">
+            </ion-input>
+            <ion-note slot="error">请输入招聘数量</ion-note>
+          </ion-item>
+          <ion-label class="title-item">招聘日期<span class="danger">*</span></ion-label>
+          <ion-item mode="md" :class="[v$.dataModel.startTime.$error||v$.dataModel.endTime.$error?'ion-invalid':'ion-valid']">
+            <ion-datetime-button datetime="startTime"></ion-datetime-button>
+            <ion-modal :keep-contents-mounted="true">
+              <ion-datetime placeholder="招聘日期" id="startTime"
+                            v-model="dataModel.startTime"  :prefer-wheel="true"
+                            dataformatas="YYYY-MM-DD" presentation="date" cancel-text="取消" done-text="确定"
+                            :show-default-buttons="true" style="text-align: left;width: 100%;">
+              </ion-datetime>
+            </ion-modal>
+            至
+            <ion-datetime-button datetime="endTime"></ion-datetime-button>
+            <ion-modal :keep-contents-mounted="true">
+              <ion-datetime placeholder="招聘日期" id="endTime"
+                            v-model="dataModel.endTime"  :prefer-wheel="true"
+                            dataformatas="YYYY-MM-DD" presentation="date" cancel-text="取消" done-text="确定"
+                            :show-default-buttons="true" style="text-align: left;width: 100%;">
+              </ion-datetime>
+            </ion-modal>
+            <ion-note slot="error">招聘开始日期与结束日期不能为空</ion-note>
+          </ion-item>
+          <ion-label class="title-item">招聘地点<span class="danger">*</span></ion-label>
+          <ion-item mode="md" :class="[v$.dataModel.jobPlace.$error?'ion-invalid':'ion-valid']">
+            <ion-textarea placeholder="请输入招聘地点" :rows="3" label-placement="stacked" :clear-input="true"
+                       v-model="dataModel.jobPlace" class="custom">
+            </ion-textarea>
+            <ion-note slot="error">请输入招聘地点</ion-note>
+          </ion-item>
+
+          <ion-item mode="md" >
+            <div class="panel-title2" style="width: 25%;">
+              <div class="item-flag"></div>
+              其他信息
+            </div>
+            <div style="width: 75%;text-align: right;">
+              <ion-icon :icon="chevronDownOutline" @click="isShow=!isShow" v-show="!isShow"
+                        style="font-size: 24px;"></ion-icon>
+              <ion-icon :icon="chevronUpOutline" @click="isShow=!isShow" v-show="isShow"
+                        style="font-size: 24px;"></ion-icon>
+            </div>
+          </ion-item>
+          <ion-list v-show="isShow" >
+            <ion-label class="title-item">岗位月薪(元)</ion-label>
+            <ion-item mode="md" >
+              <ion-input placeholder="请输入金额" label-placement="stacked"
+                         v-model="dataModel.minSalary" class="custom">
+              </ion-input>
+              <ion-label style="text-align:left;width:70px;">至</ion-label>
+              <ion-input placeholder="请输入金额" label-placement="stacked"
+                         v-model="dataModel.maxSalary" class="custom">
+              </ion-input>
+            </ion-item>
+            <ion-label class="title-item">是否有试用期</ion-label>
+            <ion-item mode="md" >
+              <ion-select interface="action-sheet" placeholder="请选择是否有试用期" cancel-text="取消"
+                          id="isTrail" v-model="dataModel.isTrail" style="width: 100%;text-align: left;">
+                <ion-select-option v-for="(record,key) in isTrailList" :key="key"
+                                   v-model:value="record.value">
+                  {{ record.name }}
+                </ion-select-option>
+              </ion-select>
+            </ion-item>
+            <ion-label class="title-item">试用期(月)</ion-label>
+            <ion-item mode="md" >
+              <ion-input type="number" placeholder="请输入试用期月数" label-placement="stacked"
+                         v-model="dataModel.trailMonths" class="custom">
+              </ion-input>
+            </ion-item>
+            <ion-label class="title-item">试用期月薪(元)</ion-label>
+            <ion-item mode="md" >
+              <ion-input type="number" placeholder="请输入金额" label-placement="stacked"
+                         v-model="dataModel.trailMinSalary" class="custom">
+              </ion-input>
+              <ion-label style="text-align:left;width:70px;">至</ion-label>
+              <ion-input type="number" placeholder="请输入金额" label-placement="stacked"
+                         v-model="dataModel.trailMaxSalary" class="custom">
+              </ion-input>
+            </ion-item>
+            <ion-label class="title-item">工作年限要求</ion-label>
+            <ion-item mode="md" >
+              <ion-select interface="action-sheet" placeholder="请选择工作年限" cancel-text="取消"
+                          id="workYear" v-model="dataModel.workYear" style="width: 100%;text-align: left;">
+                <ion-select-option v-for="(record,key) in workYearList" :key="key"
+                                   v-model:value="record.value">
+                  {{ record.name }}
+                </ion-select-option>
+              </ion-select>
+            </ion-item>
+            <ion-label class="title-item">学历要求</ion-label>
+            <ion-item mode="md" >
+              <ion-select interface="action-sheet" placeholder="请选择学历" cancel-text="取消"
+                          id="cultureRank" v-model="dataModel.cultureRank" style="width: 100%;text-align: left;">
+                <ion-select-option v-for="(record,key) in cultureRankList" :key="key"
+                                   v-model:value="record.value">
+                  {{ record.name }}
+                </ion-select-option>
+              </ion-select>
+            </ion-item>
+            <ion-label class="title-item">福利待遇</ion-label>
+            <ion-item mode="md" >
+              <ion-textarea placeholder="请输入福利待遇" :rows="3" label-placement="stacked"
+                            v-model="dataModel.welfare" class="custom">
+              </ion-textarea>
+            </ion-item>
+            <ion-label class="title-item">其他要求</ion-label>
+            <ion-item mode="md" >
+              <ion-textarea placeholder="请输入其他要求" :rows="3" label-placement="stacked"
+                            v-model="dataModel.postDesc" class="custom">
+              </ion-textarea>
+            </ion-item>
+          </ion-list>
+        </ion-list>
+      </form>
+    </ion-content>
+    <ion-footer>
+      <ion-toolbar>
+        <div slot="end">
+          <ion-button shape="round" expand="block" @click="onSave">提交</ion-button>
+        </div>
+      </ion-toolbar>
+    </ion-footer>
+  </ion-page>
+</template>
+<script lang="ts">
+import {computed, defineComponent, reactive, ref, toRefs, watch} from "vue";
+import {chevronDownOutline, chevronUpOutline, arrowBackOutline} from 'ionicons/icons';
+import {useRoute, useRouter} from "vue-router";
+import {alertController, onIonViewDidEnter} from "@ionic/vue";
+import {useVuelidate} from "@vuelidate/core";
+import {getPostByID,savePost} from "@/api/post";
+import {minLength, required} from "@vuelidate/validators";
+import {getSysDictionaryList} from "@/api/system/dictionary";
+import dayjs from "dayjs";
+
+export default defineComponent({
+  name: 'PostEdit',
+  setup() {
+    const router = useRouter();
+    const route = useRoute();
+    const isShow = ref<any>(false);
+    const isEdit = ref<any>(false);
+    const formState = reactive({
+      dataModel: {
+        companyID:null,
+        postID:null,
+        postName:null,
+        recruitCount:null,
+        startTime:dayjs().format("YYYY-MM-DD"),
+        endTime:dayjs().format("YYYY-MM-DD"),
+        jobPlace:null,
+        minSalary:null,
+        maxSalary:null,
+        isTrail:null,
+        trailMonths:null,
+        trailMinSalary:null,
+        trailMaxSalary:null,
+        workYear:null,
+        cultureRank:null,
+        welfare:null,
+        postDesc:null
+      }});
+    const rules = computed(() => {
+      return {
+        dataModel: {
+          postName: {required},
+          recruitCount: {required},
+          startTime: {required},
+          endTime: {required},
+          jobPlace:{required}
+        }
+      }
+    });
+    const v$ = useVuelidate(rules, formState);
+    const isTrailList = ref([
+      {value: true, name: '是'},
+      {value: false, name: '否'},
+    ]);
+    const workYearList = ref([]);
+    const cultureRankList = ref([]);
+
+    const presentAlert = async (message: string) => {
+      const alert = await alertController.create({
+        header: '错误!',
+        message: message,
+        buttons: [
+          '确定'
+        ],
+      });
+      await alert.present();
+    }
+
+    const onSave = async function (){
+      const isFormCorrect = await v$.value.$validate();
+      if (!isFormCorrect) {
+        console.log("当前岗位信息",formState.dataModel);
+        await presentAlert('请输入完整信息!');
+        return null;
+      }
+      savePost(formState.dataModel).then(result=>{
+        if(result){
+           router.push({path: "./postList", query: {reload:1,id:formState.dataModel.companyID,status: 3}});
+        }
+      })
+    }
+
+    const back = () => {
+      router.push({path: "./postList", query: {reload:1,id:formState.dataModel.companyID,status: 3}});
+    }
+
+    const getWorkYearList = async function(){
+      const data :any = await getSysDictionaryList("WorkYearType");
+      workYearList.value = data;
+      console.log(workYearList.value);
+    }
+    const getCultureRankList = async function(){
+      const data:any = await getSysDictionaryList("CultureLevel");
+      cultureRankList.value = data;
+      console.log(cultureRankList.value);
+    }
+
+    const loadData = async (postID: any,companyID:any) => {
+      await getWorkYearList();
+      await getCultureRankList();
+      const reqData = await getPostByID(postID);
+      formState.dataModel = reqData;
+      formState.dataModel.companyID = companyID;
+      console.log("初始化岗位信息",formState.dataModel);
+    };
+
+    const reload = (postID: any,companyID:any) => {
+      formState.dataModel.recruitCount = null;
+      loadData(postID,companyID);
+    }
+
+    onIonViewDidEnter(() => {
+      if (route.query.reload)
+        reload(route.query.id,route.query.companyID);
+    });
+
+    return {
+      ...toRefs(formState),
+      chevronDownOutline,
+      chevronUpOutline,
+      arrowBackOutline,
+      route,
+      router,
+      isShow,
+      isEdit,
+      isTrailList,
+      workYearList,
+      cultureRankList,
+      v$,
+      onSave,
+      back,
+    }
+  }
+});
+</script>
+
+<style lang="less">
+
+.custom{
+  --placeholder-color: gray;
+  --placeholder-font-style:italic;
+  --placeholder-opacity: 1;
+}
+
+.title-item{
+  margin-left: 15px;
+  color:#1c3d70 !important;
+  font-size: 14px !important;
+  font-weight: bold;
+}
+
+ion-item {
+  --border-width: 0;
+  --border-style: none;
+
+  ion-label, input, ion-select, ion-datetime {
+    font-size: 14px !important;
+  }
+}
+
+.stepFlex {
+  margin: 0;
+  display: flex;
+  width: 100%;
+
+  .stepFlex-item {
+    position: relative;
+    flex: 1;
+    text-align: center;
+    margin-top: -10px;
+
+    .stepFlex-item-label {
+      padding-top: 60px;
+      font-size: 14px;
+
+      .stepFlex-item-label-title {
+        margin-top: 30px;
+      }
+
+      .stepFlex-item-label-desc {
+        margin-top: 5px;
+        color: #b9b9bd;
+      }
+    }
+  }
+
+  .greenCircle {
+    top: calc(50% - 15px);
+    left: calc(50% - 4px);
+    position: absolute;
+    z-index: 2;
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    background-color: #31A2FE;
+  }
+
+  .now {
+    top: calc(50% - 18px);
+    left: calc(50% - 8px);
+    position: absolute;
+    z-index: 3;
+    width: 16px;
+    height: 16px;
+    border-radius: 50%;
+    background-color: #31A2FE;
+    border: 4px solid #c5e8f9;
+  }
+
+  .grayCircle {
+    top: calc(50% - 15px);
+    left: calc(50% - 4px);
+    position: absolute;
+    z-index: 2;
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    background-color: #ccc;
+  }
+
+  .greenLine {
+    width: 100%;
+    top: calc(50% - 11px);
+    left: calc(50% - 2px);
+    height: 2px;
+    background-color: #31A2FE;
+    position: absolute;
+  }
+
+  .grayLine {
+    height: 0;
+    border: 1px dashed #ccc;
+    width: 100%;
+    top: calc(50% - 11px);
+    left: calc(50% - 2px);
+    position: absolute;
+  }
+
+}
+</style>

+ 185 - 0
h5app/src/views/pages/post/list.vue

@@ -0,0 +1,185 @@
+<template>
+  <ion-page class="list-page company-list-page">
+    <ion-header class="header-theme2">
+      <ion-toolbar>
+        <ion-buttons slot="start">
+          <ion-icon :icon="arrowBackOutline" @click="onBack"></ion-icon>
+        </ion-buttons>
+        <ion-title>岗位信息管理</ion-title>
+        <ion-buttons slot="end">
+          <ion-icon :icon="addCircleOutline" @click="onAdd"></ion-icon>
+        </ion-buttons>
+      </ion-toolbar>
+    </ion-header>
+    <ion-content>
+      <ion-item class="search-item">
+        <ion-input placeholder="岗位名称" class="custom"
+                   v-model="searchParams.professionName" style="border: 1px solid #f2f2f5;border-radius: 14px;--padding-start: 10px;height: 35px;"></ion-input>
+        <ion-button slot="end" style="height: 33px;width: 70px;margin-left: 10px;--box-shadow: none;--border-radius: 14px;" @click="reload" >搜索
+        </ion-button>
+      </ion-item>
+      <ion-list class="list-content">
+        <ion-item v-for="(record,key) in dataList" :key="key" detail @click="onEdit(record.postID)">
+          <ion-label>
+            <h3>{{ record.professionName}}</h3>
+            <p>{{ record.companyName }}</p>
+            <p>{{ dayjs(record.startTime).format("YYYY-MM-DD")}}至{{ dayjs(record.endTime).format("YYYY-MM-DD")}}</p>
+            <ion-label style="display: flex;justify-content: space-between;">
+              <p>
+                招聘人数:{{ record.recruitCount == null ? "0" : record.insuredCount }}人
+              </p>
+              <p>
+                已推荐人数:{{ record.recommendNum }}
+              </p>
+            </ion-label>
+          </ion-label>
+          <ion-avatar @click="onRecommendJob(record);$event.preventDefault();$event.stopPropagation();" aria-hidden="true" class="container" slot="end">
+            <p style="font-size: 14px !important;">推荐</p>
+          </ion-avatar>
+        </ion-item>
+      </ion-list>
+      <b-empty v-if="dataList.length<=0" :loading="loading"/>
+      <ion-infinite-scroll threshold="100px" @ionInfinite="onScroll($event)">
+        <ion-infinite-scroll-content
+            :loadingText="pagination.total>pagination.current*pagination.pageSize?'正在加载...':'暂无更多'"
+            loadingSpinner="bubbles">
+        </ion-infinite-scroll-content>
+      </ion-infinite-scroll>
+    </ion-content>
+  </ion-page>
+</template>
+
+<script lang="ts">
+
+import {computed, defineComponent, reactive, ref} from 'vue';
+import dayjs from "dayjs";
+import {useRoute, useRouter} from "vue-router";
+import {arrowBackOutline, ellipse, addCircleOutline} from 'ionicons/icons';
+import {IonIcon, onIonViewDidEnter} from '@ionic/vue';
+import BEmpty from "@/components/empty.vue";
+import {getPostList} from '@/api/post/index'
+
+export default defineComponent({
+  name: 'PostList',
+  components: {IonIcon, BEmpty},
+  setup() {
+    const router = useRouter();
+    const route = useRoute();
+    const total = ref(10);
+    const loading = ref(true);
+    const pagination = computed(() => ({
+      total: total,
+      current: searchParams.pageIndex,
+      pageSize: searchParams.pageSize
+    }));
+    const searchParams = reactive({
+      pageIndex: 1,
+      pageSize: 5,
+      professionName: '',
+    });
+    const dataList = ref<any>([]);
+    const colors = ref(["secondary", "tertiary", "success", "warning"]);
+
+    const loadData = async function () {
+      loading.value = true;
+      getPostList(searchParams).then(data => {
+        dataList.value = dataList.value.concat(data.list);
+        total.value = data.total;
+        console.log(dataList.value);
+      })
+      loading.value = false;
+    }
+
+    const reload = () => {
+      dataList.value = [];
+      searchParams.pageIndex = 1;
+      loadData();
+    }
+
+    const onScroll = (e: any) => {
+      setTimeout(() => {
+        e.target.complete();
+        if (pagination.value.total.value > pagination.value.current * pagination.value.pageSize) {
+          searchParams.pageIndex += 1;
+          loadData();
+        }
+      }, 500);
+    }
+
+    const onAdd = () => {
+      router.push({path: './edit', query: {reload: 1,id: null,status: 1}});
+    }
+
+    const onEdit = (postID:string) => {
+      router.push({path: './menu', query: {reload: 1,id: postID,status: 2}});
+    }
+
+    const onRecommendJob = (item: any) =>{
+      router.push({path: './recommendJob', query: {reload: 1,professionID:item.professionID,professionName:item.professionName,postID:item.postID,companyName:item.companyName,type:0}});
+    }
+
+    const onBack = () => {
+      router.push('../');
+    }
+
+    onIonViewDidEnter(() => {
+      if(route.query.reload)reload();
+    });
+
+    return {
+      ellipse,
+      arrowBackOutline,
+      addCircleOutline,
+      router,
+      colors,
+      total,
+      loading,
+      dataList,
+      pagination,
+      searchParams,
+      onBack,
+      onAdd,
+      onEdit,
+      onRecommendJob,
+      onScroll,
+      loadData,
+      reload,
+      dayjs,
+    }
+  },created() {
+    this.loadData();
+  }
+});
+</script>
+
+<style lang="less">
+.custom{
+  --placeholder-color: gray;
+  --placeholder-font-style:italic;
+  --placeholder-opacity: 1;
+}
+
+.company-list-page {
+  .list-content {
+    margin: 0px 15px !important;
+    background-color: white !important;
+    border-radius: 0 !important;
+
+    ion-item {
+      margin-top: 10px;
+      font-size: 14px;
+      border: 1px solid rgb(242, 242, 245);
+
+      p {
+        font-size: 12px;
+      }
+    }
+  }
+}
+
+.container {
+  display: flex;
+  justify-content: center; /* 水平居中 */
+  align-items: center; /* 垂直居中 */
+}
+</style>

+ 221 - 0
h5app/src/views/pages/post/recommendJob.vue

@@ -0,0 +1,221 @@
+<template>
+  <ion-page class="list-page company-list-page">
+    <ion-header class="header-theme2">
+      <ion-toolbar>
+        <ion-buttons slot="start">
+          <ion-icon :icon="arrowBackOutline" @click="onBack"></ion-icon>
+        </ion-buttons>
+        <ion-title>求职人员推荐</ion-title>
+      </ion-toolbar>
+    </ion-header>
+    <ion-content>
+      <ion-item class="search-item">
+        <ion-label>
+          <h2>{{ searchParams.professionName }}</h2>
+          <p>{{ searchParams.companyName }}</p>
+        </ion-label>
+      </ion-item>
+      <ion-list class="list-content">
+        <ion-item v-for="(record,key) in dataList" detail :key="key">
+          <ion-label>
+            <h2>{{ record.userName }}</h2>
+            <p>应聘岗位:{{ record.professionName }}</p>
+            <p>电话:{{ record.userMobile }}</p>
+          </ion-label>
+          <ion-avatar aria-hidden="true" class="container" slot="end">
+            <ion-text style="text-align:right;" @click="onRecommend(record)">推荐</ion-text>
+          </ion-avatar>
+        </ion-item>
+      </ion-list>
+      <b-empty v-if="dataList.length<=0" :loading="loading"/>
+      <ion-infinite-scroll threshold="100px" @ionInfinite="onScroll($event)">
+        <ion-infinite-scroll-content
+            :loadingText="pagination.total>pagination.pageIndex*pagination.pageSize?'正在加载...':'暂无更多'"
+            loadingSpinner="bubbles">
+        </ion-infinite-scroll-content>
+      </ion-infinite-scroll>
+    </ion-content>
+    <ion-footer>
+      <ion-toolbar>
+        <ion-button expand="block" @click="onBatchRecommend()" fill="outline">全部推荐</ion-button>
+      </ion-toolbar>
+    </ion-footer>
+  </ion-page>
+</template>
+
+<script lang="ts">
+import {useRoute, useRouter} from "vue-router";
+import {computed, defineComponent, reactive, ref, watch} from 'vue';
+import {arrowBackOutline, addCircleOutline} from 'ionicons/icons';
+import {alertController, IonIcon, onIonViewDidEnter} from '@ionic/vue';
+import {getRecommendJobList, addRecommend} from "@/api/recommendmgt";
+
+export default defineComponent({
+  name: 'RecommendJobList',
+  components: {IonIcon},
+  setup() {
+    const loading = ref(true);
+    const router = useRouter();
+    const route = useRoute();
+    const total = ref(10);
+    const pagination = computed(() => ({
+      total: total,
+      pageIndex: searchParams.pageIndex,
+      pageSize: searchParams.pageSize
+    }));
+    const searchParams = reactive({
+      pageIndex: 1,
+      pageSize: 5,
+      postID: '',
+      professionID: '',
+      companyName: '',
+      professionName: '',
+      type: 0
+    })
+    const dataList = ref<any>([]);
+    const addRecommendList = ref<any>([]);
+    const colors = ref(["secondary", "tertiary", "success", "warning"]);
+
+    const loadData = async function () {
+      loading.value = true;
+      searchParams.postID = route.query.postID as any;
+      searchParams.companyName = route.query.companyName as any;
+      searchParams.professionID = route.query.professionID as any;
+      searchParams.professionName = route.query.professionName as any;
+      searchParams.type = route.query.type as any;
+      getRecommendJobList(searchParams).then(data => {
+        dataList.value = dataList.value.concat(data.list);
+        total.value = data.total;
+      });
+      loading.value = false;
+    }
+
+    const onScroll = (e: any) => {
+      setTimeout(() => {
+        e.target.complete();
+        if (pagination.value.total.value > pagination.value.pageIndex * pagination.value.pageSize) {
+          searchParams.pageIndex += 1;
+          loadData();
+        }
+      }, 500);
+    }
+
+    const onRecommend = (item: any) => {
+      addRecommendList.value.push({
+        recommendMgtID: item.recommendMgtID,
+        jobHuntID: item.jobhuntID,
+        postID: searchParams.postID,
+        recommendType: 0
+      });
+      addRecommend(addRecommendList.value).then(() => {
+        let index = dataList.value.findIndex((x: any) => x.recommendMgtID == item.recommendMgtID);
+        dataList.value.splice(index, 1)
+        addRecommendList.value = [];
+      });
+    };
+
+    const onBatchRecommend = () => {
+      if (dataList.value.length == 0) {
+        presentAlert("没有需要推荐的求职人员!")
+        return;
+      }
+
+      dataList.value.forEach((item: any) => {
+        addRecommendList.value.push({
+          recommendMgtID: item.recommendMgtID,
+          jobHuntID: item.jobhuntID,
+          postID: searchParams.postID,
+          recommendType: 0
+        });
+      })
+      addRecommend(addRecommendList.value).then(() => {
+        loadData();
+        dataList.value = [];
+        addRecommendList.value = [];
+      });
+    };
+
+    const presentAlert = async (message: string) => {
+      const alert = await alertController.create({
+        header: '错误!',
+        message: message,
+        buttons: [
+          '确定'
+        ],
+      });
+
+      await alert.present();
+    }
+
+    const onBack = () => {
+      router.go(-1);
+    }
+
+    const reload = () => {
+      dataList.value = [];
+      searchParams.pageIndex = 1;
+      loadData();
+    }
+    onIonViewDidEnter(() => {
+      reload();
+    });
+
+    return {
+      arrowBackOutline,
+      addCircleOutline,
+      router,
+      route,
+      colors,
+      loading,
+      pagination,
+      searchParams,
+      dataList,
+      onScroll,
+      loadData,
+      reload,
+      onBack,
+      onRecommend,
+      onBatchRecommend,
+    }
+  }
+});
+</script>
+
+<style lang="less">
+.custom {
+  --placeholder-color: gray;
+  --placeholder-font-style: italic;
+  --placeholder-opacity: 1;
+}
+
+.company-list-page {
+  .list-content {
+    margin: 0px 15px !important;
+    background-color: white !important;
+    border-radius: 0 !important;
+
+    ion-item {
+      margin-top: 10px;
+      font-size: 14px;
+      border: 1px solid rgb(242, 242, 245);
+
+      p {
+        font-size: 12px;
+      }
+    }
+  }
+}
+
+.container {
+  display: flex;
+  justify-content: center; /* 水平居中 */
+  align-items: center; /* 垂直居中 */
+}
+
+.footer-ios ion-toolbar:first-of-type{
+  --border-width:0 !important;
+  --background:#ffffff !important;
+}
+
+</style>
+

+ 13 - 7
h5app/src/views/sapp/tabMain.vue

@@ -8,7 +8,7 @@
           <div class="tool-img">
             <img src="@/assets/icon/qzxx.png">
           </div>
-          <div class="tool-title">求职人员<br/>信息收集</div>
+          <div class="tool-title">求职人员信息收集</div>
         </a>
         <a class="tool-item box-line"  @click="router.push({path:'/tabs/tabMain/company/list',query:{reload:1}})">
           <div class="tool-img">
@@ -16,17 +16,17 @@
           </div>
           <div class="tool-title">企业信息<br/>收集</div>
         </a>
-        <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/post/recommend')">
+        <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/post/list')">
           <div class="tool-img">
-            <img src="@/assets/icon/gwtj.png">
+            <img src="@/assets/icon/gwxxgl.png">
           </div>
-          <div class="tool-title">岗位推荐</div>
+          <div class="tool-title">岗位信息管理</div>
         </a>
-        <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/work/log/list')">
+        <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/post/recommend')">
           <div class="tool-img">
-            <img src="@/assets/icon/gzrz.png">
+            <img src="@/assets/icon/gwtj.png">
           </div>
-          <div class="tool-title">工作日志</div>
+          <div class="tool-title">岗位推荐</div>
         </a>
         <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/work/task/list')">
           <div class="tool-img">
@@ -46,6 +46,12 @@
           </div>
           <div class="tool-title">表单样式</div>
         </a>
+        <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/work/log/list')">
+          <div class="tool-img">
+            <img src="@/assets/icon/gzrz.png">
+          </div>
+          <div class="tool-title">工作日志</div>
+        </a>
       </div>
       <div class="panel">
         <div class="panel_title">

+ 6 - 0
h5app/src/views/sapp/tabWork.vue

@@ -90,6 +90,12 @@
                </div>
                <div class="tool-title">企业信息<br/>收集</div>
              </a>
+             <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/post/list')">
+               <div class="tool-img">
+                 <img src="@/assets/icon/gwxxgl.png">
+               </div>
+               <div class="tool-title">岗位信息管理</div>
+             </a>
              <a class="tool-item box-line"  @click="router.push('/tabs/tabMain/post/recommend')">
                <div class="tool-img">
                  <img src="@/assets/icon/gwtj.png">

+ 4 - 4
src/main/java/com/hz/employmentsite/controller/companyService/PostController.java

@@ -35,7 +35,7 @@ public class PostController {
     @GetMapping("/getList")
     public BaseResponse getList(@RequestParam("pageIndex") int pageIndex, @RequestParam("pageSize") int pageSize,
                                 @RequestParam(required = false) List<String> postIDList,
-                                @RequestParam(required = false) String postName,
+                                @RequestParam(required = false) String professionName,
                                 @RequestParam(required = false) Integer minCount,
                                 @RequestParam(required = false) Integer maxCount,
                                 @RequestParam(required = false) String companyName,
@@ -44,7 +44,7 @@ public class PostController {
                                 @RequestParam(required = false) String companyID
                                 ) {
 
-        PageInfo<PostVo> result = postService.getList(pageIndex, pageSize, postIDList, postName, minCount, maxCount, companyName, recordStatus, workName,companyID);
+        PageInfo<PostVo> result = postService.getList(pageIndex, pageSize, postIDList, professionName, minCount, maxCount, companyName, recordStatus, workName,companyID);
         return RespGenerstor.success(result);
     }
 
@@ -114,13 +114,13 @@ public class PostController {
     public BaseResponse export(HttpServletResponse response, @RequestParam(required = false) Boolean isExport,
                                @RequestParam("pageIndex") int pageIndex, @RequestParam("pageSize") int pageSize,
                                @RequestParam(required = false) List<String> postIDList,
-                               @RequestParam(required = false) String postName,
+                               @RequestParam(required = false) String professionName,
                                @RequestParam(required = false) Integer minCount,
                                @RequestParam(required = false) Integer maxCount,
                                @RequestParam(required = false) String companyName,
                                @RequestParam(required = false) String recordStatus,
                                @RequestParam(required = false) String workName) throws Exception {
-        PageInfo<PostVo> result = postService.getList(pageIndex, pageSize, postIDList, postName, minCount, maxCount, companyName, recordStatus, workName,null);
+        PageInfo<PostVo> result = postService.getList(pageIndex, pageSize, postIDList, professionName, minCount, maxCount, companyName, recordStatus, workName,null);
 
         if (isExport == null || !isExport) {
             return RespGenerstor.success(result);

+ 1 - 1
src/main/java/com/hz/employmentsite/mapper/cquery/PostCQuery.java

@@ -7,7 +7,7 @@ import org.apache.ibatis.annotations.Param;
 import java.util.List;
 
 public interface PostCQuery {
-    List<PostVo> selectPostList(@Param("postIDList")String postIDList,@Param("postName") String postName, @Param("minCount")Integer minCount, @Param("maxCount")Integer maxCount,
+    List<PostVo> selectPostList(@Param("postIDList")String postIDList,@Param("professionName") String professionName, @Param("minCount")Integer minCount, @Param("maxCount")Integer maxCount,
                                 @Param("companyName")String companyName, @Param("RecordStatus") String RecordStatus, @Param("WorkName")String WorkName,@Param("companyID")String companyID);
 
     List<RecommendPostVo> selectRecommendPostList(@Param("jobUserID") String jobUserID);

+ 2 - 2
src/main/java/com/hz/employmentsite/services/impl/companyService/PostServiceImpl.java

@@ -45,9 +45,9 @@ public class PostServiceImpl implements PostService {
     private DictionaryService dictionaryService;
 
     @Override
-    public PageInfo<PostVo> getList(Integer page, Integer rows, List<String> postIDList, String postName, Integer minCount, Integer maxCount, String companyName, String recordStatus, String WorkName,String companyID) {
+    public PageInfo<PostVo> getList(Integer page, Integer rows, List<String> postIDList, String professionName, Integer minCount, Integer maxCount, String companyName, String recordStatus, String WorkName,String companyID) {
         PageHelper.startPage(page, rows);
-        List<PostVo> list = postCQuery.selectPostList(stringUtils.ListToInSql(postIDList), postName, minCount, maxCount, companyName, recordStatus, WorkName,companyID);
+        List<PostVo> list = postCQuery.selectPostList(stringUtils.ListToInSql(postIDList), professionName, minCount, maxCount, companyName, recordStatus, WorkName,companyID);
         PageInfo<PostVo> result = new PageInfo(list);
         return result;
 

+ 1 - 1
src/main/java/com/hz/employmentsite/services/service/companyService/PostService.java

@@ -6,7 +6,7 @@ import com.hz.employmentsite.vo.companyService.PostVo;
 import java.util.List;
 
 public interface PostService {
-    PageInfo<PostVo> getList(Integer page, Integer rows, List<String> postIDList,String postName, Integer minCount, Integer maxCount, String companyName,String RecordStatus,String WorkName,String companyID);
+    PageInfo<PostVo> getList(Integer page, Integer rows, List<String> postIDList,String professionName, Integer minCount, Integer maxCount, String companyName,String RecordStatus,String WorkName,String companyID);
     PageInfo<RecommendPostVo> getCommendPostList(Integer page, Integer rows, String jobUserID);
     Integer saveCommendPost(RecommendPostVo data, String userId);
     int save(PostVo data, String userId);

+ 1 - 0
src/main/java/com/hz/employmentsite/vo/jobUserManager/RecommendCompanyPostVo.java

@@ -10,4 +10,5 @@ public class RecommendCompanyPostVo {
     public String endTime;
     public String isRecommend;
     public String companyAddress;
+    public String professionID;
 }

+ 2 - 0
src/main/java/com/hz/employmentsite/vo/jobUserManager/RecommendJobVo.java

@@ -9,4 +9,6 @@ public class RecommendJobVo {
     public String culturerankName;
     public String keypersontypeName;
     public String isRecommend;
+    public String professionID;
+    public String professionName;
 }

+ 44 - 32
src/main/resources/mapping/cquery/PostCQuery.xml

@@ -2,10 +2,12 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="com.hz.employmentsite.mapper.cquery.PostCQuery">
     <select id="selectPostList" resultType="com.hz.employmentsite.vo.companyService.PostVo">
-        select post.postID,post.workCode,post.workName,post.recruitCount,post.companyID,post.postName,post.recordStatus,post.workNature,post.validDay,
+        select
+        post.postID,post.workCode,post.workName,post.recruitCount,post.companyID,post.postName,post.recordStatus,post.workNature,post.validDay,
         post.workYear,post.cultureRank,post.postDesc,post.maxSalary,post.minSalary,post.welfare,post.postEmail,post.workTime,post.isTrail,post.trailMonths,
         post.TrailMaxSalary,post.trailMinSalary,post.createUserID,post.createTime,post.modifyUserID,post.modifyTime,post.validTime,post.startTime,post.endTime,
-        post.jobPlace,company.userName,company.userMobile,company.companyEmail,company.CompanyName,company.insuredCount,item.`Name` as cultureLevelName,
+        post.jobPlace,company.userName,company.userMobile,company.companyEmail,company.CompanyName,company.insuredCount,item.`Name`
+        as cultureLevelName,
         post.ProfessionID,pro.ProfessionName
         , IFNULL(count(rmgt.RecommendMgtID),0) as recommendNum
         from pc_post post
@@ -13,31 +15,34 @@
         left join sys_dictionary_item item on item.value=post.CultureRank and item.DictionaryCode='CultureLevel'
         left join pc_profession pro on post.ProfessionID = pro.ProfessionID
         left join pc_recommend_mgt rmgt on post.PostID = rmgt.PostID
-        <if test="postIDList != '' and postIDList != null">
-            and post.postID in (${postIDList})
-        </if>
-        <if test="postName != '' and postName != null">
-            and post.postName like Concat('%',#{postName},'%')
-        </if>
-        <if test="minCount != null and minCount != ''">
-            and post.RecruitCount <![CDATA[ >= ]]> #{minCount}
-        </if>
-        <if test="maxCount != null and maxCount != ''">
-            and post.RecruitCount <![CDATA[ <= ]]> #{maxCount}
-        </if>
-        <if test="companyName != null and companyName != ''">
-            and company.CompanyName like Concat('%',#{companyName},'%')
-        </if>
-        <if test="RecordStatus != null and RecordStatus != ''">
-            and pro.RecordStatus = #{RecordStatus}
-        </if>
-        <if test="WorkName != null and WorkName != ''">
-            and post.WorkName like Concat('%', #{WorkName},'%')
-        </if>
-        <if test="companyID != null and companyID != ''">
-            and post.CompanyID = #{companyID}
-        </if>
-        group by post.postID,post.workCode,post.workName,post.recruitCount,post.companyID,post.postName,post.recordStatus,post.workNature,post.validDay,
+        <where>
+            <if test="postIDList != '' and postIDList != null">
+                and post.postID in (${postIDList})
+            </if>
+            <if test="professionName != '' and professionName != null">
+                and pro.ProfessionName like Concat('%',#{professionName},'%')
+            </if>
+            <if test="minCount != null and minCount != ''">
+                and post.RecruitCount <![CDATA[ >= ]]> #{minCount}
+            </if>
+            <if test="maxCount != null and maxCount != ''">
+                and post.RecruitCount <![CDATA[ <= ]]> #{maxCount}
+            </if>
+            <if test="companyName != null and companyName != ''">
+                and company.CompanyName like Concat('%',#{companyName},'%')
+            </if>
+            <if test="RecordStatus != null and RecordStatus != ''">
+                and pro.RecordStatus = #{RecordStatus}
+            </if>
+            <if test="WorkName != null and WorkName != ''">
+                and post.WorkName like Concat('%', #{WorkName},'%')
+            </if>
+            <if test="companyID != null and companyID != ''">
+                and post.CompanyID = #{companyID}
+            </if>
+        </where>
+        group by
+        post.postID,post.workCode,post.workName,post.recruitCount,post.companyID,post.postName,post.recordStatus,post.workNature,post.validDay,
         post.workYear,post.cultureRank,post.postDesc,post.maxSalary,post.minSalary,post.welfare,post.postEmail,post.workTime,post.isTrail,post.trailMonths,
         post.TrailMaxSalary,post.trailMinSalary,post.createUserID,post.createTime,post.modifyUserID,post.modifyTime,post.validTime,post.startTime,post.endTime,
         post.jobPlace,company.userName,company.userMobile,company.companyEmail,company.CompanyName,company.insuredCount,item.`Name`,
@@ -45,11 +50,18 @@
         order by post.CreateTime desc
     </select>
     <select id="selectRecommendPostList" resultType="com.hz.employmentsite.vo.companyService.RecommendPostVo">
-        select post.*,recommend.recommendID,jobhunt.JobUserID,recommend.isRead,recommend.isSendNotes,company.CompanyName,company.InsuredCount  from
-            (select * from pc_post where PostID in (select PostID from pc_jobhunt where JobUserID= #{jobUserID})) post
-                left join pc_company company on post.CompanyID = company.CompanyID
-                left join (select * from pc_recommend where JobUserID= #{jobUserID}) recommend on post.PostID = recommend.PostID
-                left join pc_jobhunt jobhunt on post.PostID = jobhunt.PostID
+        select post.*,
+               recommend.recommendID,
+               jobhunt.JobUserID,
+               recommend.isRead,
+               recommend.isSendNotes,
+               company.CompanyName,
+               company.InsuredCount
+        from (select * from pc_post where PostID in (select PostID from pc_jobhunt where JobUserID = #{jobUserID})) post
+                 left join pc_company company on post.CompanyID = company.CompanyID
+                 left join (select * from pc_recommend where JobUserID = #{jobUserID}) recommend
+                           on post.PostID = recommend.PostID
+                 left join pc_jobhunt jobhunt on post.PostID = jobhunt.PostID
         where jobhunt.JobUserID = #{jobUserID}
         order by post.CreateTime desc
     </select>

+ 2 - 2
src/main/resources/mapping/cquery/RecommendMgtCQuery.xml

@@ -44,7 +44,7 @@
 <!--    推荐岗位信息-->
     <select id="getRecommendCompanyPostList" resultType="com.hz.employmentsite.vo.jobUserManager.RecommendCompanyPostVo">
         select a.postid,b.companyname,c.professionname,a.recruitcount,a.starttime,a.endtime,b.companyAddress,
-        case when d.recommendmgtid is null then '未推荐' else '已推荐' end as isRecommend,d.recommendMgtID
+        case when d.recommendmgtid is null then '未推荐' else '已推荐' end as isRecommend,d.recommendMgtID,a.professionid,c.professionname
         from pc_post a
         left join pc_company b on a.CompanyID = b.CompanyID
         left join pc_profession c on a.ProfessionID = c.ProfessionID
@@ -68,7 +68,7 @@
 <!--    推荐求职人员信息-->
     <select id="getRecommendJobList" resultType="com.hz.employmentsite.vo.jobUserManager.RecommendJobVo">
         select a.jobhuntid,b.username,b.usermobile,e.sitename,dic1.`name` as culturerankname,dic2.`name` as keypersontypename,
-        case when d.recommendmgtid is null then '未推荐' else '已推荐' end as isrecommend,d.recommendMgtID
+        case when d.recommendmgtid is null then '未推荐' else '已推荐' end as isrecommend,d.recommendMgtID,a.professionid,c.professionname
         from pc_jobhunt a
         left join pc_jobuser b on a.JobUserID = b.JobUserID
         left join pc_profession c on a.ProfessionID = c.ProfessionID

+ 4 - 3
vue/src/views/companyService/post/index.vue

@@ -3,8 +3,8 @@
     <a-form ref="formRef" name="advanced_search" class="ant-advanced-search-form" :model="searchParams">
       <a-row :gutter="24">
         <a-col :span="6">
-          <a-form-item label="岗位名称" :label-col="{span:6}" name="postName">
-            <a-input v-model:value="searchParams.postName" placeholder="" :allow-clear="true"/>
+          <a-form-item label="岗位名称" :label-col="{span:6}" name="professionName">
+            <a-input v-model:value="searchParams.professionName" placeholder="" :allow-clear="true"/>
           </a-form-item>
         </a-col>
         <a-col :span="6">
@@ -140,6 +140,7 @@ export default defineComponent({
       minCount: null,
       maxCount: null,
       workName: null,
+      professionName: null,
       recordStatus: null
     });
     const expand = ref(false);
@@ -151,7 +152,7 @@ export default defineComponent({
       url: 'companyService/post/importPost',
       columns: [
         {cnName: '企业名称', enName: 'companyName', width: 100},
-        {cnName: '岗位名称', enName: 'postName', width: 100},
+        {cnName: '岗位名称', enName: 'professionName', width: 100},
         {cnName: '招聘人数', enName: 'recruitCount', width: 100},
         {cnName: '开始日期', enName: 'startTime', width: 100},
         {cnName: '结束日期', enName: 'endTime', width: 100},

+ 0 - 1
vue/src/views/companyService/post/recommend.vue

@@ -209,7 +209,6 @@ export default defineComponent({
       searchParams.companyName = companyName;
       searchParams.professionID = professionID;
       searchParams.professionName = professionName;
-      searchParams.professionName = professionName;
       searchParams.type = type;
       loadData();
     }