Browse Source

选择城市

lifanagju_citu 7 months ago
parent
commit
f4bc1336da

+ 12 - 3
src/components/FormUI/cascade/index.vue

@@ -1,7 +1,7 @@
 <!-- 级联选择器 -->
 <template>
   <div class="d-flex" style="width: 100%;">
-    <div class="mr-2" style="line-height: 40px;">
+    <div class="mr-2" :class="`${prop.size}Title`">
       <span style="color: #777;">{{ item?.label }}</span>
       <span v-if="prop.required" style="color: var(--v-error-base);"> *</span>
       <!-- <span style="color: #777;"> :</span> -->
@@ -20,7 +20,7 @@
         @blur="handleBlur"
         @change="handleChange"
       ></el-cascader>
-      <div :style="{'display': requiredTxt? 'block' : 'inline-block'}" class="requiredTxt">{{ requiredTxt }}</div>
+      <div v-if="!prop.hideDetails" :style="{'display': requiredTxt? 'block' : 'inline-block'}" class="requiredTxt">{{ requiredTxt }}</div>
     </div>
   </div>
 </template>
@@ -41,7 +41,7 @@ const prop = {
   label: item.itemText || 'label',
   value: item.itemValue || 'value',
   required: item.required || false,
-  size: item.size || 'large',
+  size: item.size || 'large', // 'large' | 'default' | 'small'
   multiple: item.multiple || false,
   emitPath: item.emitPath || false, // 在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
   checkStrictly: item.checkStrictly || false, // 是否严格的遵守父子节点不互相关联
@@ -86,6 +86,15 @@ defineExpose({
   padding: 6px 16px 0;
   color: var(--v-error-base)
 }
+
+.largeTitle {
+  line-height: 40px;
+}
+.defaultTitle {
+  line-height: 32px;
+}
+
+
 :deep(.icon-circle-close) {
   color: #666;
   font-size: 22px;

+ 2 - 0
src/styles/index.scss

@@ -30,6 +30,8 @@
   --el-text-color-regular: #333 !important;
   --el-fill-color-light: #f3f3f3 !important;
   --el-input-border: 1px solid #000 !important;
+  --el-color-info: #00897B !important;
+  --el-cascader-tag-background: #e2f0ef !important;
 }
 
 .color-222 { color: #222; }

+ 2 - 1
src/views/recruit/personal/position/components/cityFilter.vue

@@ -1,3 +1,4 @@
+<!-- 已弃用 -->
 <template>
     <div>
       <v-tabs v-model="tab" align-tabs="start" color="primary" @update:model-value="tabClick">
@@ -11,7 +12,7 @@
     </div>
 </template>
 <script setup>
-import areaTree from './areaCascader'
+import areaTree from './cityFilter'
 import { ref } from 'vue'
 
 defineOptions({name: 'retrieval-components-cityFilter'})

+ 0 - 0
src/views/recruit/personal/position/components/areaCascader/index.vue → src/views/recruit/personal/position/components/cityFilter/index.vue


+ 14 - 96
src/views/recruit/personal/position/components/conditionFilter.vue

@@ -1,9 +1,9 @@
 <template>
   <div>
+    <cityCascadeSelect v-if="showCitySelect" @inputChange="inputChange"></cityCascadeSelect>
     <div class="d-flex" style="flex-wrap: wrap;">
       <template v-for="item in list" :key="item.key">
         <component
-          v-if="!item.hide"
           :is="item.path"
           :idName="item.key"
           :title="item.title"
@@ -21,7 +21,7 @@
     </div>
     <div v-if="showSelectList?.length">
       <div style="margin-top: 20px; border-top: 1px solid #eee;">
-        <div v-for="item in showSelectList" :key="item.key" style="margin: 4px 8px 4px 0px;" :style="`display: ${item.key.includes('cityId_') ? 'inline-block' : 'block'};`">
+        <div v-for="item in showSelectList" :key="item.key" style="margin: 4px 8px 4px 0px;">
           <template v-if="item.checkedItems?.length">
             <span style="color: #999;">{{ item.title }}:</span>
             <v-btn
@@ -45,9 +45,9 @@
 </template>
 <script setup>
 import { useRoute } from 'vue-router'; const route = useRoute()
-import { watch, ref, shallowRef, nextTick } from 'vue'
+import { watch, ref, shallowRef } from 'vue'
 import { filterList, getItemObj } from './dict'
-import { getDict } from '@/hooks/web/useDictionaries'
+import cityCascadeSelect from './conditionFilter/cityCascadeSelect.vue'
 defineOptions({name: 'retrieval-components-conditionFilter'})
 const emits = defineEmits(['change', 'reset'])
 const props = defineProps({
@@ -55,59 +55,21 @@ const props = defineProps({
     type: [Array, String],
     default: ''
   },
+  showCitySelect: { // 城市级联筛选
+    type: Boolean,
+    default: false
+  },
 })
+
 const list = shallowRef(props.showFilterList === 'all' ? filterList : props.showFilterList?.length? props.showFilterList.map(e => {
   const item = filterList.find(i => i.key === e.key)
   return item ? { ...item, ...e } : ''
 }).filter(Boolean) : [])
 
-// 城市处理
-const cityDelete = (cityLevel) => {
-  list.value.forEach(e => {
-    if (e.key.includes('cityId_') && e.cityLevel > cityLevel) {
-      emits('change', e.key, '')
-      e.del = true
-    }
-  })
-  list.value = list.value.filter(e => !e.del)
-}
-// 城市处理
-const cityDeal = (str, key, clickItem) => {
-  if (str === '10000') { // 全国
-    cityDelete(1)
-    return
-  } 
-  const i = list.value.findIndex(e => e.key === key)
-  if (i !== -1) {
-    cityDelete(list.value[i].cityLevel) // 去掉当前选中层级后面的市区
-    if (str && clickItem?.children?.length) { // 选中-添加下级
-      let noProvince = false
-      if (clickItem.children[0][list.value[i].itemText] === clickItem[list.value[i].itemText] && clickItem.children[0].children?.length) { // 直辖市
-        clickItem = clickItem.children[0]
-        noProvince = true
-      }
-      const obj = {
-        ...list.value[i], // 复制其他属性
-        toFilterDictName: null, toFilterApiType: null, displayDictName: null, displayApiType: null,
-        isSingle: Boolean(clickItem.children[0]?.children?.length),
-        provideData: clickItem.children, // 赋值下拉数据
-        toFilterDictDataList: clickItem.children // 回显使用
-      }
-      obj.cityLevel++ // 层级
-      if (noProvince) obj.cityLevel++ // 直辖市
-      obj.key = 'cityId_' + obj.cityLevel
-      obj.title = obj.cityLevel === 2 ? '市' : '区'
-      nextTick(() => {
-        list.value.splice(i+1, 0, obj)
-      })
-    }
-  }
-}
 
-const inputChange = ({ idName: key, values, clickItem }) => {
+const inputChange = ({ idName: key, values }) => {
   const str = values.length ? values.join('_') : ''
   if (!key) return
-  if (key.includes('cityId_')) cityDeal(str, key, clickItem) // 城市处理
   //
   emits('change', key, str)
 }
@@ -120,43 +82,8 @@ const deleteChip = (item, val) => { // 删除某个标签-更新路由 val结构
   inputChange({ idName: item.key, values: ids })
 }
 
-let cityLevel2 = []
 const showSelectList = ref([])
-const assembleList = async ({ key, idsStr, isRefresh = false }) => {
-  if (isRefresh && key === 'cityId_1') {
-    const res = await getDict('areaTreeData', null, 'areaTreeData')
-    const data = res?.data?.length ? res.data : []
-    const item = data.find(e => e.id === idsStr)
-    if (item) {
-      cityLevel2 = item.children?.length? item.children : []
-      cityDeal(idsStr, key, item)
-      nextTick(() => {
-        assembleList({ key, idsStr })
-      })
-    }
-  }
-  if (isRefresh && key === 'cityId_2') {
-    nextTick(async () => {
-      const item = cityLevel2.find(e => String(e.id) === String(idsStr))
-      if (item) {
-        nextTick(() => {
-          cityDeal(idsStr, key, item)
-          nextTick(() => {
-            assembleList({ key, idsStr })
-          })
-        })
-      }
-    })
-  }
-  if (isRefresh && key === 'cityId_3') {
-    nextTick(() => {
-      nextTick(() => {
-        nextTick(() => {
-          assembleList({ key, idsStr })
-        })
-      })
-    })
-  }
+const assembleList = async ({ key, idsStr }) => {
   // 添加
   const ids = typeof idsStr === 'string' ? idsStr.split('_') : []
   const obj = getItemObj({ key, ids, dictArr: list.value })
@@ -164,11 +91,6 @@ const assembleList = async ({ key, idsStr, isRefresh = false }) => {
   const index = showSelectList.value.findIndex(i => i.key === key)
   if (index === -1) showSelectList.value.push(obj)
   else showSelectList.value[index] = obj
-  //
-  showSelectList.value = [ // 城市放在一起展示
-    ...showSelectList.value.filter(item => item.key.includes('cityId_')),
-    ...showSelectList.value.filter(item => !item.key.includes('cityId_')),
-  ]
 }
 
 watch(
@@ -176,20 +98,16 @@ watch(
   (newVal = {}, oldVal = {}) => {
     // console.log('1oldVal', oldVal)
     // console.log('2newVal', newVal)
-    const arr = Object.keys(newVal).length ? [...Object.keys(newVal)] : null
-    const newKeyList = arr ? [ // 城市放在一起展示
-      ...arr.filter(key => key.includes('cityId_')),
-      ...arr.filter(key => !key.includes('cityId_')),
-    ] : ''
+    const newKeyList = Object.keys(newVal).length ? [...Object.keys(newVal)] : null
+
     // 回显已选筛选-标签
-    
     if (!newKeyList) { // 路由没有参数
       showSelectList.value = []
       list.value = list.value.filter(e => !(e.cityLevel && e.cityLevel > 1))
     }
     else if (!Object.keys(oldVal).length && newKeyList) { // 只有新加参数
       newKeyList.forEach(key => {
-        assembleList({ key, idsStr: newVal[key], isRefresh: true })
+        assembleList({ key, idsStr: newVal[key] })
       })
     }
     else { // 路由参数更新

+ 58 - 0
src/views/recruit/personal/position/components/conditionFilter/cityCascadeSelect.vue

@@ -0,0 +1,58 @@
+<!-- 工作城市 -->
+<template>
+  <div v-if="show" style="width: 400px;">
+    <cascade v-model="selectItems.value" :item="selectItems" @change="selectChange"></cascade>
+  </div>
+</template>
+
+<script setup>
+import { getDict } from '@/hooks/web/useDictionaries'
+import { ref, watch } from 'vue';
+import { useRoute } from 'vue-router'; const route = useRoute()
+defineOptions({name: 'conditionFilter-cityCascadeSelect'})
+const emits = defineEmits(['inputChange'])
+
+const selectItems = {
+  // key: 'workAreaId',
+  value: null,
+  default: null,
+  label: '工作城市:',
+  itemText: 'name',
+  itemValue: 'id',
+  size: 'default', // large default
+  required: false,
+  clearable: true,
+  multiple: true,
+  hideDetails: true,
+  checkStrictly: true,
+  placeholder: '请选择工作城市',
+  items: [],
+}
+
+const show = ref(false)
+getDict('areaTreeData', null, 'areaTreeData').then(res => {
+  selectItems.items = res?.data?.length ? res.data.filter(e => e.id !== 10000) : []
+  show.value = true
+})
+
+const selectChange = () => {
+  emits('inputChange', {
+    idName: 'areaIds',
+    values: selectItems.value,
+  })
+}
+
+watch(
+  () => route.query, 
+  (newVal) => { // newVal, oldVal
+    if (!newVal) selectItems.value = []
+    const str = newVal.areaIds?.split(',')[0]
+    const arr = str ? str.split('_') : []
+    selectItems.value = arr?.length? arr.map(e => e = Number(e)) : []
+  },
+  { immediate: true },
+  { deep: true }
+)
+</script>
+<style lang="scss" scoped>
+</style>

+ 1 - 1
src/views/recruit/personal/position/components/conditionFilter/commonPath.vue

@@ -29,7 +29,7 @@ import { getDict } from '@/hooks/web/useDictionaries'
 import { useRoute } from 'vue-router'; const route = useRoute()
 import { ref, computed, watch } from 'vue';
 
-defineOptions({name: 'conditionFilter-JobType'})
+defineOptions({name: 'conditionFilter-commonPath'})
 const emits = defineEmits(['inputChange'])
 const props = defineProps({
   isRefreshEmit: { // 刷新是否触发inputChange

+ 0 - 15
src/views/recruit/personal/position/components/dict.js

@@ -8,21 +8,6 @@ import commonPath from './conditionFilter/commonPath.vue'
 // provideData数据不为空时使用自定义下拉数据
 
 const dictList = [
-  {
-    toFilterDictName: 'menduner_area_type',
-    toFilterApiType: 'areaList',
-    displayDictName: 'areaTreeData',
-    displayApiType: 'areaTreeData',
-    displayParams: {},
-    key: 'cityId_1',
-    cityLevel: 1,
-    itemKey: 'id',
-    itemText: 'name',
-    title: '工作城市',
-    isSingle: true,
-    path: commonPath,
-    toFilterDictDataList: []
-  },
   {
     key: 'areaIds',
     title: '工作城市',

+ 1 - 7
src/views/recruit/personal/position/index.vue

@@ -13,7 +13,7 @@
         </div>
         <!-- <cityFilter class="mx-5 mb-3" ref="cityFilterRef" @change="handleQueryChange"></cityFilter> -->
         <div class="d-flex justify-space-between mx-5 mb-3">
-          <conditionFilter ref="conditionFilterRef" :showFilterList="showFilterList" @reset="handleReset" @change="handleQueryChange"></conditionFilter>
+          <conditionFilter ref="conditionFilterRef" showCitySelect :showFilterList="showFilterList" @reset="handleReset" @change="handleQueryChange"></conditionFilter>
         </div>
       </div>
       <div class="mt-3">
@@ -49,7 +49,6 @@ const route = useRoute(); const router = useRouter()
 // const cityFilterRef = ref()
 const conditionFilterRef = ref()
 const showFilterList = [
-  { key: 'cityId_1' },
   { key: 'industryIds' },
   { key: 'positionId', isSingle: true },
   { key: 'jobType' },
@@ -80,11 +79,6 @@ const getData = async () => {
     const passingOneId = ['positionId'] // 单选且传递整型
     Object.keys(routeQuery).forEach(key => {
       if (routeQuery[key] === '' || key === 'date') return
-      if (key.includes('cityId_')) { // 工作地区id集合,示例值([])
-        const cityArr = routeQuery[key].split('_')
-        if (cityArr?.length) pageReqVO.areaIds = [...pageReqVO.areaIds, ...cityArr]
-        if (!pageReqVO.areaIds?.length) delete pageReqVO.areaIds
-      }
       else if (passingStrings.includes(key)) pageReqVO[key] = routeQuery[key] // 传给后端字符串
       else if (passingOneId.includes(key)) pageReqVO[key] = +routeQuery[key] // 传给后端单选且传递整型
       else pageReqVO[key] = routeQuery[key].split('_') // 传给后端Arr