Quellcode durchsuchen

完成新版职业库

shilipojs vor 3 Jahren
Ursprung
Commit
41f01fc4b6

+ 38 - 0
src/api/webApi/vocation.js

@@ -18,6 +18,44 @@ export function getAllVocation(params){
     params
   })
 }
+
+
+// 职业概况
+export function vocationalOverview(params){
+  return request({
+    url:`front/vocational/getVocationalOverview`,
+    method:'get',
+    params
+  })
+}
+
+/**
+ * 获取就业岗位
+ * @param params
+ */
+export function vocationalPosts(params){
+  return request({
+    url:`front/vocational/getVocationalPosts`,
+    method:'get',
+    params
+  })
+}
+
+
+
+
+/**
+ * 获取职业就业详情
+ * @param params
+ */
+export function vocationalPostsDetail(params){
+  return request({
+    url:`/front/vocational/getVocationalPostDetailByPostName`,
+    method:'get',
+    params
+  })
+}
+
 /**
  * 获取职业详情
  * @param params

+ 6 - 1
src/assets/styles/common.scss

@@ -645,7 +645,9 @@
 .f24 {
   font-size: 24px;
 }
-
+.f28 {
+  font-size: 28px;
+}
 .f-red {
   color: #dd524d;
 }
@@ -704,3 +706,6 @@
 .pointer {
   cursor: pointer;
 }
+.pd20{
+  padding: 20px ;
+}

+ 1 - 1
src/router/index.js

@@ -726,7 +726,7 @@ export const constantRoutes = [{
       },
       {
         path: '/career/vocation/Detail',
-        component: (resolve) => require(['@/views/career/vocation/old-detail'], resolve),
+        component: (resolve) => require(['@/views/career/vocation/new-detail'], resolve),
         name: 'jobDetail',
         meta: {
           title: '职业-详情'

+ 333 - 76
src/views/career/vocation/new-detail.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="jobDetail" ref="jobDetail" style="padding:24px 8%;background-color:#f7f7f7;" v-loading="loading">
+  <div id="jobDetail" style="padding:24px 12%" >
     <el-card style="color: #5E5E5E;" ref="navBar">
       <el-breadcrumb separator-class="el-icon-arrow-right">
         <el-breadcrumb-item :to="{ path: '/index' }">首页</el-breadcrumb-item>
@@ -7,124 +7,381 @@
         <el-breadcrumb-item>职业详情</el-breadcrumb-item>
       </el-breadcrumb>
     </el-card>
-    <div  style="background-color: #F0F3FC;margin-top:10px;" class="header">
-      <div class="left" :style="{'backgroundColor':theme,'text-align':'center'}">
-        <div>
-          <h1 style="margin: 0;font-size: 40px;color:#525252;">{{jobDetails.name}}</h1>
+    <div class="mt20 header-content pd20">
+      <p class="f28 f-333">{{vocationDetail.name ||  ''}}</p>
+    </div>
+    <div class="tabs-wrap">
+      <span class="tabs-item" @click="tabActive = 0" :class="{'bg-primary':tabActive == 0}">职业概况</span>
+      <span class="tabs-item" @click="tabActive = 1":class="{'bg-primary':tabActive == 1}">就业岗位</span>
+    </div>
+    <p class="line"></p>
+    <div
+      v-show="loading"
+      class="loading-div"
+      v-loading="loading"
+      :style="{height:windowHeight + 'px'}">
+    </div>
+
+    <div class="content-wrap mt20" >
+      <!-- 职业概况  -->
+      <div v-if="Object.keys(vocationDetail).length > 0">
+        <div v-show="tabActive == 0">
+          <div class="desc-item">
+            <p class="format-tit">职业介绍</p>
+            <div class="text-666" v-html="vocationDetail.description"></div>
+          </div>
+          <div class="desc-item">
+            <p class="format-tit">就业岗位<span class="text-666 f14">({{vocationDetail.postJobs.length || 0}}个)</span></p>
+            <div class="post-item mb20" v-for="post in vocationDetail.postJobs">
+              <div class="post-title f16 mb10" style="cursor: pointer">{{post.name}}</div>
+              <div class="pb10 text-666 post-text">
+                <div>{{`${post.salaryMin}元-${post.salaryMax}元/月`}}</div>
+                <div>热门地区:{{post.hotCity}}</div>
+              </div>
+            </div>
+          </div>
+          <div class="desc-item">
+            <p class="format-tit">相关专业<span class="text-666 f14">({{vocationDetail.postMajors.length}}个)</span></p>
+            <div class="post-item mb20" v-for="post in vocationDetail.postMajors">
+              <div class="post-title f16 mb10" style="cursor: pointer">{{post.name}}</div>
+              <div class="pb10 text-666 post-text">
+                <div>国标代码:{{post.code}}</div>
+                <div>学制:{{post.learnYear}}</div>
+                <div>男女比例:{{`${post.maleRatio}/${post.femaleRatio}`}}</div>
+              </div>
+            </div>
+          </div>
         </div>
       </div>
-      <div class="right" style="padding:30px;">
-        <div v-html="jobDetails.zysm" class="headerText"></div>
-      </div>
-    </div>
-    <div style="margin-top: 20px;background-color: #ffffff" v-for="(item,index) in contentArr">
-      <div style="display: flex;justify-content: space-between;padding:30px 10px 0 10px;">
-        <span :style="{'color':theme}" style="background-color:#F0F3FC;font-size:16px;font-weight:bold;padding:12px 100px 10px 50px;display:inline-block;clip-path: polygon(0 0, 80% 0, 100% 100%, 0 100%);">{{getDeatailCon(index,'title')}}</span>
-        <span :style="{'color':theme}" style="font-size:36px;color:#FCE1B0;">{{getDeatailCon(index,'title02')}}</span>
+
+      <!--  就业岗位-->
+      <div v-if="vocationalPosts.length > 0">
+        <div v-show="tabActive == 1">
+          <el-row :gutter="20" type="flex" class="jobTabs">
+            <el-col class="job-item-wrap" :span="4" v-for="item in vocationalPosts" :key="item.name">
+              <div class="job-item f14 f-333" :class="{'bg-primary':jobActiveName == item.name}" @click="toActiveJob(item.name)">
+                <p class="mb10">{{item.name}}</p>
+                <p>{{`${item.salaryMin}-${item.salaryMax}`}}{{item.salaryUnit}}</p>
+              </div>
+            </el-col>
+          </el-row>
+          <!--  岗位详情  -->
+          <div v-if="Object.keys(jobDetail).length > 0">
+            <!-- 图表 -->
+            <div class="desc-item">
+              <p class="format-tit">薪资情况</p>
+              <el-row :gutter="10">
+               <el-col :span="12">
+                 <p class="text-right f-333">按趋势</p>
+                 <mx-chart :options="chartExperience" height="300px"></mx-chart>
+               </el-col>
+                <el-col :span="12">
+                  <p class="text-right f-333">按分布</p>
+                  <mx-chart :options="chartSalary" height="300px"></mx-chart>
+                </el-col>
+              </el-row>
+            </div>
+            <div class="desc-item">
+              <p class="format-tit">就业形势</p>
+            </div>
+            <div class="desc-item">
+              <p class="format-tit">招聘需求量</p>
+              <el-row :gutter="40" type="flex" class="flex-wrap">
+                <el-col :span="12" class="f16" v-for="(item,index) in  jobDetail.demand">
+                  <el-row class="format-job-wrap">
+                    <el-col :span="3" class="f18 text-center f-666">{{index + 1}}</el-col>
+                    <el-col :span="15" class="f-333">{{item.city}}</el-col>
+                    <el-col :span="6" class="f-666  text-right f14">{{item.count}}职位</el-col>
+                  </el-row>
+                </el-col>
+              </el-row>
+            </div>
+            <div class="desc-item">
+              <p class="format-tit">收入排行-按行业</p>
+              <el-row :gutter="40" type="flex" class="flex-wrap">
+                <el-col :span="12" class="f16" v-for="(item,index) in  jobDetail.industrySalary">
+                  <el-row class="format-job-wrap">
+                    <el-col :span="3" class="f18 text-center f-666">{{index + 1}}</el-col>
+                    <el-col :span="15" class="f-333">{{item.name}}</el-col>
+                    <el-col :span="6" class="f-666 text-right f14">{{item.salary}}元 / 月</el-col>
+                  </el-row>
+                </el-col>
+              </el-row>
+            </div>
+            <div class="desc-item">
+              <p class="format-tit">收入排行-按地区</p>
+              <el-row :gutter="40" type="flex" class="flex-wrap">
+                <el-col :span="12" class="f16" v-for="(item,index) in  jobDetail.citySalary">
+                  <el-row class="format-job-wrap">
+                    <el-col :span="3" class="f18 text-center f-666">{{index + 1}}</el-col>
+                    <el-col :span="15" class="f-333">{{item.city}}</el-col>
+                    <el-col :span="6" class="f-666 text-right f14">{{item.salary}}元 / 月</el-col>
+                  </el-row>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+        </div>
       </div>
-      <div style="padding:30px" v-html="getDeatailCon(index,item)"></div>
+
     </div>
   </div>
 </template>
 <script>
-import {mapState} from 'vuex';
-import {getJobDetail} from '@/api/webApi/vocation'
+import MxChart from '@/components/MxChart/index'
+import { vocationalPostsDetail, vocationalOverview, vocationalPosts } from '@/api/webApi/vocation'
 export default {
   name: "Detail",
+  components: {
+    MxChart
+  },
   data(){
     return {
       loading:false,
-      jobId:'',
-      jobDetails:{},
-      contentArr:['zydy','rwzz','zsbj','zyjn','cyzg','cygj','fzqj'],
-      title1:['职业定义','任务职责','知识背景','职业技能','从业资格','常用工具','发展前景'],
-      title2:['PROFESSIONAL DETAILS','COLLEGES AND UNIVERSITIES','CHARACTERISTICS','CHARACTERISTICS','CHARACTERISTICS','CHARACTERISTICS']
+      code:'',
+      tabActive: 0,
+      vocationalPosts: [],  // 就业岗位
+      vocationDetail:{},  // 职业概况
+      jobActiveName: '',  // 激活状态的岗位
+      jobDetail: {},  // 岗位详情
+      windowHeight:document.documentElement.clientHeight,
     }
   },
   computed:{
-    ...mapState({theme: state => state.settings.theme}),
-    getDeatailCon(){
-      return function (id,type){
-        if(type==='title'){
-          return this.title1[id]
-        }
-        if(type==='title02'){
-          return this.title2[id]
-        }
-        const flag=this.contentArr.some(item=>{
-          return item===type
-        })
-        if(flag){
-          return this.jobDetails[type]
+    // 按工资分布
+    chartSalary() {
+      if (!this.jobDetail.salary.length) return null
+      const pieData = this.jobDetail.salary.map(item => {
+        return {
+          value: item.ratio,
+          name: `${item.min}-${item.max}元/月 ${item.ratio}`,
         }
+      })
+      const options  = {
+          toolbox: {
+            show: true,
+          },
+        series: [
+          {
+            name: 'Nightingale Chart',
+            type: 'pie',
+            radius: [70, 100],
+            label:{
+              formatter: '{b}'
+            },
+            data: pieData
+          }
+        ]
       }
+      return options
+    },
+    // 按经验趋势
+    chartExperience() {
+      if (!this.jobDetail.experience.length) return null
+      const col = this.jobDetail.experience.map(item => item.year)
+      const row = this.jobDetail.experience.map(item => item.salary)
+      const options  = {
+        xAxis: {
+          data: col,
+          axisLine: {
+            lineStyle: {
+              type: 'dashed'
+            }
+          },
+          axisTick: {
+            alignWithLabel: true
+          },
+        },
+        yAxis: {
+          type: 'value',
+        },
+        series: [
+          {
+            name: 'Email',
+            type: 'line',
+            color: '#47C6A2',
+            stack: 'Total',
+            label: {
+              show: true,
+              position: 'top',
+            },
+            smooth: false,
+            data: row
+          },
+        ]
+
+      }
+      return options
     }
   },
   watch:{
-    theme:{
-      immediate:true,
-      handler(val){
-        this.$nextTick(()=>{
-          this.$refs.jobDetail.style.setProperty('--themeColor', val)
-        })
+    tabActive: {
+      handler(newVal){
+        // 1 岗位 0 概览
+        if(newVal == 0)  this.getVocationalOverview();
+        if(newVal == 1)  this.getVocationalPosts();
       }
     },
     '$route':{
       immediate:true,
       handler(val){
-        this.jobId=val.query.id;
-        if(val.query.id){
-          this.getJobDetail();
+        this.code=val.query.code;
+        if(val.query.code){
+          console.log(22222222222222222222)
+          this.getVocationalOverview();
         }
       }
     }
   },
   methods:{
-    getJobDetail(){
-      this.loading=true
+    toActiveJob(name) {
+      if(this.jobActiveName == name) return
+      this.jobActiveName = name
+      //  刷新数据
+      this.getVocationalPostsDetail()
+    },
+    //  就业岗位
+    getVocationalPosts() {
+      this.loading = true
+      const params={
+        code:this.code
+      };
+      vocationalPosts(params).then(res => {
+        this.vocationalPosts = res.data
+        if(this.jobActiveName == '') {
+          this.jobActiveName = res.data[0].name
+          this.$nextTick(_ => {
+            this.getVocationalPostsDetail()
+          })
+        }
+      }).finally(_ => {
+        this.loading = false
+      })
+    },
+    // 就业岗位详情
+    getVocationalPostsDetail() {
+      vocationalPostsDetail({postName:this.jobActiveName }).then(res => {
+          console.log(res)
+        this.jobDetail = res.data || {}
+      })
+    },
+    //  职业概况
+    getVocationalOverview(){
+      this.loading = true
       const params={
-        jobId:this.jobId
+        code:this.code
       };
-      getJobDetail(params).then(res=>{
-        this.jobDetails=res.data
-        this.loading=false;
+      vocationalOverview(params).then(res=>{
+         console.log(res)
+        this.vocationDetail = res.data
+      }).finally(_ => {
+        this.loading = false
       })
     }
   }
 }
 </script>
-<style scoped lang="scss">
-#jobDetail{
-  font-family: PingFangSC-Semibold, PingFang SC;
-  .header{
-    .headerText{
-      p{
-        background-color: #1ab394 !important;
+<style lang="scss" scoped>
+#jobDetail {
+  .header-content{
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(66, 185, 131, 0.1);
+  }
+  .tabs-wrap{
+    margin-top: 20px;
+    height: 40px;
+    .tabs-item{
+      cursor: pointer;
+      padding: 0 33px;
+      border-radius: 4px 4px 0 0;
+      display: inline-block;
+      line-height: 40px;
+      &:hover{
+        color:#47C6A2;
+      }
+      &.bg-primary{
+        background: #47C6A2 ;
+        color: white;
       }
     }
   }
-}
-</style>
-<style lang="scss">
-#jobDetail {
-  .header {
-    .left{
-      display: table-cell;
-      width:25%;
-      vertical-align: middle;
-    }
-    .right{
-      display: table-cell;
-    }
-    .headerText {
-      p {
-        span{
-          background-color: transparent !important;
-        }
-        background-color: transparent !important;
+  .bg-primary{
+    background: #47C6A2 !important;
+    color: white;
+  }
+  .format-job-wrap {
+    display: flex;
+    height: 44px;
+    line-height: 44px;
+    border-bottom: 1px solid #f2f2f2;
+  }
+  .line{
+    background:  #47C6A2;
+    height: 1px;
+  }
+  .post-text{
+    display: flex;
+    div{
+      min-width: 160px;
+      &:not(:first-child):before{
+        content: "";
+        display: inline-block;
+        width: 1px;
+        height: 12px;
+        background-color: #ccc;
+        vertical-align: text-top;
+        margin-right: 60px;
+        margin-top: 4px;
       }
     }
+  }
+  .loading-div {
+    width: 100%;
+    position: absolute;
+    background: transparent;
+    left: 0;
+  }
+
+  .post-title{
+    color: #333;
+  }
+
+  .post-item{
+    border-bottom: 1px solid #f2f2f2;
+    color: #333;
+  }
+  .format-tit{
+    border-left: 4px solid #47C6A2;
+    padding-left: 10px;
+    margin-bottom: 20px;
+    font-size: 20px;
+  }
+  .desc-item{
+    margin-bottom: 40px;
+  }
+  .text-666{
+    font-size: 14px;
+    color: #666666 !important;
+  }
 
+  .flex-wrap{
+    flex-wrap: wrap;
+  }
+  .jobTabs{
+    flex-wrap: wrap;
+    .job-item-wrap{
+      padding: 10px;
+      margin-bottom: 20px;
+      .job-item{
+        cursor: pointer;
+        border-radius: 4px;
+        padding: 10px;
+        background: #f2f2f2;
+      }
+    }
   }
 }
 </style>

+ 2 - 2
src/views/career/vocation/new-index.vue

@@ -61,8 +61,8 @@ export default {
     this.getAllVocation()
   },
   methods:{
-    goDetail(id){
-      this.$router.push({name:'jobDetail',query:{id:id}})
+    goDetail(code){
+      this.$router.push({name:'jobDetail',query:{code:code}})
     },
     getAllVocation() {
       getAllVocation({