移动端首页

This commit is contained in:
2026-07-06 21:34:40 +08:00
parent 78bf7fbebc
commit 73f5bde68f
13 changed files with 913 additions and 24 deletions
+20
View File
@@ -715,3 +715,23 @@ export function resolveDiagnosisIssue(issueId: string) {
}],
}).then(res => res.data)
}
// ==================== 修改简历名称和目标岗位(新 Java 后端接口) ====================
/** 修改简历名称/目标岗位 请求参数 */
export interface UpdateResumeInfoParams {
/** 简历 ID(必需,字符串避免大整数精度丢失) */
resumeId: string
/** 简历名称(可选,<= 100 字符) */
resumeName?: string
/** 目标岗位(可选,<= 100 字符) */
targetPosition?: string
}
/**
* 修改简历名称和目标岗位
* POST /resume/updateInfo
*/
export function updateResumeInfo(data: UpdateResumeInfoParams) {
return request.post<any, ApiResult>('/resume/updateInfo', data)
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

+1
View File
@@ -2,6 +2,7 @@
// 页面样式
@use './pages/home.scss';
@use './pages/home-mobile.scss';
@use './pages/agent.scss';
@use './pages/jobs.scss';
@use './pages/resume.scss';
+623
View File
@@ -0,0 +1,623 @@
@use '../variables' as *;
/* ==================== 移动端首页样式 ==================== */
.home-mobile {
position: relative;
width: 100%;
margin: 0 auto;
background: #FFFFFF;
font-size: 0.14rem;
padding-bottom: 0.94rem; /* 底部固定按钮的高度 */
overflow-x: hidden;
/* 背景装饰色块 */
&__orb {
position: absolute;
pointer-events: none;
&--top {
width: 5.40rem;
height: 3.00rem;
left: -0.80rem;
top: -1.20rem;
background: rgba(183, 237, 233, 0.58);
opacity: 0.5;
filter: blur(0.35rem);
}
&--hero {
width: 3.00rem;
height: 2.20rem;
left: 0.64rem;
top: 2.10rem;
background: #EAF8F7;
opacity: 0.55;
filter: blur(0.275rem);
}
}
/* 顶部 Logo */
&__header {
position: relative;
padding: 0.16rem 0.20rem;
z-index: 1;
}
&__logo {
width: 0.95rem;
height: 0.23rem;
object-fit: contain;
}
/* Hero 区域 */
&__hero {
position: relative;
padding: 0.30rem 0.24rem 0;
z-index: 1;
}
&__eyebrow {
font-weight: 700;
font-size: 0.12rem;
line-height: 0.15rem;
color: #42A8B3;
margin-bottom: 0.10rem;
}
&__headline {
font-weight: 700;
font-size: 0.38rem;
line-height: 0.46rem;
color: #12383A;
margin-bottom: 0.32rem;
}
&__subtitle {
font-weight: 400;
font-size: 0.14rem;
line-height: 0.17rem;
color: #687074;
}
/* 指令卡片 */
&__command-card {
position: relative;
width: 3.42rem;
margin: 0.40rem auto 0;
padding: 0.29rem 0.24rem 0.28rem;
background: #12383A;
box-shadow: 0px 0.16rem 0.28rem rgba(79, 194, 201, 0.16);
border-radius: 0.18rem;
z-index: 1;
}
&__command-title {
font-weight: 700;
font-size: 0.16rem;
line-height: 0.19rem;
color: #FFFFFF;
margin-bottom: 0.11rem;
}
&__command-sub {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #B7EDE9;
margin-bottom: 0.24rem;
}
&__progress {
margin-bottom: 0.18rem;
}
&__progress-rail {
width: 100%;
height: 0.08rem;
background: #0F2F32;
border-radius: 0.05rem;
overflow: hidden;
}
&__progress-fill {
width: 74%;
height: 0.08rem;
background: #4FC2C9;
border-radius: 0.05rem;
}
&__command-chips {
font-weight: 700;
font-size: 0.11rem;
line-height: 0.13rem;
color: #FFFFFF;
}
/* 数据统计卡片 */
&__stats-card {
position: relative;
width: 3.42rem;
margin: 0.23rem auto 0;
padding: 0.30rem 0.20rem;
background: #FFFFFF;
box-shadow: 0px 0.12rem 0.22rem rgba(17, 17, 17, 0.07);
border-radius: 0.18rem;
display: flex;
justify-content: space-around;
align-items: center;
z-index: 1;
}
&__stat {
text-align: center;
}
&__stat-num {
display: block;
font-weight: 700;
font-size: 0.28rem;
line-height: 0.34rem;
color: #2A8186;
margin-bottom: 0.04rem;
}
&__stat-label {
font-weight: 400;
font-size: 0.11rem;
line-height: 0.13rem;
color: #8D9399;
}
/* 功能介绍区 */
&__functions {
position: relative;
padding: 0.60rem 0.24rem 0;
z-index: 1;
}
&__section-title {
font-weight: 700;
font-size: 0.24rem;
line-height: 0.29rem;
color: #111111;
margin-bottom: 0.09rem;
}
&__section-sub {
font-weight: 400;
font-size: 0.13rem;
line-height: 0.16rem;
color: #687074;
margin-bottom: 0.26rem;
}
&__feature-list {
display: flex;
flex-direction: column;
gap: 0.20rem;
}
&__feature-card {
width: 100%;
padding: 0.22rem 0.20rem;
background: #FFFFFF;
box-shadow: 0px 0.10rem 0.18rem rgba(17, 17, 17, 0.06);
border-radius: 0.18rem;
display: flex;
align-items: center;
gap: 0.18rem;
}
&__feature-icon {
width: 0.42rem;
height: 0.42rem;
border-radius: 0.12rem;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
span {
font-size: 0.20rem;
}
}
&__feature-text {
h3 {
font-weight: 700;
font-size: 0.17rem;
line-height: 0.21rem;
color: #111111;
margin-bottom: 0.06rem;
}
p {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #687074;
}
}
/* 每天都有新机会 */
&__jobs-section {
position: relative;
margin-top: 0.50rem;
padding: 0.40rem 0.24rem;
background: #DDF4F2;
z-index: 1;
}
&__job-chips {
display: flex;
flex-direction: column;
gap: 0.16rem;
}
&__job-chip {
padding: 0.14rem 0.20rem;
border-radius: 0.14rem;
&--dark {
width: 100%;
background: #12383A;
.home-mobile__job-chip-company {
font-weight: 700;
font-size: 0.12rem;
line-height: 0.15rem;
color: #4FC2C9;
}
.home-mobile__job-chip-role {
font-weight: 400;
font-size: 0.13rem;
line-height: 0.16rem;
color: #FFFFFF;
}
}
&--light {
flex: 1;
background: #FFFFFF;
box-shadow: 0px 0.08rem 0.16rem rgba(17, 17, 17, 0.06);
.home-mobile__job-chip-company {
font-weight: 700;
font-size: 0.12rem;
line-height: 0.15rem;
color: #42A8B3;
}
.home-mobile__job-chip-role {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #111111;
}
}
}
&__job-chip-company,
&__job-chip-role {
display: block;
}
&__job-chip-company {
margin-bottom: 0.04rem;
}
&__job-chip-row {
display: flex;
gap: 0.16rem;
}
/* 万千毕业生的信赖之选 */
&__proof {
position: relative;
padding: 0.50rem 0.24rem 0;
z-index: 1;
}
&__quote-card {
width: 100%;
padding: 0.30rem 0.24rem;
background: #12383A;
border-radius: 0.18rem;
margin-top: 0.20rem;
}
&__quote-text {
font-weight: 700;
font-size: 0.15rem;
line-height: 0.18rem;
color: #FFFFFF;
margin-bottom: 0.24rem;
}
&__quote-author {
display: flex;
align-items: center;
gap: 0.14rem;
}
&__quote-avatar {
width: 0.38rem;
height: 0.38rem;
background: #D9E3EA;
border-radius: 50%;
flex-shrink: 0;
}
&__quote-info {
display: flex;
flex-direction: column;
gap: 0.04rem;
}
&__quote-name {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #B7EDE9;
}
&__quote-school {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #B7EDE9;
}
/* 常见问题 */
&__faq {
position: relative;
padding: 0.50rem 0.24rem 0;
z-index: 1;
}
&__faq-list {
margin-top: 0.20rem;
display: flex;
flex-direction: column;
gap: 0.14rem;
}
&__faq-item {
width: 100%;
background: #FFFFFF;
box-shadow: 0px 0.08rem 0.16rem rgba(17, 17, 17, 0.06);
border-radius: 0.14rem;
overflow: hidden;
}
&__faq-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.18rem 0.20rem;
cursor: pointer;
span:first-child {
font-weight: 700;
font-size: 0.14rem;
line-height: 0.17rem;
color: #111111;
}
}
&__faq-icon {
font-weight: 700;
font-size: 0.18rem;
line-height: 0.22rem;
color: #111111;
flex-shrink: 0;
}
&__faq-answer {
padding: 0 0.20rem 0.18rem;
p {
font-size: 0.12rem;
line-height: 0.18rem;
color: #687074;
}
}
/* 底部 CTA */
&__bottom-cta {
position: relative;
margin-top: 0.50rem;
padding: 0.40rem 0.24rem;
background: #12383A;
z-index: 1;
h2 {
font-weight: 700;
font-size: 0.26rem;
line-height: 0.31rem;
color: #FFFFFF;
margin-bottom: 0.12rem;
}
p {
font-weight: 400;
font-size: 0.13rem;
line-height: 0.16rem;
color: #9AA0A6;
margin-bottom: 0.32rem;
}
}
&__bottom-footer {
font-weight: 700;
font-size: 0.13rem;
line-height: 0.16rem;
color: #4FC2C9;
}
/* 固定底部按钮 */
&__fixed-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 0.12rem 0.24rem;
padding-bottom: calc(0.12rem + env(safe-area-inset-bottom, 0px));
background: #FFFFFF;
z-index: 100;
display: flex;
flex-direction: column;
align-items: center;
}
&__pc-hint {
font-weight: 400;
font-size: 0.12rem;
line-height: 0.15rem;
color: #2A8186;
margin-bottom: 0.06rem;
}
&__cta-btn {
width: calc(100% - 0.48rem);
max-width: 3.42rem;
height: 0.54rem;
background: #4FC2C9;
box-shadow: 0px 0.10rem 0.24rem rgba(0, 0, 0, 0.18);
border-radius: 0.27rem;
border: none;
font-weight: 700;
font-size: 0.16rem;
line-height: 0.19rem;
color: #FFFFFF;
cursor: pointer;
&:active {
opacity: 0.85;
}
}
/* 弹窗遮罩 */
&__overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
display: flex;
align-items: flex-end;
justify-content: center;
}
/* 弹窗内容 */
&__dialog {
width: 100%;
max-width: 100%;
background: #FFFFFF;
border-radius: 0.24rem;
padding: 0.16rem 0.20rem 0.2rem 0.2rem;
position: relative;
text-align: center;
margin: 0 0.16rem 0.24rem 0.16rem;
}
&__dialog-handle {
width: 0.60rem;
height: 0.04rem;
background: #DDF4F2;
border-radius: 0.02rem;
margin: 0 auto 0.20rem;
}
&__dialog-close {
position: absolute;
top: 0.16rem;
right: 0.20rem;
font-size: 0.24rem;
color: #42A8B3;
background: none;
border: none;
cursor: pointer;
line-height: 1;
}
&__dialog h3 {
font-weight: 700;
font-size: 0.22rem;
line-height: 0.28rem;
color: #111111;
margin-bottom: 0.14rem;
text-align: left;
}
&__dialog-desc {
font-weight: 400;
font-size: 0.13rem;
line-height: 0.20rem;
color: #687074;
margin-bottom: 0.20rem;
text-align: left;
}
&__dialog-url {
width: 100%;
padding: 0.14rem 0.16rem;
background: #EAF8F7;
border-radius: 0.12rem;
font-weight: 400;
font-size: 0.14rem;
color: #111111;
text-align: left;
margin-bottom: 0.24rem;
}
&__dialog-qr-title {
font-weight: 700;
font-size: 0.14rem;
color: #111111;
text-align: left;
margin-bottom: 0.14rem;
}
&__dialog-qr {
width: 2.00rem;
height: 2.00rem;
margin: 0 auto 0.12rem;
border-radius: 0.08rem;
display: flex;
align-items: center;
justify-content: center;
background: #EAF8F7;
}
&__dialog-qr-img {
width: 1.60rem;
height: 1.60rem;
object-fit: contain;
}
&__dialog-qr-hint {
font-size: 0.11rem;
color: #8D9399;
margin-bottom: 0.14rem;
}
&__dialog-btn {
width: 100%;
height: 0.50rem;
background: #4FC2C9;
border-radius: 0.25rem;
border: none;
font-weight: 700;
font-size: 0.16rem;
color: #FFFFFF;
cursor: pointer;
&:active {
opacity: 0.85;
}
}
}
+3 -3
View File
@@ -50,7 +50,7 @@
<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import { saveResumeMain } from '@/api/resume'
import { updateResumeInfo } from '@/api/resume'
import { ElMessage } from 'element-plus'
// ==================== Props & Emits ====================
@@ -108,7 +108,7 @@ function handleClose() {
visible.value = false
}
/** 保存简历名称和目标岗位 */
/** 保存简历名称和目标岗位(调用新 Java 后端接口 /resume/updateInfo */
async function handleSave() {
if (!form.resumeName.trim()) {
ElMessage.warning('请输入简历名称')
@@ -117,7 +117,7 @@ async function handleSave() {
saving.value = true
try {
const res = await saveResumeMain({
const res = await updateResumeInfo({
resumeId: props.resumeId,
resumeName: form.resumeName.trim(),
targetPosition: form.targetPosition.trim(),
+21 -2
View File
@@ -28,7 +28,26 @@ const remAdaptPlugin: Plugin = {
if (!body) return
if (isMobile()) {
// 移动端:使用 transform scale 缩放整个页面
// 移动端首页(/m):不使用 scale 缩放,直接以移动端原生尺寸渲染
const isMobileHome = window.location.pathname === '/m'
if (isMobileHome) {
body.style.width = ''
body.style.height = ''
body.style.minHeight = ''
body.style.overflowY = ''
body.style.transform = ''
body.style.transformOrigin = ''
docEl.style.height = ''
docEl.style.overflow = ''
// 移动端首页 1rem = 视口宽度 / 3.90(设计稿 390px
const mobileFontSize = clientWidth / 3.90
docEl.style.fontSize = mobileFontSize + 'px'
docEl.style.setProperty('--app-height', '100vh')
docEl.style.setProperty('--chat-width', '100%')
return
}
// 其他页面:使用 transform scale 缩放整个页面
const scale = clientWidth / designWidth
body.style.width = designWidth + 'px'
body.style.transform = `scale(${scale})`
@@ -36,7 +55,7 @@ const remAdaptPlugin: Plugin = {
// 屏幕越小 scale 越小,适当增大 rem 基准让字体视觉上更大
// 首页和其他页面使用不同的缩放系数
const isHomePage = window.location.pathname === '/' || window.location.pathname === '/index.html'
const isHomePage = window.location.pathname === '/' || window.location.pathname === '/index.html' || window.location.pathname === '/m'
const homeMultiplier = 0.6 // 首页字体放大系数,可单独调整
const otherMultiplier = 2.0 // 其他页面字体放大系数
const multiplier = isHomePage ? homeMultiplier : otherMultiplier
+1 -1
View File
@@ -23,7 +23,7 @@ const componentMap: Record<string, () => Promise<any>> = {
* 如果后端返回了一个 component 字符串在映射表里找不到,会跳过该条路由并打印警告
* 已在静态路由中注册的路径(如 /jobs)不再重复注册
*/
const STATIC_PATHS = ['/', '/jobs', '/resume/:id', '/jobs/:id', '/mentor/:id']
const STATIC_PATHS = ['/', '/m', '/jobs', '/resume/:id', '/jobs/:id', '/mentor/:id']
export function buildDynamicRoutes(menus: MenuItemRaw[]): RouteRecordRaw[] {
const routes: RouteRecordRaw[] = []
+28 -1
View File
@@ -8,6 +8,7 @@ import { checkLogin } from '@/api/auth'
*/
const staticRoutes: RouteRecordRaw[] = [
{ path: '/', name: 'Home', component: () => import('@/views/Home.vue') },
{ path: '/m', name: 'HomeMobile', component: () => import('@/views/HomeMobile.vue') },
{ path: '/login', name: 'Login', component: () => import('@/views/Login.vue') },
{
path: '/jobs',
@@ -38,6 +39,14 @@ const router = createRouter({
routes: staticRoutes,
})
/**
* 检测是否为移动端设备
*/
function isMobileDevice(): boolean {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|| window.innerWidth < 768
}
/**
* 上次静默校验登录状态的时间戳,用于节流(5 分钟内不重复请求)
*/
@@ -55,6 +64,17 @@ const CHECK_INTERVAL = 5 * 60 * 1000 // 5 分钟
* 4. 不需要鉴权的路由 → 静默同步登录状态(不阻止导航、不弹登录框),5 分钟内节流
*/
router.beforeEach(async (to, _from, next) => {
// 移动端访问首页时重定向到移动版首页
if (to.name === 'Home' && isMobileDevice()) {
next({ name: 'HomeMobile', replace: true })
return
}
// PC端访问移动版首页时重定向到PC首页
if (to.name === 'HomeMobile' && !isMobileDevice()) {
next({ name: 'Home', replace: true })
return
}
// 动态路由只需加载一次,与登录状态无关
if (!store.state.routesLoaded) {
try {
@@ -62,7 +82,14 @@ router.beforeEach(async (to, _from, next) => {
next({ ...to, replace: true })
} catch (err) {
console.error('[router] 加载动态路由失败', err)
next({ name: 'Home' })
// 即使接口失败也标记路由已加载,确保首页正常展示
store.commit('SET_ROUTES_LOADED', true)
// 首页不需要依赖动态路由接口,正常放行
if (to.name === 'Home' || to.name === 'HomeMobile') {
next()
} else {
next({ name: 'Home' })
}
}
return
}
+16
View File
@@ -0,0 +1,16 @@
/**
* 每日岗位数量哈希算法工具
* 根据当前日期生成 3000~4000 之间的确定性数值
* 同一天所有用户看到的数字一致
*/
/** 根据当前日期生成确定性岗位数量 */
export function getDailyJobCount(): number {
const today = new Date()
const seed = today.getFullYear() * 10000 + (today.getMonth() + 1) * 100 + today.getDate()
let hash = seed
hash = ((hash >> 16) ^ hash) * 0x45d9f3b
hash = ((hash >> 16) ^ hash) * 0x45d9f3b
hash = (hash >> 16) ^ hash
return 3000 + (Math.abs(hash) % 1001)
}
+2 -12
View File
@@ -493,6 +493,7 @@ import IndustrySelector from '@/components/tools/IndustrySelector.vue'
import RegionSelector from '@/components/tools/RegionSelector.vue'
import JobCategorySelector from '@/components/tools/JobCategorySelector.vue'
import AgreementPreviewDialog from '@/components/tools/AgreementPreviewDialog.vue'
import { getDailyJobCount } from '@/utils/dailyJobCount'
/** 路由实例 */
const router = useRouter()
@@ -502,18 +503,7 @@ const store = useStore()
/** 页面是否已向下滚动超过 20px — 用于导航栏背景切换 */
const isScrolled = ref(false)
/** 根据当前日期生成 3000~4000 之间的确定性岗位数量(同一天所有用户看到的数字一致 */
function getDailyJobCount(): number {
const today = new Date()
const seed = today.getFullYear() * 10000 + (today.getMonth() + 1) * 100 + today.getDate()
let hash = seed
hash = ((hash >> 16) ^ hash) * 0x45d9f3b
hash = ((hash >> 16) ^ hash) * 0x45d9f3b
hash = (hash >> 16) ^ hash
return 3000 + (Math.abs(hash) % 1001)
}
/** 今日更新岗位数量 — 每日确定性变化 */
/** 今日更新岗位数量 — 每日确定性变化(使用公共哈希工具 */
const dailyJobCount = getDailyJobCount()
/** 当前展开的 FAQ 索引,-1 表示全部收起 */
+198
View File
@@ -0,0 +1,198 @@
<template>
<!-- 移动端首页 -->
<div class="home-mobile">
<!-- 背景装饰色块 -->
<div class="home-mobile__orb home-mobile__orb--top"></div>
<div class="home-mobile__orb home-mobile__orb--hero"></div>
<!-- 顶部 Logo -->
<header class="home-mobile__header">
<img src="@/assets/images/logo.png" alt="Offer派" class="home-mobile__logo" />
</header>
<!-- Hero 区域 -->
<section class="home-mobile__hero">
<p class="home-mobile__eyebrow">大学生AI求职平台</p>
<h1 class="home-mobile__headline">一站式求职辅助</h1>
<p class="home-mobile__subtitle">
"大海捞针"式求职说再见<br/>
Offer派用AI技术为你精准匹配岗位自动投递量身定制简历<br/>
让每一步都更快更准
</p>
</section>
<!-- 指令卡片 -->
<section class="home-mobile__command-card">
<p class="home-mobile__command-title">Offer 派工作模式</p>
<p class="home-mobile__command-sub">网投正在进行中...</p>
<div class="home-mobile__progress">
<div class="home-mobile__progress-rail">
<div class="home-mobile__progress-fill"></div>
</div>
</div>
<p class="home-mobile__command-chips">网投成功 32 · 投递中 5 · 已完成 82%</p>
</section>
<!-- 数据统计卡片 -->
<section class="home-mobile__stats-card">
<div class="home-mobile__stat">
<span class="home-mobile__stat-num">40+</span>
<span class="home-mobile__stat-label">岗位总数</span>
</div>
<div class="home-mobile__stat">
<span class="home-mobile__stat-num">{{ dailyJobCount }}</span>
<span class="home-mobile__stat-label">今日更新</span>
</div>
<div class="home-mobile__stat">
<span class="home-mobile__stat-num">82%</span>
<span class="home-mobile__stat-label">节省时间</span>
</div>
</section>
<!-- 功能介绍区 -->
<section class="home-mobile__functions">
<h2 class="home-mobile__section-title">Offer派能帮你做什么</h2>
<p class="home-mobile__section-sub">AI驱动的一站式求职解决方案</p>
<!-- 功能卡片列表 -->
<div class="home-mobile__feature-list">
<div class="home-mobile__feature-card" v-for="(feat, i) in features" :key="i">
<div class="home-mobile__feature-icon" :style="{ background: feat.iconBg }">
<span>{{ feat.icon }}</span>
</div>
<div class="home-mobile__feature-text">
<h3>{{ feat.title }}</h3>
<p>{{ feat.desc }}</p>
</div>
</div>
</div>
</section>
<!-- 每天都有新机会 -->
<section class="home-mobile__jobs-section">
<h2 class="home-mobile__section-title">每天都有新机会</h2>
<p class="home-mobile__section-sub">实时汇集海量优质校招职位</p>
<div class="home-mobile__job-chips">
<div class="home-mobile__job-chip home-mobile__job-chip--dark">
<span class="home-mobile__job-chip-company">字节跳动 · 15分钟前</span>
<span class="home-mobile__job-chip-role">高级产品经理</span>
</div>
<div class="home-mobile__job-chip-row">
<div class="home-mobile__job-chip home-mobile__job-chip--light">
<span class="home-mobile__job-chip-company">腾讯</span>
<span class="home-mobile__job-chip-role">后端开发工程师</span>
</div>
<div class="home-mobile__job-chip home-mobile__job-chip--light">
<span class="home-mobile__job-chip-company">阿里巴巴</span>
<span class="home-mobile__job-chip-role">产品经理</span>
</div>
</div>
</div>
</section>
<!-- 万千毕业生的信赖之选 -->
<section class="home-mobile__proof">
<h2 class="home-mobile__section-title">万千毕业生的信赖之选</h2>
<div class="home-mobile__quote-card">
<p class="home-mobile__quote-text">
"真没想到校招居然可以这么轻松高效!一周就收到了3个面试邀约。"
</p>
<div class="home-mobile__quote-author">
<div class="home-mobile__quote-avatar"></div>
<div class="home-mobile__quote-info">
<span class="home-mobile__quote-name">李同学</span>
<span class="home-mobile__quote-school">西安交通大学</span>
</div>
</div>
</div>
</section>
<!-- 常见问题 -->
<section class="home-mobile__faq">
<h2 class="home-mobile__section-title">常见问题</h2>
<div class="home-mobile__faq-list">
<div
v-for="(faq, i) in faqs"
:key="i"
class="home-mobile__faq-item"
:class="{ 'home-mobile__faq-item--open': faqOpen === i }"
>
<div class="home-mobile__faq-header" @click="faqOpen = faqOpen === i ? -1 : i">
<span>{{ faq.q }}</span>
<span class="home-mobile__faq-icon">{{ faqOpen === i ? '×' : '+' }}</span>
</div>
<div v-show="faqOpen === i" class="home-mobile__faq-answer">
<p>{{ faq.a }}</p>
</div>
</div>
</div>
</section>
<!-- 底部 CTA -->
<section class="home-mobile__bottom-cta">
<h2>准备开始投递</h2>
<p>自动网申简历生成和岗位投递需要在 PC 官网完成<br/>手机端可先了解功能正式操作请用电脑访问官网</p>
<span class="home-mobile__bottom-footer">Offer派 · 大学生AI求职首选平台</span>
</section>
<!-- 固定底部按钮 -->
<div class="home-mobile__fixed-bar">
<span class="home-mobile__pc-hint">完整产品请前往电脑端</span>
<button class="home-mobile__cta-btn" @click="showDialog = true">免费使用</button>
</div>
<!-- 弹窗引导去电脑端 -->
<div v-if="showDialog" class="home-mobile__overlay" @click.self="showDialog = false">
<div class="home-mobile__dialog">
<div class="home-mobile__dialog-handle"></div>
<button class="home-mobile__dialog-close" @click="showDialog = false">×</button>
<h3>请在电脑端使用 Offer派</h3>
<p class="home-mobile__dialog-desc">
自动网申简历生成和岗位投递需要在 PC 官网完成<br/>
手机端可先了解功能正式操作请用电脑访问官网
</p>
<div class="home-mobile__dialog-url">
PC 官网www.offerpai.com.cn
</div>
<p class="home-mobile__dialog-qr-title">保存二维码扫码加入求职交流群</p>
<div class="home-mobile__dialog-qr">
<img src="@/assets/images/home/mobile-qcCode.png" alt="二维码" class="home-mobile__dialog-qr-img" />
</div>
<p class="home-mobile__dialog-qr-hint">长按保存二维码获取更多求职资料公开课</p>
<button class="home-mobile__dialog-btn" @click="showDialog = false">知道了</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getDailyJobCount } from '@/utils/dailyJobCount'
/** 今日更新岗位数量 */
const dailyJobCount = getDailyJobCount()
/** 弹窗显示状态 */
const showDialog = ref(false)
/** 当前展开的 FAQ 索引 */
const faqOpen = ref(-1)
/** 功能卡片数据 */
const features = [
{ icon: '🎯', iconBg: '#4FC2C9', title: '个性化岗位匹配', desc: '基于简历精准推荐最合适的岗位' },
{ icon: '⚡', iconBg: '#12383A', title: '一键自动网申', desc: '投递一键搞定,覆盖各大网申系统' },
{ icon: '📄', iconBg: '#42A8B3', title: '岗位定制简历', desc: '根据每个岗位智能优化简历内容' },
{ icon: '🤝', iconBg: '#80D8C8', title: '名企内推人脉直通', desc: '实时获取名企最新内推信息' },
{ icon: '🤖', iconBg: '#2A8186', title: '24h AI求职助手', desc: '随时提供求职指导和面试技巧' },
]
/** 常见问题数据 — 与PC端保持一致 */
const faqs = [
{ q: '平台免费使用吗?', a: 'Offer派为所有用户免费开放3天会员权益,帮你省心省力找工作。3天后,依然可以免费使用各项功能,但有使用次数限制。如果你需要不受限制地使用所有功能,更快更高效地获得Offer,建议您升级为付费会员,让求职效率翻倍。' },
{ q: '我的信息会被分享吗?', a: 'Offer派高度重视你的隐私安全。未经你明确同意,我们绝不会将你的个人信息提供给任何第三方。你的所有数据仅用于在平台内为你提供AI智能岗位匹配、简历优化等个性化求职服务。' },
{ q: '平台的岗位来源是什么?', a: 'Offer派的岗位来自上万家企业的官方招聘网站,同时聚合了各大主流平台的最新职位——你不需要在多个网站之间来回切换,就能一站式搜罗全网高质量的工作机会。' },
{ q: '平台与其他求职平台有什么不同?', a: '不同于BOSS直聘等传统平台的"手动式"求职,Offer派如同一位经验丰富的职业导师,通过AI能力搭建智能工具,自动处理简历优化、岗位匹配、申请投递等环节,大幅度提升你的求职效率。' },
]
</script>
-3
View File
@@ -37,9 +37,6 @@
>
<td class="resume-page__td">
<div class="resume-page__name-cell">
<!-- <span class="resume-page__avatar" :style="{ background: item.avatarColor }">-->
<!-- {{ item.avatarLetter }}-->
<!-- </span>-->
<span class="resume-page__name">{{ item.name }}</span>
<span v-if="item.isDefault" class="resume-page__default-tag">默认</span>
<!-- 编辑名称岗位图标 -->