Forráskód Böngészése

求职意向-新增其它感兴趣的城市

Xiao_123 9 hónapja
szülő
commit
91b34a2a76

+ 100 - 208
src/components/AreaSelect/index.vue

@@ -1,252 +1,144 @@
 <template>
 <template>
-  <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>
+  <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.name }}</v-chip>
       </div>
       </div>
-    </v-card>
-    <v-card v-if="rightObj.show" class="card rightCardBox">
       <div class="rightCard">
       <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 v-for="item in items" :key="item.id">
           <div class="rowItem d-flex">
           <div class="rowItem d-flex">
             <div class="categoryName2">{{ item.name }}</div>
             <div class="categoryName2">{{ item.name }}</div>
             <div class="rightContent">
             <div class="rightContent">
               <div v-if="!item.children?.length"></div>
               <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
+                v-else
+                :class="['jobItem', {'active': idChecked.includes(val.id)}]"
+                v-for="val in item.children" :key="val.id"
+                @click="handleClick(val)"
+              >{{ val.name }}</div>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
     </v-card>
     </v-card>
-  </div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
+defineOptions({ name:'common-components-area'})
 import { getDict } from '@/hooks/web/useDictionaries'
 import { getDict } from '@/hooks/web/useDictionaries'
-import { reactive, ref } from 'vue';
-defineOptions({ name:'common-components-jobTypeCard'})
-
-const emits = defineEmits(['handleAreaClick'])
+import { ref } from 'vue'
+import Snackbar from '@/plugins/snackbar'
 
 
+const emits = defineEmits(['handleClick'])
 const props = defineProps({
 const props = defineProps({
-  // 是否单选(首页为单选)
-  isSingle: {
+  limit: { // 限制最大可选择数量, 不限制传false或者0
+    type: [Number, Boolean],
+    default: 3
+  },
+  select: {
+    type: Array,
+    default: () => []
+  },
+  showSelect: {
     type: Boolean,
     type: Boolean,
     default: false
     default: false
   },
   },
-  select: {
+  currentData: {
     type: Array,
     type: Array,
     default: () => []
     default: () => []
   }
   }
 })
 })
