Files
graduation-design-wr/src/views/Report.vue

424 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="page">
<h2>招聘信息浏览与交互模块</h2>
<p class="intro">
为理工科毕业生提供多维度的岗位检索能力以及与企业进行高效互动的入口
</p>
<!-- 多维度搜索 -->
<section class="card">
<h3>1. 多维度搜索</h3>
<form class="filter-bar" @submit.prevent>
<input v-model="filter.keyword" placeholder="输入岗位关键词例如Java、测试" />
<select v-model="filter.major">
<option value="">专业方向</option>
<option value="计算机">计算机相关</option>
<option value="机械">机械相关</option>
<option value="电子">电子信息</option>
</select>
<select v-model="filter.companyType">
<option value="">企业类型</option>
<option value="国企">国企</option>
<option value="外企">外企</option>
<option value="民企">民企</option>
</select>
<select v-model="filter.hot">
<option value="">岗位热度</option>
<option value="高"></option>
<option value="中"></option>
<option value="低"></option>
</select>
</form>
</section>
<section class="layout">
<!-- 岗位列表 -->
<section class="card job-list-card">
<h3>2. 岗位列表</h3>
<div class="job-list">
<div
v-for="job in filteredJobs"
:key="job.id"
class="job-item"
:class="{ active: selectedJob && selectedJob.id === job.id }"
@click="selectJob(job)"
>
<div>
<div class="job-title-row">
<span class="job-title">{{ job.title }}</span>
<span class="job-company">{{ job.company }}</span>
</div>
<div class="job-meta">
<span>{{ job.city }}</span>
<span>{{ job.salary }}</span>
<span>{{ job.companyType }}</span>
</div>
</div>
<div class="job-actions">
<button
type="button"
@click.stop="toggleFavorite(job.id)"
:class="{ secondary: isFavorite(job.id) }"
>
{{ isFavorite(job.id) ? '已收藏' : '收藏' }}
</button>
<button
type="button"
class="primary"
@click.stop="apply(job.id)"
>
{{ isApplied(job.id) ? '已投递' : '投递简历' }}
</button>
</div>
</div>
<p v-if="!filteredJobs.length" class="empty-text">
暂无符合当前筛选条件的岗位可以尝试调整搜索条件
</p>
</div>
</section>
<!-- 岗位详情页 -->
<section class="card detail-card">
<h3>3. 岗位详情</h3>
<div v-if="selectedJob" class="detail">
<h4>{{ selectedJob.title }} · {{ selectedJob.company }}</h4>
<p class="detail-sub">
{{ selectedJob.city }} · {{ selectedJob.salary }} ·
{{ selectedJob.companyType }}
</p>
<h5>岗位职责</h5>
<ul>
<li v-for="(duty, index) in selectedJob.duties" :key="index">
{{ duty }}
</li>
</ul>
<h5>任职要求</h5>
<ul>
<li v-for="(req, index) in selectedJob.requirements" :key="index">
{{ req }}
</li>
</ul>
<h5>企业介绍与薪资福利</h5>
<p class="detail-desc">{{ selectedJob.companyIntro }}</p>
</div>
<p v-else class="empty-text">
在左侧列表中选择一个岗位查看详细信息与岗位要求
</p>
</section>
</section>
</div>
</template>
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
type JobItem = {
id: number
title: string
company: string
city: string
salary: string
companyType: string
majorTag: string
hot: '高' | '中' | '低'
duties: string[]
requirements: string[]
companyIntro: string
}
const jobs = ref<JobItem[]>([
{
id: 1,
title: 'Java 后端开发工程师',
company: '云计算科技有限公司',
city: '北京',
salary: '18-25K',
companyType: '民企',
majorTag: '计算机',
hot: '高',
duties: [
'参与后端服务的设计与开发,保证系统稳定性与性能。',
'参与需求评审,与前端及产品协作完成业务功能。',
'编写相关技术文档与单元测试。'
],
requirements: [
'计算机或相关理工科专业,本科及以上学历。',
'熟悉 Java 语言及 SpringBoot 框架。',
'掌握 MySQL、Redis 等常用中间件,具备良好的编码习惯。'
],
companyIntro: '专注云计算与大数据解决方案,为各行业提供技术服务。'
},
{
id: 2,
title: '自动化测试工程师',
company: '智能硬件科技集团',
city: '深圳',
salary: '15-20K',
companyType: '民企',
majorTag: '电子',
hot: '中',
duties: [
'参与产品测试方案设计及测试用例编写。',
'搭建和维护自动化测试框架。',
'跟踪和推动缺陷修复,保障产品质量。'
],
requirements: [
'电子信息、计算机等相关理工科专业。',
'熟悉 Python、Shell 等脚本语言。',
'了解常见自动化测试工具和方法。'
],
companyIntro: '国内领先的智能硬件设计与生产企业,产品覆盖多领域。'
},
{
id: 3,
title: '机械设计工程师',
company: '高端装备制造股份有限公司',
city: '上海',
salary: '12-18K',
companyType: '国企',
majorTag: '机械',
hot: '高',
duties: [
'负责机械部件及整机结构的方案设计与优化。',
'输出二维工程图与三维模型,并跟进生产制造。',
'参与样机装配与测试验证。'
],
requirements: [
'机械设计相关专业,本科及以上学历。',
'熟练使用 SolidWorks、CATIA 等三维设计软件。',
'具备良好的沟通协调能力和团队协作精神。'
],
companyIntro: '国有大型装备制造企业,深耕高端装备领域多年。'
}
])
const filter = reactive({
keyword: '',
major: '',
companyType: '',
hot: ''
})
const selectedJob = ref<JobItem | null>(null)
const favoriteIds = ref<number[]>([])
const appliedIds = ref<number[]>([])
const filteredJobs = computed(() =>
jobs.value.filter((job) => {
const byKeyword = filter.keyword
? job.title.includes(filter.keyword) ||
job.company.includes(filter.keyword)
: true
const byMajor = filter.major ? job.majorTag === filter.major : true
const byCompanyType = filter.companyType
? job.companyType === filter.companyType
: true
const byHot = filter.hot ? job.hot === filter.hot : true
return byKeyword && byMajor && byCompanyType && byHot
})
)
function selectJob(job: JobItem) {
selectedJob.value = job
}
function isFavorite(id: number) {
return favoriteIds.value.includes(id)
}
function toggleFavorite(id: number) {
if (isFavorite(id)) {
favoriteIds.value = favoriteIds.value.filter((v) => v !== id)
} else {
favoriteIds.value.push(id)
}
}
function isApplied(id: number) {
return appliedIds.value.includes(id)
}
function apply(id: number) {
if (!isApplied(id)) {
appliedIds.value.push(id)
alert('简历已投递(示例),可在个人中心查看投递状态。')
}
}
</script>
<style scoped>
.page h2 {
margin-top: 0;
margin-bottom: 8px;
font-size: 20px;
font-weight: 600;
}
.intro {
margin: 0 0 16px;
color: #4b5563;
font-size: 14px;
}
.card {
background: #f9fafb;
border-radius: 12px;
padding: 14px 16px;
border: 1px solid #e5e7eb;
}
.filter-bar {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
}
.filter-bar input,
.filter-bar select {
border-radius: 999px;
border: 1px solid #d1d5db;
padding: 6px 10px;
font-size: 13px;
}
.layout {
margin-top: 16px;
display: grid;
grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.2fr);
gap: 16px;
}
@media (max-width: 900px) {
.layout {
grid-template-columns: 1fr;
}
}
.job-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.job-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
border-radius: 10px;
background: #ffffff;
border: 1px solid #e5e7eb;
cursor: pointer;
}
.job-item.active {
border-color: #2563eb;
box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.3);
}
.job-title-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: baseline;
}
.job-title {
font-size: 15px;
font-weight: 500;
}
.job-company {
font-size: 13px;
color: #6b7280;
}
.job-meta {
margin-top: 4px;
display: flex;
flex-wrap: wrap;
gap: 8px;
font-size: 12px;
color: #6b7280;
}
.job-actions {
display: flex;
flex-direction: column;
gap: 6px;
margin-left: 10px;
}
button {
border-radius: 999px;
border: none;
padding: 5px 12px;
font-size: 12px;
cursor: pointer;
background: #2563eb;
color: #ffffff;
}
button:hover {
background: #1d4ed8;
}
.primary {
background: #f97316;
}
.primary:hover {
background: #ea580c;
}
.secondary {
background: #e5e7eb;
color: #374151;
}
.detail-card {
min-height: 260px;
}
.detail h4 {
margin: 0 0 4px;
font-size: 16px;
}
.detail-sub {
margin: 0 0 10px;
font-size: 13px;
color: #6b7280;
}
.detail h5 {
margin: 10px 0 6px;
font-size: 14px;
}
.detail ul {
padding-left: 18px;
margin: 0;
font-size: 13px;
color: #4b5563;
}
.detail-desc {
font-size: 13px;
color: #4b5563;
margin: 0;
}
.empty-text {
margin-top: 6px;
font-size: 13px;
color: #9ca3af;
}
</style>