Browse Source

求职意向

Xiao_123 11 months ago
parent
commit
7015c1c2f0

+ 8 - 0
src/api/common/index.js

@@ -65,6 +65,14 @@ export const getPositionTreeClick = async (data) => {
   })
 }
 
+// 获取职位列表
+export const getPositionData = async (params) => {
+  return request.get({
+    url: '/app-api/menduner/system/position/list',
+    params
+  })
+}
+
 // 获取热门职位
 export const getHotPositionList = async (params) => {
   return await request.get({

+ 22 - 0
src/api/resume.js

@@ -102,4 +102,26 @@ export const saveResumePersonSkill = async (data) => {
     url: '/app-api/menduner/system/person/resume/save/person/skill',
     data
   })
+}
+
+// 保存求职意向
+export const saveResumeJobInterested = async (data) => {
+  return await request.post({
+    url: '/app-api/menduner/system/person/resume/save/job/interested',
+    data
+  })
+}
+
+// 删除求职意向
+export const deleteResumeJobInterested = async (id) => {
+  return await request.delete({
+    url: '/app-api/menduner/system/person/resume/remove/job/interested?id=' + id
+  })
+}
+
+// 获取求职意向
+export const getResumeJobInterested = async () => {
+  return await request.get({
+    url: '/app-api/menduner/system/person/resume/get/job/interested'
+  })
 }

+ 249 - 5
src/components/AreaSelect/index.vue

@@ -1,11 +1,255 @@
 <template>
-  <div>xxx</div>
+  <div class="d-flex floatCard" :style="{ 'z-index': 999 }" @mouseleave="handleMouseLeave">
+    <v-card class="card">
+      <div class="leftCard">
+        <div
+          class="leftCardItem" :class="{'leftIndexAct': index === leftIndex}"
+          v-for="(item, index) in items" :key="item.id"
+          @mouseover="handleMouseOver(item, index)"
+        >
+          <div class="rowItem d-flex">
+            <span class="categoryName">{{ item.name }}</span>
+            <span class="mdi mdi-menu-right"></span>
+          </div>
+        </div>
+      </div>
+    </v-card>
+    <v-card v-if="rightObj.show" class="card rightCardBox">
+      <div class="rightCard">
+        <div class="categoryName">{{ rightObj.data.name }}</div>
+        <div v-for="(item, index) in rightObj.data.children" :key="item.id">
+          <v-divider v-if="index" class="divider"></v-divider>
+          <div class="rowItem d-flex">
+            <div class="categoryName2">{{ item.name }}</div>
+            <div class="rightContent">
+              <div v-if="!item.children?.length"></div>
+              <div 
+                v-else 
+                :class="['jobItem', {'active': selectItems.includes(val.id)}]" 
+                v-for="val in item.children" 
+                :key="val.id" 
+                @click="handleAreaClick(val, item.name)"
+              >
+              {{ val.name }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </v-card>
+  </div>
 </template>
 
 <script setup>
-defineOptions({ name: 'formPage'})
-</script>
+import { getDict } from '@/hooks/web/useDictionaries'
+import { reactive, ref, defineEmits } from 'vue';
+defineOptions({ name:'common-components-jobTypeCard'})
+
+const emits = defineEmits(['handleAreaClick'])
+
+const props = defineProps({
+  // 是否单选(首页为单选)
+  isSingle: {
+    type: Boolean,
+    default: false
+  },
+  select: {
+    type: Array,
+    default: () => []
+  }
+})
+const selectItems = ref([])
+// 回显
+if (props.select.length) {
+  selectItems.value = props.select.map(e => {
+    if (typeof e === 'string') e = Number(e)
+    return e
+  })
+}
+
+// 点击
+const handleAreaClick = async (val, preName) => {
+  const obj = selectItems.value.includes(val.id)
+  if (props.isSingle) {
+    selectItems.value = [val.id]
+  } else {
+    if (obj) {
+      selectItems.value = selectItems.value.filter(e => e.id !== val.id)
+    } else selectItems.value.push(val.id)
+  }
+  emits('handleAreaClick', selectItems.value, val.name, preName)
+}
 
-<style scoped lang="scss">
+let items = ref([])
+getDict('areaTreeData', null, 'areaTreeData').then(({ data }) => {
+  data = data?.length && data || []
+  const chinaTreeData = data.filter(e => e.id === 1)
+  if (!chinaTreeData.length) return
+  items.value = chinaTreeData[0].children
+})
+
+// 右侧列表信息
+const leftIndex = ref(null)
+const rightObj = reactive({ show: false, data: {} })
+
+const handleMouseOver = (val, index) => {
+  leftIndex.value = index
+  rightObj.data = val
+  rightObj.show = true
+}
+const handleMouseLeave = () => {
+  rightObj.show = false
+  leftIndex.value = null
+}
+</script>
 
-</style>
+<style lang="scss" scoped>
+.active {
+  color: var(--v-primary-base) !important;
+  font-weight: 700;
+}
+:deep(.v-window) {
+  height: 392px !important;
+}
+.floatCard {
+  .leftIndexAct { color: var(--v-primary-base); }
+  .leftCard {
+    height: 242px;
+    width: 172px;
+    margin: 4px 0;
+    overflow-y: auto;
+    .leftCardItem {
+      height: 36px;
+      line-height: 36px;
+      padding: 0 16px;
+      cursor: pointer;
+      &:hover {
+        color: var(--v-primary-base);
+        background-color: #f8f8f8;
+      }
+      .categoryName { font-size: 14px; font-family: 微软雅黑; }
+    }
+    .rowItem { justify-content: space-between; }
+  }
+  .rightCardBox { margin-left: 4px; }
+  .rightCard {
+    height: 242px;
+    width: 525px;
+    margin: 4px 0;
+    padding: 0 16px;
+    overflow-y: auto;
+    .categoryName { font-size: 16px; line-height: 28px; margin-top: 6px;}
+    .categoryName2 { font-size: 14px; color: #666666; width: 110px; margin-right: 4px;}
+    .jobItem { font-size: 14px; color: #333333; }
+    .rowItem {
+      padding: 8px 0;
+    }
+    .divider {
+      margin-left: 110px;
+    }
+    .rightContent {
+      flex: 1;
+      div {
+        margin: 4px 28px 2px 0;
+        float: left;
+        cursor: pointer;
+        color: #333333;
+        &:hover {
+          color: var(--v-primary-base);
+        }
+      }
+    }
+  }
+}
+.hasPageCard {
+  width: 100%;
+  .card { border-radius: 12px; }
+  .leftIndexAct {
+    height: 48px;
+    margin: 0 4px;
+    border-radius: 12px;
+    // background-color: var(--v-primary-base);
+  }
+  justify-content: center; // 后面的flex会继承
+  .leftCard {
+    height: 384px;
+    width: 380px;
+    margin: 4px 0;
+    overflow-x: hidden;
+    overflow-y: auto;
+    .leftCardItem {
+      height: 42px;
+      line-height: 42px;
+      padding: 0 16px;
+      .title { font-size: 14px; }
+      .mdi-menu-right { font-size: 20px; }
+    }
+    .jobItemsBox {
+      flex: 1;
+      padding:0 8px;
+      .outerCovering {
+        display: flex;
+        flex-wrap: wrap; /* 允许换行 */
+        width: 100%; /* 设置容器宽度 */
+        height: 42px;
+        overflow: hidden;
+        // border: 1px solid red; /* 可视化边界 */
+        .jobItems {
+          font-size: 14px;
+          margin-left: 12px;
+          cursor: pointer;
+          color: #666666;
+          font-family: 微软雅黑; 
+          &:hover {
+            color: var(--v-primary-base);
+            // background-color: #f8f8f8;
+          }
+        }
+      }
+    }
+  }
+  .rightCardBox { flex: 1; margin-left: 12px;}
+  .rightCard {
+    height: 384px;
+    // min-width: 786px;
+    margin: 4px 0;
+    padding: 0 16px;
+    overflow-y: auto;
+    .categoryName { font-size: 16px; line-height: 28px; margin-top: 6px; color: var(--v-primary-base)}
+    .categoryName2 { font-size: 14px; color: #666666; width: 110px; margin-right: 4px;}
+    .jobItem { font-size: 14px; color: #333333; }
+    .rowItem {
+      padding: 8px 0;
+    }
+    .divider {
+      margin-left: 110px;
+    }
+    .rightContent {
+      flex: 1;
+      div {
+        margin: 4px 28px 2px 0;
+        float: left;
+        cursor: pointer;
+        color: #333333;
+        &:hover {
+          color: var(--v-primary-base);
+        }
+      }
+    }
+  }
+}
+// ::v-deep {
+  ::-webkit-scrollbar {
+    width: 4px;
+    height: 10px;
+    // display: none;
+  }
+  ::-webkit-scrollbar-thumb, .temporaryAdd ::-webkit-scrollbar-thumb, .details_edit ::-webkit-scrollbar-thumb {
+    // 滚动条-颜色
+    background: #c3c3c379;
+  }
+  ::-webkit-scrollbar-track, .temporaryAdd ::-webkit-scrollbar-track, .details_edit ::-webkit-scrollbar-track {
+    // 滚动条-底色
+    background: #e5e5e58f;
+  }
+// }
+</style>

+ 46 - 4
src/components/industryTypeCard/index.vue

@@ -1,5 +1,18 @@
 <template>
   <v-card class="card rightCardBox">
+      <div v-if="showSelect" class="pa-3 currentSelect">
+        <span>已选择:</span>
+        <v-chip 
+          class="mr-3" 
+          label
+          size="small"
+          color="primary"
+          closable
+          v-for="k in currentSelect" 
+          :key="k.id"
+          @click:close="handleClick(k)"
+        >{{ k.nameCn }}</v-chip>
+      </div>
       <div class="rightCard">
         <div v-for="item in items" :key="item.id">
           <!-- <v-divider v-if="index" class="divider"></v-divider> -->
@@ -24,14 +37,35 @@
 import { getDict } from '@/hooks/web/useDictionaries'
 import { reactive, ref } from 'vue';
 import { useRoute } from 'vue-router';
+import Snackbar from '@/plugins/snackbar'
 defineOptions({ name:'common-components-industryTypeCard'})
 const emits = defineEmits(['handleClickIndustry'])
+const props = defineProps({
+  select: {
+    type: Array,
+    default: () => []
+  },
+  showSelect: {
+    type: Boolean,
+    default: false
+  },
+  currentData: {
+    type: Array,
+    default: () => []
+  }
+})
 
 const route = useRoute()
 const routeQuery = route?.query
 
 let items = ref()
 let idChecked = reactive([])
+let currentSelect = reactive([])
+
+// 回显
+if (props.currentData.length) currentSelect = props.currentData
+if (props.select.length) idChecked = props.select.map(e => Number(e))
+
 getDict('industryTreeData', null, 'industryTreeData').then(({ data }) => {
   data = data?.length && data || []
   items.value = data
@@ -43,18 +77,26 @@ if (routeQuery && routeQuery.industryIds) {
 // 设置选中ids
 const handleClick = (val) => {
   const findIndex = idChecked?.length ? idChecked.findIndex(j => j === val.id) : -1
-  if (findIndex === -1) {  
-    idChecked.push(val.id) // 添加  
-  } else {  
+  if (findIndex === -1) {
+    if (props.showSelect && currentSelect.length === 3) return Snackbar.warning('最多可选三个行业')
+    currentSelect.push(val)
+    idChecked.push(val.id) // 添加
+  } else {
+    currentSelect.splice(findIndex, 1)
     idChecked.splice(findIndex, 1) // 删除  
   }
-  if (idChecked?.length) emits('handleClickIndustry', idChecked)
+  emits('handleClickIndustry', idChecked, currentSelect)
 }
 </script>
 
 <style lang="scss" scoped>
+.currentSelect {
+  position: sticky;
+  background-color: #f2f4f7;
+}
 .card { border-radius: 12px; }
 .rightCard {
+  position: relative;
   height: 384px;
   width: 786px;
   margin: 4px 0;

+ 9 - 1
src/components/jobTypeCard/index.vue

@@ -83,10 +83,18 @@ const props = defineProps({
   isSingle: {
     type: Boolean,
     default: false
+  },
+  select: {
+    type: Array,
+    default: () => []
   }
 })
 const isPage = props.page
 const selectItems = ref([])
+
+// 回显
+if (props.select.length) selectItems.value = props.select.map(e => Number(e))
+
 const route = useRoute()
 const routeQuery = route?.query
 
@@ -101,7 +109,7 @@ const handleJobClick = async (val) => {
       selectItems.value = selectItems.value.filter(e => e.id !== val.id)
     } else selectItems.value.push(val.id)
   }
-  emits('handleJobClick', selectItems.value)
+  emits('handleJobClick', selectItems.value, selectItems.value.length ? val.nameCn : '')
 }
 
 // 翻页数据

+ 4 - 2
src/hooks/web/useDictionaries.js

@@ -4,7 +4,8 @@ import {
   getIndustryTreeData,
   getAreaListData,
   getPositionTreeData,
-  getAreaTreeData
+  getAreaTreeData,
+  getPositionData
 } from '@/api/common/index'
 // 定义对应的api
 // const DICT_CITY_API = {
@@ -33,7 +34,8 @@ export const getDict = (type, params, apiType = 'dict') => {
         areaTreeData: getAreaTreeData, // 区域tree
         industryTreeData: getIndustryTreeData, // 行业tree
         industryList: getIndustryListData,
-        areaList: getAreaListData
+        areaList: getAreaListData,
+        positionData: getPositionData
       }
       apiFn[apiType](query).then(data => {
         setDict(type, data, Date.now())

+ 74 - 0
src/views/resume/components/dict.js

@@ -0,0 +1,74 @@
+import { reactive } from 'vue'
+import { getDict } from '@/hooks/web/useDictionaries'
+
+const dictObj = reactive({})
+const dictList = [
+  { 
+    type: 'positionData', 
+    apiType: 'positionData', 
+    key: 'positionId', 
+    label: 'position', 
+    value: 'positionTypeData', 
+    itemKey: 'id', 
+    itemText: 'nameCn'
+  },
+  { 
+    type: 'industryList', 
+    apiType: 'industryList', 
+    key: 'industryIdList', 
+    label: 'industry', 
+    isArray: true, 
+    value: 'industryTypeData', 
+    itemKey: 'id', 
+    itemText: 'nameCn' 
+  },
+  { 
+    type: 'menduner_area_type',
+    apiType: 'areaList',
+    key: 'workAreaId',
+    label: 'workArea',
+    value: 'areaTypeData',
+    itemKey: 'id',
+    itemText: 'name'
+  },
+  { 
+    type: 'menduner_job_type',
+    key: 'jobType',
+    label: 'jobTypeName',
+    value: 'jobTypeData',
+    itemKey: 'value',
+    itemText: 'label'
+  }
+]
+
+// 字典
+const getDictList = async () => {
+  dictList.forEach(async (val) => {
+    const { data } = await getDict(val.type, val.params, val.apiType)
+    dictObj[val.value] = data
+  })
+}
+
+const getData = async () => {
+  await getDictList()
+}
+getData()
+
+export const dealJobData = (list) => {
+  let res = {}
+  dictList.forEach(item => {
+    res = list.map(e => {
+      let obj = {}
+      if (item.isArray) {
+        e[item.label] = e[item.key].map(val => {
+          return obj = dictObj[item.value].find(i => i[item.itemKey] === val)
+        })
+      } else {
+        obj = dictObj[item.value].find(k => Number(k[item.itemKey]) === Number(e[item.key]))
+        e[item.label] = obj[item.itemText]
+      }
+      return e
+    })
+  })
+  return res
+}

+ 150 - 65
src/views/resume/components/jobIntention.vue

@@ -5,79 +5,100 @@
       <v-btn v-if="!isAdd" variant="text" color="primary" prepend-icon="mdi-plus-box" @click="isAdd = true">{{ $t('common.add') }}</v-btn>
     </div>
     <div v-if="!isAdd">
-      <div v-if="positionList.length">
+      <div v-if="interestList.length">
         <div
-          :class="['position-item']" 
-          v-for="(k, i) in positionList" 
+          :class="['position-item', 'mx-n2', 'px-2']" 
+          v-for="(k, i) in interestList" 
           :key="i" 
           @mouseenter="k.active = true" 
           @mouseleave="k.active = false"
         >
-          <span>{{ k.name }}</span>
-          <span class="vline"></span>
-          <span>{{k.payFrom}}-{{k.payTo}}k</span>
-          <span class="vline"></span>
-          <span class="grey-text">{{ k.industryIds }}</span>
-          <span class="vline"></span>
-          <span class="grey-text">{{ k.areaName }}</span>
-          <span class="vline"></span>
-          <span class="grey-text">{{ k.jobType }}</span>
-          <span class="float-right" v-if="k.active">
-            <v-btn variant="text" color="primary" prepend-icon="mdi-square-edit-outline">{{ $t('common.edit') }}</v-btn>
-            <v-btn variant="text" color="primary" prepend-icon="mdi-trash-can-outline">{{ $t('common.delete') }}</v-btn>
-          </span>
+          <div class="d-flex">
+            <div>{{ k.position }}</div>
+            <div class="line">|</div>
+            <div>{{k.payFrom}}-{{k.payTo}}</div>
+            <div class="line">|</div>
+            <div class="grey-text text-box">{{ k.industry.map(e => e.nameCn).join('、') }}</div>
+            <div class="line">|</div>
+            <div class="grey-text">{{ k.jobTypeName }}</div>
+            <div class="line">|</div>
+            <div class="grey-text">{{ k.workArea }}</div>
+          </div>
+          <div class="float-right" v-if="k.active">
+            <v-btn variant="text" color="primary" prepend-icon="mdi-square-edit-outline" @click="handleEdit(k)">{{ $t('common.edit') }}</v-btn>
+            <v-btn variant="text" color="primary" prepend-icon="mdi-trash-can-outline" @click="handleDelete(k)">{{ $t('common.delete') }}</v-btn>
+          </div>
         </div>
       </div>
       <div v-else class="resumeNoDataText">请填写您的求职意向...</div>
     </div>
     <div v-if="isAdd" class="mt-2">
-      <CtForm :items="items" style="width: 100%;">
+      <CtForm ref="formPageRef" :items="items" style="width: 100%;">
+        <!-- 期望岗位 -->
         <template #positionId="{ item }">
           <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
             <template v-slot:activator="{  props }">
               <textUI
                 :modelValue="item.value"
                 :item="item"
-                @blur="item.blur"
                 v-bind="props"
                 style="position: relative;"
               ></textUI>
             </template>
-            <jobTypeCard class="jobTypeCardBox" :isCustomer="true" @handleJobClick="handleJobClickItem"></jobTypeCard>
+            <jobTypeCard class="jobTypeCardBox" :select="[query.positionId].filter(Boolean)" :isSingle="true" @handleJobClick="handleJobClickItem"></jobTypeCard>
           </v-menu>
         </template>
+        <!-- 期望行业 -->
         <template #industryIdList="{ item }">
           <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs" :close-on-content-click="false">
             <template v-slot:activator="{  props }">
               <textUI
                 v-model="item.value"
                 :item="item"
-                @blur="item.blur"
+                v-bind="props"
+              ></textUI>
+            </template>
+            <industryTypeCard :select="query.industryIdList" :currentData="currentSelect" showSelect @handleClickIndustry="handleIndustry"></industryTypeCard>
+          </v-menu>
+        </template>
+        <template #workAreaId="{ item }">
+          <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
+            <template v-slot:activator="{  props }">
+              <textUI
+                v-model="item.value"
+                :item="item"
                 v-bind="props"
                 style="position: relative;"
               ></textUI>
             </template>
-            <industryTypeCard @inputChange="handleIndustry"></industryTypeCard>
+            <areaType :select="[query.workAreaId].filter(Boolean)" @handleAreaClick="handleArea" class="jobTypeCardBox" isSingle></areaType>
           </v-menu>
         </template>
       </CtForm>
       <div class="text-end">
-        <v-btn class="half-button mr-3" variant="tonal" @click="isAdd = false">{{ $t('common.cancel') }}</v-btn>
-        <v-btn color="primary" class="half-button">{{ $t('common.save') }}</v-btn>
+        <v-btn class="half-button mr-3" variant="tonal" @click="isAdd = false; resetForm()">{{ $t('common.cancel') }}</v-btn>
+        <v-btn color="primary" class="half-button" @click="handleSave">{{ $t('common.save') }}</v-btn>
       </div>
     </div>
   </div>
 </template>
 
 <script setup name="jobIntention">
-import { ref } from 'vue'
+import { ref, reactive } from 'vue'
 import CtForm from '@/components/CtForm'
 import textUI from '@/components/FormUI/TextInput'
 import jobTypeCard from '@/components/jobTypeCard'
 import industryTypeCard from '@/components/industryTypeCard'
+import areaType from '@/components/AreaSelect'
+import Snackbar from '@/plugins/snackbar'
+import Confirm from '@/plugins/confirm'
+import { saveResumeJobInterested, getResumeJobInterested, deleteResumeJobInterested } from '@/api/resume'
+import { dealJobData } from './dict'
 
 const isAdd = ref(false)
-
+const formPageRef = ref()
+const editId = ref(null)
+let query = reactive({})
 const items = ref({
   options: [
     {
@@ -87,6 +108,7 @@ const items = ref({
       col: 6,
       label: '期望岗位 *',
       flexStyle: 'mr-3',
+      valueKey: 'position', 
       hideDetails: true,
       outlined: true,
       rules: [v => !!v || '请选择期望岗位']
@@ -104,7 +126,7 @@ const items = ref({
       type: 'number',
       key: 'payFrom',
       value: null,
-      placeholder: '期望薪资(最低要求) *',
+      label: '期望薪资(最低要求) *',
       col: 6,
       flexStyle: 'mr-3',
       outlined: true,
@@ -114,85 +136,138 @@ const items = ref({
       type: 'number',
       key: 'payTo',
       value: null,
-      placeholder: '期望薪资(最高要求) *',
+      label: '期望薪资(最高要求) *',
       col: 6,
       outlined: true,
       rules: [v => !!v || '请输入薪资最高要求']
     },
     {
-      type: 'autocomplete',
+      slotName: 'workAreaId',
       key: 'workAreaId',
       value: null,
-      placeholder: '请选择工作城市 *',
-      outlined: true,
-      itemText: 'label',
+      label: '工作城市 *',
+      valueKey: 'workArea',
       col: 6,
-      itemValue: 'value',
       flexStyle: 'mr-3',
-      rules: [v => !!v || '请选择工作城市'],
-      items: []
+      rules: [v => !!v || '请选择工作城市']
     },
     {
       type: 'autocomplete',
       key: 'jobType',
       value: null,
-      placeholder: '请选择求职类型 *',
+      label: '求职类型 *',
       outlined: true,
       itemText: 'label',
       col: 6,
       itemValue: 'value',
       rules: [v => !!v || '请选择求职类型'],
       items: [
-        { label: '全职', value: 0 },
-        { label: '兼职', value: 1 },
-        { label: '临时', value: 2 },
-        { label: '实习', value: 3 }
+        { label: '全职', value: '0' },
+        { label: '兼职', value: '1' },
+        { label: '临时', value: '2' },
+        { label: '实习', value: '3' }
       ]
     }
   ]
 })
 
+// 获取求职意向
+const interestList = ref([])
+const getJobInterested = async () => {
+  const data = await getResumeJobInterested()
+  interestList.value = data
+  interestList.value = dealJobData(data)
+}
+getJobInterested()
+
+const setValue = (key, value) => {
+  items.value.options.find(e => e.key === key).value = value
+}
+
 // 期望职位
-const handleJobClickItem = (val) => {
-  items.value.options.find(e => e.key === 'positionId').value = val[0].nameCn
+const handleJobClickItem = (list, name) => {
+  if (!list.length) return
+  query.positionId = list[0]
+  setValue('positionId', name)
 }
 
-const handleIndustry = (list) => {
-  console.log(list, 'industry')
+// 行业类型
+let currentSelect = reactive([])
+const handleIndustry = (list, arr) => {
+  if (!list.length) return setValue('industryIdList', '不限')
+  query.industryIdList = list
+  currentSelect = arr
+  const str = arr.map(e => e.nameCn).join('、')
+  setValue('industryIdList', str)
 }
 
-const positionList = ref([
-  {
-    name: '前端开发工程师',
-    payFrom: 5,
-    payTo: 20,
-    industryIds: '行业不限',
-    areaName: '广州',
-    jobType: '全职',
-    active: false
-  },
-  {
-    name: '规控算法',
-    payFrom: 9,
-    payTo: 10,
-    industryIds: '医疗设备',
-    areaName: '广州',
-    jobType: '兼职',
-    active: false
-  }
-])
+// 工作城市
+const handleArea = (list, name) => {
+  if (!list.length) return
+  query.workAreaId = list[0]
+  setValue('workAreaId', name)
+}
+
+const resetForm = () => {
+  items.value.options.forEach(e => {
+    if (e.key === 'industryIdList') e.value = '不限'
+    else e.value = null
+  })
+  editId.value = null
+  query = {}
+  currentSelect = []
+}
+
+const arr = ['payFrom', 'payTo', 'jobType']
+const handleSave = async () => {
+  const { valid } = await formPageRef.value.formRef.validate()
+  if (!valid) return
+  items.value.options.forEach(e => {
+    if (arr.includes(e.key)) query[e.key] = e.value 
+  })
+  if (editId.value) query.id = editId.value
+  await saveResumeJobInterested(query)
+  Snackbar.success('保存成功')
+  isAdd.value = false
+  resetForm()
+  getJobInterested()
+}
+
+const handleEdit = (item) => {
+  editId.value = item.id
+  items.value.options.forEach(e => {
+    query[e.key] = item[e.key] 
+    if (e.valueKey) {
+      e.value = item[e.valueKey]
+    } else e.value = item[e.key]
+    if (e.key === 'industryIdList') e.value = item.industry.map(e => e.nameCn).join('、')
+  })
+  currentSelect = item.industry
+  isAdd.value = true
+}
+
+const handleDelete = ({ id }) => {
+  Confirm('系统提示', '是否确认删除此项求职意向?').then(async () => {
+    await deleteResumeJobInterested(id)
+    Snackbar.success('删除成功!')
+    getJobInterested()
+  })
+}
 </script>
 
 <style scoped lang="scss">
 .jobTypeCardBox {
   position: absolute;
-  top: 0;
+  top: -22px;
   left: 0;
 }
 .position-item {
+  display: flex;
+  justify-content: space-between;
   cursor: pointer;
   border-radius: 6px;
-  line-height: 36px;
+  line-height: 40px;
+  font-size: 15px;
   &:hover {
     background-color: #f8f8f8;
   }
@@ -203,4 +278,14 @@ const positionList = ref([
     color: #999;
   }
 }
+.text-box {
+  max-width: 200px;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.line {
+  color: #e0e0e0;
+  margin: 0 10px;
+}
 </style>