-const selectItems = ref([])
-// 回显
-if (props.select.length) {
-  selectItems.value = props.select
-}
 
 
-// 点击
-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)
-}
+let items = ref()
+let idChecked = ref([])
+let currentSelect = ref([])
+// 回显
+if (props.currentData.length) currentSelect.value = props.currentData
+console.log(props.select, 'props')
+if (props.select.length) idChecked.value = props.select.map(e => e + '') // 数据中的id是字符串
 
 
-let items = ref([])
 getDict('areaTreeData', null, 'areaTreeData').then(({ data }) => {
 getDict('areaTreeData', null, 'areaTreeData').then(({ data }) => {
   data = data?.length && data || []
   data = data?.length && data || []
-  const chinaTreeData = data.filter(e => e.id === '1')
-  if (!chinaTreeData.length) return
-  items.value = chinaTreeData[0].children
+  const china = data.find(e => e.id === '1')
+  items.value = china?.children?.length ? china.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
+// 设置选中ids
+const handleClick = (val) => {
+  const isExist = idChecked.value.includes(val.id)
+  if (!isExist) {
+    // 添加
+    if (props.limit === 1) {
+      currentSelect.value = [val]
+      idChecked.value = [val.id]
+    } else {
+      if (props.limit === idChecked.value.length) return Snackbar.warning(`最多可选${props.limit}个城市`)
+      currentSelect.value.push(val)
+      idChecked.value.push(val.id)
+    }
+  } else {
+    // 删除
+    currentSelect.value = currentSelect.value.filter(e => e.id !== val.id)
+    idChecked.value = idChecked.value.filter(e => e !== val.id)
+  }
+  emits('handleClick', idChecked.value, currentSelect.value)
 }
 }
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-.active {
-  color: var(--v-primary-base) !important;
-  font-weight: 700;
-}
-:deep(.v-window) {
-  height: 392px !important;
+.currentSelect {
+  position: sticky;
+  background-color: var(--color-f2f4f7);
 }
 }
-.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;
+.card { border-radius: 12px; }
+.rightCard {
+  position: relative;
+  height: 384px;
+  width: 786px;
+  margin: 4px 0;
+  padding: 0 16px;
+  overflow-y: auto;
+  .categoryName2 { font-size: 14px; color: #000; width: 150px; margin-right: 4px;}
+  .jobItem { font-size: 14px; color: var(--color-333); }
+  .active { color: var(--v-primary-base); font-weight: 700; }
+  .rowItem {
+    padding: 8px 0;
+  }
+  .divider {
+    margin-left: 150px;
+  }
+  .rightContent {
+    flex: 1;
+    div {
+      margin: 4px 28px 2px 0;
+      float: left;
       cursor: pointer;
       cursor: pointer;
       &:hover {
       &:hover {
         color: var(--v-primary-base);
         color: var(--v-primary-base);
-        background-color: var(--color-f8);
-      }
-      .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: var(--color-666); width: 110px; margin-right: 4px;}
-    .jobItem { font-size: 14px; color: var(--color-333); }
-    .rowItem {
-      padding: 8px 0;
-    }
-    .divider {
-      margin-left: 110px;
-    }
-    .rightContent {
-      flex: 1;
-      div {
-        margin: 4px 28px 2px 0;
-        float: left;
-        cursor: pointer;
-        color: var(--color-333);
-        &: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: var(--color-666);
-          font-family: 微软雅黑; 
-          &:hover {
-            color: var(--v-primary-base);
-            // background-color: var(--color-f8);
-          }
-        }
-      }
-    }
-  }
-  .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: var(--color-666); width: 110px; margin-right: 4px;}
-    .jobItem { font-size: 14px; color: var(--color-333); }
-    .rowItem {
-      padding: 8px 0;
-    }
-    .divider {
-      margin-left: 110px;
-    }
-    .rightContent {
-      flex: 1;
-      div {
-        margin: 4px 28px 2px 0;
-        float: left;
-        cursor: pointer;
-        color: var(--color-333);
-        &:hover {
-          color: var(--v-primary-base);
-        }
-      }
-    }
-  }
+
+::-webkit-scrollbar {
+  width: 4px;
+  height: 10px;
 }
 }
-// ::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>
+::-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>

+ 15 - 15
src/views/recruit/enterprise/talentPool/components/filter.vue

@@ -119,21 +119,21 @@ const formItems = ref({
       dictTypeName: 'menduner_exp_type',
       dictTypeName: 'menduner_exp_type',
       items: []
       items: []
     },
     },
-    {
-      slotName: 'residence',
-      key: 'residence',
-      value: null,
-      col: 6,
-      flexStyle: 'mr-3',
-      label: '户籍地'
-    },
-    {
-      slotName: 'areaIds',
-      key: 'areaIds',
-      value: null,
-      col: 6,
-      label: '期望城市'
-    },
+    // {
+    //   slotName: 'residence',
+    //   key: 'residence',
+    //   value: null,
+    //   col: 6,
+    //   flexStyle: 'mr-3',
+    //   label: '户籍地'
+    // },
+    // {
+    //   slotName: 'areaIds',
+    //   key: 'areaIds',
+    //   value: null,
+    //   col: 6,
+    //   label: '期望城市'
+    // },
     {
     {
       type: 'vueDatePicker',
       type: 'vueDatePicker',
       key: 'firstWorkTime',
       key: 'firstWorkTime',

+ 16 - 3
src/views/recruit/personal/remuse/components/dict.js

@@ -38,6 +38,16 @@ const dictList = [
     value: 'jobTypeData',
     value: 'jobTypeData',
     itemKey: 'value',
     itemKey: 'value',
     itemText: 'label'
     itemText: 'label'
+  },
+  { 
+    type: 'menduner_area_type', 
+    apiType: 'areaList', 
+    key: 'interestedAreaIdList', 
+    label: 'interestedArea', 
+    isArray: true, 
+    value: 'areaTypeData', 
+    itemKey: 'id', 
+    itemText: 'name' 
   }
   }
 ]
 ]
 
 
@@ -60,9 +70,12 @@ export const dealJobData = (list) => {
     res = list.map(e => {
     res = list.map(e => {
       let obj = {}
       let obj = {}
       if (item.isArray) {
       if (item.isArray) {
-        e[item.label] = e[item.key].map(val => {
-          return obj = dictObj[item.value].find(i => i[item.itemKey] === val)
-        })
+        if (e[item.key] && e[item.key].length) {
+          const result = e[item.key].map(val => {
+            return obj = dictObj[item.value].find(i => i[item.itemKey] === val)
+          })
+          e[item.label] = result && result.length ? result.filter(Boolean) : []
+        }
       } else {
       } else {
         obj = dictObj[item.value].find(k => Number(k[item.itemKey]) === Number(e[item.key]))
         obj = dictObj[item.value].find(k => Number(k[item.itemKey]) === Number(e[item.key]))
         if (!obj) return
         if (!obj) return

+ 56 - 18
src/views/recruit/personal/remuse/components/jobIntention.vue

@@ -22,7 +22,9 @@
             <div class="line" v-if="k.industry.length && k.jobTypeName">|</div>
             <div class="line" v-if="k.industry.length && k.jobTypeName">|</div>
             <div class="grey-text">{{ k.jobTypeName }}</div>
             <div class="grey-text">{{ k.jobTypeName }}</div>
             <div class="line" v-if="k.jobTypeName && k.workArea">|</div>
             <div class="line" v-if="k.jobTypeName && k.workArea">|</div>
-            <div class="grey-text">{{ k.workArea }}</div>
+            <div class="grey-text ellipsis" style="max-width: 160px;">
+              {{ k.interestedArea && k.interestedArea.length ? k.workArea + ',' + k.interestedArea.map(e => e.name).join(',') : k.workArea }}
+            </div>
           </div>
           </div>
           <div class="float-right" v-if="k.active">
           <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-square-edit-outline" @click="handleEdit(k)">{{ $t('common.edit') }}</v-btn>
@@ -61,6 +63,20 @@
             <industryTypeCard :select="query.industryIdList" :currentData="currentSelect" showSelect @handleClickIndustry="handleIndustry"></industryTypeCard>
             <industryTypeCard :select="query.industryIdList" :currentData="currentSelect" showSelect @handleClickIndustry="handleIndustry"></industryTypeCard>
           </v-menu>
           </v-menu>
         </template>
         </template>
+        <!-- 其它感兴趣的城市 -->
+        <template #interestedAreaIdList="{ item }">
+          <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs" :close-on-content-click="false">
+            <template v-slot:activator="{  props }">
+              <TextInput
+                v-model="item.value"
+                :item="item"
+                v-bind="props"
+                style="position: relative;"
+              ></TextInput>
+            </template>
+            <AreaSelect :select="query.interestedAreaIdList" :currentData="areaSelect" :limit="false" showSelect @handleClick="handleArea"></AreaSelect>
+          </v-menu>
+        </template>
       </CtForm>
       </CtForm>
       <div class="text-end">
       <div class="text-end">
         <v-btn class="half-button mr-3" variant="tonal" @click="isAdd = false; resetForm()">{{ $t('common.cancel') }}</v-btn>
         <v-btn class="half-button mr-3" variant="tonal" @click="isAdd = false; resetForm()">{{ $t('common.cancel') }}</v-btn>
@@ -115,8 +131,7 @@ const items = ref({
       key: 'payFrom',
       key: 'payFrom',
       value: null,
       value: null,
       label: '期望薪资(最低要求) *',
       label: '期望薪资(最低要求) *',
-      col: 6,
-      flexStyle: 'mr-3',
+      col: 4,
       outlined: true,
       outlined: true,
       rules: [v => !!v || '请输入薪资最低要求']
       rules: [v => !!v || '请输入薪资最低要求']
     },
     },
@@ -125,10 +140,28 @@ const items = ref({
       key: 'payTo',
       key: 'payTo',
       value: null,
       value: null,
       label: '期望薪资(最高要求) *',
       label: '期望薪资(最高要求) *',
-      col: 6,
+      col: 4,
       outlined: true,
       outlined: true,
+      flexStyle: 'mx-3',
       rules: [v => !!v || '请输入薪资最高要求']
       rules: [v => !!v || '请输入薪资最高要求']
     },
     },
+    {
+      type: 'autocomplete',
+      key: 'jobType',
+      value: null,
+      label: '求职类型 *',
+      outlined: true,
+      itemText: 'label',
+      col: 4,
+      itemValue: 'value',
+      rules: [v => !!v || '请选择求职类型'],
+      items: [
+        { label: '全职', value: '0' },
+        { label: '兼职', value: '1' },
+        { label: '临时', value: '2' },
+        { label: '实习', value: '3' }
+      ]
+    },
     {
     {
       type: 'autocomplete',
       type: 'autocomplete',
       key: 'workAreaProvinceId',
       key: 'workAreaProvinceId',
@@ -158,21 +191,10 @@ const items = ref({
       change: null
       change: null
     },
     },
     {
     {
-      type: 'autocomplete',
-      key: 'jobType',
+      slotName: 'interestedAreaIdList',
+      key: 'interestedAreaIdList',
       value: null,
       value: null,
-      label: '求职类型 *',
-      outlined: true,
-      itemText: 'label',
-      col: 12,
-      itemValue: 'value',
-      rules: [v => !!v || '请选择求职类型'],
-      items: [
-        { label: '全职', value: '0' },
-        { label: '兼职', value: '1' },
-        { label: '临时', value: '2' },
-        { label: '实习', value: '3' }
-      ]
+      label: '其它感兴趣的城市'
     }
     }
   ]
   ]
 })
 })
@@ -229,6 +251,16 @@ const handleIndustry = (list, arr) => {
   setValue('industryIdList', str)
   setValue('industryIdList', str)
 }
 }
 
 
+// 其它感兴趣的城市
+let areaSelect = reactive([])
+const handleArea = (list, arr) => {
+  if (!list.length) return setValue('interestedAreaIdList', '')
+  query.interestedAreaIdList = list
+  areaSelect = arr
+  const str = arr.map(e => e.name).join('、')
+  setValue('interestedAreaIdList', str)
+}
+
 const resetForm = () => {
 const resetForm = () => {
   items.value.options.forEach(e => {
   items.value.options.forEach(e => {
     if (e.key === 'industryIdList') e.value = ''
     if (e.key === 'industryIdList') e.value = ''
@@ -237,6 +269,7 @@ const resetForm = () => {
   editId.value = null
   editId.value = null
   query = {}
   query = {}
   currentSelect = []
   currentSelect = []
+  areaSelect = []
 }
 }
 
 
 const arr = ['payFrom', 'payTo', 'jobType', 'workAreaId']
 const arr = ['payFrom', 'payTo', 'jobType', 'workAreaId']
@@ -263,6 +296,10 @@ const handleEdit = async (item) => {
       e.value = item[e.valueKey]
       e.value = item[e.valueKey]
     } else e.value = item[e.key]
     } else e.value = item[e.key]
     if (e.key === 'industryIdList') e.value = item.industry.map(e => e.nameCn).join('、')
     if (e.key === 'industryIdList') e.value = item.industry.map(e => e.nameCn).join('、')
+    if (e.key === 'interestedAreaIdList') {
+      e.value = item.interestedArea && item.interestedArea.length ? item.interestedArea.map(e => e.name).join('、') : []
+      query.interestedAreaIdList = item.interestedAreaIdList && item.interestedAreaIdList.length ? item.interestedAreaIdList : []
+    }
     if (e.key === 'workAreaId' && item[e.key]) workAreaId = item[e.key]
     if (e.key === 'workAreaId' && item[e.key]) workAreaId = item[e.key]
   })
   })
   if (workAreaId) { // 省份回显
   if (workAreaId) { // 省份回显
@@ -275,6 +312,7 @@ const handleEdit = async (item) => {
     }
     }
   }
   }
   currentSelect = item.industry
   currentSelect = item.industry
+  areaSelect = item.interestedArea && item.interestedArea.length ? item.interestedArea : []
   isAdd.value = true
   isAdd.value = true
 }
 }