|
@@ -1,34 +1,18 @@
|
|
<template>
|
|
<template>
|
|
- <div class="d-flex" :style="{ 'z-index': isPage ? '' : 999 }" :class="isPage ? 'hasPageCard' : 'floatCard'" @mouseleave="handleMouseLeave">
|
|
|
|
|
|
+ <div class="floatCard d-flex" style="z-index: 999" @mouseleave="handleMouseLeave">
|
|
<v-card class="card">
|
|
<v-card class="card">
|
|
<div class="leftCard">
|
|
<div class="leftCard">
|
|
<div
|
|
<div
|
|
- class="leftCardItem" :class="{'leftIndexAct': index === leftIndex, 'elevation-5': (index === leftIndex && isPage)}"
|
|
|
|
|
|
+ class="leftCardItem"
|
|
|
|
+ :class="{'leftIndexAct': index === leftIndex,'leftSelectedAct': leftEchoIdArr?.length ? leftEchoIdArr.includes(item.id) : false}"
|
|
v-for="(item, index) in items" :key="item.id"
|
|
v-for="(item, index) in items" :key="item.id"
|
|
@mouseover="handleMouseOver(item, index)"
|
|
@mouseover="handleMouseOver(item, index)"
|
|
>
|
|
>
|
|
<div class="rowItem d-flex">
|
|
<div class="rowItem d-flex">
|
|
<span class="categoryName">{{ item.nameCn }}</span>
|
|
<span class="categoryName">{{ item.nameCn }}</span>
|
|
- <div class="jobItemsBox">
|
|
|
|
- <div class="outerCovering" v-if="isPage && item.children?.length && item.children[0].children.length">
|
|
|
|
- <div class="jobItems" v-for="val in item.children[0].children" :key="val.id" @click="handleJobClick(val)">{{ val.nameCn }}</div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
<span class="mdi mdi-menu-right"></span>
|
|
<span class="mdi mdi-menu-right"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- <!-- 分页 -->
|
|
|
|
- <div v-if="isPage" class="mt-2" @mouseover.stop="handleMouseLeave" style="border-top: 1px dashed #e6e6e6; position: absolute; bottom: 4px; width: 100%;">
|
|
|
|
- <div class="d-flex justify-space-between align-center mx-4" style="height: 40px">
|
|
|
|
- <div style="color: var(--v-primary-base); font-size: 14px;">
|
|
|
|
- {{ pageInfo.current }} / {{ pageCount }}
|
|
|
|
- </div>
|
|
|
|
- <div>
|
|
|
|
- <v-btn @click="previous" size="x-small" class="ml-2" color="primary" variant="tonal" style="font-size: 20px;"><v-icon icon="mdi-menu-left" size="x-small"></v-icon></v-btn>
|
|
|
|
- <v-btn @click="nextPage" size="x-small" class="ml-2" color="primary" variant="tonal" style="font-size: 20px;"><v-icon icon="mdi-menu-right" size="x-small"></v-icon></v-btn>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
</div>
|
|
</div>
|
|
</v-card>
|
|
</v-card>
|
|
<v-card v-if="rightObj.show" class="card rightCardBox">
|
|
<v-card v-if="rightObj.show" class="card rightCardBox">
|
|
@@ -42,10 +26,10 @@
|
|
<div v-if="!item.children?.length"></div>
|
|
<div v-if="!item.children?.length"></div>
|
|
<div
|
|
<div
|
|
v-else
|
|
v-else
|
|
- :class="['jobItem', {'active': selectItems.includes(val.id)}]"
|
|
|
|
|
|
+ :class="['jobItem', {'active': selectItems.includes(val.id)}]"
|
|
v-for="val in item.children"
|
|
v-for="val in item.children"
|
|
:key="val.id"
|
|
:key="val.id"
|
|
- @click="handleJobClick(val)"
|
|
|
|
|
|
+ @click="handleClick(val)"
|
|
>
|
|
>
|
|
{{ val.nameCn }}</div>
|
|
{{ val.nameCn }}</div>
|
|
</div>
|
|
</div>
|
|
@@ -53,54 +37,79 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</v-card>
|
|
</v-card>
|
|
- <v-card height="392px" v-if="isPage && !rightObj.show" class="card rightCardBox">
|
|
|
|
- <v-carousel show-arrows="hover" cycle>
|
|
|
|
- <v-carousel-item v-for="(item, i) in carouselList" :key="i">
|
|
|
|
- <div style="height: 392px; overflow: hidden;">
|
|
|
|
- <v-img :src="item.src" cover style="height: 100%; overflow: hidden;"></v-img>
|
|
|
|
- </div>
|
|
|
|
- </v-carousel-item>
|
|
|
|
- </v-carousel>
|
|
|
|
- </v-card>
|
|
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
-import { getPositionTreeClick } from '@/api/common/index'
|
|
|
|
import { getDict } from '@/hooks/web/useDictionaries'
|
|
import { getDict } from '@/hooks/web/useDictionaries'
|
|
|
|
+import { buryingPoint } from '@/hooks/web/buryingPoint'
|
|
import { reactive, ref, defineEmits } from 'vue';
|
|
import { reactive, ref, defineEmits } from 'vue';
|
|
-import { useRoute } from 'vue-router'
|
|
|
|
defineOptions({ name:'common-components-jobTypeCard'})
|
|
defineOptions({ name:'common-components-jobTypeCard'})
|
|
|
|
|
|
const emits = defineEmits(['handleJobClick', 'jobClick'])// 定义一个或多个自定义事件
|
|
const emits = defineEmits(['handleJobClick', 'jobClick'])// 定义一个或多个自定义事件
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
- page: { // 左侧数据是否分页(首页有分页)
|
|
|
|
|
|
+ echo: { // 是否回显
|
|
|
|
+ type: Boolean,
|
|
|
|
+ default: false
|
|
|
|
+ },
|
|
|
|
+ isSingle: { // 是否单选
|
|
type: Boolean,
|
|
type: Boolean,
|
|
default: false
|
|
default: false
|
|
},
|
|
},
|
|
- // 是否单选(首页为单选)
|
|
|
|
- isSingle: {
|
|
|
|
|
|
+ isBuryingPoint: { // 是否埋点
|
|
type: Boolean,
|
|
type: Boolean,
|
|
default: false
|
|
default: false
|
|
},
|
|
},
|
|
- select: {
|
|
|
|
|
|
+ select: { // 已选中
|
|
type: Array,
|
|
type: Array,
|
|
default: () => []
|
|
default: () => []
|
|
}
|
|
}
|
|
})
|
|
})
|
|
-const isPage = props.page
|
|
|
|
const selectItems = ref([])
|
|
const selectItems = ref([])
|
|
|
|
+let leftEchoIdArr = ref([])
|
|
|
|
+let loading = ref(false)
|
|
|
|
|
|
// 回显
|
|
// 回显
|
|
if (props.select.length) selectItems.value = props.select.map(e => e)
|
|
if (props.select.length) selectItems.value = props.select.map(e => e)
|
|
|
|
+// 回显左侧level:1选中
|
|
|
|
+const echoLeft = async () => {
|
|
|
|
+ if (!props.echo || !items.value?.length) return loading.value = false
|
|
|
|
+ if (!selectItems.value.length) {
|
|
|
|
+ leftEchoIdArr.value = ref([])
|
|
|
|
+ loading.value = false
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ traverse(items.value)
|
|
|
|
+ try {
|
|
|
|
+ loading.value = true
|
|
|
|
+ await traverse(items.value)
|
|
|
|
+ } catch (error) {
|
|
|
|
+ loading.value = false
|
|
|
|
+ }
|
|
|
|
+ function traverse(nodes) {
|
|
|
|
+ for (const node of nodes) {
|
|
|
|
+ if (selectItems.value.includes(node.id)) {
|
|
|
|
+ const fId = node.path ? node.path.split(',')[0] : null
|
|
|
|
+ if (fId) leftEchoIdArr.value = leftEchoIdArr.value.length ? [...leftEchoIdArr.value, fId] : [fId]
|
|
|
|
+ }
|
|
|
|
+ if (node.children) {
|
|
|
|
+ traverse(node.children)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
-const route = useRoute()
|
|
|
|
-const routeQuery = route?.query
|
|
|
|
|
|
+let items = ref([])
|
|
|
|
+getDict('positionTreeData', null, 'positionTreeData').then(({ data }) => {
|
|
|
|
+ data = data?.length && data || []
|
|
|
|
+ items.value = data
|
|
|
|
+ echoLeft()
|
|
|
|
+})
|
|
|
|
|
|
// 职位点击
|
|
// 职位点击
|
|
-const handleJobClick = async (val) => {
|
|
|
|
- await getPositionTreeClick({ id: val.id }) // 埋点
|
|
|
|
|
|
+const handleClick = async (val) => {
|
|
|
|
+ if (props.isBuryingPoint) buryingPoint({ id: val.id })
|
|
const obj = selectItems.value.includes(val.id)
|
|
const obj = selectItems.value.includes(val.id)
|
|
if (props.isSingle) {
|
|
if (props.isSingle) {
|
|
selectItems.value = obj ? [] : [val.id]
|
|
selectItems.value = obj ? [] : [val.id]
|
|
@@ -109,38 +118,10 @@ const handleJobClick = async (val) => {
|
|
selectItems.value = selectItems.value.filter(e => e.id !== val.id)
|
|
selectItems.value = selectItems.value.filter(e => e.id !== val.id)
|
|
} else selectItems.value.push(val.id)
|
|
} else selectItems.value.push(val.id)
|
|
}
|
|
}
|
|
|
|
+ echoLeft()
|
|
emits('handleJobClick', selectItems.value, selectItems.value.length ? val.nameCn : '')
|
|
emits('handleJobClick', selectItems.value, selectItems.value.length ? val.nameCn : '')
|
|
}
|
|
}
|
|
|
|
|
|
-// 翻页数据
|
|
|
|
-const pageInfo = reactive({ current: 1, size: 8 })
|
|
|
|
-let pageCount = ref(0)
|
|
|
|
-let defaultItems = ref()
|
|
|
|
-
|
|
|
|
-let items = ref([])
|
|
|
|
-// 翻页
|
|
|
|
-const getPageItems = () => {
|
|
|
|
- const startIndex = (pageInfo.current - 1) * pageInfo.size
|
|
|
|
- const endIndex = Math.min(startIndex + pageInfo.size, defaultItems.value.length)
|
|
|
|
- items.value = defaultItems.value.slice(startIndex, endIndex)
|
|
|
|
-}
|
|
|
|
-getDict('positionTreeData', null, 'positionTreeData').then(({ data }) => {
|
|
|
|
- data = data?.length && data || []
|
|
|
|
- if (isPage) { // 有翻页
|
|
|
|
- defaultItems.value = data
|
|
|
|
- if (defaultItems.value?.length) {
|
|
|
|
- pageCount.value = Math.ceil(defaultItems.value.length / pageInfo.size)
|
|
|
|
- getPageItems()
|
|
|
|
- } else pageInfo.current = 0
|
|
|
|
- } else {
|
|
|
|
- items.value = data
|
|
|
|
- }
|
|
|
|
-})
|
|
|
|
-
|
|
|
|
-// 翻页按钮
|
|
|
|
-const previous = () => { if (pageInfo.current > 1) pageInfo.current--; getPageItems() }
|
|
|
|
-const nextPage = () => { if (pageInfo.current < pageCount.value) pageInfo.current++; getPageItems() }
|
|
|
|
-
|
|
|
|
// 右侧职位信息
|
|
// 右侧职位信息
|
|
const leftIndex = ref(null)
|
|
const leftIndex = ref(null)
|
|
const rightObj = reactive({ show: false, data: {} })
|
|
const rightObj = reactive({ show: false, data: {} })
|
|
@@ -148,22 +129,12 @@ const rightObj = reactive({ show: false, data: {} })
|
|
const handleMouseOver = (val, index) => { // 鼠标移入
|
|
const handleMouseOver = (val, index) => { // 鼠标移入
|
|
leftIndex.value = index
|
|
leftIndex.value = index
|
|
rightObj.data = val
|
|
rightObj.data = val
|
|
- // 回显
|
|
|
|
- if (routeQuery && routeQuery.positionId) {
|
|
|
|
- if (props.isSingle) selectItems.value = [routeQuery.positionId]
|
|
|
|
- else selectItems.value = routeQuery.positionId.split('_')
|
|
|
|
- }
|
|
|
|
rightObj.show = true
|
|
rightObj.show = true
|
|
}
|
|
}
|
|
const handleMouseLeave = () => { // 鼠标移出
|
|
const handleMouseLeave = () => { // 鼠标移出
|
|
rightObj.show = false // true false
|
|
rightObj.show = false // true false
|
|
leftIndex.value = null
|
|
leftIndex.value = null
|
|
}
|
|
}
|
|
-// 轮播图片
|
|
|
|
-const carouselList = ref([
|
|
|
|
- { src: 'https://img.kinpan.com/Files/design/detailimages/20161228/6361853956839262507798973.jpg', },
|
|
|
|
- { src: 'https://img0.baidu.com/it/u=3769341087,3426515789&fm=253&fmt=auto&app=138&f=JPEG?w=1180&h=472', },
|
|
|
|
-])
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
@@ -171,11 +142,13 @@ const carouselList = ref([
|
|
color: var(--v-primary-base) !important;
|
|
color: var(--v-primary-base) !important;
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
+
|
|
:deep(.v-window) {
|
|
:deep(.v-window) {
|
|
height: 392px !important;
|
|
height: 392px !important;
|
|
}
|
|
}
|
|
.floatCard {
|
|
.floatCard {
|
|
.leftIndexAct { color: var(--v-primary-base); }
|
|
.leftIndexAct { color: var(--v-primary-base); }
|
|
|
|
+ .leftSelectedAct { color: var(--v-primary-base) !important; }
|
|
.leftCard {
|
|
.leftCard {
|
|
height: 242px;
|
|
height: 242px;
|
|
width: 172px;
|
|
width: 172px;
|
|
@@ -224,83 +197,6 @@ const carouselList = ref([
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-.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 {
|
|
// ::v-deep {
|
|
::-webkit-scrollbar {
|
|
::-webkit-scrollbar {
|
|
width: 4px;
|
|
width: 4px;
|