Files
ks-app-employment-service/packageA/pages/myResume/myResume.vue
史典卓 0216f6053a flat:AI+
2025-03-28 15:19:42 +08:00

633 lines
20 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>
<view class="container">
<!-- 头部信息 -->
<view class="header">
<view class="avatar"></view>
<view class="info">
<view class="name-row">
<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>
</view>
<text class="details">
<dict-Label dictType="sex" :value="userInfo.sex"></dict-Label>
{{ state.age }}
</text>
</view>
</view>
<!-- 简历信息 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">出生年月</text>
<!-- <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>
</view>
<view class="card-content">
<text class="label">学历</text>
<!-- <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>
</view>
<view class="card-content">
<text class="label">政治面貌</text>
<!-- <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>
</view>
<view class="card-content" style="padding-bottom: 3px">
<text class="label">联系方式</text>
<!-- <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="输入手机号"
/>
</view>
</view>
</view>
<!-- 期望职位 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">期望职位</text>
<view class="value">
<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>
</view>
</view>
</view>
</view>
<!-- 期望薪资 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label">期望薪资</text>
<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>
</view>
</view>
</view>
<!-- 期望工作地 -->
<view class="resume-info">
<view class="info-card">
<view class="card-content">
<text class="label long">期望工作地</text>
<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>
</view>
</view>
</view>
<!-- 上传按钮 -->
<view class="upload-btn">
<button class="btn">
<uni-icons type="cloud-upload" size="30" color="#FFFFFF"></uni-icons>
上传简历
</button>
</view>
<!-- 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>
</view>
</template>
<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;
};
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}`;
}
</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
position relative
.name
font-size 36rpx
font-weight bold
color #fff
.edit-icon
width 40rpx
height 40rpx
border-radius 50%
position: absolute
right: -60rpx
top: 6rpx
.img
width: 100%
height: 100%
.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
position: relative
.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
right: 10rpx
top: 10rpx
width 40rpx
height 40rpx
.img
width: 100%
height: 100%
.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
/* 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;
}
}
}
</style>