添加招聘分类筛选功能
This commit is contained in:
@@ -83,6 +83,11 @@ export interface JobListParams {
|
|||||||
statusFilter?: number[]
|
statusFilter?: number[]
|
||||||
/** 搜索关键词 */
|
/** 搜索关键词 */
|
||||||
keyword?: string
|
keyword?: string
|
||||||
|
/** 招聘分类 0=校招 1=实习 2=社招 3=其他 */
|
||||||
|
recruitCategory?: number
|
||||||
|
/** 排除岗位ID列表(用于推荐时排除已推荐过的) */
|
||||||
|
excludeJobIds?: number[]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 求职意向 ====================
|
// ==================== 求职意向 ====================
|
||||||
@@ -123,6 +128,9 @@ export function saveJobIntention(data: JobIntention) {
|
|||||||
* @param params 岗位列表查询参数
|
* @param params 岗位列表查询参数
|
||||||
*/
|
*/
|
||||||
export function fetchJobList(params: JobListParams = {}) {
|
export function fetchJobList(params: JobListParams = {}) {
|
||||||
|
//兼容旧的数据组件,让招聘分类参数从工作类型那里拿,工作类型不需要传了
|
||||||
|
params.recruitCategory = params.employmentType
|
||||||
|
delete params.employmentType
|
||||||
return request.post<any, ApiResult<JobPageData>>('/job/list', {
|
return request.post<any, ApiResult<JobPageData>>('/job/list', {
|
||||||
pageNum: params.pageNum ?? 1,
|
pageNum: params.pageNum ?? 1,
|
||||||
pageSize: params.pageSize ?? 15,
|
pageSize: params.pageSize ?? 15,
|
||||||
|
|||||||
@@ -234,6 +234,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { formatEmploymentType } from '@/stores/index'
|
||||||
import ProfilePageContent from '@/components/ProfilePageContent.vue'
|
import ProfilePageContent from '@/components/ProfilePageContent.vue'
|
||||||
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
||||||
import JobGoalDialog from '@/components/JobGoalDialog.vue'
|
import JobGoalDialog from '@/components/JobGoalDialog.vue'
|
||||||
@@ -282,7 +283,7 @@ const intentionIndustryNames = computed(() => (store.state.jobIntention?.industr
|
|||||||
const intentionRegionNames = computed(() => (store.state.jobIntention?.regionCodes || []).map((code: string) => resolveRegionName(code)).filter(Boolean))
|
const intentionRegionNames = computed(() => (store.state.jobIntention?.regionCodes || []).map((code: string) => resolveRegionName(code)).filter(Boolean))
|
||||||
|
|
||||||
/** 求职意向 — 就业类型文案 */
|
/** 求职意向 — 就业类型文案 */
|
||||||
const intentionEmploymentLabel = computed(() => store.state.jobIntention?.employmentType === 1 ? '实习' : '全职')
|
const intentionEmploymentLabel = computed(() => formatEmploymentType(store.state.jobIntention?.employmentType))
|
||||||
|
|
||||||
// ==================== 浏览器插件 ====================
|
// ==================== 浏览器插件 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, computed, watch, onMounted } from 'vue'
|
import { ref, reactive, computed, watch, onMounted } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { formatEmploymentType } from '@/stores/index'
|
||||||
import ProfilePageContent from '@/components/ProfilePageContent.vue'
|
import ProfilePageContent from '@/components/ProfilePageContent.vue'
|
||||||
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
||||||
import JobGoalDialog from '@/components/JobGoalDialog.vue'
|
import JobGoalDialog from '@/components/JobGoalDialog.vue'
|
||||||
@@ -402,7 +403,7 @@ const showJobGoalDialog = ref(false)
|
|||||||
const intentionCategoryNames = computed(() => (store.state.jobIntention.categoryIds || []).map((id: number) => resolveJobCategoryName(id)))
|
const intentionCategoryNames = computed(() => (store.state.jobIntention.categoryIds || []).map((id: number) => resolveJobCategoryName(id)))
|
||||||
const intentionIndustryNames = computed(() => (store.state.jobIntention.industryIds || []).map((id: number) => resolveIndustryName(id)))
|
const intentionIndustryNames = computed(() => (store.state.jobIntention.industryIds || []).map((id: number) => resolveIndustryName(id)))
|
||||||
const intentionRegionNames = computed(() => (store.state.jobIntention.regionCodes || []).map((code: string) => resolveRegionName(code)))
|
const intentionRegionNames = computed(() => (store.state.jobIntention.regionCodes || []).map((code: string) => resolveRegionName(code)))
|
||||||
const intentionEmploymentLabel = computed(() => store.state.jobIntention.employmentType === 1 ? '实习' : '全职')
|
const intentionEmploymentLabel = computed(() => formatEmploymentType(store.state.jobIntention.employmentType))
|
||||||
|
|
||||||
interface MatchedJobItem extends JobListItem { feedback: string }
|
interface MatchedJobItem extends JobListItem { feedback: string }
|
||||||
const matchedJobs = ref<MatchedJobItem[]>([])
|
const matchedJobs = ref<MatchedJobItem[]>([])
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { Close } from '@element-plus/icons-vue'
|
import { Close } from '@element-plus/icons-vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { JOB_TYPE_OPTIONS, formatEmploymentType } from '@/stores/index'
|
||||||
import RegionSelector from './tools/RegionSelector.vue'
|
import RegionSelector from './tools/RegionSelector.vue'
|
||||||
import IndustrySelector from './tools/IndustrySelector.vue'
|
import IndustrySelector from './tools/IndustrySelector.vue'
|
||||||
import JobCategorySelector from './tools/JobCategorySelector.vue'
|
import JobCategorySelector from './tools/JobCategorySelector.vue'
|
||||||
@@ -117,8 +118,8 @@ const selectedIndustryIds = ref<number[]>([])
|
|||||||
const selectedRegionCodes = ref<string[]>([])
|
const selectedRegionCodes = ref<string[]>([])
|
||||||
const selectedJobType = ref('全职')
|
const selectedJobType = ref('全职')
|
||||||
|
|
||||||
/** 工作类型选项列表 */
|
/** 工作类型选项列表 — 从全局常量提取 label 生成 */
|
||||||
const jobTypes = ['实习', '全职']
|
const jobTypes = JOB_TYPE_OPTIONS.map(item => item.label)
|
||||||
|
|
||||||
/** 弹窗打开时从 store 同步数据到本地编辑副本 */
|
/** 弹窗打开时从 store 同步数据到本地编辑副本 */
|
||||||
watch(() => props.modelValue, (v) => {
|
watch(() => props.modelValue, (v) => {
|
||||||
@@ -127,7 +128,7 @@ watch(() => props.modelValue, (v) => {
|
|||||||
selectedCategoryIds.value = [...(intention.categoryIds || [])]
|
selectedCategoryIds.value = [...(intention.categoryIds || [])]
|
||||||
selectedIndustryIds.value = [...(intention.industryIds || [])]
|
selectedIndustryIds.value = [...(intention.industryIds || [])]
|
||||||
selectedRegionCodes.value = [...(intention.regionCodes || [])]
|
selectedRegionCodes.value = [...(intention.regionCodes || [])]
|
||||||
selectedJobType.value = intention.employmentType === 1 ? '实习' : '全职'
|
selectedJobType.value = formatEmploymentType(intention.employmentType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ async function handleSave() {
|
|||||||
categoryIds: [...selectedCategoryIds.value],
|
categoryIds: [...selectedCategoryIds.value],
|
||||||
industryIds: [...selectedIndustryIds.value],
|
industryIds: [...selectedIndustryIds.value],
|
||||||
regionCodes: [...selectedRegionCodes.value],
|
regionCodes: [...selectedRegionCodes.value],
|
||||||
employmentType: selectedJobType.value === '实习' ? 1 : 0,
|
employmentType: JOB_TYPE_OPTIONS.find(o => o.label === selectedJobType.value)?.value ?? 0,
|
||||||
})
|
})
|
||||||
visible.value = false
|
visible.value = false
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -208,6 +208,7 @@
|
|||||||
import { ref, reactive, watch, computed } from 'vue'
|
import { ref, reactive, watch, computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { formatEmploymentType } from '@/stores/index'
|
||||||
import { logout } from '@/api/auth'
|
import { logout } from '@/api/auth'
|
||||||
import { fetchMemberStatus, type MemberStatus } from '@/api/member'
|
import { fetchMemberStatus, type MemberStatus } from '@/api/member'
|
||||||
import { fetchAgreement } from '@/api/common'
|
import { fetchAgreement } from '@/api/common'
|
||||||
@@ -367,7 +368,7 @@ const intentionRegionNames = computed(() => {
|
|||||||
|
|
||||||
/** 就业类型标签 */
|
/** 就业类型标签 */
|
||||||
const intentionEmploymentLabel = computed(() => {
|
const intentionEmploymentLabel = computed(() => {
|
||||||
return store.state.jobIntention.employmentType === 1 ? '实习' : '全职'
|
return formatEmploymentType(store.state.jobIntention.employmentType)
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 编辑目标岗位 — 打开求职目标弹窗 */
|
/** 编辑目标岗位 — 打开求职目标弹窗 */
|
||||||
|
|||||||
@@ -10,6 +10,23 @@ import type { JobIntention } from '@/api/jobs'
|
|||||||
import { fetchUserInfo } from '@/api/auth'
|
import { fetchUserInfo } from '@/api/auth'
|
||||||
import type { UserInfo } from '@/api/auth'
|
import type { UserInfo } from '@/api/auth'
|
||||||
|
|
||||||
|
/** 工作类型选项:label → 接口参数 employmentType(0=全职 1=实习) */
|
||||||
|
export const JOB_TYPE_OPTIONS: { label: string; value: number }[] = [
|
||||||
|
{ label: '校招', value: 0 },
|
||||||
|
{ label: '实习', value: 1 },
|
||||||
|
{ label: '社招', value: 2 },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 工作类型映射:数字 → 中文标签 */
|
||||||
|
export const JOB_TYPE_MAP: Record<number, string> = Object.fromEntries(
|
||||||
|
JOB_TYPE_OPTIONS.map(item => [item.value, item.label]),
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 根据 employmentType 值获取中文标签,未匹配返回"未知" */
|
||||||
|
export function formatEmploymentType(type: number | undefined | null): string {
|
||||||
|
return JOB_TYPE_MAP[type ?? -1] ?? '未知'
|
||||||
|
}
|
||||||
|
|
||||||
/** 职位列表页缓存数据(从详情页返回时恢复用) */
|
/** 职位列表页缓存数据(从详情页返回时恢复用) */
|
||||||
export interface JobListCache {
|
export interface JobListCache {
|
||||||
/** 缓存的职位列表 */
|
/** 缓存的职位列表 */
|
||||||
|
|||||||
@@ -288,6 +288,7 @@
|
|||||||
import { ref, reactive, computed, nextTick, onMounted } from 'vue'
|
import { ref, reactive, computed, nextTick, onMounted } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { formatEmploymentType } from '@/stores/index'
|
||||||
import SideNav from '@/components/SideNav.vue'
|
import SideNav from '@/components/SideNav.vue'
|
||||||
import AiChat from '@/components/AiChat.vue'
|
import AiChat from '@/components/AiChat.vue'
|
||||||
import JobPageHeader from '@/components/JobPageHeader.vue'
|
import JobPageHeader from '@/components/JobPageHeader.vue'
|
||||||
@@ -311,11 +312,7 @@ const jobId = route.params.id as string
|
|||||||
|
|
||||||
// ==================== 工具函数 ====================
|
// ==================== 工具函数 ====================
|
||||||
|
|
||||||
/** 工作类型映射:数字 → 中文 */
|
/** 工作类型映射:使用全局统一的 formatEmploymentType */
|
||||||
function formatEmploymentType(type: number | undefined): string {
|
|
||||||
const map: Record<number, string> = { 0: '全职', 1: '兼职' }
|
|
||||||
return map[type ?? -1] ?? '未知'
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 学历要求映射:数字 → 中文 */
|
/** 学历要求映射:数字 → 中文 */
|
||||||
function formatEducation(edu: number | undefined): string {
|
function formatEducation(edu: number | undefined): string {
|
||||||
|
|||||||
+3
-5
@@ -285,6 +285,7 @@
|
|||||||
import { ref, watch, onMounted, onBeforeUnmount, nextTick, computed } from 'vue'
|
import { ref, watch, onMounted, onBeforeUnmount, nextTick, computed } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { JOB_TYPE_OPTIONS } from '@/stores/index'
|
||||||
import SideNav from '@/components/SideNav.vue'
|
import SideNav from '@/components/SideNav.vue'
|
||||||
import AiChat from '@/components/AiChat.vue'
|
import AiChat from '@/components/AiChat.vue'
|
||||||
import JobPageHeader from '@/components/JobPageHeader.vue'
|
import JobPageHeader from '@/components/JobPageHeader.vue'
|
||||||
@@ -449,11 +450,8 @@ const filters = ref<FilterItem[]>([
|
|||||||
{ label: '工作类型', key: 'jobType', selected: '' },
|
{ label: '工作类型', key: 'jobType', selected: '' },
|
||||||
])
|
])
|
||||||
|
|
||||||
/** 工作类型选项映射:label → 接口参数 employmentType(0=全职 1=实习) */
|
/** 工作类型选项映射:从全局 store 常量统一引入 */
|
||||||
const jobTypeOptions: { label: string; value: number }[] = [
|
const jobTypeOptions = JOB_TYPE_OPTIONS
|
||||||
{ label: '全职', value: 0 },
|
|
||||||
{ label: '实习', value: 1 },
|
|
||||||
]
|
|
||||||
|
|
||||||
/** 工作类型下拉菜单是否显示 */
|
/** 工作类型下拉菜单是否显示 */
|
||||||
const showJobTypeDropdown = ref(false)
|
const showJobTypeDropdown = ref(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user