Files
ks-app-employment-service/packageA/pages/myResume/myResume.vue

633 lines
20 KiB
Vue
Raw Normal View History

2024-11-18 16:33:37 +08:00
<template>
<view class="container">
<!-- 头部信息 -->
<view class="header">
<view class="avatar"></view>
<view class="info">
<view class="name-row">
2025-03-28 15:19:42 +08:00
<text class="name" v-if="state.disbleName">{{ state.name || '编辑用户名' }}</text>
<input
class="uni-input name"
style="padding-top: 6px"
v-else
v-model="state.name"
placeholder-class="name"
type="text"
placeholder="输入用户名"
/>
<view class="edit-icon">
<image
class="img"
v-if="state.disbleName"
src="../../../static/icon/edit.png"
@click="editName"
></image>
<image v-else class="img" src="../../../static/icon/save.png" @click="completeUserName"></image>
</view>
2024-11-18 16:33:37 +08:00
</view>
2025-03-28 15:19:42 +08:00
<text class="details">
<dict-Label dictType="sex" :value="userInfo.sex"></dict-Label>
{{ state.age }}
</text>
2024-11-18 16:33:37 +08:00
</view>
</view>
<!-- 简历信息 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">出生年月</text>
2025-03-28 15:19:42 +08:00
<!-- <text class="value">2001/01/01</text> -->
<picker
mode="date"
:disabled="state.disbleDate"
:value="state.date"
:start="startDate"
:end="endDate"
@change="bindDateChange"
>
<view class="uni-input">{{ state.date }}</view>
</picker>
<view class="edit-icon">
<image
v-if="state.disbleDate"
class="img"
src="../../../static/icon/edit.png"
@click="editResume"
></image>
<image v-else class="img" src="../../../static/icon/save.png" @click="completeResume"></image>
</view>
2024-11-18 16:33:37 +08:00
</view>
<view class="card-content">
<text class="label">学历</text>
2025-03-28 15:19:42 +08:00
<!-- <text class="value">
<dict-Label dictType="education" :value="userInfo.education"></dict-Label>
</text> -->
<picker
@change="bindEducationChange"
range-key="label"
:disabled="state.disbleDate"
:value="state.education"
:range="state.educationList"
>
<view class="uni-input">{{ state.educationList[state.education].label }}</view>
</picker>
2024-11-18 16:33:37 +08:00
</view>
<view class="card-content">
<text class="label">政治面貌</text>
2025-03-28 15:19:42 +08:00
<!-- <text class="value">2001/01/01</text> -->
<picker
@change="bindPoliticalAffiliationChange"
range-key="label"
:disabled="state.disbleDate"
:value="state.politicalAffiliation"
:range="state.affiliationList"
>
<view class="uni-input">{{ state.affiliationList[state.politicalAffiliation].label }}</view>
</picker>
2024-11-18 16:33:37 +08:00
</view>
2025-03-28 15:19:42 +08:00
<view class="card-content" style="padding-bottom: 3px">
2024-11-18 16:33:37 +08:00
<text class="label">联系方式</text>
2025-03-28 15:19:42 +08:00
<!-- <text class="value">2001/01/01</text> -->
<input
class="uni-input"
style="padding-top: 6px"
:disabled="state.disbleDate"
v-model="state.phone"
placeholder-class="value"
type="number"
placeholder="输入手机号"
/>
2024-11-18 16:33:37 +08:00
</view>
</view>
</view>
<!-- 期望职位 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">期望职位</text>
<view class="value">
2025-03-28 15:19:42 +08:00
<view v-for="item in userInfo.jobTitle" :key="item">{{ item }}</view>
</view>
<view class="edit-icon">
<image class="img" @click="editJobs" src="../../../static/icon/edit.png"></image>
2024-11-18 16:33:37 +08:00
</view>
</view>
</view>
</view>
<!-- 期望薪资 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">期望薪资</text>
2025-03-28 15:19:42 +08:00
<view class="value">
<picker
@change="changeSalary"
@columnchange="changeColumeSalary"
range-key="label"
:disabled="state.disbleSalary"
:value="state.salary"
:range="state.salayList"
mode="multiSelector"
>
<view class="uni-input">{{ state.salaryMin / 1000 }}k-{{ state.salaryMax / 1000 }}k</view>
</picker>
</view>
<view class="edit-icon">
<image
v-if="state.disbleSalary"
class="img"
src="../../../static/icon/edit.png"
@click="salaryExpectation"
></image>
<image
v-else
class="img"
src="../../../static/icon/save.png"
@click="completesalaryExpectation"
></image>
</view>
2024-11-18 16:33:37 +08:00
</view>
</view>
</view>
<!-- 期望工作地 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label long">期望工作地</text>
2025-03-28 15:19:42 +08:00
<view class="value">
<view v-if="state.disaleArea">
青岛 -
<dict-Label dictType="area" :value="Number(state.area)"></dict-Label>
</view>
<view v-else>
<picker
@change="bindAreaChange"
range-key="label"
:disabled="state.disaleArea"
:value="state.area"
:range="state.areaList"
>
<view class="uni-input">
青岛 -
{{ state.areaList[state.area].label }}
</view>
</picker>
</view>
</view>
<view class="edit-icon">
<image
v-if="state.disaleArea"
class="img"
src="../../../static/icon/edit.png"
@click="state.disaleArea = false"
></image>
<image v-else class="img" src="../../../static/icon/save.png" @click="completeArea"></image>
</view>
2024-11-18 16:33:37 +08:00
</view>
</view>
</view>
<!-- 上传按钮 -->
<view class="upload-btn">
<button class="btn">
<uni-icons type="cloud-upload" size="30" color="#FFFFFF"></uni-icons>
上传简历
</button>
</view>
2025-03-28 15:19:42 +08:00
<!-- piker -->
<custom-popup :content-h="100" :visible="state.visible" :header="false">
<view class="popContent">
<view class="s-header">
<view class="heade-lf" @click="state.visible = false">取消</view>
<view class="heade-ri" @click="confimPopup">确认</view>
</view>
<view class="sex-content fl_1">
<expected-station
:search="false"
@onChange="changeJobTitleId"
:station="state.stations"
:max="5"
></expected-station>
</view>
</view>
</custom-popup>
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog
mode="base"
title="确定退出登录吗?"
type="info"
:duration="2000"
:before-close="true"
@confirm="confirm"
@close="close"
></uni-popup-dialog>
</uni-popup>
2024-11-18 16:33:37 +08:00
</view>
</template>
2025-03-28 15:19:42 +08:00
<script setup>
import { reactive, inject, watch, ref, onMounted, computed } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
const { $api, navTo, checkingPhoneRegExp, salaryGlobal, setCheckedNodes } = inject('globalFunction');
import useUserStore from '@/stores/useUserStore';
import useDictStore from '@/stores/useDictStore';
const { getUserResume } = useUserStore();
const { getDictData, oneDictData } = useDictStore();
const userInfo = ref({});
const salay = salaryGlobal();
const state = reactive({
date: getDate(),
education: 0,
politicalAffiliation: 0,
phone: '',
name: '',
jobTitleId: '',
salaryMin: 2000,
salaryMax: 2000,
area: 0,
salary: [0, 0],
disbleDate: true,
disbleName: true,
disbleSalary: true,
disaleArea: true,
visible: false,
educationList: oneDictData('education'),
affiliationList: oneDictData('affiliation'),
areaList: oneDictData('area'),
stations: [],
copyData: {},
salayList: [salay, salay[0].children],
});
const startDate = computed(() => {
return getDate('start');
});
const endDate = computed(() => {
return getDate('end');
});
onShow(() => {
initload();
});
onLoad(() => {
setTimeout(() => {
const { age, birthDate } = useUserStore().userInfo;
const newAge = calculateAge(birthDate);
// 计算年龄是否对等
if (age != newAge) {
console.log(age, newAge);
completeResume();
}
}, 1000);
});
const calculateAge = (birthDate) => {
const birth = new Date(birthDate);
const today = new Date();
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
const dayDiff = today.getDate() - birth.getDate();
// 如果生日的月份还没到,或者刚到生日月份但当天还没过,则年龄减 1
if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
age--;
}
return age;
2024-11-18 16:33:37 +08:00
};
2025-03-28 15:19:42 +08:00
function initload() {
userInfo.value = useUserStore().userInfo;
state.name = userInfo.value.name;
state.date = userInfo.value.birthDate;
state.age = userInfo.value.age;
state.phone = userInfo.value.phone;
state.salaryMax = userInfo.value.salaryMax;
state.salaryMin = userInfo.value.salaryMin;
state.area = userInfo.value.area;
state.educationList.map((iv, index) => {
if (iv.value === userInfo.value.education) state.education = index;
});
state.affiliationList.map((iv, index) => {
if (iv.value === userInfo.value.politicalAffiliation) state.politicalAffiliation = index;
});
$api.createRequest('/app/common/jobTitle/treeselect', {}, 'GET').then((resData) => {
if (userInfo.value.jobTitleId) {
const ids = userInfo.value.jobTitleId.split(',').map((id) => Number(id));
setCheckedNodes(resData.data, ids);
}
state.jobTitleId = userInfo.value.jobTitleId;
state.stations = resData.data;
});
}
function bindAreaChange(val) {
state.area = val.detail.value;
}
function bindDateChange(val) {
state.date = val.detail.value;
}
function bindEducationChange(val) {
state.education = val.detail.value;
}
function bindPoliticalAffiliationChange(val) {
state.politicalAffiliation = val.detail.value;
}
function completeArea() {
let params = {
area: state.area,
};
$api.createRequest('/app/user/resume', params, 'post').then((resData) => {
$api.msg('完成');
state.disaleArea = true;
getUserResume().then(() => {
initload();
});
});
}
function completesalaryExpectation() {
let params = {
salaryMin: state.salaryMin,
salaryMax: state.salaryMax,
};
$api.createRequest('/app/user/resume', params, 'post').then((resData) => {
$api.msg('完成');
state.disbleSalary = true;
getUserResume().then(() => {
initload();
});
});
}
function completeResume() {
let params = {
birthDate: state.date,
age: calculateAge(state.date),
education: state.educationList[state.education].value,
politicalAffiliation: state.affiliationList[state.politicalAffiliation].value,
phone: state.phone,
};
if (!params.birthDate) {
return $api.msg('请选择出生年月');
}
if (!params.education) {
return $api.msg('请选择学历');
}
if (!params.politicalAffiliation) {
return $api.msg('请选择政治面貌');
}
if (!checkingPhoneRegExp(params.phone)) {
return $api.msg('请输入正确手机号');
}
$api.createRequest('/app/user/resume', params, 'post').then((resData) => {
$api.msg('完成');
state.disbleDate = true;
getUserResume().then(() => {
initload();
});
});
}
function completeUserName() {
if (!state.name) {
return $api.msg('请输入用户名称');
}
$api.createRequest('/app/user/resume', { name: state.name }, 'post').then((resData) => {
$api.msg('完成');
state.disbleName = true;
getUserResume().then(() => {
initload();
});
});
}
function confimPopup() {
$api.createRequest('/app/user/resume', { jobTitleId: state.jobTitleId }, 'post').then((resData) => {
$api.msg('完成');
state.visible = false;
getUserResume().then(() => {
initload();
});
});
}
function editResume() {
state.copyData.date = state.date;
state.copyData.education = state.education;
state.copyData.politicalAffiliation = state.politicalAffiliation;
state.copyData.phone = state.phone;
state.disbleDate = false;
}
function salaryExpectation() {
state.disbleSalary = false;
}
function editName() {
state.name = userInfo.value.name;
state.disbleName = false;
}
function changeJobTitleId(ids) {
state.jobTitleId = ids;
}
function editJobs() {
state.visible = true;
}
function changeColumeSalary(e) {
const { column, value } = e.detail;
if (column === 0) {
state.salary[1] = 0;
state.salayList[1] = salay[value].children;
}
}
function changeSalary(e) {
const [minIndex, maxIndex] = e.detail.value;
const min = state.salayList[0][minIndex];
const max = state.salayList[0][minIndex].children[maxIndex];
state.salaryMin = min.value;
state.salaryMax = max.value;
}
function getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 60;
} else if (type === 'end') {
year = year + 2;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}-${month}-${day}`;
}
2024-11-18 16:33:37 +08:00
</script>
<style lang="stylus" scoped>
.container
width: 100%;
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
background: linear-gradient( 180deg, #4778EC 0%, #002979 100%);
display: flex;
flex-direction: column;
align-items center
.header
display flex
align-items center
padding 30rpx 60rpx
width calc(100% - 120rpx)
border-radius 0 0 20rpx 20rpx
.avatar
width 100rpx
height 100rpx
background-color #ccc
border-radius 50%
margin-right 20rpx
.info
display flex
flex-direction column
.name-row
display flex
align-items center
2025-03-28 15:19:42 +08:00
position relative
2024-11-18 16:33:37 +08:00
.name
font-size 36rpx
font-weight bold
color #fff
.edit-icon
2025-03-28 15:19:42 +08:00
width 40rpx
height 40rpx
2024-11-18 16:33:37 +08:00
border-radius 50%
2025-03-28 15:19:42 +08:00
position: absolute
right: -60rpx
top: 6rpx
.img
width: 100%
height: 100%
2024-11-18 16:33:37 +08:00
.details
font-size 24rpx
color #dbeafe
.resume-info
padding: 0 26rpx
width calc(100% - 52rpx)
margin-top 20rpx
.info-card
display flex
flex-direction: column
justify-content space-between
align-items center
color #fff
padding 10rpx 24rpx
border-radius 12rpx
margin-bottom 10rpx
background: #4778EC;
box-shadow: 0rpx 7rpx 7rpx 0rpx rgba(0,0,0,0.25);
border-radius: 17rpx 17rpx 17rpx 17rpx;
position: relative
.card-content
width: 100%
display flex
line-height: 58rpx
margin-top 16rpx
2025-03-28 15:19:42 +08:00
position: relative
2024-11-18 16:33:37 +08:00
.label
width 160rpx
height: 32rpx
font-size 28rpx
color #FFFFFF
text-align:justify;
margin-right: 20rpx
.long
width 180rpx
margin-right: 0rpx
.label:after
content: '';
display: inline-block;
width: 100%;
.value
font-size: 28rpx;
color: #FFFFFF;
.card-content:first-child
margin-top 0
.edit-icon
position: absolute
2025-03-28 15:19:42 +08:00
right: 10rpx
top: 10rpx
2024-11-18 16:33:37 +08:00
width 40rpx
height 40rpx
.img
width: 100%
height: 100%
2025-03-28 15:19:42 +08:00
2024-11-18 16:33:37 +08:00
.upload-btn
margin-top 20rpx
.btn
display: flex
align-items: center
box-shadow: 0rpx 7rpx 7rpx 0rpx rgba(0,0,0,0.25);
height 80rpx
background-color #22c55e
color #fff
font-size 28rpx
font-weight bold
border-radius 20rpx
2025-03-28 15:19:42 +08:00
/* popup */
.popContent {
padding: 24rpx;
background: #4778ec;
height: calc(100% - 49rpx);
.sex-content {
border-radius: 20rpx;
width: 100%;
margin-top: 20rpx;
margin-bottom: 40rpx;
display: flex;
overflow: hidden;
height: calc(100% - 100rpx);
border: 1px solid #4778ec;
}
.s-header {
display: flex;
justify-content: space-between;
text-align: center;
font-size: 16px;
.heade-lf {
line-height: 30px;
width: 50px;
height: 30px;
border-radius: 4px;
border: 1px solid #666666;
color: #666666;
background: #ffffff;
}
.heade-ri {
line-height: 30px;
width: 50px;
height: 30px;
border-radius: 4px;
border: 1px solid #1b66ff;
background-color: #1b66ff;
color: #ffffff;
}
}
}
2024-11-18 16:33:37 +08:00
</style>