|
@@ -0,0 +1,179 @@
|
|
|
+<template>
|
|
|
+ <div style="max-height: 80vh; overflow-y: auto;">
|
|
|
+ <div class="d-flex align-center mt-5">
|
|
|
+ <TextInput v-model="textItem.value" :item="textItem" @appendInnerClick="handleSearch"></TextInput>
|
|
|
+ <span class="pl-6 color-666" style="width: 60px; min-width: 60px;" @click="emit('close')">取消</span>
|
|
|
+ </div>
|
|
|
+ <v-divider class="my-3"></v-divider>
|
|
|
+ <!-- 职位 -->
|
|
|
+ <div class="mb-3">
|
|
|
+ <div class="mb-2 font-size-20">职位</div>
|
|
|
+ <div class="d-flex font-size-14 flex-wrap">
|
|
|
+ <div v-for="val in items" :key="val.id" class="mr-2 tag mb-2" :class="{'active': val.active}" @click="handleFirst(val)">{{ val.nameCn }}</div>
|
|
|
+ </div>
|
|
|
+ <div v-if="children.length" class="mx-3" style="border-top: 1px dashed #ccc;"></div>
|
|
|
+ <div v-if="children.length" class="mt-5 font-size-14 d-flex flex-wrap triangle-container pa-3">
|
|
|
+ <div
|
|
|
+ v-for="k in children"
|
|
|
+ :key="k.id"
|
|
|
+ class="second-tag mr-2 mb-2"
|
|
|
+ :class="{'active': select.findIndex(e => e.id === k.id) !== -1}"
|
|
|
+ @click="handleSecond(k)"
|
|
|
+ >{{ k.nameCn }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 最高学历、工作经验 -->
|
|
|
+ <div v-for="val in list" :key="val.key" class="mb-3">
|
|
|
+ <div class="mb-2 font-size-20">{{ val.title }}</div>
|
|
|
+ <v-chip-group v-model="val.value" selected-class="text-primary" mandatory @update:modelValue="e => val.value = e" class="flex-wrap">
|
|
|
+ <v-chip v-for="val in val.items" :key="val.id" :text="val.label" :value="val.value" label filter></v-chip>
|
|
|
+ </v-chip-group>
|
|
|
+ </div>
|
|
|
+ <div class="white-bgc pb-5" style="position: sticky; bottom: 0;">
|
|
|
+ <v-divider class="mb-5"></v-divider>
|
|
|
+ <div class="d-flex align-center">
|
|
|
+ <v-btn color="primary" variant="outlined" style="width: 100px;" @click="handleReset">重 置</v-btn>
|
|
|
+ <v-btn class="ml-5" color="primary" style="flex: 1;" @click="handleConfirm">确 定</v-btn>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+defineOptions({ name: 'filterPage'})
|
|
|
+import { ref } from 'vue'
|
|
|
+import { getDict } from '@/hooks/web/useDictionaries'
|
|
|
+
|
|
|
+const emit = defineEmits(['close', 'search'])
|
|
|
+const textItem = ref({
|
|
|
+ type: 'text',
|
|
|
+ value: '',
|
|
|
+ label: '请输入关键词搜索',
|
|
|
+ clearable: false,
|
|
|
+ hideDetails: true,
|
|
|
+ appendInnerIcon: 'mdi-magnify'
|
|
|
+})
|
|
|
+const query = ref({
|
|
|
+ content: '',
|
|
|
+ positionIds: [],
|
|
|
+ areaIds: [],
|
|
|
+ expType: '',
|
|
|
+ eduType: ''
|
|
|
+})
|
|
|
+const list = ref([
|
|
|
+ {
|
|
|
+ title: '最高学历',
|
|
|
+ dictTypeName: 'menduner_education_type',
|
|
|
+ items: [],
|
|
|
+ value: -1,
|
|
|
+ key: 'eduType'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '工作经验',
|
|
|
+ dictTypeName: 'menduner_exp_type',
|
|
|
+ items: [],
|
|
|
+ value: -1,
|
|
|
+ key: 'expType'
|
|
|
+ }
|
|
|
+])
|
|
|
+list.value.forEach(e => {
|
|
|
+ getDict(e.dictTypeName).then(({ data }) => {
|
|
|
+ e.items = [{ value: -1, label: '不限' }, ...data] || []
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+// 职位树状
|
|
|
+const items = ref([])
|
|
|
+getDict('positionTreeData', {}, 'positionTreeData').then(({ data }) => {
|
|
|
+ if (!data) return
|
|
|
+ items.value = data.map(e => {
|
|
|
+ e.active = false
|
|
|
+ return e
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+const children = ref([])
|
|
|
+const handleFirst = (val) => {
|
|
|
+ if (val.active) {
|
|
|
+ val.active = false
|
|
|
+ children.value = []
|
|
|
+ select.value = select.value.filter(e => e.parentId !== val.id)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ items.value.forEach(e => e.active = false)
|
|
|
+ val.active = !val.active
|
|
|
+ children.value = val.children || []
|
|
|
+}
|
|
|
+
|
|
|
+const handleSearch = () => {
|
|
|
+ query.value.content = textItem.value.value
|
|
|
+ emit('search', query.value)
|
|
|
+}
|
|
|
+
|
|
|
+const select = ref([])
|
|
|
+const handleSecond = (val) => {
|
|
|
+ const index = select.value.findIndex(e => e.id === val.id)
|
|
|
+ if (index !== -1) {
|
|
|
+ select.value.splice(index, 1)
|
|
|
+ } else select.value.push(val)
|
|
|
+ console.log(select.value, 'select')
|
|
|
+ // emit('select', select.value)
|
|
|
+}
|
|
|
+
|
|
|
+// 重置
|
|
|
+const handleReset = () => {
|
|
|
+ query.value = {
|
|
|
+ content: '',
|
|
|
+ positionIds: [],
|
|
|
+ areaIds: [],
|
|
|
+ expType: '',
|
|
|
+ eduType: ''
|
|
|
+ }
|
|
|
+ select.value = []
|
|
|
+ list.value.forEach(e => e.value = -1)
|
|
|
+ items.value.forEach(e => e.active = false)
|
|
|
+ emit('search', query.value)
|
|
|
+}
|
|
|
+const handleConfirm = () => {
|
|
|
+ query.value.content = textItem.value.value
|
|
|
+ query.value.positionIds = select.value.map(e => e.id)
|
|
|
+ list.value.forEach(e => query.value[e.key] = e.value === -1 ? '' : e.value)
|
|
|
+ emit('search', query.value)
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.active {
|
|
|
+ border: 1px solid var(--v-primary-base) !important;
|
|
|
+ color: var(--v-primary-base) !important;
|
|
|
+}
|
|
|
+.tag {
|
|
|
+ padding: 5px 15px;
|
|
|
+ border: 1px solid #d3d0d0;
|
|
|
+ border-radius: 5px;
|
|
|
+}
|
|
|
+.second-tag {
|
|
|
+ background-color: #fff;
|
|
|
+ color: #666;
|
|
|
+ padding: 5px 15px;
|
|
|
+ border-radius: 5px;
|
|
|
+}
|
|
|
+.triangle-container {
|
|
|
+ position: relative;
|
|
|
+ background-color: #f2f2f2;
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
+ position: absolute;
|
|
|
+ left: 10%;
|
|
|
+ top: -19px;
|
|
|
+ margin-left: -5px;
|
|
|
+ border-width: 10px 10px 10px 10px;
|
|
|
+ border-style: solid;
|
|
|
+ border-color: transparent transparent #f2f2f2 transparent;
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.v-slide-group__content) {
|
|
|
+ width: 100% !important;
|
|
|
+ flex-wrap: wrap !important;
|
|
|
+}
|
|
|
+</style>
|