From 14dafac1472bda96332eb639f31a066027ab6ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E8=BE=89?= <13935151924@163.com> Date: Thu, 16 Oct 2025 16:44:30 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=B8=83=E5=B1=80=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserTypeSwitcher/UserTypeSwitcher.vue | 100 ++++ components/selectFilter/selectFilter.vue | 16 + components/tabbar/midell-box.vue | 146 ++++-- pages.json | 14 + pages/index/components/index-one.vue | 279 ++++++++++- pages/job/publishJob.vue | 454 ++++++++++++++++++ pages/test/userTypeTest.vue | 218 +++++++++ static/tabbar/publish-job-selected.svg | 3 + static/tabbar/publish-job.svg | 3 + stores/useDictStore.js | 1 + stores/useUserStore.js | 6 + 用户类型导航功能说明.md | 95 ++++ 12 files changed, 1281 insertions(+), 54 deletions(-) create mode 100644 components/UserTypeSwitcher/UserTypeSwitcher.vue create mode 100644 pages/job/publishJob.vue create mode 100644 pages/test/userTypeTest.vue create mode 100644 static/tabbar/publish-job-selected.svg create mode 100644 static/tabbar/publish-job.svg create mode 100644 用户类型导航功能说明.md diff --git a/components/UserTypeSwitcher/UserTypeSwitcher.vue b/components/UserTypeSwitcher/UserTypeSwitcher.vue new file mode 100644 index 0000000..cee16dc --- /dev/null +++ b/components/UserTypeSwitcher/UserTypeSwitcher.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/components/selectFilter/selectFilter.vue b/components/selectFilter/selectFilter.vue index 69db35e..5741750 100644 --- a/components/selectFilter/selectFilter.vue +++ b/components/selectFilter/selectFilter.vue @@ -72,6 +72,16 @@ import { ref, reactive, nextTick, onBeforeMount } from 'vue'; import useDictStore from '@/stores/useDictStore'; const { getTransformChildren } = useDictStore(); +// 岗位类型数据 +const getJobTypeData = () => { + return [ + { label: '常规岗位', value: 'regular', text: '常规岗位' }, + { label: '就业见习岗位', value: 'internship', text: '就业见习岗位' }, + { label: '实习实训岗位', value: 'training', text: '实习实训岗位' }, + { label: '社区实践岗位', value: 'community', text: '社区实践岗位' } + ]; +}; + const area = ref(true); const maskClick = ref(false); const maskClickFn = ref(null); @@ -164,6 +174,12 @@ function getoptions() { if (area.value) { arr.push(getTransformChildren('area', '区域')); } + // 添加岗位类型选项 + arr.push({ + label: '岗位类型', + key: 'jobType', + options: getJobTypeData() + }); filterOptions.value = arr; activeTab.value = 'education'; } diff --git a/components/tabbar/midell-box.vue b/components/tabbar/midell-box.vue index 89ec8b2..669f88d 100644 --- a/components/tabbar/midell-box.vue +++ b/components/tabbar/midell-box.vue @@ -21,6 +21,9 @@ diff --git a/pages.json b/pages.json index d1ba1d1..680199d 100644 --- a/pages.json +++ b/pages.json @@ -47,6 +47,20 @@ "navigationStyle": "custom" } }, + { + "path": "pages/test/userTypeTest", + "style": { + "navigationBarTitleText": "用户类型测试", + "navigationStyle": "custom" + } + }, + { + "path": "pages/job/publishJob", + "style": { + "navigationBarTitleText": "发布岗位", + "navigationStyle": "custom" + } + }, { "path": "pages/chat/chat", "style": { diff --git a/pages/index/components/index-one.vue b/pages/index/components/index-one.vue index 4e92dd0..d2472be 100644 --- a/pages/index/components/index-one.vue +++ b/pages/index/components/index-one.vue @@ -8,18 +8,99 @@ - + 附近工作 好岗职等你来 - + + + + + + + + + + + + + 服务指导 + + + + + + + + + + 事业单位招录 + + + + + + + + 简历制作 + + + + + + + + + + 劳动政策指引 + + + + + + + + 技能培训信息 + + + + + + + + 技能评价指引 + + + + + + + + 题库和考试 + + + + + + + + 素质测评 + + + + + + + + AI智能面试 - + @@ -176,6 +257,7 @@ import selectFilter from '@/components/selectFilter/selectFilter.vue'; import { useRecommedIndexedDBStore, jobRecommender } from '@/stores/useRecommedIndexedDBStore.js'; import { useScrollDirection } from '@/hook/useScrollDirection'; import { useColumnCount } from '@/hook/useColumnCount'; +import UserTypeSwitcher from '@/components/UserTypeSwitcher/UserTypeSwitcher.vue'; const { isScrollingDown, handleScroll } = useScrollDirection(); const recommedIndexDb = useRecommedIndexedDBStore(); const emits = defineEmits(['onShowTabbar']); @@ -209,6 +291,8 @@ const rangeOptions = ref([ { value: 3, text: '疆外' }, ]); const isLoaded = ref(false); +// 控制用户类型切换器显示(测试用) +const showUserTypeSwitcher = ref(true); const { columnCount, columnSpace } = useColumnCount(() => { pageState.pageSize = 10 * (columnCount.value - 1); @@ -297,6 +381,35 @@ function nextDetail(job) { navTo(`/packageA/pages/post/post?jobId=${btoa(job.jobId)}`); } +function navToService(serviceType) { + // 根据服务类型跳转到不同页面 + const serviceRoutes = { + 'service-guidance': '/pages/service/guidance', + 'public-recruitment': '/pages/service/public-recruitment', + 'resume-creation': '/packageA/pages/myResume/myResume', + 'labor-policy': '/pages/service/labor-policy', + 'skill-training': '/pages/service/skill-training', + 'skill-evaluation': '/pages/service/skill-evaluation', + 'question-bank': '/pages/service/question-bank', + 'quality-assessment': '/pages/service/quality-assessment', + 'ai-interview': '/pages/chat/chat', + 'job-search': '/pages/search/search', + 'career-planning': '/pages/service/career-planning', + 'salary-query': '/pages/service/salary-query', + 'company-info': '/pages/service/company-info', + 'interview-tips': '/pages/service/interview-tips', + 'employment-news': '/pages/service/employment-news', + 'more-services': '/pages/service/more-services' + }; + + const route = serviceRoutes[serviceType]; + if (route) { + navTo(route); + } else { + $api.msg('功能开发中,敬请期待'); + } +} + function openFilter() { showFilter.value = true; emits('onShowTabbar', false); @@ -304,6 +417,7 @@ function openFilter() { title: '筛选', maskClick: true, success: (values) => { + console.log('---', values); pageState.search = { ...pageState.search, }; @@ -596,7 +710,7 @@ defineExpose({ loadData }); padding: 10rpx 28rpx display: grid grid-gap: 38rpx; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr; .card height: calc(158rpx - 40rpx); padding: 22rpx 26rpx @@ -624,6 +738,163 @@ defineExpose({ loadData }); background-size: cover; background-position: center; +// 服务功能网格样式 +.service-grid + padding: 20rpx 28rpx + display: grid + grid-template-columns: 1fr 1fr 1fr 1fr + grid-gap: 20rpx + .service-item + display: flex + flex-direction: column + align-items: center + justify-content: center + height: 120rpx + background: transparent + padding: 10px 0px + .service-icon + width: 88rpx + height: 88rpx + border-radius: 12rpx + margin-bottom: 8rpx + flex-shrink: 0 + .service-icon-1 + background: linear-gradient(180deg, #FF8E8E 0%, #E53E3E 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-2 + background: linear-gradient(180deg, #6ED5CE 0%, #38B2AC 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-3 + background: linear-gradient(180deg, #6BC5D8 0%, #3182CE 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-4 + background: linear-gradient(180deg, #FFB74D 0%, #ED8936 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-5 + background: linear-gradient(180deg, #F06292 0%, #C2185B 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-6 + background: linear-gradient(180deg, #FFB74D 0%, #ED8936 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-7 + background: linear-gradient(180deg, #6BC5D8 0%, #3182CE 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-8 + background: linear-gradient(180deg, #81C784 0%, #4CAF50 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-9 + background: linear-gradient(180deg, #6BC5D8 0%, #3182CE 100%) + position: relative + display: flex + align-items: center + justify-content: center + .service-icon-10 + background: linear-gradient(135deg, #9C27B0 0%, #BA68C8 100%) + position: relative + &::before + content: '🔍' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-11 + background: linear-gradient(135deg, #FF9800 0%, #FFB74D 100%) + position: relative + &::before + content: '📈' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-12 + background: linear-gradient(135deg, #4CAF50 0%, #81C784 100%) + position: relative + &::before + content: '💰' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-13 + background: linear-gradient(135deg, #607D8B 0%, #90A4AE 100%) + position: relative + &::before + content: '🏢' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-14 + background: linear-gradient(135deg, #E91E63 0%, #F06292 100%) + position: relative + &::before + content: '💡' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-15 + background: linear-gradient(135deg, #795548 0%, #A1887F 100%) + position: relative + &::before + content: '📰' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-icon-16 + background: linear-gradient(135deg, #424242 0%, #757575 100%) + position: relative + &::before + content: '⚙️' + position: absolute + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 32rpx + .service-title + font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif + font-weight: 500 + font-size: 24rpx + color: #333333 + text-align: center + line-height: 1.2 + white-space: nowrap + overflow: hidden + text-overflow: ellipsis + width: 100% + max-width: 100% + .nav-filter padding: 16rpx 28rpx 0 28rpx font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif; diff --git a/pages/job/publishJob.vue b/pages/job/publishJob.vue new file mode 100644 index 0000000..f159601 --- /dev/null +++ b/pages/job/publishJob.vue @@ -0,0 +1,454 @@ + + + + + diff --git a/pages/test/userTypeTest.vue b/pages/test/userTypeTest.vue new file mode 100644 index 0000000..799b23b --- /dev/null +++ b/pages/test/userTypeTest.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/static/tabbar/publish-job-selected.svg b/static/tabbar/publish-job-selected.svg new file mode 100644 index 0000000..408c313 --- /dev/null +++ b/static/tabbar/publish-job-selected.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/tabbar/publish-job.svg b/static/tabbar/publish-job.svg new file mode 100644 index 0000000..12b610e --- /dev/null +++ b/static/tabbar/publish-job.svg @@ -0,0 +1,3 @@ + + + diff --git a/stores/useDictStore.js b/stores/useDictStore.js index 80769dc..5cc02e3 100644 --- a/stores/useDictStore.js +++ b/stores/useDictStore.js @@ -135,6 +135,7 @@ const useDictStore = defineStore("dict", () => { return null } + async function getDictSelectOption(dictType, isDigital) { const resp = await createRequest(`/app/common/dict/${dictType}`); if (resp.code === 200 && resp.data) { diff --git a/stores/useUserStore.js b/stores/useUserStore.js index 882f15b..776df76 100644 --- a/stores/useUserStore.js +++ b/stores/useUserStore.js @@ -111,6 +111,12 @@ const useUserStore = defineStore("user", () => { resume.value = values.data; // 将用户信息同时存储到resume中 // role.value = values.role; hasLogin.value = true; + + // 模拟添加用户类型字段,实际项目中应该从接口获取 + if (!userInfo.value.userType) { + userInfo.value.userType = 0; // 默认设置为企业用户 + } + // 持久化存储用户信息到本地缓存 uni.setStorageSync('userInfo', values.data); } diff --git a/用户类型导航功能说明.md b/用户类型导航功能说明.md new file mode 100644 index 0000000..07a85cb --- /dev/null +++ b/用户类型导航功能说明.md @@ -0,0 +1,95 @@ +# 用户类型导航功能实现说明 + +## 功能概述 + +根据用户类型动态显示不同的底部导航栏: +- **企业用户(userType=0)**:显示"发布岗位"导航,隐藏"招聘会"导航 +- **其他用户(userType=1,2,3)**:显示"招聘会"导航 + +## 实现内容 + +### 1. 用户信息扩展 +- 在 `stores/useUserStore.js` 中添加了模拟的 `userType` 字段 +- 默认设置为企业用户(userType=0) + +### 2. 导航栏组件修改 +- 修改了 `components/tabbar/midell-box.vue` +- 根据 `userInfo.userType` 动态生成不同的导航配置 +- 企业用户显示"发布岗位",其他用户显示"招聘会" +- 修复了跳转逻辑:tabBar页面使用 `switchTab`,普通页面使用 `navigateTo` +- 更新了发布岗位图标:使用自定义SVG图标 + - 未选中状态:深灰色 (#666666) - 新图标设计 + - 选中状态:蓝色 (#256BFA) - 新图标设计 + +### 3. 发布岗位页面 +- 创建了 `pages/job/publishJob.vue` 发布岗位页面 +- 包含完整的岗位信息表单 +- 支持岗位基本信息、薪资待遇、任职要求、岗位描述、联系方式等 + +### 4. 测试组件 +- 创建了 `components/UserTypeSwitcher/UserTypeSwitcher.vue` 用于测试 +- 创建了 `pages/test/userTypeTest.vue` 测试页面 +- 在首页添加了用户类型切换器(可控制显示/隐藏) + +## 用户类型定义 + +```javascript +const userTypes = [ + { value: 0, label: '企业用户' }, + { value: 1, label: '求职者' }, + { value: 2, label: '网格员' }, + { value: 3, label: '政府人员' } +]; +``` + +## 导航栏配置 + +### 企业用户(userType=0) +- 首页 +- 发布岗位(招聘会导航完全隐藏) +- AI助手 +- 消息 +- 我的 + +### 其他用户(userType=1,2,3) +- 首页 +- 招聘会 +- AI助手 +- 消息 +- 我的 + +## 使用方法 + +### 1. 切换用户类型 +```javascript +// 在组件中切换用户类型 +userInfo.value.userType = 0; // 切换到企业用户 +uni.setStorageSync('userInfo', userInfo.value); +``` + +### 2. 测试功能 +- 访问 `/pages/test/userTypeTest` 页面进行测试 +- 在首页可以看到用户类型切换器(测试用) + +### 3. 生产环境 +- 移除测试相关的组件和代码 +- 从后端接口获取真实的用户类型信息 + +## 注意事项 + +1. 当前是模拟实现,实际项目中需要从后端接口获取用户类型 +2. 发布岗位页面已存在:`/packageA/pages/addPosition/addPosition` +3. 招聘会页面已存在:`/pages/careerfair/careerfair` +4. 测试完成后可以隐藏用户类型切换器 + +## 文件修改清单 + +- `stores/useUserStore.js` - 添加 userType 字段 +- `components/tabbar/midell-box.vue` - 动态导航配置 +- `pages/job/publishJob.vue` - 发布岗位页面 +- `static/tabbar/publish-job.svg` - 发布岗位图标(普通状态) +- `static/tabbar/publish-job-selected.svg` - 发布岗位图标(选中状态) +- `components/UserTypeSwitcher/UserTypeSwitcher.vue` - 测试组件 +- `pages/test/userTypeTest.vue` - 测试页面 +- `pages/index/components/index-one.vue` - 添加测试组件 +- `pages.json` - 添加页面配置