feat: add seeker center (resume editor, applications, profile)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0a44e4a18d
commit
ca629a403c
|
|
@ -1,3 +1,35 @@
|
|||
<template>
|
||||
<div>我的投递 - 开发中</div>
|
||||
<div>
|
||||
<h2>我的投递</h2>
|
||||
<el-table :data="applications" v-loading="loading" border>
|
||||
<el-table-column prop="job_title" label="职位" />
|
||||
<el-table-column prop="company_name" label="公司" />
|
||||
<el-table-column prop="applied_at" label="投递时间" :formatter="(r,c,v) => v?.slice(0,10)" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="applications.length === 0 && !loading" description="暂无投递记录" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getMyApplications } from '@/api/applications'
|
||||
|
||||
const applications = ref([])
|
||||
const loading = ref(false)
|
||||
|
||||
const STATUS_MAP = { pending:'待查看', viewed:'已查看', interviewing:'面试中', hired:'已录用', rejected:'已拒绝' }
|
||||
const STATUS_TYPE = { pending:'info', viewed:'', interviewing:'warning', hired:'success', rejected:'danger' }
|
||||
const statusLabel = s => STATUS_MAP[s] || s
|
||||
const statusType = s => STATUS_TYPE[s] || ''
|
||||
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
const { data } = await getMyApplications()
|
||||
applications.value = data.results
|
||||
loading.value = false
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,36 @@
|
|||
<template>
|
||||
<div>账号设置 - 开发中</div>
|
||||
<div>
|
||||
<h2>账号设置</h2>
|
||||
<el-card style="max-width:480px">
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item>
|
||||
<el-form-item label="手机号"><el-input v-model="form.phone" /></el-form-item>
|
||||
<el-button type="primary" @click="save" :loading="saving">保存</el-button>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { updateMe } from '@/api/auth'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const auth = useAuthStore()
|
||||
const form = ref({ email: '', phone: '' })
|
||||
const saving = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
form.value.email = auth.user?.email || ''
|
||||
form.value.phone = auth.user?.phone || ''
|
||||
})
|
||||
|
||||
async function save() {
|
||||
saving.value = true
|
||||
try {
|
||||
await updateMe({ email: form.value.email, phone: form.value.phone })
|
||||
ElMessage.success('保存成功')
|
||||
} catch { ElMessage.error('保存失败') }
|
||||
finally { saving.value = false }
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,91 @@
|
|||
<template>
|
||||
<div>我的简历 - 开发中</div>
|
||||
<div v-loading="loading">
|
||||
<h2>我的简历</h2>
|
||||
<el-form :model="form" label-width="80px" v-if="form">
|
||||
<el-card style="margin-bottom:16px">
|
||||
<template #header>基本信息</template>
|
||||
<el-form-item label="姓名"><el-input v-model="form.name" /></el-form-item>
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="form.gender">
|
||||
<el-radio value="male">男</el-radio>
|
||||
<el-radio value="female">女</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="生日"><el-date-picker v-model="form.birthday" type="date" value-format="YYYY-MM-DD" /></el-form-item>
|
||||
</el-card>
|
||||
|
||||
<el-card style="margin-bottom:16px">
|
||||
<template #header>
|
||||
教育经历
|
||||
<el-button size="small" @click="addEducation" style="float:right">添加</el-button>
|
||||
</template>
|
||||
<div v-for="(edu, i) in form.education" :key="i" style="margin-bottom:8px">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="8"><el-input v-model="edu.school" placeholder="学校名称" /></el-col>
|
||||
<el-col :span="6"><el-input v-model="edu.degree" placeholder="学历" /></el-col>
|
||||
<el-col :span="7"><el-input v-model="edu.major" placeholder="专业" /></el-col>
|
||||
<el-col :span="3"><el-button type="danger" link @click="form.education.splice(i,1)">删除</el-button></el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card style="margin-bottom:16px">
|
||||
<template #header>
|
||||
工作经历
|
||||
<el-button size="small" @click="addExperience" style="float:right">添加</el-button>
|
||||
</template>
|
||||
<div v-for="(exp, i) in form.experience" :key="i" style="margin-bottom:8px">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="8"><el-input v-model="exp.company" placeholder="公司名称" /></el-col>
|
||||
<el-col :span="7"><el-input v-model="exp.position" placeholder="职位" /></el-col>
|
||||
<el-col :span="6"><el-input v-model="exp.duration" placeholder="时长(如:2年)" /></el-col>
|
||||
<el-col :span="3"><el-button type="danger" link @click="form.experience.splice(i,1)">删除</el-button></el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card style="margin-bottom:16px">
|
||||
<template #header>简历附件</template>
|
||||
<el-upload action="/api/resumes/me/" :headers="uploadHeaders" name="attachment" accept=".pdf,.doc,.docx" method="patch">
|
||||
<el-button>上传简历(PDF/Word)</el-button>
|
||||
</el-upload>
|
||||
</el-card>
|
||||
|
||||
<el-button type="primary" @click="save" :loading="saving">保存简历</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { getMyResume, updateMyResume } from '@/api/resumes'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const form = ref(null)
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const uploadHeaders = computed(() => ({
|
||||
Authorization: `Bearer ${localStorage.getItem('access_token')}`
|
||||
}))
|
||||
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
const { data } = await getMyResume()
|
||||
form.value = { ...data, education: data.education || [], experience: data.experience || [] }
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const addEducation = () => form.value.education.push({ school: '', degree: '', major: '' })
|
||||
const addExperience = () => form.value.experience.push({ company: '', position: '', duration: '' })
|
||||
|
||||
async function save() {
|
||||
saving.value = true
|
||||
try {
|
||||
await updateMyResume(form.value)
|
||||
ElMessage.success('简历已保存')
|
||||
} catch {
|
||||
ElMessage.error('保存失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue