Procházet zdrojové kódy

feat: 更新注册优化流程代码

yezhihao před 5 měsíci
rodič
revize
9554e97247
43 změnil soubory, kde provedl 3817 přidání a 996 odebrání
  1. 2 1
      .hbuilderx/launch.json
  2. 90 0
      common.scss
  3. 4 2
      common/config.js
  4. 170 0
      components/async-switch.vue
  5. 46 0
      components/resume/chat-card.vue
  6. 46 0
      components/resume/index-card.vue
  7. 476 0
      components/resume/preview-resume.vue
  8. 273 0
      components/resume/resume-card.vue
  9. 146 0
      components/swiper-delete.vue
  10. 20 0
      constants/common.js
  11. 29 0
      constants/userInfo.js
  12. 5 4
      manifest.json
  13. 207 191
      package/jobIntention/addExpectation.vue
  14. 10 21
      package/jobIntention/basicInfo.vue
  15. 24 22
      package/jobIntention/jobList.vue
  16. 43 59
      package/jobIntention/jobSkills.vue
  17. 386 0
      package/jobIntention/updateCertificates.vue
  18. 365 0
      package/my/editUserInfo.vue
  19. 276 0
      package/my/hiddenManagement/hiddenCompany.vue
  20. 128 0
      package/my/hiddenManagement/index.vue
  21. 121 0
      package/my/previewResume/index.vue
  22. 36 0
      pages.json
  23. 59 47
      pages/index/index.vue
  24. 67 43
      pages/my/educationExperience.vue
  25. 56 22
      pages/my/index.vue
  26. 477 461
      pages/my/onlineResume.vue
  27. 181 114
      pages/my/workExperience.vue
  28. 20 9
      pages/public/loginV2.vue
  29. binární
      static/images/onKeyLogin/checked.png
  30. binární
      static/images/onKeyLogin/phone.png
  31. binární
      static/images/onKeyLogin/unchecked.png
  32. binární
      static/images/onKeyLogin/wechat.png
  33. binární
      static/images/resume/card1.png
  34. binární
      static/images/resume/card2.png
  35. 8 0
      static/images/svg/bag.svg
  36. 13 0
      static/images/svg/building.svg
  37. 2 0
      static/images/svg/female.svg
  38. 4 0
      static/images/svg/file.svg
  39. 2 0
      static/images/svg/gray-briefcase.svg
  40. 8 0
      static/images/svg/heart.svg
  41. 5 0
      static/images/svg/male.svg
  42. 4 0
      static/images/svg/search.svg
  43. 8 0
      static/images/svg/toolbox.svg

+ 2 - 1
.hbuilderx/launch.json

@@ -8,7 +8,8 @@
             "type" : "uni-app:app-android"
         },
         {
-            "playground" : "custom",
+            "customPlaygroundType" : "device",
+            "playground" : "standard",
             "type" : "uni-app:app-ios"
         }
     ]

+ 90 - 0
common.scss

@@ -0,0 +1,90 @@
+// 导航栏
+.nav-bar {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	margin-bottom: 30rpx;
+	padding: 0 40rpx;
+
+	.nav-left {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.nav-title {
+		color: rgba(51, 51, 51, 1);
+		font-family: DM Sans;
+		font-size: 32rpx;
+		font-weight: 700;
+		line-height: 26px;
+		text-align: center;
+	}
+	.nav-right {
+		min-width: 38rpx;
+	}
+}
+
+// 表单内容
+.form-container {
+	padding: 0 40rpx;
+	
+	.form-item {
+		margin-bottom: 32rpx;
+
+		.form-label {
+			color: rgba(31, 44, 55, 1);
+			font-family: DM Sans;
+			font-size: 32rpx;
+			font-weight: 500;
+			line-height: 22px;
+			letter-spacing: 0%;
+			text-align: left;
+			margin-bottom: 20rpx;
+			position: relative;
+
+			.word-count {
+				font-size: 24rpx;
+				color: #aaa;
+				position: absolute;
+				bottom: 0;
+				right: 0;
+			}
+
+			.required-mark {
+				color: #FF3B30;
+				font-size: 18px;
+				font-weight: 500;
+				margin-right: 4rpx;
+			}
+
+			.label-text {
+				color: rgba(31, 44, 55, 1);
+				font-family: DM Sans;
+				font-size: 16px;
+				font-weight: 500;
+				line-height: 22px;
+				letter-spacing: 0%;
+				text-align: left;
+			}
+		}
+	}
+}
+
+
+// 底部提交按钮
+.fixed-section {
+	position: fixed;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	padding: 40rpx;
+	box-shadow: 0px -4px 16px 0px rgba(0, 0, 0, 0.04);
+	background-color: #fff;
+	.submit-btn {
+		height: 90rpx;
+		font-size: 32rpx;
+		border-radius: 90rpx;
+		background: linear-gradient(90.00deg, rgba(13, 39, 247, 1),rgba(19, 193, 234, 1));
+	}
+}

+ 4 - 2
common/config.js

@@ -23,8 +23,10 @@ if (process.env.NODE_ENV !== 'development'||mobile) {
 	};
 }else{
 	//测试环境
-	const ROOTPATH = "/sqx_fast";
-	const ROOTPATH1 = "/sqx_fast";
+	// const ROOTPATH = "/sqx_fast";
+	const ROOTPATH = "https://yizhizan.edccc.cn/sqx_fast";
+	// const ROOTPATH1 = "/sqx_fast";
+	const ROOTPATH1 = "https://yizhizan.edccc.cn/sqx_fast";
 	const ROOTPATH2 = "wss://www.bosszan.com/wss/websocket/"; //联系客服
 	const ROOTPATH3 = "ws://192.168.0.10:7155/sqx_fast/chatSocket/"; //聊天
 	const ROOTPATH4 = "";

+ 170 - 0
components/async-switch.vue

@@ -0,0 +1,170 @@
+<template>
+	<view class="async-switch"
+		:class="{
+			'async-switch--active': value,
+			'async-switch--disabled': disabled,
+			'async-switch--loading': innerLoading
+		}"
+		@click="handleClick"
+	>
+		<!-- 开关轨道 -->
+		<view class="async-switch__track"></view>
+		<!-- 开关按钮 -->
+		<view class="async-switch__thumb"></view>
+		<!-- 加载状态遮罩 -->
+		<view v-if="innerLoading" class="async-switch__loading-mask">
+			<u-loading mode="circle"></u-loading>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'AsyncSwitch',
+		props: {
+			// 开关当前状态(双向绑定)
+			value: {
+				type: Boolean,
+				default: false
+			},
+			// 是否禁用
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			// 加载状态(外部可控制)
+			loading: {
+				type: Boolean,
+				default: false
+			},
+			// 开关激活色
+			activeColor: {
+				type: String,
+				default: '#016BF6'
+			},
+			// 开关未激活色
+			inactiveColor: {
+				type: String,
+				default: '#ffffff'
+			},
+			// 异步变更处理函数(必须返回Promise)
+			asyncChange: {
+				type: Function,
+				required: true
+			}
+		},
+		data() {
+			return {
+				// 内部加载状态(避免外部直接覆盖)
+				innerLoading: this.loading
+			};
+		},
+		watch: {
+			// 监听外部传入的loading属性变化,同步到内部状态
+			loading(newVal) {
+				this.innerLoading = newVal;
+			}
+		},
+		methods: {
+			/**
+			 * 处理开关点击事件(Vue2 异步方法写法)
+			 */
+			async handleClick() {
+				// 禁用/加载中时不响应点击
+				if (this.disabled || this.innerLoading) return;
+
+				// 目标状态(当前状态取反)
+				const targetValue = !this.value;
+
+				try {
+					// 开启加载状态
+					this.innerLoading = true;
+					// 执行外部传入的异步操作
+					const result = await this.asyncChange(targetValue);
+
+					// 异步操作成功且返回值不为false时,更新开关状态
+					if (result !== false) {
+						// Vue2 触发自定义事件,实现v-model双向绑定
+						this.$emit('input', targetValue); // v-model 底层依赖input事件
+						this.$emit('change', targetValue); // 额外的change回调
+					}
+				} catch (error) {
+					// 异步操作失败,触发error事件
+					this.$emit('error', error);
+					console.error('Switch异步更新失败:', error);
+				} finally {
+					// 无论成功/失败,关闭加载状态
+					this.innerLoading = false;
+				}
+			}
+		}
+	};
+</script>
+
+<style scoped>
+	.async-switch {
+		position: relative;
+		width: 52px;
+		height: 32px;
+		border-radius: 16px;
+		background-color: #ffffff;
+		transition: background-color 0.3s ease;
+		cursor: pointer;
+		box-sizing: border-box;
+		border: 1px solid #eee;
+	}
+
+	/* 激活状态 */
+	.async-switch--active {
+		background-color: #016BF6;
+	}
+
+	/* 禁用状态 */
+	.async-switch--disabled {
+		opacity: 0.5;
+		cursor: not-allowed;
+	}
+
+	/* 加载状态 */
+	.async-switch--loading {
+		opacity: 0.8;
+		cursor: wait;
+	}
+
+	.async-switch__track {
+		width: 100%;
+		height: 100%;
+		border-radius: 16px;
+	}
+
+	.async-switch__thumb {
+		position: absolute;
+		top: 1px;
+		left: 1px;
+		width: 28px;
+		height: 28px;
+		border-radius: 50%;
+		background-color: #fff;
+		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+		transition: left 0.3s ease;
+	}
+
+	.async-switch--active .async-switch__thumb {
+		left: 22px;
+	}
+
+	/* 加载遮罩 */
+	.async-switch__loading-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		border-radius: 16px;
+		background-color: rgba(0, 0, 0, 0.15);
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		z-index: 10;
+	}
+</style>

+ 46 - 0
components/resume/chat-card.vue

@@ -0,0 +1,46 @@
+<template>
+	<view class="chat-card">
+		<view class="tip">您的简历在招聘方会话框的展示效果</view>
+
+		<view class="card-box">
+			<resumeCard></resumeCard>
+		</view>
+	</view>
+</template>
+
+<script>
+	import resumeCard from './resume-card.vue';
+
+	export default {
+		components: {
+			resumeCard
+		},
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+	.chat-card {
+		height: 100%;
+		background-image: url('@/static/images/resume/card2.png');
+		background-size: auto 90%;
+		background-repeat: no-repeat;
+		background-position: center 64rpx;
+
+		.tip {
+			font-size: 24rpx;
+			line-height: 28rpx;
+			color: rgba(153, 153, 153, 1);
+			text-align: center;
+			margin-bottom: 300rpx;
+		}
+
+		.card-box {
+			margin: 0 20rpx;
+		}
+	}
+</style>

+ 46 - 0
components/resume/index-card.vue

@@ -0,0 +1,46 @@
+<template>
+	<view class="index-card">
+		<view class="tip">您的简历在招聘方首页列表展示效果</view>
+
+		<view class="card-box">
+			<resumeCard></resumeCard>
+		</view>
+	</view>
+</template>
+
+<script>
+	import resumeCard from './resume-card.vue';
+	
+	export default {
+		components: {
+			resumeCard
+		},
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.index-card {
+		height: 100%;
+		background-image: url('@/static/images/resume/card1.png');
+		background-size: auto 90%;
+		background-repeat: no-repeat;
+		background-position: center 64rpx;
+
+		.tip {
+			font-size: 24rpx;
+			line-height: 28rpx;
+			color: rgba(153, 153, 153, 1);
+			text-align: center;
+			margin-bottom: 300rpx;
+		}
+
+		.card-box {
+			margin: 0 20rpx;
+		}
+	}
+</style>

+ 476 - 0
components/resume/preview-resume.vue

@@ -0,0 +1,476 @@
+<template>
+	<view class="preview-resume-container">
+		<view class="user-info">
+			<view class="flex justify-between align-center">
+				<view class="name">{{ userName }}</view>
+				<view class="avatar-box">
+					<image :src="avatarUrl ? avatarUrl : '/static/images/logo.jpg'" class="avatar"></image>
+					<image src="@/static/images/svg/male.svg" class="sex-tag" v-if="sex == 1"></image>
+					<image src="@/static/images/svg/female.svg" class="sex-tag" v-else-if="sex == 2"></image>
+				</view>
+			</view>
+			<view class="flex sub-info">
+				<image src="@/static/images/svg/gray-briefcase.svg" class="icon"></image>
+				{{ currentCompanyName }} · {{ currentPositionName }}
+			</view>
+			<view class="sub-info">{{ jobStatusName }}</view>
+			<view class="tags">
+				<view class="tag" v-for="(tag, index) in baseInfoList" :key="index">{{ tag }}</view>
+			</view>
+			<view class="advantages">{{ adv }}</view>
+			<view class="resume-tag">
+				<image src="@/static/images/svg/file.svg" class="resume-icon"></image>
+				已上传附件简历
+			</view>
+		</view>
+		
+		<!-- 求职期望 -->
+		<view class="job-expect-container">
+			<view class="job-expect-title">求职期望</view>
+			<view class="job-expect" v-for="(item, index) in intentions" :key="index">
+				<view class="flex justify-between align-center">
+					<view class="text">
+						<text>{{ item.ruleClassifyName }}</text>
+						<text>{{ item.citys }}</text>
+					</view>
+					<view class="salary">{{ formatSalary(item.minSalary, item.maxSalary) }}</view>
+				</view>
+				<view class="skills">{{ formatTag(item.industry) }}</view>
+			</view>
+		</view>
+		
+		<!-- 工作经历 -->
+		<view class="work-exprience-container">
+			<view class="title-bar flex align-center">
+				<image src="@/static/images/svg/toolbox.svg" class="title-icon"></image>
+				工作经历
+			</view>
+			
+			<view class="common-section">
+				<view class="work-item" v-for="work in showWrokExpList" :key="work.workExpId">
+					<view class="company-name-title">
+						<view class="company-name">{{ work.companyName }}</view>
+						<view class="company-tag" v-if="work.isCrossCompany">跨境</view>
+					</view>
+					<view class="position-item" v-for="(item, index) in work.workExpDetailList" :key="index">
+						<view class="position-info">{{ item.position }} &nbsp; {{ item.startTime }}-{{ item.endTime }}</view>
+						<view class="content">
+							<view class="content-title">工作内容</view>
+							<view class="content-text">{{ item.workContent }}</view>
+						</view>
+						<view class="content">
+							<view class="content-title">工作业绩</view>
+							<view class="content-text">{{ item.workPerformance }}</view>
+						</view>
+						<view class="tags">
+							<view class="tag" v-for="(skill, i) in item.skills" :key="i">{{ skill }}</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			
+			<view class="show-all-btn" v-if="workExpList.length > 1 && !toggle" @click="handleShowAll">展开全部工作经历</view>
+		</view>
+		
+		<!-- 教育经历 -->
+		<view class="common-section">
+			<view class="title">教育经历</view>
+			<view class="edu-item" v-for="item in eduList" :key="item.eduId">
+				<view class="school-name">{{ item.school }}</view>
+				<view class="edu-base-info">{{ item.degree }} • {{ item.profession }} • {{ item.time }}</view>
+				<view class="desc">{{ item.detail }}</view>
+			</view>
+		</view>
+		
+		<!-- 资质证书 -->
+		<view class="common-section">
+			<view class="title">资质证书</view>
+			<view class="tags">
+				<view class="tag" v-for="item in certificates" :key="item.certificateId">{{ item.certificateName }}</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { jobStatus as jobStatusList } from '@/constants/userInfo'
+
+	export default {
+		data() {
+			return {
+				userName: '',
+				sex: '',
+				avatarUrl: '',
+				currentCompanyName: '',
+				currentPositionName: '',
+				jobStatus: '',
+				baseInfoList: [], // 工作年限、学历、年龄
+				adv: '', // 个人优势
+				intentions: [], // 求职期望
+				workExpList: [], // 工作经历
+				eduList: [], // 教育经历
+				certificates: [], // 资质证书
+				toggle: false
+			};
+		},
+		computed: {
+			jobStatusName() {
+				return jobStatusList[this.jobStatus]?.text
+			},
+			showWrokExpList() {
+				if (!this.toggle) {
+					return this.workExpList.filter((wrok, index) => {
+						if (index < 1) {
+							return wrok
+						}
+					})
+				}
+				return this.workExpList
+			}
+		},
+		mounted() {
+			this.getData()
+		},
+		methods: {
+			// 获取数据
+			getData() {
+				this.$Request
+					.getT('/app/userFirst/getUserResumes')
+					.then((res) => {
+						console.log(res)
+						if (res.code === 0) {
+							const data = res.data
+							this.userName = data.userEntity.userName
+							this.sex = data.userEntity.sex
+							this.avatarUrl = data.userEntity.avatar
+							this.jobStatus = data.resumeList.resumesStatus
+							if (data.workExpList.length) {
+								this.currentCompanyName = data.workExpList[0].companyName
+								this.currentPositionName = data.workExpList[0].position
+							}
+							// 添加工作年限
+							if (data.resumeList?.resumesWorkExperience) {
+								this.baseInfoList.push(data.resumeList.resumesWorkExperience)
+							}
+							// 添加学历
+							if (data.eduList) {
+								this.baseInfoList.push(this.$queue.getHighestEducation(data.eduList))
+							}
+							// 添加年龄
+							if (data.userEntity) {
+								this.baseInfoList.push(`${data.userEntity.age}岁`)
+							}
+							this.adv = data.resumeList.adv
+							
+							// 求职期望
+							this.intentions = data.intentions
+							
+							// 工作经历
+							this.workExpList = data.workExps.map(work => {
+								let workExpDetailList = []
+								let isCrossCompany = false
+								data.workExpList.forEach(item => {
+									if (work.workExpId == item.workExpId) {
+										item.skills = JSON.parse(item.skills)
+										
+										workExpDetailList.push(item)
+									}
+								})
+								
+								// 判断是否是跨境公司
+								if (work.type && JSON.parse(work.type)?.[0] == 0) {
+									isCrossCompany = true
+								}
+								
+								work.workExpDetailList = workExpDetailList
+								work.isCrossCompany = isCrossCompany
+								return work
+							})
+							console.log(this.workExpList);
+							
+							// 教育经历
+							this.eduList = data.eduList.map(edu => {
+								let time = ''
+								if (edu.startTime && edu.endTime) {
+									time = `${edu.startTime.split('-')[0]}-${edu.endTime.split('-')[0]}`
+								}
+								edu.time = time
+								return edu
+							})
+							
+							// 资质证书
+							this.certificates = data.certificates
+						}
+					})
+			},
+			// 格式化薪资
+			formatSalary(min, max) {
+				if (min && max) {
+					return `${min / 1000}-${max / 1000}K`
+				}
+				return '--'
+			},
+			// 格式化标签
+			formatTag(text) {
+				return text.replace(/\//g, '|')
+			},
+			// 展示所有工作经历
+			handleShowAll() {
+				this.toggle = true
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.preview-resume-container {
+		font-family: DM Sans;
+		padding: 20rpx 40rpx 40rpx;
+		background: #fff;
+
+		// 个人基本信息
+		.user-info {
+			.name {
+				font-size: 48rpx;
+				font-weight: 700;
+				line-height: 60rpx;
+			}
+			.avatar-box {
+				position: relative;
+				.avatar {
+					display: block;
+					width: 72rpx;
+					height: 72rpx;
+					border-radius: 72rpx;
+					border: 1px solid rgba(240, 240, 240, 1);
+				}
+				.sex-tag {
+					position: absolute;
+					top: 0;
+					right: 0;
+					width: 22rpx;
+					height: 22rpx;
+					border-radius: 22rpx;
+					background: #fff;
+				}
+			}
+			.sub-info {
+				font-size: 24rpx;
+				line-height: 40rpx;
+				color: rgba(156, 164, 171, 1);
+				margin: 20rpx 0;
+				.icon {
+					display: block;
+					width: 40rpx;
+					height: 40rpx;
+					margin-right: 8rpx;
+				}
+			}
+			.advantages {
+				font-size: 28rpx;
+				line-height: 36rpx;
+				color: rgba(97, 110, 124, 1);
+				margin-top: 20rpx;
+			}
+			.resume-tag {
+				display: flex;
+				align-items: center;
+				font-size: 24rpx;
+				line-height: 32rpx;
+				color: rgba(1, 107, 246, 1);
+				padding: 16rpx 0;
+				margin-top: 20rpx;
+				.resume-icon {
+					display: block;
+					width: 32rpx;
+					height: 32rpx;
+					margin-right: 8rpx;
+				}
+			}
+		}
+
+		// 求职期望
+		.job-expect-container {
+			margin-top: 20rpx;
+			.job-expect-title {
+				font-size: 32rpx;
+				line-height: 48rpx;
+				color: rgba(34, 37, 42, 1);
+				margin-bottom: 20rpx;
+			}
+			.job-expect {
+				margin-bottom: 20rpx;
+				.text {
+					width: 500rpx;
+					font-size: 24rpx;
+					line-height: 32rpx;
+					color: rgba(153, 153, 153, 1);
+					padding: 6rpx 0;
+					margin-bottom: 12rpx;
+					text {
+						margin-right: 8rpx;
+					}
+				}
+				.salary {
+					font-size: 32rpx;
+					line-height: 40rpx;
+					font-weight: 700;
+					color: rgba(1, 107, 246, 1);
+				}
+				.skills {
+					font-size: 20rpx;
+					line-height: 24rpx;
+					color: rgba(153, 153, 153, 1);
+				}
+			}
+		}
+
+		// 工作经历
+		.work-exprience-container {
+			.title-bar {
+				border-radius: 110rpx;
+				box-shadow: 0px 16rpx 300rpx 0px rgba(0, 0, 0, 0.06);
+				background: rgba(1, 107, 246, 0.1);
+				padding: 12rpx 24rpx;
+				color: rgba(1, 107, 246, 1);
+				font-size: 32rpx;
+				line-height: 44rpx;
+				margin-bottom: 20rpx;
+				.title-icon {
+					display: block;
+					width: 28rpx;
+					height: 28rpx;
+					margin-right: 8rpx;
+				}
+			}
+
+			.work-item {
+				margin-bottom: 40rpx;
+				&:last-child {
+					margin-bottom: 0;
+				}
+			}
+
+			.company-name-title {
+				display: flex;
+				justify-content: space-between;
+				margin-bottom: 8rpx;
+				.company-name {
+					flex: 1;
+					font-size: 28rpx;
+					color: rgba(23, 23, 37, 1);
+					line-height: 32rpx;
+					padding: 6rpx 0;
+				}
+				.company-tag {
+					height: 32rpx;
+					font-size: 20rpx;
+					line-height: 1;
+					color: #fff;
+					border-radius: 8rpx;
+					background: linear-gradient(90.00deg, rgba(13, 39, 247, 0.75) 0%,rgba(19, 193, 234, 0.75) 100%);
+					padding: 6rpx 7rpx;
+					margin-top: 6rpx;
+					margin-left: 20rpx;
+					box-sizing: border-box;
+				}
+			}
+
+			.position-item {
+				padding-bottom: 36rpx;
+				margin-bottom: 20rpx;
+				border-bottom: 1px solid rgba(227, 231, 236, 0.55);
+
+				.position-info {
+					color: rgba(102, 102, 102, 1);
+					font-size: 24rpx;
+					line-height: 32rpx;
+					margin-bottom: 8rpx;
+				}
+				.content {
+					margin-bottom: 20rpx;
+					.content-title {
+						font-size: 28rpx;
+						line-height: 36rpx;
+						color: #000;
+						margin-bottom: 8rpx;
+					}
+					.content-text {
+						font-size: 28rpx;
+						line-height: 36rpx;
+						color: rgba(120, 130, 138, 1);
+					}
+				}
+
+				&:last-child {
+					padding-bottom: 0;
+					margin-bottom: 0;
+					border-bottom: none;
+				}
+			}
+
+			.show-all-btn {
+				font-size: 20rpx;
+				line-height: 26rpx;
+				color: rgba(1, 107, 246, 1);
+				margin-bottom: 20rpx;
+			}
+		}
+
+		.common-section {
+			padding: 32rpx;
+			border:  1px solid rgba(227, 231, 236, 1);
+			border-radius: 24rpx;
+			margin-bottom: 20rpx;
+			.title {
+				font-size: 32rpx;
+				font-weight: 700;
+				line-height: 48rpx;
+				color: rgba(23, 23, 37, 1);
+				margin-bottom: 24rpx;
+			}
+			.edu-item {
+				margin-bottom: 56rpx;
+
+				.school-name {
+					font-size: 28rpx;
+					line-height: 44rpx;
+					color: rgba(23, 23, 37, 1);
+					margin-bottom: 6rpx;
+				}
+
+				.edu-base-info {
+					font-size: 24rpx;
+					line-height: 40rpx;
+					font-weight: 500;
+					color: rgba(120, 130, 138, 1);
+				}
+				.desc {
+					font-size: 28rpx;
+					line-height: 36rpx;
+					color: rgba(120, 130, 138, 1);
+					margin-top: 6rpx;
+				}
+
+				&:last-child {
+					margin-bottom: 0;
+				}
+			}
+		}
+
+		// tag样式
+		.tags {
+			display: flex;
+			flex-wrap: wrap;
+			gap: 8rpx;
+			.tag {
+				padding: 8rpx;
+				border-radius: 8rpx;
+				background: rgba(198, 198, 198, 0.1);
+				font-size: 20rpx;
+				line-height: 1;
+				color: rgba(153, 153, 153, 1);
+			}
+		}
+	}
+</style>

+ 273 - 0
components/resume/resume-card.vue

@@ -0,0 +1,273 @@
+<template>
+	<view class="resume-card">
+		<view class="top-section flex justify-between">
+			<view class="flex user-info">
+				<view class="avatar-container">
+					<image :src="avatar ? avatar : '/static/images/logo.jpg'" class="avatar"></image>
+					<image src="@/static/images/svg/male.svg" class="sex-icon" v-if="sex == 1"></image>
+					<image src="@/static/images/svg/female.svg" class="sex-icon" v-else-if="sex == 2"></image>
+				</view>
+				<view class="user-info-box">
+					<view class="flex">
+						<text class="name">{{ userName }}</text>
+						<view class="online-status" :class="{ online: lineValue == ONLINE, offline: lineValue == OFFLINE }">{{ lineText }}</view>
+					</view>
+					<view class="base-info flex align-center">
+						<text v-for="(item, index) in baseInfoArr" :key="index">{{ item }}</text>
+					</view>
+				</view>
+			</view>
+			<view class="salary">{{ salaryRange }}</view>
+		</view>
+		<view class="flex align-center justify-between company-info">
+			<view class="flex align-center">
+				<image src="@/static/images/svg/bag.svg" class="icon"></image>
+				<text class="text">{{ companyName }} · {{ positionName }}</text>
+				<view class="company-tag" v-if="isCrossCompany">跨境</view>
+			</view>
+			<view class="time">{{ companyTime }}</view>
+		</view>
+		<view class="tags">
+			<view class="tag" v-for="(item, index) in skills" :key="index">{{ item }}</view>
+		</view>
+		<view class="bottom-section flex align-center">
+			<image src="@/static/images/svg/heart.svg" class="expection-icon"></image>
+			求职期望:{{ ruleClassifyName }}
+		</view>
+	</view>
+</template>
+
+<script>
+	const ONLINE = 'ONLINE'
+	const OFFLINE = 'OFFLINE'
+	
+	export default {
+		data() {
+			return {
+				avatar: '',
+				sex: 0, // 1男、2女
+				userName: '',
+				baseInfoArr: [], // 基本信息
+				companyName: '', // 公司
+				positionName: '', // 职位
+				salaryRange: '', // 薪资范围
+				lineValue: '', // 在线状态
+				isCrossCompany: false, // 是否是跨境
+				companyTime: '', // 当前公司工作时间
+				ruleClassifyName: '', // 期望岗位
+				skills: [], // 技能标签
+			};
+		},
+		computed: {
+			lineText() {
+				if (this.lineValue === ONLINE) {
+					return '在线'
+				} else if (this.lineValue === OFFLINE) {
+					return '离线'
+				}
+				return ''
+			}
+		},
+		mounted() {
+			this.getData()
+		},
+		methods: {
+			// 获取数据
+			getData() {
+				this.$Request
+					.getT('/app/resumes/getResumesReviewData')
+					.then(res => {
+						if (res.code === 0) {
+							const data = res.data
+							this.avatar = data.userAvatar
+							this.sex = data.userSex
+							this.userName = data.userName
+							this.lineValue = data.onlineStatus
+							
+							// 设置薪资
+							this.salaryRange = this.setSalaryRange(data.salaryRange)
+							
+							// 设置年龄、工龄、学历
+							if (data.userAge) {
+								this.baseInfoArr.push(`${data.userAge}岁`)
+							}
+							if (data.resumesWorkExperience) {
+								this.baseInfoArr.push(data.resumesWorkExperience)
+							}
+							if (data.degree) {
+								this.baseInfoArr.push(data.degree)
+							}
+							
+							this.companyName = data.companyName
+							this.positionName = data.position
+							this.ruleClassifyName = data.ruleClassifyName
+							// this.skills
+						}
+						console.log(res)
+					})
+			},
+			setSalaryRange(value) {
+				if (value && value.indexOf('-')) {
+					const salaryValue = value.split('-')
+					return `${formatNumberToK(salaryValue[0])}-${formatNumberToK(salaryValue[1])}`
+				}
+				return ''
+			},
+			formatNumberToK(numStr) {
+				// 1. 异常处理:空值、非字符串、非数字字符串直接返回原内容
+				if (typeof numStr !== 'string' || numStr.trim() === '') {
+				    return numStr || '';
+				}
+				
+				// 2. 将字符串转为数字(自动忽略首尾空格)
+				const num = Number(numStr.trim());
+				
+				// 3. 非有效数字的情况,返回原字符串(如"abc"、"12a3")
+				if (isNaN(num)) {
+				    return numStr;
+				}
+				
+				// 4. 小于1000的数字,直接返回原数字的字符串(无格式变化)
+				if (num < 1000) {
+				    return String(Math.floor(num)); // 确保无小数(比如"999.9"转"999")
+				}
+				
+				// 5. 大于等于1000的数字,除以1000取整后拼接K
+				const kNum = Math.floor(num / 1000);
+				return `${kNum}K`;
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.resume-card {
+		background: #fff;
+		border-radius: 12rpx;
+		padding: 16rpx 36rpx;
+
+		.top-section {
+			margin-bottom: 12rpx;
+			.avatar-container {
+				position: relative;
+				margin-right: 20rpx;
+				.avatar {
+					width: 72rpx;
+					height: 72rpx;
+					border-radius: 72rpx;
+					border: 1px solid rgba(240, 240, 240, 1);
+				}
+				.sex-icon {
+					position: absolute;
+					top: 0;
+					right: 0;
+					width: 22rpx;
+					height: 22rpx;
+					background: #fff;
+					border-radius: 22rpx;
+				}
+			}
+			.user-info-box {
+				.name {
+					font-size: 28rpx;
+					font-weight: 500;
+					line-height: 36rpx;
+					color: rgba(51, 51, 51, 1);
+					margin-right: 20rpx;
+				}
+				.online-status {
+					font-size: 16rpx;
+					line-height: 20rpx;
+					padding: 8rpx 20rpx;
+					border-radius: 8rpx;
+				}
+				.online {
+					color: rgba(29, 209, 104, 1);
+					background: rgba(213, 255, 231, 1);
+				}
+				.offline {
+					color: #999;
+					background: #ddd;
+				}
+				// .other {
+				// 	color: #8858C5;
+				// 	background: #ECE1FD;
+				// }
+				.base-info {
+					margin-top: 6rpx;
+					text {
+						font-size: 24rpx;
+						line-height: 32rpx;
+						color: rgba(1, 107, 246, 1);
+						margin-right: 12rpx;
+					}
+				}
+			}
+			.salary {
+				font-size: 24rpx;
+				font-weight: 700;
+				line-height: 40rpx;
+				background-image: linear-gradient(90.00deg, rgba(13, 39, 247, 1),rgba(19, 193, 234, 1));
+				-webkit-background-clip: text;
+				color: transparent;
+				background-clip: text;
+			}
+		}
+
+		.company-info {
+			.icon {
+				width: 40rpx;
+				height: 40rpx;
+				margin-right: 8rpx;
+			}
+			.text {
+				max-width: 420rpx;
+				color: rgba(156, 164, 171, 1);
+				font-size: 24rpx;
+				line-height: 40rpx;
+			}
+			.company-tag {
+				height: 32rpx;
+				font-size: 20rpx;
+				line-height: 1;
+				color: #fff;
+				border-radius: 8rpx;
+				background: linear-gradient(90.00deg, rgba(13, 39, 247, 0.75) 0%,rgba(19, 193, 234, 0.75) 100%);
+				padding: 6rpx 7rpx;
+				margin-left: 20rpx;
+				box-sizing: border-box;
+			}
+			.time {
+				font-size: 20rpx;
+				line-height: 40rpx;
+				color: rgba(144.88, 87.8, 191.25, 1);
+			}
+		}
+		// tag样式
+		.tags {
+			display: flex;
+			flex-wrap: wrap;
+			.tag {
+				padding: 8rpx;
+				border-radius: 8rpx;
+				background: rgba(198, 198, 198, 0.1);
+				font-size: 20rpx;
+				line-height: 1;
+				color: rgba(153, 153, 153, 1);
+				margin-top: 8rpx;
+				margin-right: 8rpx;
+			}
+		}
+		.bottom-section {
+			color: rgba(156, 164, 171, 1);
+			font-size: 24rpx;
+			line-height: 40rpx;
+			margin-top: 12rpx;
+			.expection-icon {
+				width: 40rpx;
+				height: 40rpx;
+				margin-right: 8rpx;
+			}
+		}
+	}
+</style>

+ 146 - 0
components/swiper-delete.vue

@@ -0,0 +1,146 @@
+<template>
+	<view class="swipe-delete-wrapper">
+		<view
+			class="swipe-delete-container"
+			:style="{ transform: `translateX(${translateX}px)`, transition: transitionStyle }"
+			@touchstart="handleTouchStart"
+			@touchmove="handleTouchMove"
+			@touchend="handleTouchEnd"
+		>
+			<!-- 主体内容插槽:完全交给外部控制样式 -->
+			<view class="swipe-content">
+				<slot></slot>
+			</view>
+			<!-- 删除按钮:仅保留基础样式,无额外间距/边框 -->
+			<view class="swipe-delete-btn" @tap.stop="handleDelete">
+				{{ btnText || '删除' }}
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'SwipeDelete',
+		props: {
+			btnText: {
+				type: String,
+				default: '删除'
+			},
+			btnWidth: {
+				type: [Number, String],
+				default: 80
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				translateX: 0,
+				startX: 0,
+				startY: 0,
+				isMoving: false,
+				transitionStyle: 'transform 0.3s ease',
+				maxSlide: 0,
+				startTranslateX: 0
+			};
+		},
+		created() {
+			this.maxSlide = -Number(this.btnWidth);
+		},
+		methods: {
+			handleTouchStart(e) {
+				if (this.disabled) return;
+				e.preventDefault(); // 阻止iOS默认触摸行为
+				this.transitionStyle = 'none'; // 滑动时取消动画,更跟手
+				this.startX = e.changedTouches[0].clientX;
+				this.startY = e.changedTouches[0].clientY;
+				this.startTranslateX = this.translateX; // 记录当前偏移量,避免展开后继续滑触发动画
+				this.isMoving = true;
+			},
+			handleTouchMove(e) {
+				if (!this.isMoving || this.disabled) return;
+				const moveX = e.changedTouches[0].clientX - this.startX;
+				const moveY = e.changedTouches[0].clientY - this.startY;
+
+				// 过滤竖向滑动,避免上下滚动误触
+				if (Math.abs(moveY) > Math.abs(moveX)) {
+					this.isMoving = false;
+					return;
+				}
+
+				// 基于当前偏移量计算新位置,严格限制滑动边界(0 ~ -btnWidth)
+				let newTranslateX = this.startTranslateX + moveX;
+				newTranslateX = Math.max(this.maxSlide, Math.min(0, newTranslateX));
+
+				// 仅偏移量变化时更新,避免冗余动画
+				if (newTranslateX !== this.translateX) {
+					this.translateX = newTranslateX;
+				}
+			},
+			handleTouchEnd() {
+				if (this.disabled) return;
+				this.isMoving = false;
+				this.transitionStyle = 'transform 0.3s ease'; // 恢复动画,平滑复位/展开
+
+				// 低阈值判断,避免回滑突然复位(滑动超过30%才展开)
+				const slideRatio = Math.abs(this.translateX) / Math.abs(this.maxSlide);
+				this.translateX = slideRatio > 0.3 ? this.maxSlide : 0;
+			},
+			handleDelete() {
+				this.$emit('delete'); // 触发删除事件,交给外部处理逻辑
+				this.translateX = 0; // 点击删除后自动收回
+			},
+			close() {
+				// 供外部手动关闭(比如列表刷新时)
+				this.transitionStyle = 'transform 0.3s ease';
+				this.translateX = 0;
+			}
+		}
+	};
+</script>
+
+<style scoped>
+	/* 外层容器:仅保留溢出隐藏和定位,无边框/间距 */
+	.swipe-delete-wrapper {
+		width: 100%;
+		overflow: hidden;
+		/* 核心:隐藏右侧的删除按钮 */
+		position: relative;
+	}
+
+	/* 滑动容器:宽度=100%+按钮宽,确保删除按钮在屏幕外 */
+	.swipe-delete-container {
+		display: flex;
+		width: calc(100% + 80px);
+		height: 100%;
+		position: relative;
+	}
+
+	/* 主体内容:仅占满宽度,无额外样式,交给外部控制 */
+	.swipe-content {
+		width: 100%;
+		height: 100%;
+		box-sizing: border-box;
+		/* 避免外部padding导致宽度溢出 */
+	}
+
+	/* 删除按钮:仅保留核心样式,无圆角/边框,适配外部容器 */
+	.swipe-delete-btn {
+		width: 80px;
+		height: 100%;
+		background-color: #ff4757;
+		color: #fff;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 14px;
+		flex-shrink: 0;
+		/* 防止宽度被压缩 */
+		position: absolute;
+		right: 0;
+		top: 0;
+	}
+</style>

+ 20 - 0
constants/common.js

@@ -0,0 +1,20 @@
+// 公共业务
+// 公司类型
+export const companyType = [
+    {
+        label: '跨境电商',
+        value: '0',
+    },
+    {
+        label: '国内电商',
+        value: '1',
+    },
+    {
+        label: '外贸',
+        value: '2',
+    },
+    {
+        label: '其他',
+        value: '3',
+    }
+];

+ 29 - 0
constants/userInfo.js

@@ -0,0 +1,29 @@
+// 用户信息相关
+// 工作状态
+export const jobStatus = [
+    {
+        value: '0',
+        text: '离职-随时到岗',
+        recommended: true // 是否推荐
+    },
+    {
+        value: '1',
+        text: '在职-月内到岗',
+        recommended: true
+    },
+    {
+        value: '2',
+        text: '在职-考虑机会',
+        recommended: false
+    },
+    {
+        value: '3',
+        text: '在职-暂不考虑',
+        recommended: false
+    },
+    {
+        value: '4',
+        text: '实习',
+        recommended: false
+    }
+];

+ 5 - 4
manifest.json

@@ -8,9 +8,9 @@
     "sassImplementationName" : "node-sass",
     /* 5+App特有相关 */
     "app-plus" : {
-		"safearea": {
-		    "bottom": "none"
-		},
+        "safearea" : {
+            "bottom" : "none"
+        },
         "usingComponents" : true,
         "nvueStyleCompiler" : "uni-app",
         "compilerVersion" : 3,
@@ -238,7 +238,8 @@
                     }
                 },
                 "/sqx_fast" : {
-                    "target" : "https://www.bosszan.com",
+                    // "target" : "https://www.bosszan.com", // 生产环境
+                    "target" : "https://yizhizan.edccc.cn", // 测试环境
                     "changeOrigin" : true,
                     "secure" : false
                 }

+ 207 - 191
package/jobIntention/addExpectation.vue

@@ -44,7 +44,7 @@
 						</view>
 					</view>
 					<!-- 范围滑块 -->
-					<view class="range-slider-container">
+					<!-- <view class="range-slider-container">
 						<view class="range-slider-track" @click="onTrackClick">
 							<view class="range-slider-progress" :style="progressStyle"></view>
 							<view 
@@ -62,12 +62,12 @@
 								@touchend="onRightThumbEnd"
 							></view>
 						</view>
-					</view>
+					</view> -->
 				</view>
 			</view>
 
 			<!-- 工作类型 -->
-			<view class="form-item">
+			<!-- view class="form-item">
 				<text class="form-label">工作类型</text>
 				<view class="job-type-container">
 					<view 
@@ -85,7 +85,7 @@
 						<text>兼职</text>
 					</view>
 				</view>
-			</view>
+			</view> -->
 
 			<!-- 从事方向 -->
 			<view class="form-item">
@@ -96,18 +96,9 @@
 				</view>
 			</view>
 		</view>
-		<view class="footer">
-		  <u-button
-		    type="primary"
-		    @click="saveWorkExperience"
-		    :customStyle="{
-		      height: '90rpx',
-		      fontSize: '32rpx',
-		      borderRadius: '45rpx',
-		      margin: '40rpx 0',
-		    }"
-		    >提交</u-button
-		  >
+		
+		<view class="fixed-section">
+			<u-button type="primary" class="submit-btn" @click="saveWorkExperience">保存</u-button>
 		</view>
 	</view>
 </template>
@@ -147,25 +138,25 @@ export default {
 		rightPercent() {
 			return ((this.maxValue - this.sliderMin) / (this.sliderMax - this.sliderMin)) * 100
 		},
-		// 进度条样式
-		progressStyle() {
-			return {
-				left: this.leftPercent + '%',
-				width: (this.rightPercent - this.leftPercent) + '%'
-			}
-		},
-		// 左侧滑块样式
-		leftThumbStyle() {
-			return {
-				left: this.leftPercent + '%'
-			}
-		},
-		// 右侧滑块样式
-		rightThumbStyle() {
-			return {
-				left: this.rightPercent + '%'
-			}
-		}
+		// // 进度条样式
+		// progressStyle() {
+		// 	return {
+		// 		left: this.leftPercent + '%',
+		// 		width: (this.rightPercent - this.leftPercent) + '%'
+		// 	}
+		// },
+		// // 左侧滑块样式
+		// leftThumbStyle() {
+		// 	return {
+		// 		left: this.leftPercent + '%'
+		// 	}
+		// },
+		// // 右侧滑块样式
+		// rightThumbStyle() {
+		// 	return {
+		// 		left: this.rightPercent + '%'
+		// 	}
+		// }
 	},
 	methods: {
 		getData(){
@@ -211,106 +202,106 @@ export default {
 				url: '/package/jobIntention/preferenceSetting?jobId='+this.jobId+'&jobTitle='+this.jobTitle+'&selectedPreferences='+encodeURIComponent(JSON.stringify(this.industry==''||this.industry==null?[]:this.industry.split('/')))
 			})
 		},
-		selectJobType(type) {
-			this.jobType = type
-		},
-		// 获取滑块轨道宽度
-		getTrackWidth() {
-			uni.createSelectorQuery().in(this).select('.range-slider-track').boundingClientRect(data => {
-				this.trackWidth = data.width
-			}).exec()
-		},
-		// 将像素位置转换为数值
-		pixelToValue(pixel) {
-			const percent = (pixel / this.trackWidth) * 100
-			const value = this.sliderMin + (percent / 100) * (this.sliderMax - this.sliderMin)
-			return Math.round(value / this.step) * this.step
-		},
-		// 左侧滑块开始拖拽
-		onLeftThumbStart(e) {
-			this.draggingThumb = 'left'
-			this.startX = e.touches[0].clientX
-			this.startValue = this.minValue
-			e.preventDefault()
-		},
-		// 左侧滑块拖拽中
-		onLeftThumbMove(e) {
-			if (this.draggingThumb !== 'left') return
+		// selectJobType(type) {
+		// 	this.jobType = type
+		// },
+		// // 获取滑块轨道宽度
+		// getTrackWidth() {
+		// 	uni.createSelectorQuery().in(this).select('.range-slider-track').boundingClientRect(data => {
+		// 		this.trackWidth = data.width
+		// 	}).exec()
+		// },
+		// // 将像素位置转换为数值
+		// pixelToValue(pixel) {
+		// 	const percent = (pixel / this.trackWidth) * 100
+		// 	const value = this.sliderMin + (percent / 100) * (this.sliderMax - this.sliderMin)
+		// 	return Math.round(value / this.step) * this.step
+		// },
+		// // 左侧滑块开始拖拽
+		// onLeftThumbStart(e) {
+		// 	this.draggingThumb = 'left'
+		// 	this.startX = e.touches[0].clientX
+		// 	this.startValue = this.minValue
+		// 	e.preventDefault()
+		// },
+		// // 左侧滑块拖拽中
+		// onLeftThumbMove(e) {
+		// 	if (this.draggingThumb !== 'left') return
 			
-			const deltaX = e.touches[0].clientX - this.startX
-			const deltaPercent = (deltaX / this.trackWidth) * 100
-			const deltaValue = (deltaPercent / 100) * (this.sliderMax - this.sliderMin)
-			let newValue = this.startValue + deltaValue
+		// 	const deltaX = e.touches[0].clientX - this.startX
+		// 	const deltaPercent = (deltaX / this.trackWidth) * 100
+		// 	const deltaValue = (deltaPercent / 100) * (this.sliderMax - this.sliderMin)
+		// 	let newValue = this.startValue + deltaValue
 			
-			// 限制范围
-			newValue = Math.max(this.sliderMin, Math.min(newValue, this.maxValue - this.step))
-			newValue = Math.round(newValue / this.step) * this.step
+		// 	// 限制范围
+		// 	newValue = Math.max(this.sliderMin, Math.min(newValue, this.maxValue - this.step))
+		// 	newValue = Math.round(newValue / this.step) * this.step
 			
-			this.minValue = newValue
-			this.minSalary = newValue.toString()
-			e.preventDefault()
-		},
-		// 左侧滑块结束拖拽
-		onLeftThumbEnd(e) {
-			this.draggingThumb = null
-			e.preventDefault()
-		},
-		// 右侧滑块开始拖拽
-		onRightThumbStart(e) {
-			this.draggingThumb = 'right'
-			this.startX = e.touches[0].clientX
-			this.startValue = this.maxValue
-			e.preventDefault()
-		},
-		// 右侧滑块拖拽中
-		onRightThumbMove(e) {
-			if (this.draggingThumb !== 'right') return
+		// 	this.minValue = newValue
+		// 	this.minSalary = newValue.toString()
+		// 	e.preventDefault()
+		// },
+		// // 左侧滑块结束拖拽
+		// onLeftThumbEnd(e) {
+		// 	this.draggingThumb = null
+		// 	e.preventDefault()
+		// },
+		// // 右侧滑块开始拖拽
+		// onRightThumbStart(e) {
+		// 	this.draggingThumb = 'right'
+		// 	this.startX = e.touches[0].clientX
+		// 	this.startValue = this.maxValue
+		// 	e.preventDefault()
+		// },
+		// // 右侧滑块拖拽中
+		// onRightThumbMove(e) {
+		// 	if (this.draggingThumb !== 'right') return
 			
-			const deltaX = e.touches[0].clientX - this.startX
-			const deltaPercent = (deltaX / this.trackWidth) * 100
-			const deltaValue = (deltaPercent / 100) * (this.sliderMax - this.sliderMin)
-			let newValue = this.startValue + deltaValue
+		// 	const deltaX = e.touches[0].clientX - this.startX
+		// 	const deltaPercent = (deltaX / this.trackWidth) * 100
+		// 	const deltaValue = (deltaPercent / 100) * (this.sliderMax - this.sliderMin)
+		// 	let newValue = this.startValue + deltaValue
 			
-			// 限制范围
-			newValue = Math.max(this.minValue + this.step, Math.min(newValue, this.sliderMax))
-			newValue = Math.round(newValue / this.step) * this.step
+		// 	// 限制范围
+		// 	newValue = Math.max(this.minValue + this.step, Math.min(newValue, this.sliderMax))
+		// 	newValue = Math.round(newValue / this.step) * this.step
 			
-			this.maxValue = newValue
-			this.maxSalary = newValue.toString()
-			e.preventDefault()
-		},
-		// 右侧滑块结束拖拽
-		onRightThumbEnd(e) {
-			this.draggingThumb = null
-			e.preventDefault()
-		},
-		// 点击轨道
-		onTrackClick(e) {
-			if (this.draggingThumb) return
+		// 	this.maxValue = newValue
+		// 	this.maxSalary = newValue.toString()
+		// 	e.preventDefault()
+		// },
+		// // 右侧滑块结束拖拽
+		// onRightThumbEnd(e) {
+		// 	this.draggingThumb = null
+		// 	e.preventDefault()
+		// },
+		// // 点击轨道
+		// onTrackClick(e) {
+		// 	if (this.draggingThumb) return
 			
-			const rect = e.currentTarget.getBoundingClientRect()
-			const clickX = e.detail.x - rect.left
-			const clickPercent = (clickX / rect.width) * 100
-			const clickValue = this.sliderMin + (clickPercent / 100) * (this.sliderMax - this.sliderMin)
+		// 	const rect = e.currentTarget.getBoundingClientRect()
+		// 	const clickX = e.detail.x - rect.left
+		// 	const clickPercent = (clickX / rect.width) * 100
+		// 	const clickValue = this.sliderMin + (clickPercent / 100) * (this.sliderMax - this.sliderMin)
 			
-			// 判断点击位置更靠近哪个滑块
-			const distanceToLeft = Math.abs(clickValue - this.minValue)
-			const distanceToRight = Math.abs(clickValue - this.maxValue)
+		// 	// 判断点击位置更靠近哪个滑块
+		// 	const distanceToLeft = Math.abs(clickValue - this.minValue)
+		// 	const distanceToRight = Math.abs(clickValue - this.maxValue)
 			
-			if (distanceToLeft < distanceToRight) {
-				// 更靠近左侧滑块
-				let newValue = Math.round(clickValue / this.step) * this.step
-				newValue = Math.max(this.sliderMin, Math.min(newValue, this.maxValue - this.step))
-				this.minValue = newValue
-				this.minSalary = newValue.toString()
-			} else {
-				// 更靠近右侧滑块
-				let newValue = Math.round(clickValue / this.step) * this.step
-				newValue = Math.max(this.minValue + this.step, Math.min(newValue, this.sliderMax))
-				this.maxValue = newValue
-				this.maxSalary = newValue.toString()
-			}
-		},
+		// 	if (distanceToLeft < distanceToRight) {
+		// 		// 更靠近左侧滑块
+		// 		let newValue = Math.round(clickValue / this.step) * this.step
+		// 		newValue = Math.max(this.sliderMin, Math.min(newValue, this.maxValue - this.step))
+		// 		this.minValue = newValue
+		// 		this.minSalary = newValue.toString()
+		// 	} else {
+		// 		// 更靠近右侧滑块
+		// 		let newValue = Math.round(clickValue / this.step) * this.step
+		// 		newValue = Math.max(this.minValue + this.step, Math.min(newValue, this.sliderMax))
+		// 		this.maxValue = newValue
+		// 		this.maxSalary = newValue.toString()
+		// 	}
+		// },
 		saveWorkExperience() {
 		  if (!this.jobId) {
 		    uni.showToast({ title: "请选择工作职位", icon: "none" });
@@ -320,6 +311,13 @@ export default {
 		    uni.showToast({ title: "请选择城市", icon: "none" });
 		    return;
 		  }
+		  // 限制最低工资不能高于最高工资
+		  const minSalary = Number(this.minSalary) || 0
+		  const maxSalary = Number(this.maxSalary) || 0
+		  if (minSalary > maxSalary) {
+			  uni.showToast({ title: "最低薪酬不能大于最高薪酬", icon: "none" });
+			  return;
+		  }
 		  if (!this.industry) {
 		    uni.showToast({ title: "请选择跨境标签", icon: "none" });
 		    return;
@@ -365,10 +363,10 @@ export default {
 		},
 	},
 	mounted() {
-		// 初始化滑块轨道宽度
-		this.$nextTick(() => {
-			this.getTrackWidth()
-		})
+		// // 初始化滑块轨道宽度
+		// this.$nextTick(() => {
+		// 	this.getTrackWidth()
+		// })
 	},
 	onLoad(options) {
 		// 获取状态栏高度
@@ -405,9 +403,10 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+@import '../../common.scss';
+	
 .add-expectation {
 	min-height: 100vh;
-	padding: 0 40rpx 40rpx 40rpx;
 }
 
 .nav-bar {
@@ -415,6 +414,7 @@ export default {
 	align-items: center;
 	justify-content: space-between;
 	margin-bottom: 30rpx;
+	padding: 0 40rpx;
 
 	.nav-left {
 		display: flex;
@@ -436,6 +436,7 @@ export default {
 	background: #ffffff;
 	border-radius: 20rpx;
 	margin-top: 30rpx;
+	padding: 0 40rpx;
 }
 
 .form-item {
@@ -483,13 +484,12 @@ export default {
 		display: flex;
 		align-items: center;
 		margin: 20rpx 0 30rpx 0;
-        gap: 50rpx;
 
 		.salary-input {
 			display: flex;
 			align-items: center;
 			flex: 1;
-			padding: 20rpx;
+			padding: 30rpx 20rpx;
 			border-radius: 12rpx;
             box-shadow: 0px 8px 150px 0px rgba(0, 0, 0, 0.06);
             background: rgba(255, 255, 255, 1);
@@ -504,6 +504,9 @@ export default {
                 font-size: 28rpx;
 			}
 		}
+		.salary-input:first-child {
+			margin-right: 50rpx;
+		}
 
 		.salary-separator {
 			margin: 0 20rpx;
@@ -512,72 +515,85 @@ export default {
 		}
 	}
 
-	.range-slider-container {
-		padding: 20rpx 10rpx;
-	}
+	// .range-slider-container {
+	// 	padding: 20rpx 10rpx;
+	// }
 
-	.range-slider-track {
-		position: relative;
-		height: 6rpx;
-		background-color: #E5E5EA;
-		border-radius: 3rpx;
-		cursor: pointer;
-	}
+	// .range-slider-track {
+	// 	position: relative;
+	// 	height: 6rpx;
+	// 	background-color: #E5E5EA;
+	// 	border-radius: 3rpx;
+	// 	cursor: pointer;
+	// }
 
-	.range-slider-progress {
-		position: absolute;
-		top: 0;
-		height: 100%;
-		background-color: #007AFF;
-		border-radius: 3rpx;
-		transition: all 0.1s ease;
-	}
+	// .range-slider-progress {
+	// 	position: absolute;
+	// 	top: 0;
+	// 	height: 100%;
+	// 	background-color: #007AFF;
+	// 	border-radius: 3rpx;
+	// 	transition: all 0.1s ease;
+	// }
 
-	.range-slider-thumb {
-		position: absolute;
-		top: 50%;
-		width: 40rpx;
-		height: 40rpx;
-		background-color: #007AFF;
-		border-radius: 50%;
-		border: 4rpx solid #ffffff;
-		box-shadow: 0 2rpx 8rpx rgba(0, 122, 255, 0.3);
-		transform: translate(-50%, -50%);
-		cursor: pointer;
-		transition: all 0.1s ease;
-	}
+	// .range-slider-thumb {
+	// 	position: absolute;
+	// 	top: 50%;
+	// 	width: 40rpx;
+	// 	height: 40rpx;
+	// 	background-color: #007AFF;
+	// 	border-radius: 50%;
+	// 	border: 4rpx solid #ffffff;
+	// 	box-shadow: 0 2rpx 8rpx rgba(0, 122, 255, 0.3);
+	// 	transform: translate(-50%, -50%);
+	// 	cursor: pointer;
+	// 	transition: all 0.1s ease;
+	// }
 
-	.range-slider-thumb:active {
-		transform: translate(-50%, -50%) scale(1.1);
-		box-shadow: 0 4rpx 12rpx rgba(0, 122, 255, 0.4);
-	}
+	// .range-slider-thumb:active {
+	// 	transform: translate(-50%, -50%) scale(1.1);
+	// 	box-shadow: 0 4rpx 12rpx rgba(0, 122, 255, 0.4);
+	// }
 }
 
-.job-type-container {
-	display: flex;
-	gap: 50rpx;
-    margin-top: 20rpx;
+// .job-type-container {
+// 	display: flex;
+// 	gap: 50rpx;
+//     margin-top: 20rpx;
 
-	.job-type-btn {
-		flex: 1;
-		padding: 24rpx 20rpx;
-		border: 1rpx solid #E5E5EA;
-		border-radius: 42rpx;
-		text-align: center;
+// 	.job-type-btn {
+// 		flex: 1;
+// 		padding: 24rpx 20rpx;
+// 		border: 1rpx solid #E5E5EA;
+// 		border-radius: 42rpx;
+// 		text-align: center;
 
-		text {
-			color: rgba(97, 110, 124, 1);
-			font-size: 28rpx;
-		}
+// 		text {
+// 			color: rgba(97, 110, 124, 1);
+// 			font-size: 28rpx;
+// 		}
 
-		&.active {
-			background: #016BF6;
+// 		&.active {
+// 			background: #016BF6;
 
-			text {
-				color: #FFFFFF;
-				font-weight: 400;
-			}
-		}
-	}
-}
+// 			text {
+// 				color: #FFFFFF;
+// 				font-weight: 400;
+// 			}
+// 		}
+// 	}
+// }
+
+// .footer {
+// 	position: fixed;
+// 	left: 0;
+// 	right: 0;
+// 	bottom: 0;
+// 	padding: 0 40rpx;
+// 	box-shadow: 0px -4px 16px 0px rgba(0, 0, 0, 0.04);
+// 	background-color: #fff;
+// 	.submit-btn {
+// 		background: linear-gradient(90.00deg, rgba(13, 39, 247, 1),rgba(19, 193, 234, 1));
+// 	}
+// }
 </style>

+ 10 - 21
package/jobIntention/basicInfo.vue

@@ -11,10 +11,7 @@
 				</view>
 				<view @click="chooseAvatar" class="avatar-container">
 					<image :src="avatar?avatar:'../../static/images/logo.jpg'" class="user-avatar" mode="aspectFill"></image>
-					<view class="edit-avatar-icon">
-						<image src="../../static/images/index/Combined-Shape.svg" style="width: 32rpx;height: 32rpx;"
-							mode=""></image>
-					</view>
+					<view class="tip">重新上传</view>
 				</view>
 			</view>
 
@@ -159,8 +156,7 @@
 				showDatePicker: false, // 控制日期选择器显示
 				dateParams: {
 					year: true,
-					month: true,
-					day: true
+					month: true
 				},
 				// 求职状态相关
 				showJobStatusModal: false,
@@ -264,7 +260,7 @@
 					month,
 					day
 				} = e;
-				this.birthDateText = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
+				this.birthDateText = `${year}-${String(month).padStart(2, '0')}`;
 				this.showDatePicker = false;
 			},
 			// 显示求职状态选择器
@@ -464,26 +460,19 @@
 
 			// 头像样式
 			.avatar-container {
-				position: relative;
-				display: inline-block;
+				display: flex;
+				align-items: center;
 
 				.user-avatar {
 					width: 80rpx;
 					height: 80rpx;
 					border-radius: 50%;
+					margin-right: 24rpx;
 				}
-
-				.edit-avatar-icon {
-					position: absolute;
-					bottom: 10rpx;
-					left: 60rpx;
-					width: 25rpx;
-					height: 25rpx;
-					border-radius: 50%;
-					display: flex;
-					align-items: center;
-					justify-content: center;
-					box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
+				.tip {
+					font-size: 20rpx;
+					line-height: 44rpx;
+					color: rgba(1, 107, 246, 1);
 				}
 			}
 

+ 24 - 22
package/jobIntention/jobList.vue

@@ -36,7 +36,7 @@
 		<view class="list flex justify-between" v-else>
 			<!-- 左侧分类 -->
 			<view class="list-l">
-				<scroll-view scroll-y="true" style="width: 100%;height: 100%;padding-bottom: 20rpx;">
+				<scroll-view scroll-y="true" style="width: 100%;height: 100%;padding-bottom: 20rpx;padding-top: 20rpx;">
 					<view class="list-l-item flex align-center " @click="setRightList(index)" :class="current==index?'active':''" v-for="(item,index) in list" :key="index">
 						{{item.ruleClassifyName}}
 					</view>
@@ -47,7 +47,7 @@
 			<view class="list-r">
 				<!-- 中间标题列 -->
 				<view class="list-r-titles">
-					<scroll-view scroll-y="true" style="width: 100%;height: 100%;padding-bottom: 20rpx;">
+					<scroll-view scroll-y="true" style="width: 100%;height: 100%;">
 						<view class="list-r-title-item" @click="setActiveTitle(index)" :class="activeTitle==index?'active':''" v-for="(item,index) in rightList" :key="index">
 							{{item.title}}
 						</view>
@@ -246,7 +246,7 @@
 		}
 	}
 	.search{
-		margin: 0 32rpx;
+		padding: 0 32rpx;
 		height: 100rpx;
 		border-bottom: 1rpx solid #F2F2F7;
 		box-sizing: border-box;
@@ -265,18 +265,18 @@
 		border-radius: 6px;
 	}
 	.list{
-		margin: 0 32rpx;
+		margin: 20rpx 32rpx 0;
 		flex: 1;
-		gap: 12rpx;
 		overflow: auto;
 		.list-l{
-			width: 25%;
+			width: 164rpx;
 			height: 100%;
 			border-radius: 6px;
 			background: rgba(245, 245, 245, 1);
+			margin-right: 16rpx;
 			
 			.list-l-item{
-				margin-top: 20rpx;
+				margin-bottom: 20rpx;
 				color: rgba(102, 102, 102, 1);
 				font-family: DM Sans;
 				padding: 20rpx 10rpx;
@@ -294,7 +294,8 @@
 			flex: 1;
 			height: 100%;
 			background-color: #ffffff;
-			border-left: 1rpx solid #F2F2F7;
+			border-radius: 12rpx;
+			box-shadow: 0px 16rpx 300rpx 0px rgba(0, 0, 0, 0.05);
 			box-sizing: border-box;
 			display: flex;
 			flex-direction: row;
@@ -305,20 +306,19 @@
 				box-sizing: border-box;
 				
 				.list-r-title-item{
-					margin-top: 20rpx;
-					padding: 20rpx 10rpx;
-					color: var(--016BF6, rgba(1, 107, 246, 1));
+					margin-top: 16rpx;
+					padding: 16rpx 20rpx;
+					color: rgba(153, 153, 153, 1);
 					font-family: DM Sans;
-					font-size: 16px;
+					font-size: 32rpx;
 					font-weight: 400;
-					line-height: 21px;
+					line-height: 40rpx;
 					letter-spacing: 0%;
 					text-align: center;
 					
 					&.active{
 						color: rgba(1, 107, 246, 1) !important;
-						background: rgba(252, 233, 220, 1);
-						padding: 20rpx 10rpx;
+						background: rgba(1, 107, 246, 0.1);
 						border-left: none !important;
 						border-radius: 0 !important;
 					}
@@ -333,15 +333,13 @@
 					width: 100%;
 					display: flex;
 					flex-direction: column;
-					gap: 12rpx;
 					padding: 20rpx;
 					
 					.list-r-item-childs-i{
 						width: 100%;
-						padding: 15rpx 20rpx;
-						background-color: #F5F5F5;
+						padding: 16rpx;
+						background: #f5f5f5;
 						border-radius: 8rpx;
-						margin-bottom: 4rpx;
 						color: rgba(102, 102, 102, 1);
 						font-family: DM Sans;
 						font-size: 14px;
@@ -349,6 +347,7 @@
 						line-height: 18px;
 						letter-spacing: 0.5%;
 						text-align: center;
+						margin-bottom: 16rpx;
 						
 						&:active {
 							background-color: #E5E5E5;
@@ -365,9 +364,12 @@
 		// bottom: 0;
 		// left: 0;
 		// right: 0;
-		margin: 30rpx 20rpx;
-		background: #fff;
-		border-top: 1px solid #f0f0f0;
+		// margin: 30rpx 20rpx;
+		// background: #fff;
+		// border-top: 1px solid #f0f0f0;
+		padding: 40rpx;
+		box-shadow: 0px -4px 16px 0px rgba(0, 0, 0, 0.04);
+		background-color: #fff;
 	}
 	
 	.confirm-btn {

+ 43 - 59
package/jobIntention/jobSkills.vue

@@ -6,27 +6,33 @@
 				<view class="nav-left" @click="goBack">
 					<u-icon name="close" color="#333" size="32"></u-icon>
 				</view>
-				<view class="nav-title">{{this.jobId==0||this.jobId==''?'我的':'岗位'}}跨境标签</view>
+				<view class="nav-title">
+					<template v-if="onlyShowCustomTag">我的技能</template>
+					<template v-else>{{this.jobId==0||this.jobId==''?'我的':'岗位'}}跨境标签</template>
+				</view>
 				<view class="nav-right"></view>
 			</view>
 		</view>
 
 		<!-- 主要内容 -->
 		<view class="main-content">
-			<view class="job-title">{{ jobTitle }}-跨境标签</view>
-			<view class="description">根据你的偏好设置,为你推荐更匹配的职位</view>
-
-			<!-- 运营方向 -->
-			<view class="skills-section" v-for="(it, ind) in operationOptions" :key="ind">
-				<view class="section-title">{{it.postSkillName}}</view>
-				<view class="skills-grid">
-					<view v-for="(item, index) in it.childrenList" :key="index" class="skill-tag"
-						:class="{ active: selectedOperation.includes(item.postSkillName) }"
-						@click="toggleOperation(ind,item.postSkillName)">
-						<text>{{ item.postSkillName }}</text>
+			<template v-if="!onlyShowCustomTag">
+				<view class="job-title">{{ jobTitle }}-跨境标签</view>
+				<view class="description">根据你的偏好设置,为你推荐更匹配的职位</view>
+
+				<!-- 运营方向 -->
+				<view class="skills-section" v-for="(it, ind) in operationOptions" :key="ind">
+					<view class="section-title">{{it.postSkillName}}</view>
+					<view class="skills-grid">
+						<view v-for="(item, index) in it.childrenList" :key="index" class="skill-tag"
+							:class="{ active: selectedOperation.includes(item.postSkillName) }"
+							@click="toggleOperation(ind,item.postSkillName)">
+							<text>{{ item.postSkillName }}</text>
+						</view>
 					</view>
 				</view>
-			</view>
+			</template>
+			<view class="tip" v-else>请您添加你的技能标签</view>
 			
 			<!-- 自定义标签 -->
 			<view class="skills-section">
@@ -48,10 +54,8 @@
 		</view>
 
 		<!-- 底部确定按钮 -->
-		<view class="bottom-btn-container">
-			<view class="confirm-btn" @click="confirmSelection">
-				<text>确定</text>
-			</view>
+		<view class="fixed-section">
+			<u-button type="primary" class="submit-btn" @click="confirmSelection">保存</u-button>
 		</view>
 
 		<!-- 添加标签弹窗 -->
@@ -85,7 +89,16 @@
 				operationOptions: [],
 				tagParam: '' ,// 新增:保存传入的tag参数
 				ruleClassifyId:'',
-				fromPage: '', // 判断从哪个页面进入
+				fromPage: '', // 判断从哪个页面进入 userInfo个人信息、onlineResume在线简历
+			}
+		},
+		computed: {
+			// 只展示自定义标签(userInfo个人信息、onlineResume在线简历)
+			onlyShowCustomTag() {
+				if (this.fromPage == 'onlineResume' || this.fromPage == 'userInfo') {
+					return true;
+				}
+				return false;
 			}
 		},
 		onLoad(options) {
@@ -112,7 +125,7 @@
 			}
 			this.getData()
 			set = options && options.set ? options.set : 0
-			// 判断从哪个页面进入 onlineResume在线简历
+			// 判断从哪个页面进入 onlineResume在线简历、userInfo个人信息
 			if (options.from) {
 				this.fromPage = options.from
 			}
@@ -134,9 +147,9 @@
 					if (res.code == 0) {
 						this.operationOptions = res.data
 						
-						if (this.fromPage === 'onlineResume') {
+						if (this.onlyShowCustomTag) {
 							const tags = res.data.map(tag => tag.skillName)
-							this.setCustomTags(tags)							
+							this.setCustomTags(tags)
 						} else if (this.tagParam) {
 							// 数据加载完成后处理标签回显
 							this.handleTagDisplay(this.tagParam)
@@ -239,7 +252,7 @@
 			},
 			confirmSelection() {
 				// 合并选择的标签和自定义标签并回传
-				const allSelectedTags = this.fromPage === 'onlineResume' ? this.customTags : [...this.selectedOperation, ...this.customTags]
+				const allSelectedTags = this.onlyShowCustomTag ? this.customTags : [...this.selectedOperation, ...this.customTags]
 				// 触发事件通知上一页面
 				uni.$emit('skillsUpdated', {
 					jobTitle: this.jobTitle,
@@ -257,12 +270,14 @@
 </script>
 
 <style lang="scss" scoped>
+	@import '@/common.scss';
+	
 	.job-skills {
 		height: 100vh;
 		background: #fff;
 		display: flex;
 		flex-direction: column;
-		padding: 0 40rpx;
+		padding: 0 40rpx 200rpx;
 	}
 
 	.navbar-content {
@@ -295,6 +310,11 @@
 		margin-top: 20rpx;
 		flex: 1;
 		overflow: auto;
+		
+		.tip {
+			padding: 72rpx 0 32rpx;
+			color: #666;
+		}
 	}
 
 	.job-title {
@@ -440,42 +460,6 @@
 		}
 	}
 
-	.bottom-btn-container {
-		// position: fixed;
-		// bottom: 0;
-		// left: 0;
-		// right: 0;
-		padding: 32rpx;
-		background: #fff;
-		border-top: 1rpx solid #f0f0f0;
-		z-index: 10;
-	}
-
-	.confirm-btn {
-		width: 100%;
-		height: 96rpx;
-		background: linear-gradient(90deg, #007AFF 0%, #2DB0F0 100%);
-		border-radius: 48rpx;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		box-shadow: 0 6rpx 16rpx rgba(0, 122, 255, 0.2);
-		transition: all 0.2s ease;
-		cursor: pointer;
-
-		text {
-			font-size: 34rpx;
-			font-weight: 600;
-			color: #fff;
-		}
-
-		&:active {
-			background: linear-gradient(90deg, #0056CC 0%, #4A9FE7 100%);
-			transform: scale(0.98);
-			box-shadow: 0 4rpx 12rpx rgba(0, 122, 255, 0.15);
-		}
-	}
-
 	// 添加标签弹窗样式
 	.add-tag-popup {
 		background: #fff;

+ 386 - 0
package/jobIntention/updateCertificates.vue

@@ -0,0 +1,386 @@
+<template>
+	<view class="certificates">
+		<!-- 自定义导航栏 -->
+		<view class="custom-navbar" :style="{ paddingTop: (12 + statusBarHeight) + 'px' }">
+			<view class="navbar-content">
+				<view class="nav-left" @click="goBack">
+					<u-icon name="close" color="#333" size="32"></u-icon>
+				</view>
+				<view class="nav-title">资质证书</view>
+				<view class="nav-right"></view>
+			</view>
+		</view>
+		
+		<!-- 主要内容 -->
+		<view class="main-content">
+			<view class="tip">请您添加您的资质证书</view>
+			
+			<!-- 资质证书 -->
+			<view class="skills-section">
+				<view class="section-title">资质证书</view>
+		
+				<!-- 资质证书区域 -->
+				<view class="custom-tags">
+					<view v-for="(item, index) in certificates" :key="index" class="custom-tag"
+						@click="removeCustomTag(index)">
+						<text>{{ item }}</text>
+						<u-icon name="close" color="#007AFF" size="18"></u-icon>
+					</view>
+					<view class="add-tag" @click="showAddCertificatesModal">
+						<text>添加资质证书</text>
+						<u-icon name="plus" color="#333" size="18"></u-icon>
+					</view>
+				</view>
+			</view>
+		</view>
+		
+		<!-- 底部确定按钮 -->
+		<view class="fixed-section">
+			<u-button type="primary" class="submit-btn" @click="confirmSelection">保存</u-button>
+		</view>
+		
+		<!-- 添加证书弹窗 -->
+		<u-popup v-model="showAddCertificates" mode="center" border-radius="24" width="80%">
+			<view class="add-tag-popup">
+				<view class="popup-title">添加资质证书</view>
+				<view class="popup-content">
+					<input v-model="newCertificates" placeholder="请输入资质证书(不要带上,  ; 这种字符)" class="tag-input" maxlength="10" />
+				</view>
+				<view class="popup-buttons">
+					<view class="popup-btn cancel-btn" @click="cancelAdd">取消</view>
+					<view class="popup-btn confirm-btn" @click="confirmAdd">确定</view>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				statusBarHeight: 0, // 状态栏高度
+				certificates: [],
+				newCertificates: '',
+				showAddCertificates: false,
+			};
+		},
+		onLoad(options) {
+			// 获取状态栏高度
+			let systemInfo = uni.getSystemInfoSync();
+			this.statusBarHeight = systemInfo.statusBarHeight || 0;
+			
+			// 设置资质证书回显
+			if (options.certificates) {
+				this.certificates = decodeURIComponent(options.certificates).split(';')
+			}
+		},
+		methods: {
+			goBack() {
+				uni.navigateBack()
+			},
+			showAddCertificatesModal() {
+				this.showAddCertificates = true
+				this.newCertificates = ''
+			},
+			cancelAdd() {
+				this.showAddCertificates = false
+				this.newCertificates = ''
+			},
+			confirmAdd() {
+				if (this.newCertificates.trim()) {
+					let realLength = this.certificates.filter(item => item !== '不限').length;
+					if (realLength < 10) {
+						this.certificates.push(this.newCertificates.trim())
+						this.showAddCertificates = false
+						this.newCertificates = ''
+					} else {
+						uni.showToast({
+							title: '最多添加10个资质证书',
+							icon: 'none'
+						})
+					}
+				} else {
+					uni.showToast({
+						title: '请输入资质证书',
+						icon: 'none'
+					})
+				}
+			},
+			confirmSelection() {
+				const certificates = this.certificates.map(certificate => {
+					return {
+						userId: '',
+						certificateId: '',
+						certificateName: certificate,
+						isuse: 1
+					}
+				})
+				uni.showLoading({ title: "保存中..." })
+				this.$Request
+					.postJson('/app/userFirst/updateCertificate', certificates)
+					.then((res) => {
+						if (res.code == 0) {
+							uni.showToast({ title: '保存成功', icon: 'none' })
+						    // 实际开发中可以在这里添加跳转逻辑
+							uni.$emit('updateResume')
+							setTimeout(() => {
+								uni.navigateBack()
+							}, 1000)
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none',
+							})
+						}
+					})
+					.finally(() => {
+						uni.hideLoading()
+					})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import '@/common.scss';
+	.certificates {
+		height: 100vh;
+		background: #fff;
+		display: flex;
+		flex-direction: column;
+		padding: 0 40rpx 200rpx;
+	}
+	
+	.navbar-content {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		height: 88rpx;
+	}
+	
+	.nav-left,
+	.nav-right {
+		width: 60rpx;
+		height: 60rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+	
+	.nav-title {
+		color: rgba(51, 51, 51, 1);
+		font-family: DM Sans;
+		font-size: 36rpx;
+		font-weight: 700;
+		line-height: 26px;
+		letter-spacing: 0px;
+		text-align: center;
+	}
+	
+	.main-content {
+		margin-top: 20rpx;
+		flex: 1;
+		overflow: auto;
+		
+		.tip {
+			padding: 72rpx 0 32rpx;
+			color: #666;
+		}
+	}
+	
+	.skills-section {
+		margin-bottom: 50rpx;
+	}
+	
+	.section-title {
+		color: rgba(34, 37, 42, 1);
+		font-family: DM Sans;
+		font-size: 36rpx;
+		font-weight: 500;
+		line-height: 24px;
+		letter-spacing: 0px;
+		text-align: left;
+		margin-bottom: 24rpx;
+		padding-left: 4rpx;
+	}
+	
+	.skills-grid {
+		display: flex;
+		flex-wrap: wrap;
+		gap: 20rpx;
+	}
+	
+	.skill-tag {
+		padding: 16rpx 24rpx;
+		background: #F7F8FA;
+		border: 1rpx solid #E5E5EA;
+		border-radius: 16rpx;
+		transition: all 0.2s ease;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		cursor: pointer;
+	
+		text {
+			font-size: 26rpx;
+			color: rgba(102, 102, 102, 1);
+			font-weight: 400;
+			text-align: center;
+			line-height: 1.2;
+		}
+	
+		&:hover {
+			background: rgba(153, 196, 250, 0.2);
+			border-color: rgba(1, 107, 246, 0.3);
+		}
+	
+		&.active {
+			background: rgba(1, 107, 246, 0.1);
+			border: 1rpx solid rgba(1, 107, 246, 1);
+			box-shadow: 0 4rpx 12rpx rgba(1, 107, 246, 0.15);
+	
+			text {
+				color: rgba(1, 107, 246, 1);
+				font-weight: 500;
+			}
+		}
+	
+		&:active {
+			transform: scale(0.96);
+		}
+	}
+	
+	.custom-tags {
+		display: flex;
+		flex-wrap: wrap;
+		gap: 20rpx;
+	}
+	
+	.custom-tag {
+		padding: 14rpx 20rpx;
+		background: rgba(153, 196, 250, 0.4);
+		border: 1rpx solid rgba(1, 107, 246, 1);
+		border-radius: 16rpx;
+		display: flex;
+		align-items: center;
+		gap: 10rpx;
+		cursor: pointer;
+		transition: all 0.2s ease;
+	
+		text {
+			font-size: 24rpx;
+			color: rgba(1, 107, 246, 1);
+			font-weight: 400;
+		}
+	
+		&:hover {
+			background: rgba(153, 196, 250, 0.6);
+		}
+	
+		&:active {
+			transform: scale(0.96);
+		}
+	}
+	
+	.add-tag {
+		padding: 14rpx 20rpx;
+		background: #F7F8FA;
+		border: 1rpx dashed #E5E5EA;
+		border-radius: 16rpx;
+		display: flex;
+		align-items: center;
+		gap: 10rpx;
+		cursor: pointer;
+		transition: all 0.2s ease;
+	
+		text {
+			font-size: 24rpx;
+			color: rgba(102, 102, 102, 1);
+			font-weight: 400;
+		}
+	
+		&:hover {
+			background: #f0f0f0;
+			border-color: #d9d9d9;
+		}
+	
+		&:active {
+			transform: scale(0.96);
+		}
+	}
+	
+	// 添加标签弹窗样式
+	.add-tag-popup {
+		background: #fff;
+		border-radius: 24rpx;
+		padding: 48rpx 40rpx;
+		width: 100%;
+	
+		.popup-title {
+			color: rgba(34, 37, 42, 1);
+			font-family: DM Sans;
+			font-size: 36rpx;
+			font-weight: 500;
+			line-height: 24px;
+			text-align: center;
+			margin-bottom: 36rpx;
+		}
+	
+		.popup-content {
+			margin-bottom: 40rpx;
+	
+			.tag-input {
+				width: 100%;
+				height: 90rpx;
+				padding: 0 24rpx;
+				border: 1rpx solid #E5E5EA;
+				border-radius: 16rpx;
+				font-size: 28rpx;
+				color: rgba(34, 37, 42, 1);
+				background: #F7F8FA;
+				box-sizing: border-box;
+			}
+	
+			.tag-input::placeholder {
+				color: #C9CDD4;
+			}
+		}
+	
+		.popup-buttons {
+			display: flex;
+			gap: 24rpx;
+	
+			.popup-btn {
+				flex: 1;
+				height: 88rpx;
+				border-radius: 16rpx;
+				display: flex;
+						align-items: center;
+				justify-content: center;
+				font-size: 30rpx;
+				font-weight: 500;
+				transition: all 0.2s ease;
+				cursor: pointer;
+			}
+	
+			.cancel-btn {
+				background: #F7F8FA;
+				color: rgba(102, 102, 102, 1);
+	
+				&:active {
+					background: #eaeaea;
+				}
+			}
+	
+			.confirm-btn {
+				background: #007AFF;
+				color: #fff;
+	
+				&:active {
+					background: #0056CC;
+				}
+			}
+		}
+	}
+</style>

+ 365 - 0
package/my/editUserInfo.vue

@@ -0,0 +1,365 @@
+<template>
+	<view class="container">
+		<!-- 顶部导航 -->
+		<view class="nav-bar" :style="{ paddingTop: (12 + statusBarHeight) + 'px' }">
+			<view class="nav-left" @click="goBack">
+				<u-icon name="arrow-leftward" color="rgba(51, 51, 51, 1)" style="font-size: 38rpx;"></u-icon>
+			</view>
+			<view class="nav-title">个人信息</view>
+			<view class="nav-right"></view>
+		</view>
+		
+		<!-- 表单内容 -->
+		<view class="form-container">
+			<view class="form-item">
+				<view class="form-label">
+					<text class="required-mark">*</text>
+					<text class="label-text">求职状态</text>
+				</view>
+				<view class="form-content flex-between select-picker form-content-border" @click="showJobStatusPicker">
+					<text class="select-text">{{ jobStatusList[selectedJobStatus].text }}</text>
+					<u-icon name="arrow-down" color="#999" size="24"></u-icon>
+				</view>
+			</view>
+			
+			<view class="form-item">
+				<view class="form-label">
+					<text class="label-text">我的优势</text>
+					<text class="text-num">({{ textNum }}/1000)</text>
+				</view>
+				<view class="form-content form-content-border">
+					<textarea class="form-input" type="text" maxlength="1000" auto-height placeholder="请填写您的个人优势" v-model="advantages" />
+				</view>
+			</view>
+			
+			<view class="form-item">
+				<view class="form-label">
+					<text class="label-text">我的技能</text>
+				</view>
+				<view class="form-content flex-between form-content-border skills-content">
+					<view class="skills-tags">
+						<view v-for="(skill, index) in skills" :key="index" class="skill-tag">
+							<text>{{ skill }}</text>
+						</view>
+					</view>
+					<view class="add-skill-btn" @click="addSkill()">
+						<u-icon name="plus" color="rgba(102, 102, 102, 1)" size="28"></u-icon>
+					</view>
+				</view>
+			</view>
+		</view>
+		
+		<!-- 求职状态选择器 -->
+		<u-popup v-model="showJobStatusModal" mode="bottom" border-radius="42" height="auto"
+			:safe-area-inset-bottom="true">
+			<view class="job-status-picker">
+				<view class="picker-header">
+					<text class="picker-title">求职状态</text>
+				</view>
+		
+				<view class="picker-content">
+					<view class="status-option" :class="{ active: selectedJobStatus == item.value }"
+						v-for="item in jobStatusList" :key="item.value" @click="selectJobStatus(item)">
+						<view class="option-left">
+							<view class="radio-btn" :class="{ checked: selectedJobStatus == item.value }">
+								<u-icon v-if="selectedJobStatus == item.value" name="checkmark" color="#ffffff"
+									size="28"></u-icon>
+							</view>
+							<text class="option-text">{{ item.text }}</text>
+							<view v-if="item.recommended" class="recommend-tag">
+								<text>推荐</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</u-popup>
+		
+		<view class="fixed-section">
+			<u-button type="primary" class="submit-btn" @click="submitData">保存</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { jobStatus } from '@/constants/userInfo.js'
+	
+	export default {
+		data() {
+			return {
+				statusBarHeight: 0, // 状态栏高度
+				selectedJobStatus: 0,
+				jobStatusList: jobStatus,
+				showJobStatusModal: false,
+				advantages: '', // 优势
+				skills: [], // 我的技能
+			};
+		},
+		computed: {
+			textNum() {
+				if (typeof this.advantages == 'string') {
+					return this.advantages.length
+				}
+				return '0'
+			}
+		},
+		onLoad() {
+			// 获取状态栏高度
+			let systemInfo = uni.getSystemInfoSync();
+			this.statusBarHeight = systemInfo.statusBarHeight || 0;
+			
+			this.getUserInfoData()
+			
+			// 监听技能设置更新
+			uni.$on('skillsUpdated', (data) => {
+				if (data.set != 1)
+					return
+				this.updateSkills(data.selectedTags)
+			})
+		},
+		methods: {
+			goBack() {
+				uni.navigateBack()
+			},
+			// 获取用户数据
+			getUserInfoData() {
+				uni.showLoading({
+					title: '加载中'
+				})
+				this.$Request.getT("/app/userFirst/getUserResumes", {}).then((res) => {
+					if (res.code === 0) {
+						this.selectedJobStatus = res.data.resumeList.resumesStatus
+						this.advantages = res.data.resumeList.adv
+						this.skills = res.data.skills.map(skill => skill.skillName)
+					}
+				}).finally(() => {
+					uni.hideLoading()
+				})
+			},
+			// 显示求职状态选择器
+			showJobStatusPicker() {
+				this.showJobStatusModal = true;
+			},
+			// 选择求职状态
+			selectJobStatus(item) {
+				this.selectedJobStatus = item.value;
+				this.showJobStatusModal = false;
+			},
+			// 移除技能
+			removeSkill(index) {
+				this.skills.splice(index, 1)
+			},
+			// 增加技能
+			addSkill() {
+				uni.navigateTo({
+					url: '/package/jobIntention/jobSkills?from=userInfo&set=1&jobTitle=我的&skill=' + encodeURIComponent(JSON
+						.stringify(this.skills == null ? [] : this.$queue.array_column(this
+							.skills, 'skillName')))
+				})
+			},
+			// 更新本地技能数据
+			updateSkills(data) {
+				this.skills = data;
+			},
+			// 保存数据
+			submitData() {
+				uni.showLoading({
+					title: '保存中'
+				})
+				this.$Request.postJson('/app/user/updatePersonalInfo', {
+					resumesStatus: this.selectedJobStatus,
+					adv: this.advantages,
+					skills: this.skills.map(skill => {
+						return {
+							isUse: 1,
+							skillId: '',
+							skillName: skill,
+							userId: ''
+						}
+					})
+				}).then((res) => {
+					uni.showToast({
+						title: '更新成功',
+						icon: 'none',
+					})
+					setTimeout(() => {
+						uni.$emit('updateResume')
+						uni.navigateBack()
+					}, 1000)
+				}).catch(err => {
+					uni.showToast({
+						title: err.msg,
+						icon: 'none'
+					})
+				}).finally(() => {
+					uni.hideLoading()
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+@import '../../common.scss';
+
+.container {
+	.flex-between {
+		display: flex;
+		justify-content: space-between;
+	}
+	.form-content-border {
+		min-height: 75rpx;
+		border: 1px solid rgba(227, 231, 236, 1);
+		border-radius: 48rpx;
+		padding: 24rpx 32rpx;
+		font-size: 28rpx;
+		color: #78828a; 
+	}
+	// 下拉选择器样式
+	.select-picker {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+
+		.select-text {
+			color: #78828a; 
+			font-family: DM Sans;
+			font-size: 14px;
+			font-weight: 400;
+			line-height: 22px;
+			letter-spacing: 0%;
+			text-align: left;
+		}
+	}
+	// 求职状态选择器样式
+	.job-status-picker {
+		background: #fff;
+		border-radius: 42rpx 42rpx 0 0;
+
+		.picker-header {
+			padding: 40rpx 40rpx 20rpx 40rpx;
+			text-align: center;
+			border-bottom: 1px solid #f0f0f0;
+
+			.picker-title {
+				color: rgba(23, 23, 37, 1);
+				font-family: DM Sans;
+				font-size: 18px;
+				font-weight: 600;
+				line-height: 26px;
+				letter-spacing: 0%;
+				text-align: center;
+			}
+		}
+
+		.picker-content {
+			padding: 20rpx 40rpx 40rpx 40rpx;
+
+			.status-option {
+				padding: 30rpx 0;
+				border-bottom: 1px solid #f0f0f0;
+
+				&:last-child {
+					border-bottom: none;
+				}
+
+				.option-left {
+					display: flex;
+					align-items: center;
+
+					.radio-btn {
+						width: 40rpx;
+						height: 40rpx;
+						border-radius: 50%;
+						border: 2px solid #e0e0e0;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						margin-right: 20rpx;
+
+						&.checked {
+							background-color: #007AFF;
+							border-color: #007AFF;
+						}
+					}
+
+					.option-text {
+						flex: 1;
+						color: rgba(23, 23, 37, 1);
+						font-family: DM Sans;
+						font-size: 16px;
+						font-weight: 400;
+						line-height: 22px;
+						letter-spacing: 0%;
+						text-align: left;
+					}
+
+					.recommend-tag {
+						background-color: #007AFF;
+						border-radius: 8rpx;
+						padding: 4rpx 12rpx;
+						margin-left: 16rpx;
+
+						text {
+							color: #fff;
+							font-family: DM Sans;
+							font-size: 12px;
+							font-weight: 500;
+							line-height: 16px;
+							letter-spacing: 0%;
+							text-align: center;
+						}
+					}
+				}
+			}
+		}
+	}
+	// 输入框内容
+	.form-input {
+		font-size: 28rpx;
+		line-height: 32rpx;
+	}
+	.text-num {
+		font-weight: normal;
+		color: #78828a;
+		font-size: 28rpx;
+	}
+	// 我的技能
+	.skills-content {
+		align-items: center;
+		
+		.skills-tags {
+			display: flex;
+			flex-wrap: wrap;
+			gap: 12rpx;
+			flex: 1;
+		
+			.skill-tag {
+				padding: 8rpx 16rpx;
+				background: #F5F5F5;
+				border-radius: 8rpx;
+				display: flex;
+				align-items: center;
+		
+				text {
+					font-size: 24rpx;
+					color: #666666;
+					margin-right: 8rpx;
+				}
+			}
+		}
+		
+		.add-skill-btn {
+			width: 40rpx;
+			height: 40rpx;
+			border: 1rpx solid rgba(102, 102, 102, 1);
+			border-radius: 8rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			background: #fff;
+			flex-shrink: 0;
+		}
+	}	
+}
+</style>

+ 276 - 0
package/my/hiddenManagement/hiddenCompany.vue

@@ -0,0 +1,276 @@
+<template>
+	<view class="hidden-management">
+		<nav-bar color="#000" title="屏蔽管理"></nav-bar>
+		<view class="content">
+			<view class="search-bar flex align-center justify-between">
+				<view class="search-input flex align-center">
+					<image src="@/static/images/svg/search.svg" class="search-icon"></image>
+					<input v-model="searchValue" type="text" placeholder="输入的是一个公司的名称,全模糊搜索" class="input" />
+				</view>
+				<view class="search-btn" @click="handleSearch">搜索</view>
+			</view>
+			<scroll-view :scroll-y="true" class="scroll-view">
+				<view class="scroll-wrapper">
+					<view class="company-item" v-for="company in companys" :key="company.id">
+						<u-checkbox 
+							v-model="company.checked" 
+							:name="company.id"
+							@change="checkboxChange"
+						>{{company.name}}</u-checkbox>						
+					</view>
+				</view>
+			</scroll-view>			
+		</view>
+		
+		<view class="fixed-section">
+			<u-button type="primary" class="submit-btn" @click="handleSave">屏蔽所选公司({{ selectCount }})</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import navBar from '@/components/nav-bar/index.vue'
+	export default {
+		components: {
+			navBar
+		},
+		data() {
+			return {
+				searchValue: '',
+				selectCount: 0,
+				companys: [
+					{
+						name: 'Apple',
+						id: '1',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Google',
+						id: '2',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '特斯拉',
+						id: '3',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '英伟达',
+						id: '4',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Meta',
+						id: '5',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'X',
+						id: '6',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '甲骨文',
+						id: '7',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '微软',
+						id: '8',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'OpenIA',
+						id: '9',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Space X',
+						id: '10',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Meta',
+						id: '11',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'X',
+						id: '12',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '甲骨文',
+						id: '13',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '微软',
+						id: '14',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'OpenIA',
+						id: '15',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Space X',
+						id: '16',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Meta',
+						id: '17',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'X',
+						id: '18',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '甲骨文',
+						id: '19',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '微软',
+						id: '20',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'OpenIA',
+						id: '21',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Space X',
+						id: '22',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: '微软',
+						id: '23',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'OpenIA',
+						id: '24',
+						checked: false,
+						disabled: false
+					},
+					{
+						name: 'Space X',
+						id: '25',
+						checked: false,
+						disabled: false
+					},
+				],
+				selectCompanyIds: [],
+			};
+		},
+		methods: {
+			// 搜索
+			handleSearch() {
+				console.log(this.searchValue)
+			},
+			// 选择公司
+			checkboxChange(item) {
+				if (!item.value) {
+					// 删除
+					let deleteId = 0
+					this.selectCompanyIds.forEach((id, index) => {
+						if (id == item.name) {
+							deleteId = index
+						}
+					})
+					this.selectCompanyIds.splice(deleteId, 1)
+					this.selectCount--
+				} else {
+					// 新增
+					this.selectCompanyIds.push(item.name)
+					this.selectCount++
+				}
+			},
+			// 提交数据
+			handleSave() {
+				console.log(this.selectCompanyIds)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import '@/common.scss';
+	
+	.hidden-management {
+		height: 100vh;
+		font-family: DM Sans;
+		
+		.content {
+			padding: 0 40rpx;
+		}
+		.search-bar {
+			margin: 32rpx 0 40rpx;
+			.search-input {
+				flex: 1;
+				box-sizing: border-box;
+				border: 1px solid rgba(227, 231, 236, 1);
+				border-radius: 48rpx;
+				background: rgba(241, 241, 241, 1);
+				padding: 8rpx 32rpx;
+				.search-icon {
+					display: block;
+					width: 36rpx;
+					height: 36rpx;
+					margin-right: 16rpx;
+				}
+				.input {
+					width: 500rpx;
+					font-size: 20rpx;
+					font-weight: 500;
+					color: rgba(51, 51, 51, 1);
+				}
+			}
+			.search-btn {
+				font-size: 20rpx;
+				font-weight: 500;
+				line-height: 48rpx;
+				color: rgba(1, 107, 246, 1);
+				padding-left: 16rpx;
+			}
+		}
+		
+		.scroll-view {
+			height: calc(100vh - 160rpx);
+			padding-bottom: 200rpx;
+			.scroll-wrapper {
+				padding-bottom: 100rpx;
+			}
+		}
+	}
+</style>

+ 128 - 0
package/my/hiddenManagement/index.vue

@@ -0,0 +1,128 @@
+<template>
+	<view class="hidden-management">
+		<view>
+			<nav-bar color="#000" title="屏蔽管理"></nav-bar>
+			<view class="content">
+				<view class="title">屏蔽管理</view>
+				<view class="tip">请设置指定公司不可看见你的简历,屏蔽后双向不被推荐</view>
+				<view class="search-bar flex align-center" @click="toHiddenCompany">
+					<image src="@/static/images/svg/search.svg" class="search-icon"></image>
+					搜索需要屏蔽的公司
+				</view>
+			</view>
+		</view>
+		<scroll-view :scroll-y="true" class="company-list">
+			<view class="scroll-wrapper">
+				<view class="company-item" v-for="item in 30" :key="item">
+					<siwper-delete @delete="handleDelete">
+						<view class="company-content flex align-center">
+							<image src="@/static/images/logo.jpg" class="company-icon"></image>
+							<view class="company-info">
+								<view class="company-name">深圳市四海新舟科技有限公司</view>
+								<view class="text">100-400 · 跨境电商</view>
+							</view>
+						</view>
+					</siwper-delete>
+				</view>				
+			</view>
+		</scroll-view>			
+	</view>
+</template>
+
+<script>
+	import navBar from '@/components/nav-bar/index.vue'
+	import siwperDelete from '@/components/swiper-delete.vue'
+	
+	export default {
+		components: {
+			navBar,
+			siwperDelete
+		},
+		data() {
+			return {
+				
+			};
+		},
+		methods: {
+			handleDelete() {
+				console.log(1123)
+			},
+			toHiddenCompany() {
+				uni.navigateTo({
+					url: '/package/my/hiddenManagement/hiddenCompany'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.hidden-management {
+		height: 100vh;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		font-family: DM Sans;
+		
+		.content {
+			padding: 32rpx 40rpx 0;
+			
+			.title {
+				font-size: 48rpx;
+				font-weight: 700;
+				line-height: 60rpx;
+				color: rgba(51, 51, 51, 1);
+				margin-bottom: 20rpx;
+			}
+			
+			.tip {
+				font-size: 24rpx;
+				line-height: 32rpx;
+				color: rgba(102, 102, 102, 1);
+				margin-bottom: 28rpx;
+			}
+			
+			.search-bar {
+				border: 1px solid rgba(231, 230, 228, 1);
+				border-radius: 12rpx;
+				background: rgba(237, 237, 237, 1);
+				padding: 16rpx 24rpx;
+				color: rgba(188, 188, 188, 1);
+				font-size: 28rpx;
+				margin-bottom: 28rpx;
+				.search-icon {
+					width: 32rpx;
+					height: 32rpx;
+					margin-right: 16rpx;
+				}
+			}
+		}
+		
+		.company-list {
+			height: 300px;
+			flex: 1;
+			padding: 0 40rpx;
+			.scroll-wrapper {
+				padding-bottom: 20rpx;
+			}
+			.company-item {
+				border: 1px solid rgba(227, 231, 236, 1);
+				border-radius: 12rpx;
+				box-sizing: border-box;
+				margin-bottom: 20rpx;
+				overflow: hidden;
+			}
+			.company-content {
+				padding: 20rpx 32rpx;
+				.company-icon {
+					display: block;
+					width: 60rpx;
+					height: 60rpx;
+					margin-right: 24rpx;
+					border: 1px solid #eee;
+					border-radius: 60rpx;
+				}
+			}
+		}
+	}
+</style>

+ 121 - 0
package/my/previewResume/index.vue

@@ -0,0 +1,121 @@
+<template>
+	<view class="preview-resume">
+		<nav-bar title="简历预览" color="#000" class="nav-bar">
+			<view class="import-btn" slot="right">导出</view>
+		</nav-bar>
+		
+		<view class="tabs">
+			<view class="tab" :class="{ active: index === activeIndex }" v-for="(tab, index) in tabs" :key="index" @click="handleChangeTab(index)">
+				<view class="tab-name">{{ tab.name }}</view>
+				<view class="tab-active"></view>
+			</view>
+		</view>
+		
+		<scroll-view class="content" :scroll-y="true">
+			<previewResume v-if="activeIndex == 0"></previewResume>
+			<indexCard v-else-if="activeIndex == 1"></indexCard>
+			<chatCard v-else-if="activeIndex == 2"></chatCard>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	import navBar from "@/components/nav-bar/index.vue";
+	import previewResume from '@/components/resume/preview-resume.vue';
+	import indexCard from '@/components/resume/index-card.vue';
+	import chatCard from '@/components/resume/chat-card.vue';
+		
+	export default {
+		components: {
+			navBar,
+			previewResume,
+			indexCard,
+			chatCard
+		},
+		data() {
+			return {
+				tabs: [
+					{
+						name: '在线简历'
+					},
+					{
+						name: '首页卡片'
+					},
+					{
+						name: '沟通卡片'
+					}
+				],
+				activeIndex: 0
+			}
+		},
+		onLoad(options) {
+			if (options.type) {
+				// type: index首页卡片、chat沟通卡片
+				if (options.type === 'index') {
+					this.activeIndex = 1
+				} else if (options.type === 'chat') {
+					this.activeIndex = 2
+				}
+			}
+		},
+		methods: {
+			handleChangeTab(index) {
+				this.activeIndex = index
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.nav-bar {
+		height: 96rpx;
+		background: #fff;
+	}
+	.import-btn {
+		font-size: 24rpx;
+		font-weight: 400;
+		color: rgba(153, 153, 153, 1);
+	}
+	.preview-resume {
+		display: flex;
+		flex-direction: column;
+		height: 100vh;
+		background: rgba(241, 245, 248, 1);
+	}
+	
+	// tabs栏
+	.tabs {
+		display: flex;
+		justify-content: center;
+		background-color: #fff;
+		height: 80rpx;
+		.tab {
+			padding: 24rpx 32rpx 12rpx;
+			.tab-name {
+				color: rgba(51, 51, 51, 1);
+				line-height: 32rpx;
+			}
+			.tab-active {
+				width: 50rpx;
+				height: 6rpx;
+				border-radius: 6rpx;
+				margin: 6rpx auto 0;
+			}
+		}
+		.active {
+			.tab-name {
+				color: rgba(1, 107, 246, 1);
+				font-weight: bold;
+			}
+			.tab-active {
+				background: rgba(1, 107, 246, 1);
+			}
+		}
+	}
+	
+	.content {
+		height: 100px;
+		flex: 1;
+		margin-top: 32rpx;
+	}
+</style>

+ 36 - 0
pages.json

@@ -895,6 +895,42 @@
 						"enablePullDownRefresh": true,
 						"navigationStyle": "custom"
 					}
+				},
+				{
+					"path": "my/editUserInfo",
+					"style": {
+						"navigationBarTitleText": "个人信息",
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "my/previewResume/index",
+					"style": {
+						"navigationBarTitleText": "简历预览",
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "my/hiddenManagement/index",
+					"style": {
+						"navigationBarTitleText": "屏蔽管理",
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "my/hiddenManagement/hiddenCompany",
+					"style": {
+						"navigationBarTitleText": "屏蔽管理",
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "jobIntention/updateCertificates",
+					"style": {
+						"navigationBarTitleText": "资质证书",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
 				}
 			]
 		},

+ 59 - 47
pages/index/index.vue

@@ -1,6 +1,6 @@
 <template>
 	<view style="background-color: #f2f2f7;">
-		<block v-if="XCXIsSelect != '是'">
+		<template v-if="XCXIsSelect != '是'">
 			<view class="banner flex justify-center">
 				<view class="banner-box">
 					<swiper :indicator-dots="false" style="width: 100%;height: 100%;" :autoplay="true" :interval="300"
@@ -30,8 +30,8 @@
 					</view>
 				</view>
 			</view>
-		</block>
-		<block v-else>
+		</template>
+		<template v-else>
 			<!-- 用户端 -->
 			<view v-if="userType == 1" class="page-container" :style="{ paddingTop: (12 + statusBarHeight) + 'px' }">
 
@@ -42,14 +42,13 @@
 						<view class="topbg-sticky-title flex justify-between align-center">
 							<view class="topbg-sticky-title-left flex align-center">
 								<image src="../../static/images/index/xingIcon.svg" class="xing-icon" />
-								<view>星光不负逐梦人</view>
+								<view>亿职赞,愿你在追梦路上找到心仪工作</view>
 							</view>
 							<view class="topbg-sticky-title-right flex align-center"
 								@click="goNavs('/package/search/search')">
 								<u-icon name="search" color="#ffffff" size="40"></u-icon>
 							</view>
 						</view>
-						<view class="topbg-sticky-subtitle">亿职赞,愿你在追梦路上找到心仪工作</view>
 					</view>
 
 					<!-- tabs和筛选 -->
@@ -89,7 +88,7 @@
 									</view>
 
 									<!-- <text style="color: #CCCCCC;margin-left: 30rpx;margin-right: 30rpx;">|</text> -->
-									<block v-if="current != typeList.length - 1">
+									<template v-if="current != typeList.length - 1">
 										<!-- 筛选 -->
 										<view class="topbg-sx-box-filter flex align-center"
 											:class="{ activeColor: filledFieldsCount }">
@@ -99,8 +98,8 @@
 											<u-icon name="arrow-down" :color="filledFieldsCount ? '#016bf6' : '#999999'"
 												size="16" @click="goNavs('/package/screen/screen')"></u-icon>
 										</view>
-									</block>
-									<block v-else>
+									</template>
+									<template v-else>
 										<!-- 筛选 -->
 										<view class="topbg-sx-box-filter flex align-center"
 											:class="{ activeColor: filledFieldsCount }">
@@ -110,7 +109,7 @@
 											<u-icon name="arrow-down" color="filledFieldsCount?'#016bf6':'#999999'"
 												size="16" @click="goNavs('/package/screen/screenComp')"></u-icon>
 										</view>
-									</block>
+									</template>
 								</view>
 							</view>
 
@@ -167,7 +166,7 @@
 							v-if="current == typeList.length - 1 && companList.length>0"></view> -->
 				</view>
 				<!-- 岗位推荐 -->
-				<block v-if="current != typeList.length - 1">
+				<template v-if="current != typeList.length - 1">
 					<view class="gwList flex justify-center" v-if="dataList.length > 0">
 						<view class="gwList-box">
 							<scroll-view scroll-y="true" style="width: 100%;height: 100%;" refresher-enabled="true"
@@ -183,12 +182,12 @@
 											<view class="title-left flex align-center">
 												<view class="job-title-text"
 													style="max-width: 450rpx;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;-o-text-overflow:ellipsis;">
-													<!-- <block v-if="isSameName(item.ruleClassifyName,item.stationName)">
+													<!-- <template v-if="isSameName(item.ruleClassifyName,item.stationName)">
 														{{item.ruleClassifyName}}-
-													</block> -->
-													<block>
+													</template> -->
+													<template>
 														{{ item.ruleClassifyName }}
-													</block>
+													</template>
 												</view>
 												<view v-if="item.isDue == 1" class="salary-text-box">
 													<image src="../../static/images/index/jipinIcom.svg"
@@ -196,7 +195,11 @@
 													<text class="jipin-text">急聘</text>
 												</view>
 											</view>
-											<text class="salary-text">{{ item.salaryRange }}</text>
+											<view>
+												<text class="clip-color">{{ item.salaryRange }}</text>
+												<text class="clip-color"> · </text>
+												<text class="clip-color">{{ item.salaryTimes }}</text>
+											</view>
 										</view>
 										<!-- 公司名称-公司人数 -->
 										<view class="gwList-box-item-box-name flex align-center">
@@ -205,6 +208,8 @@
 											<text class="company-people" v-if="item.company">{{ item.company ?
 												item.company.companyPeople : '0人' }}</text>
 										</view>
+										<!-- 福利标签 -->
+										<!-- <view class="benefits">{{ formatBenefits(item.welfareTag) }}</view> -->
 										<!-- 职位标签 -->
 										<view class="gwList-box-item-box-label flex align-center flex-wrap">
 											<text class="job-tag">{{ item.education }}</text>
@@ -246,7 +251,7 @@
 					<view class="gwList" v-else>
 						<empty />
 					</view>
-				</block>
+				</template>
 
 				<view class="companyListBox" v-if="current == typeList.length - 1 && companList.length > 0">
 					<companyListIndex @goInfo="goInfo" :item="item" v-for="(item, index) in companList" :key="index" />
@@ -442,23 +447,23 @@
 									
 									<view class="qyList-box-item-job flex align-center">
 										<image src="../../static/images/aixin.svg" class="job-icon" mode="aspectFit"></image>
-										<block v-if="item.companyName">
+										<template v-if="item.companyName">
 											<view class="flex justify-between" style="flex:1">
 												<view class="work-school">
 													{{ item.companyName ? item.companyName : '' }} · {{ item.lastWorkPosition ? item.lastWorkPosition : '' }}
 													<view class="txt-desc">{{calculateWorkDuration(item.lastWorkStartTime,item.lastWorkEndTime)}}</view>
 												</view>
 											</view>
-										</block>
-										<block v-else>
+										</template>
+										<template v-else>
 											暂无工作经历
-										</block>
+										</template>
 									</view>
 									<view class="qyList-box-item-job flex align-center">
 										<image src="../../static/images/xiangzi.svg" class="job-icon" mode="aspectFit"></image>
-										<block v-if="item.expectedPosition">
+										<template v-if="item.expectedPosition">
 											<view class="work-school">求职期望: {{ item.expectedPosition }}</view>
-										</block>
+										</template>
 									</view>
 									<!-- 跨境标签 -->
 									<view v-if="item.intentPostSkill" class="flex align-center flex-wrap" style="gap:8rpx;margin: 12rpx 0;">
@@ -487,7 +492,7 @@
 					</view>
 				</view>
 			</view>
-		</block>
+		</template>
 
 		<view v-if="goback == true" class="goback" @click="gotoBack">
 			<image style="width: 88rpx;height: 88rpx;border-radius: 50%;" src="../../static/images/up.jpg" mode="">
@@ -2017,6 +2022,13 @@ export default {
 			this.positionTagArr = preference
 			this.page = 1;
 			this.getPeopList();
+		},
+		// 格式化福利
+		formatBenefits(benefits) {
+			if (Array.isArray(benefits)) {
+				return benefits.join('|')
+			}
+			return ''
 		}
 	}
 }
@@ -2293,6 +2305,7 @@ page {
 	.attachment-icon {
 		width: 38rpx;
 		height: 38rpx;
+		margin-left: 20rpx;
 	}
 }
 
@@ -2542,8 +2555,8 @@ page {
 .job-title-text {
 	color: rgba(23, 23, 37, 1);
 	font-family: DM Sans;
-	font-size: 38rpx;
-	font-weight: 700;
+	font-size: 32rpx;
+	font-weight: bold;
 	line-height: 48rpx;
 	letter-spacing: 0.5%;
 	text-align: left;
@@ -2555,33 +2568,33 @@ page {
 	display: flex;
 	justify-content: flex-start;
 	align-items: center;
-	padding: 6rpx 24rpx;
+	padding: 0 16rpx;
 
 	.jipin-icon {
 		width: 20rpx;
 		height: 20rpx;
-		margin-right: 4rpx;
+		margin-right: 8rpx;
 	}
 
 	.jipin-text {
 		color: rgba(237, 66, 69, 1);
 		font-family: DM Sans;
-		font-size: 18rpx;
+		font-size: 16rpx;
 		font-weight: 400;
-		line-height: 30rpx;
+		line-height: 40rpx;
 		letter-spacing: 0.5%;
 		text-align: left;
 	}
 }
 
-.salary-text {
-	color: rgba(27, 229, 223, 1);
-	font-family: DM Sans;
-	font-size: 28rpx;
-	font-weight: 700;
+.clip-color {
+	font-size: 24rpx;
+	font-weight: bold;
 	line-height: 40rpx;
-	letter-spacing: 0.5%;
-	text-align: right;
+	background-image: linear-gradient(90.00deg, rgba(13, 39, 247, 1),rgba(19, 193, 234, 1));
+	-webkit-background-clip: text;
+	color: transparent;
+	background-clip: text;
 }
 
 .company-name,
@@ -2649,19 +2662,17 @@ page {
 
 		.gwList-box-item {
 			width: 100%;
-			// height: 329rpx;
 			background-color: #ffffff;
 			border-radius: 12rpx;
-			margin-bottom: 20rpx;
-			padding-bottom: 20rpx;
+			box-shadow: 0px 2rpx 4rpx 0px rgba(0, 0, 0, 0.1);
+			background: rgba(253, 253, 253, 1);
+			margin-bottom: 12rpx;
+			padding: 16rpx 36rpx;
 		}
 
 		.gwList-box-item-box {
-			width: 623rpx;
-			height: 100%;
-
 			.gwList-box-item-box-title {
-				margin-top: 28rpx;
+				// margin-top: 28rpx;
 			}
 
 			.gwList-box-item-box-label {
@@ -2669,10 +2680,11 @@ page {
 			}
 
 			.gwList-box-item-box-name {
-				margin-top: 14rpx;
-				color: #999999;
-				font-size: 28rpx;
-				font-weight: 500;
+				margin-top: 12rpx;
+				color: rgba(156, 164, 171, 1);
+				font-size: 24rpx;
+				font-weight: 400;
+				line-height: 40rpx;
 			}
 
 			.gwList-box-item-box-line {

+ 67 - 43
pages/my/educationExperience.vue

@@ -8,7 +8,6 @@
 				</view>
 				<view class="nav-title">
 					<view>教育经历</view>
-					<view style="font-size: 20rpx;color:#666;font-weight: 400;">(请填写最高学历)</view>
 				</view>
 				<view class="nav-right"></view>
 			</view>
@@ -16,21 +15,21 @@
 		
 		<!-- 主要内容 -->
 		<view class="main-content">
-			<!-- 公司信息 -->
 			<view class="form-section">				
-				<!-- 公司名称 -->
+				<!-- 学校名称 -->
 				<view class="form-item">
-					<view class="form-label">学校名称</view>
+					<view class="form-label">
+						<text class="required-mark">*</text>
+						<text class="label-text">学校名称</text>
+					</view>
 					<input 
 						v-model="formData.companyName" 
 						placeholder="请填写学校名称" 
 						class="form-input"
 					/>
 				</view>
-				
 			</view>
 			
-			<!-- 岗位履历 -->
 			<view class="form-section">
 				<!-- 在校时间 -->
 				<view class="form-item">
@@ -92,7 +91,7 @@
 
 				</view>
 				
-				<!-- 所在部门 -->
+				<!-- 学历 -->
 				<view class="form-item">
 					<view class="form-label">
 						<text class="required-mark">*</text>
@@ -105,23 +104,29 @@
 						<u-icon name="arrow-down" color="#999" size="36"></u-icon>
 					</view>
 				</view>
-				<!-- 工作业绩 -->
+				<!-- 专业 -->
 				<view class="form-item">
-					<view class="form-label">专业</view>
+					<view class="form-label">
+						<text class="required-mark">*</text>
+						<text class="label-text">专业</text>
+					</view>
 					<view class="form-input">
-						<textarea auto-height v-model="formData.workPerformance" placeholder="选填,请输入"></textarea>
+						<textarea auto-height v-model="formData.workPerformance" placeholder="请输入专业"></textarea>
 					</view>
 				</view>
 				
-				<!-- 工作内容 -->
+				<!-- 教育经历 -->
 				<view class="form-item">
-					<view class="form-label">经历内容</view>
+					<view class="form-label">教育经历</view>
 					<view class="form-input">
-						<textarea auto-height v-model="formData.workContent" placeholder="选填,请输入"></textarea>
+						<textarea auto-height v-model="formData.workContent" placeholder="请输入教育经历内容"></textarea>
 					</view>
 				</view>
-				
 			</view>
+			
+			<!-- 删除教育经历 -->
+			<view class="delete-experience" v-if="isEdit" @click="handleDeleteExp">删除教育经历</view>
+			
 			<!-- 底部保存按钮 -->
 			<view class="bottom-btn-container">
 				<view class="save-btn" @click="saveWorkExperience">
@@ -129,27 +134,6 @@
 				</view>
 			</view>
 		</view>
-		
-		
-		
-		<!-- 添加技能弹窗 -->
-		<u-popup v-model="showAddSkill" mode="center" border-radius="24" width="80%">
-			<view class="add-skill-popup">
-				<view class="popup-title">添加技能</view>
-				<view class="popup-content">
-					<input 
-						v-model="newSkillName" 
-						placeholder="请输入技能名称" 
-						class="skill-input"
-						maxlength="10"
-					/>
-				</view>
-				<view class="popup-buttons">
-					<view class="popup-btn cancel-btn" @click="cancelAddSkill">取消</view>
-					<view class="popup-btn confirm-btn" @click="confirmAddSkill">确定</view>
-				</view>
-			</view>
-		</u-popup>
 	</view>
 </template>
 
@@ -159,8 +143,6 @@ export default {
 	data() {
 		return {
 			statusBarHeight: 0, // 状态栏高度
-			showAddSkill: false,
-			newSkillName: '',
 			currentResumeIndex: 0,
 			formData: {
 				companyName: '',
@@ -181,7 +163,8 @@ export default {
 						"博士",
 						"博士后"
 				],
-			isWork:false
+			isWork:false,
+			isEdit: false
 		}
 	},
 	onLoad(options) {
@@ -194,6 +177,10 @@ export default {
 		this.getData()
 		this.initYearMonth();
 		// 监听技能设置更新
+		
+		if (options && options.id) {
+			this.isEdit = true
+		}
 	},
 	beforeDestroy() {
 		
@@ -365,6 +352,35 @@ export default {
 		    }
 		  });
 		},
+		
+		// 删除教育经历
+		handleDeleteExp() {
+			this.$queue.appConfirm('确定删除该教育经历吗?', (res) => {
+				if (!res) {
+					return;
+				}
+				this.$Request.postJson('/app/userFirst/deleteEdu', {
+					eduId: id
+				}).then((res) => {
+					if (res.code == 0) {
+						uni.showToast({
+							title: "操作成功",
+							icon: "none"
+						});
+						// 实际开发中可以在这里添加跳转逻辑
+						uni.$emit('updateResume')
+						setTimeout(() => {
+							uni.navigateBack()
+						}, 1000);
+					} else {
+						uni.showToast({
+							title: res.msg,
+							icon: "none",
+						});
+					}
+				});
+			})
+		},
 	}
 }
 </script>
@@ -486,11 +502,10 @@ export default {
 		}
 		picker{
 			width: 100%;
-		}		textarea{
-			width: 100%;
-			padding: 20rpx 0;
-			height: fit-content;
-			min-height: 40rpx;
+		}
+		textarea{
+			font-size: 28rpx;
+			line-height: 32rpx;
 		}
 	}
 }
@@ -598,6 +613,15 @@ export default {
 	}
 }
 
+// 删除教育经历
+.delete-experience {
+	font-size: 32rpx;
+	text-align: center;
+	line-height: 88rpx;
+	color: rgba(153, 153, 153, 1);
+	margin-top: 32rpx;
+}
+
 .bottom-btn-container {
 	position: fixed;
 	bottom: 0;

+ 56 - 22
pages/my/index.vue

@@ -23,10 +23,10 @@
 						:style="{ paddingTop: token && XCXIsSelect != '否' ? '0' : '100rpx' }">
 						<view class="info-box">
 							<view @click="goNav('/pages/my/onlineResume')"
-								class="info-box-header flex justify-between align-center">
-								<view style="width: 60%; height: 100%" class="flex align-center">
+								class="info-box-header flex justify-between align-end">
+								<view class="flex align-center">
 									<view class="info-box-header-l">
-										<image :src="avatar ? avatar : '../../static/logo.png'" mode="aspectFill"></image>
+										<image :src="avatar ? avatar : '@/static/images/logo.jpg'" mode="aspectFill"></image>
 									</view>
 									<view class="info-box-header-r">
 										<view class="info-box-header-r-name flex align-center">
@@ -38,14 +38,21 @@
 										</view>
 										<view v-if="token && XCXIsSelect != '否'"
 											class="info-box-header-r-bj flex align-center">
-											编辑简历
+											基本信息
 											<image src="@/static/images/jobApplicant/edit-user.svg"
 												mode="scaleToFill" />
 										</view>
 									</view>
 								</view>
-								<view class="flex align-center status-txt">
-									<u-icon name="arrow-right"></u-icon>
+								<!-- 简历完善度 -->
+								<view class="resume-progress">
+									<view class="text-tip flex align-center justify-between">
+										<text>简历完善度</text>
+										<text>{{ score }}%</text>
+									</view>
+									<view class="progress-box">
+										<view class="progress-bar" :style="{ width: `${score}%` }"></view>
+									</view>
 								</view>
 								<!-- <view
                   class="flex align-center status-txt"
@@ -188,7 +195,7 @@
 					<!-- 更多工具 -->
 					<!-- 更多功能区域 -->
 					<view class="more-functions">
-						<text class="section-title">更多功能</text>
+						<view class="section-title">更多功能</view>
 						<view class="function-grid">
 							<!-- <view class="function-item">
 								<image src="../../static/images/index/moreSkill2.svg" class="function-icon"></image>
@@ -210,6 +217,10 @@
 								<image src="../../static/images/index/moreSkill1.svg" class="function-icon"></image>
 								<text class="function-text">猎头服务</text>
 							</view>
+							<view class="function-item" @click="goNav('/package/my/hiddenManagement/index')">
+								<image src="@/static/images/svg/building.svg" class="function-icon"></image>
+								<text class="function-text">屏蔽管理</text>
+							</view>
 							<!-- <view v-if="token" class="function-item" @click="goOut()">
 								<image src="../../static/images/my/icon/utils/utils8.png"
 									class="function-icon"></image>
@@ -306,7 +317,7 @@
 							</view>
 						</view>
 					</view>
-					<!-- <view class="beian">客服电话 400-000-0100 工作时间08:00-22:00</view> -->
+					<view class="beian">客服电话 400-000-0100 工作时间08:00-22:00</view>
 					<view class="beian">人力资源服务许可证 营业执照 深圳市人社局监督电话</view>
 					<view class="beian">粤ICP备2025494494号-2A</view>
 				</view>
@@ -719,7 +730,7 @@
 							</view>
 						</view>
 					</view>
-					<!-- 			<view class="beian">客服电话 400-000-0100 工作时间08:00-22:00</view> -->
+					<view class="beian">客服电话 400-000-0100 工作时间08:00-22:00</view>
 					<view class="beian">人力资源服务许可证 营业执照 深圳市人社局监督电话</view>
 					<view class="beian">粤ICP备2025494494号-2A</view>
 				</view>
@@ -834,7 +845,8 @@ export default {
 			companyStatus: "", //企业认证状态(1:审核中 2:已通过 3:已拒绝 空:未认证)
 			isAndroid: false,
 			iosAudit: 1,
-			showNotice:false
+			showNotice:false,
+			score: 0, // 简历完善度
 		};
 	},
 	onLoad(e) {
@@ -1074,6 +1086,7 @@ export default {
 					if (res.data) {
 						this.resumesStatus = res.data.resumesStatus;
 						this.resumesId = res.data.resumesId;
+						this.score = res.data.score;
 						if (this.resumesStatus == 1) {
 							this.list = [{
 								id: 2,
@@ -1805,14 +1818,6 @@ page {
 	}
 }
 
-.status-txt {
-	color: #fff;
-	font-family: DM Sans;
-	font-size: 28rpx;
-	font-weight: 400;
-	line-height: 44rpx;
-}
-
 // 推广横幅
 .promo-banner {
 	margin: 10rpx 40rpx 10rpx 40rpx;
@@ -2086,6 +2091,31 @@ page {
 					}
 				}
 			}
+			
+			// 简历完善度
+			.resume-progress {
+				width: 180rpx;
+				margin-bottom: 12rpx;
+				.text-tip {
+					font-size: 24rpx;
+					font-weight: 500;
+					line-height: 28rpx;
+					color: #fff;
+					margin-bottom: 8rpx;
+				}
+				.progress-box {
+					width: 100%;
+					height: 10rpx;
+					border-radius: 10rpx;
+					background: rgba(255, 255, 255, 0.5);
+					.progress-bar {
+						width: 0;
+						height: 100%;
+						border-radius: 4px;
+						background: linear-gradient(90.00deg, rgba(27, 234, 228, 1),rgba(1, 107, 251, 1) 100%);
+					}
+				}
+			}
 		}
 
 		.info-box-num {
@@ -2325,25 +2355,28 @@ page {
 		line-height: 44rpx;
 		letter-spacing: 0%;
 		text-align: left;
+		padding-bottom: 16rpx;
+		border-bottom: 0.5px solid rgba(238, 238, 238, 1);
 	}
 
 	.function-grid {
 		margin-top: 24rpx;
 		display: flex;
-		// justify-content: space-between;
-		border-top: 0.5px solid rgba(238, 238, 238, 1);
+		flex-wrap: wrap;
 		padding-top: 16rpx;
-		gap: 70rpx;
+		// gap: 70rpx;
+		margin: -12rpx -35rpx; // 兼容低版本系统不支持gap属性
 
 		.function-item {
 			display: flex;
 			flex-direction: column;
 			align-items: center;
-			gap: 16rpx;
+			margin: 12rpx 35rpx;
 
 			.function-icon {
 				width: 48rpx;
 				height: 48rpx;
+				margin-bottom: 16rpx;
 			}
 
 			.function-text {
@@ -2388,6 +2421,7 @@ page {
 	border-radius: 40rpx;
 }
 .info-box-header-r-text{
+	width: 340rpx;
 	height: fit-content;
 	overflow: hidden;
 	white-space: nowrap;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 477 - 461
pages/my/onlineResume.vue


+ 181 - 114
pages/my/workExperience.vue

@@ -17,7 +17,10 @@
 			<view class="form-section">
 				<!-- 公司名称 -->
 				<view class="form-item">
-					<view class="form-label">公司名称</view>
+					<view class="form-label">
+						<text class="required-mark">*</text>
+						<text class="label-text">公司名称</text>
+					</view>
 					<view class="form-input">
 						<input v-model="formData.companyName" placeholder="请填写公司名称" maxlength="50" />
 						<u-icon v-if="formData.companyName" name="close-circle-fill" color="#C9CDD4" size="28"
@@ -55,27 +58,29 @@
 				<view class="form-item">
 					<view class="form-label">
 						<text class="required-mark">*</text>
-						<text class="label-text">{{ hasCrossBorderExperience ? '任职时间' : '在职时间' }}</text>
+						<text class="label-text">在职时间</text>
 					</view>
 					<view class="form-input time-range">
-						<view class="time-input">
-							<uni-datetime-picker v-model="resume.employmentTime[0]" type="date"
-								:border="false" placeholder="开始时间" />
+						<view class="time-input" @click="handleSelectDate(index, 'start', resume.employmentTime[0])">
+							{{ resume.employmentTime[0] || '开始时间' }}
+							<!-- <uni-datetime-picker v-model="resume.employmentTime[0]" type="date"
+								:border="false" placeholder="开始时间" /> -->
 							<!-- <image src="../../static/images/index/Iconly_Light_Calendar.svg"
 								style="width: 48rpx; height: 48rpx;" mode="aspectFit"></image> -->
 						</view>
 						<view class="time-separator">至</view>
-						<view class="time-input">
-							<uni-datetime-picker v-model="resume.employmentTime[1]" type="date"
-								:border="false" placeholder="结束时间" />
-							<image src="../../static/images/index/Iconly_Light_Calendar.svg"
-								style="width: 48rpx; height: 48rpx;" mode="aspectFit"></image>
+						<view class="time-input" @click="handleSelectDate(index, 'end', resume.employmentTime[1])">
+							{{ resume.employmentTime[1] || '结束时间' }}
+							<!-- <uni-datetime-picker v-model="resume.employmentTime[1]" type="date"
+								:border="false" placeholder="结束时间" /> -->
 						</view>
+						<image src="../../static/images/index/Iconly_Light_Calendar.svg"
+							style="width: 48rpx; height: 48rpx;" mode="aspectFit"></image>
 					</view>
 				</view>
 
 				<!-- 所在部门 -->
-				<view class="form-item">
+				<!-- <view class="form-item">
 					<view class="form-label">
 						<text class="required-mark">*</text>
 						<text class="label-text">所在部门</text>
@@ -87,7 +92,7 @@
 						</picker>
 						<u-icon name="arrow-down" color="#999" size="36"></u-icon>
 					</view>
-				</view>
+				</view> -->
 
 				<!-- 岗位 -->
 				<view class="form-item">
@@ -103,7 +108,7 @@
 				</view>
 
 				<!-- 岗位职级 -->
-				<view class="form-item">
+				<!-- <view class="form-item">
 					<view class="form-label">岗位职级</view>
 					<view class="form-input">
 						<picker class="picker" :data-index="index" mode="selector" :range="positionLevels"
@@ -112,7 +117,7 @@
 						</picker>
 						<u-icon name="arrow-down" color="#999" size="36"></u-icon>
 					</view>
-				</view>
+				</view> -->
 
 				<!-- 岗位职业技能 -->
 				<view class="form-item">
@@ -136,12 +141,9 @@
 
 				<!-- 工作内容 -->
 				<view class="form-item">
-					<view class="form-label">
-						工作内容
-						<text class="word-count">{{ resume.workContent && resume.workContent.length || 0 }}/1000</text>
-					</view>
+					<view class="form-label">工作内容</view>
 					<view class="form-input">
-						<textarea v-model="resume.workContent" placeholder="选填,请输入" maxlength="1000" auto-height
+						<textarea v-model="resume.workContent" placeholder="请输入工作内容" auto-height
 							@input="handleTextareaInput($event, 'workContent', index)" class="form-textarea"></textarea>
 						<view class="textarea-clear" v-if="resume.workContent"
 							@click="clearTextarea('workContent', index)">
@@ -152,12 +154,9 @@
 
 				<!-- 工作业绩 -->
 				<view class="form-item">
-					<view class="form-label">
-						工作业绩
-						<text class="word-count">{{ resume.workPerformance && resume.workPerformance.length || 0 }}/1000</text>
-					</view>
+					<view class="form-label">工作业绩</view>
 					<view class="form-input">
-						<textarea v-model="resume.workPerformance" placeholder="选填,请输入" maxlength="1000" auto-height
+						<textarea v-model="resume.workPerformance" placeholder="请输入工作绩效" auto-height
 							@input="handleTextareaInput($event, 'workPerformance', index)"
 							class="form-textarea"></textarea>
 						<view class="textarea-clear" v-if="resume.workPerformance"
@@ -173,12 +172,13 @@
 					<text>添加岗位履历</text>
 				</view>
 			</view>
+			
+			<!-- 删除工作经历 -->
+			<view class="delete-experience" v-if="isEdit" @click="handleDeleteExp">删除全部工作经验</view>
 
 			<!-- 底部保存按钮 -->
-			<view class="bottom-btn-container">
-				<view class="save-btn" @click="saveWorkExperience">
-					<text>保存</text>
-				</view>
+			<view class="fixed-section">
+				<u-button type="primary" class="submit-btn" @click="saveWorkExperience">保存</u-button>
 			</view>
 		</view>
 
@@ -199,6 +199,9 @@
 		<!-- 清除确认弹窗 -->
 		<u-modal v-model="showClearConfirm" :content="'确定要清除所有填写的内容吗?'" show-cancel-button confirm-text="确定清除"
 			cancel-text="取消" @confirm="clearAllContent" confirm-color="#FF4444"></u-modal>
+			
+		<!-- 时间控件弹窗 -->
+		<u-select v-model="showSelectDate" :default-value="defaultDate" :list="dateList" @confirm="handleConfirmDate"></u-select>
 	</view>
 </template>
 
@@ -255,7 +258,15 @@ export default {
 			departmentsIds: [],
 			positionLevels: ['初级', '中级','高级','资深','其它'],
 			operateKey: 0,
-			isWork: false
+			isWork: false,
+			isEdit: false, // 是否是编辑
+			showSelectDate: false,
+			selectParams: {
+				index: 0,
+				type: 'start', // start、end
+			},
+			currentDate: '', // 当前时间,记录选中的时间,用于u-select控件回显
+			dateList: []
 		}
 	},
 	onLoad(options) {
@@ -277,6 +288,9 @@ export default {
 		}
 		this.getDepartment()
 		id = options && options.id ? options.id : ''
+		if (options && options.id) {
+			this.isEdit = true;
+		}
 		// 监听技能设置更新
 		uni.$on('jobs', (data) => {
 			console.log('岗位设置已更新:', data)
@@ -291,6 +305,9 @@ export default {
 			// 这里可以更新对应的技能显示
 			this.formData.resumes[this.operateKey].skills = data.selectedTags
 		})
+		
+		// 生成时间组件数据
+		this.dateList = this.generateYearMonthArray()
 	},
 	beforeDestroy() {
 		// 移除事件监听
@@ -311,9 +328,84 @@ export default {
 					resume.workPerformance ||
 					resume.skills.length > 0
 				)
+		},
+		// 时间控件回显
+		defaultDate() {
+			let currentIndex = 0
+			this.dateList.forEach((date, index) => {
+				if (this.currentDate == date.value) {
+					currentIndex = index
+				}
+			})
+			return [currentIndex]
 		}
 	},
 	methods: {
+		// 生成时间控件列表数据
+		generateYearMonthArray() {
+			// 定义起始年份和月份
+			const startYear = 1950;
+			const startMonth = 1; // 1月
+			
+			// 获取当前日期
+			const now = new Date();
+			const endYear = now.getFullYear();
+			const endMonth = now.getMonth() + 1; // 月份从0开始,所以要+1
+			
+			// 存储最终结果的数组
+			const result = [];
+			
+			// 遍历年份,从起始年到当前年
+			for (let year = startYear; year <= endYear; year++) {
+				// 确定当前年份需要遍历的月份范围
+				let currentEndMonth = 12; // 默认到12月
+				// 如果是当前年份,只遍历到当前月份
+				if (year === endYear) {
+					currentEndMonth = endMonth;
+				}
+				
+				// 遍历月份,从1月到当前年份的结束月份
+				for (let month = startMonth; month <= currentEndMonth; month++) {
+					// 格式化value:确保月份是两位数(如1月显示为01)
+					const formattedMonth = month.toString().padStart(2, '0');
+					const value = `${year}-${formattedMonth}`;
+					
+					// 格式化label:直接显示月份数字(如1月)
+					const label = `${year}年 ${month}月`;
+					
+					// 添加到结果数组
+					result.unshift({ value, label });
+				}
+			}
+			
+			// 添加“至今”选项
+			result.unshift({
+				value: '至今',
+				label: '至今'
+			})
+			
+			return result;
+		},
+		// 打开日期选择控件
+		handleSelectDate(index, type, date) {
+			this.selectParams.index = index;
+			this.selectParams.type = type;
+			this.currentDate = date;
+			this.showSelectDate = true;
+		},
+		// 选择时间
+		handleConfirmDate(data) {
+			for (let i = 0; i < this.formData.resumes.length; i++) {
+				if (i === this.selectParams.index) {
+					if (this.selectParams.type == 'end') {
+						this.formData.resumes[i].employmentTime[1] = data[0].value
+					} else {
+						this.formData.resumes[i].employmentTime[0] = data[0].value
+					}
+					break
+				}
+			}
+		},
 		getDataInfo(jobId) {
 			let data = {
 				ruleClassifyId: jobId
@@ -388,12 +480,12 @@ export default {
 				}
 			});
 		},
-		selectDepartment(e) {
-			var key = Number(e.currentTarget.dataset.index)
-			this.formData.resumes[key].departmentId = this.departmentsIds[e.detail.value]
-			this.formData.resumes[key].departmentIndex = e.detail.value
-			this.formData.resumes[key].department = this.departments[e.detail.value]
-		},
+		// selectDepartment(e) {
+		// 	var key = Number(e.currentTarget.dataset.index)
+		// 	this.formData.resumes[key].departmentId = this.departmentsIds[e.detail.value]
+		// 	this.formData.resumes[key].departmentIndex = e.detail.value
+		// 	this.formData.resumes[key].department = this.departments[e.detail.value]
+		// },
 		formatter(type, value) {
 			if (type === 'year') {
 				return `${value}年`
@@ -427,10 +519,10 @@ export default {
 				url: '/package/jobIntention/jobList'
 			})
 		},
-		selectPositionLevel(e) {
-			var key = Number(e.currentTarget.dataset.index)
-			this.formData.resumes[key].positionLevel = this.positionLevels[e.detail.value]
-		},
+		// selectPositionLevel(e) {
+		// 	var key = Number(e.currentTarget.dataset.index)
+		// 	this.formData.resumes[key].positionLevel = this.positionLevels[e.detail.value]
+		// },
 		addSkill(index) {
 			this.operateKey = index
 			//this.currentResumeIndex = index
@@ -548,6 +640,35 @@ export default {
 				icon: 'success'
 			});
 		},
+		
+		// 删除工作经历
+		handleDeleteExp() {
+			this.$queue.appConfirm('确定删除该工作经历吗?', (res) => {
+				if (!res) {
+					return;
+				}
+				this.$Request.postJson('/app/userFirst/deleteWorkExp', {
+					workExpId: id
+				}).then((res) => {
+					if (res.code == 0) {
+						uni.showToast({
+							title: "操作成功",
+							icon: "none"
+						});
+						// 实际开发中可以在这里添加跳转逻辑
+						uni.$emit('updateResume')
+						setTimeout(() => {
+							uni.navigateBack()
+						}, 1000);
+					} else {
+						uni.showToast({
+							title: res.msg,
+							icon: "none",
+						});
+					}
+				});
+			})
+		},
 
 		saveWorkExperience() {
 			console.log(this.formData.resumes)
@@ -671,9 +792,11 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+@import '@/common.scss';
+	
 .work-experience {
 	height: 100vh;
-	padding-bottom: 120rpx;
+	padding-bottom: 172rpx;
 	display: flex;
 	flex-direction: column;
 }
@@ -811,12 +934,8 @@ export default {
 		}
 
 		.form-textarea {
-			width: 100%;
-			min-height: 80rpx;
-			padding: 20rpx 0;
-			line-height: 1.5;
-			resize: none;
-			background: transparent;
+			font-size: 28rpx;
+			line-height: 32rpx;
 		}
 	}
 }
@@ -837,6 +956,7 @@ export default {
 		flex-wrap: wrap;
 		gap: 12rpx;
 		flex: 1;
+		padding: 16rpx 0;
 
 		.skill-tag {
 			padding: 8rpx 16rpx;
@@ -869,45 +989,28 @@ export default {
 .add-resume-btn {
 	width: 100%;
 	height: 80rpx;
-	border: 1rpx solid #007AFF;
 	border-radius: 60rpx;
 	display: flex;
 	align-items: center;
 	justify-content: center;
 	margin-top: 20rpx;
+	border-radius: 100px;
+	background: rgba(1, 107, 246, 0.1);
 
 	text {
-		color: #007AFF;
-		font-size: 28rpx;
+		color: #016bf6;
+		font-size: 32rpx;
 		font-weight: 500;
 	}
 }
 
-.bottom-btn-container {
-	position: fixed;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	padding: 30rpx 20rpx;
-	background: #fff;
-	border-top: 1px solid #f0f0f0;
-	z-index: 98;
-}
-
-.save-btn {
-	width: 100%;
-	height: 88rpx;
-	background: linear-gradient(90deg, rgba(13, 39, 247, 1), rgba(19, 193, 234, 1) 100%);
-	border-radius: 44rpx;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-
-	text {
-		font-size: 32rpx;
-		font-weight: 600;
-		color: #fff;
-	}
+// 删除工作经历
+.delete-experience {
+	font-size: 32rpx;
+	text-align: center;
+	line-height: 88rpx;
+	color: rgba(153, 153, 153, 1);
+	margin-top: 32rpx;
 }
 
 .add-skill-popup {
@@ -993,50 +1096,14 @@ export default {
 	}
 }
 
-.form-textarea {
-	height: auto;
-
-}
-
 /* 时间选择器样式 */
 .time-range {
 	display: flex;
 	align-items: center;
 	justify-content: space-between;
-}
-
-.time-input {
-	flex: 1;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	// border-bottom: 1rpx solid #E5E5EA;
-	// padding-bottom: 10rpx;
-	text-align: center;
-}
-
-.time-input:first-child {
-	margin-right: 20rpx;
-}
-
-.time-input:last-child {
-	margin-left: 20rpx;
-}
-
-.time-separator {
-	font-size: 28rpx;
-	color: #666;
-}
-
-/* 调整日期选择器输入框样式 */
-.time-input /deep/ .uni-datetime-picker__input {
-	width: 100%;
-	font-size: 28rpx;
-	color: #333;
-}
-
-.time-input /deep/ .uni-datetime-picker__placeholder {
-	color: #999;
-	font-size: 28rpx;
+	.time-input {
+		flex: 1;
+		text-align: center;
+	}
 }
 </style>

+ 20 - 9
pages/public/loginV2.vue

@@ -42,7 +42,18 @@
 			}
 		},
 		onLoad() {
-			this.handleLogin()
+			// this.handleLogin()
+			// uni.getPhoneNumber({
+			// 	provider: 'univerify',
+			// 	success: (res) => {
+			// 		console.log('fail----------------')
+			// 		console.log(JSON.parse(JSON.stringify(err)))
+			// 	},
+			// 	fail: (err) => {
+			// 		console.log('fail----------------')
+			// 		console.log(JSON.parse(JSON.stringify(err)))
+			// 	}
+			// })
 		},
 		methods: {
 			login() {
@@ -62,7 +73,7 @@
 					univerifyStyle: {
 					    fullScreen: true,
 						icon: {
-							path: 'static/images/avator.png',
+							path: 'static/images/logo.jpg',
 						},
 						authButton: {
 							normalColor: '#016BF6'
@@ -75,29 +86,29 @@
 						},
 						privacyTerms: {
 							defaultCheckBoxState: false,
-							uncheckedImage: 'static/images/jobApplicant/border.svg',
-							checkedImage: 'static/images/jobApplicant/check.svg',
+							uncheckedImage: 'static/images/onKeyLogin/unchecked.png',
+							checkedImage: 'static/images/onKeyLogin/checked.png',
 							privacyItems: [
 								{
-									"url": "/my/setting/xieyi", // 点击跳转的协议详情页面
+									"url": "https://h5.bosszan.com/my/setting/xieyi", // 点击跳转的协议详情页面
 									"title": "亿职赞用户协议" // 协议名称
 								},
 								{
-									"url": "/my/setting/mimi", // 点击跳转的协议详情页面
+									"url": "https://h5.bosszan.com/my/setting/mimi", // 点击跳转的协议详情页面
 									"title": "隐私协议" // 协议名称
 								},
 							]
 						},
 						buttons: {
-							iconWidth: '60px',
+							iconWidth: '45px',
 							list: [
 								{
 									provider: 'weixin',
-									iconPath: 'static/images/avator.png'
+									iconPath: 'static/images/onKeyLogin/wechat.png'
 								},
 								{
 									provider: 'phone',
-									iconPath: 'static/images/avator.png'
+									iconPath: 'static/images/onKeyLogin/phone.png'
 								}
 							]
 						}

binární
static/images/onKeyLogin/checked.png


binární
static/images/onKeyLogin/phone.png


binární
static/images/onKeyLogin/unchecked.png


binární
static/images/onKeyLogin/wechat.png


binární
static/images/resume/card1.png


binární
static/images/resume/card2.png


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
static/images/svg/bag.svg


+ 13 - 0
static/images/svg/building.svg

@@ -0,0 +1,13 @@
+<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none">
+	<rect id="svg 73" width="24.000000" height="24.000000" x="0.000000" y="0.000000" />
+	<path id="矢量 69" d="M0 0.601074L22.7978 0.601074L22.7978 23.3988L0 23.3988L0 0.601074Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 70" d="M2.56569 16.6976L16.7015 16.6976C18.1405 16.6976 18.86 17.4171 18.86 18.856L18.86 18.8564C18.86 20.2954 18.1405 21.0149 16.7015 21.0149L2.56569 21.0149C1.12671 21.0149 0.407227 20.2954 0.407227 18.8564L0.407227 18.856C0.407227 17.4171 1.12671 16.6976 2.56569 16.6976Z" opacity="0.699999988" fill="rgb(92,192,255)" fill-rule="nonzero" />
+	<path id="矢量 71" d="M3.50341 1.17188L15.6884 1.17188C15.9743 1.17188 16.2551 1.24712 16.5026 1.39004C16.7502 1.53296 16.9557 1.73853 17.0987 1.98608C17.2416 2.23363 17.3168 2.51444 17.3168 2.80029L17.3168 18.3553L1.875 18.3553L1.875 2.80029C1.875 2.51444 1.95024 2.23363 2.09317 1.98608C2.23609 1.73853 2.44166 1.53296 2.68921 1.39004C2.93676 1.24712 3.21757 1.17188 3.50341 1.17188L3.50341 1.17188Z" fill="rgb(92,192,255)" fill-rule="nonzero" />
+	<path id="矢量 72" d="M4.17016 4.56958L5.79858 4.56958C6.34138 4.56958 6.61278 4.84098 6.61278 5.38379C6.61278 5.92659 6.34138 6.19799 5.79858 6.19799L4.17016 6.19799C3.62736 6.19799 3.35596 5.92659 3.35596 5.38379C3.35596 4.84098 3.62736 4.56958 4.17016 4.56958L4.17016 4.56958Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 73" d="M4.17016 8.13495L5.79858 8.13495C6.34138 8.13495 6.61278 8.40635 6.61278 8.94915C6.61278 9.49196 6.34138 9.76336 5.79858 9.76336L4.17016 9.76336C3.62736 9.76336 3.35596 9.49196 3.35596 8.94915C3.35596 8.40635 3.62736 8.13495 4.17016 8.13495L4.17016 8.13495Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 74" d="M4.17016 11.7004L5.79858 11.7004C6.34138 11.7004 6.61278 11.9718 6.61278 12.5146C6.61278 13.0574 6.34138 13.3288 5.79858 13.3288L4.17016 13.3288C3.62736 13.3288 3.35596 13.0574 3.35596 12.5146C3.35596 11.9718 3.62736 11.7004 4.17016 11.7004L4.17016 11.7004Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 75" d="M10.4094 8.13495L12.0378 8.13495C12.5806 8.13495 12.852 8.40635 12.852 8.94915C12.852 9.49196 12.5806 9.76336 12.0378 9.76336L10.4094 9.76336C9.86662 9.76336 9.59522 9.49196 9.59522 8.94915C9.59522 8.40635 9.86662 8.13495 10.4094 8.13495L10.4094 8.13495Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 76" d="M10.4099 4.56958L12.0383 4.56958C12.5811 4.56958 12.8525 4.84098 12.8525 5.38379C12.8525 5.92659 12.5811 6.19799 12.0383 6.19799L10.4099 6.19799C9.86711 6.19799 9.5957 5.92659 9.5957 5.38379C9.5957 4.84098 9.86711 4.56958 10.4099 4.56958Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+	<path id="矢量 77" d="M10.9917 16.698C10.9917 18.0735 11.4272 19.4138 12.2357 20.5266C13.0442 21.6394 14.1843 22.4678 15.4925 22.8928C16.8007 23.3179 18.21 23.3179 19.5182 22.8928C20.8264 22.4678 21.9665 21.6394 22.775 20.5266C23.5835 19.4138 24.019 18.0735 24.019 16.698C24.019 15.3224 23.5835 13.9822 22.775 12.8693C21.9665 11.7565 20.8264 10.9282 19.5182 10.5031C18.21 10.0781 16.8007 10.0781 15.4925 10.5031C14.1843 10.9282 13.0442 11.7565 12.2357 12.8693C11.4272 13.9822 10.9917 15.3224 10.9917 16.698L10.9917 16.698Z" opacity="0.74000001" fill="rgb(28,155,234)" fill-rule="nonzero" />
+	<path id="矢量 78" d="M14.6555 16.0714L20.355 16.0714C20.8978 16.0714 21.1692 16.3428 21.1692 16.8856C21.1692 17.4284 20.8978 17.6998 20.355 17.6998L14.6555 17.6998C14.1127 17.6998 13.8413 17.4284 13.8413 16.8856C13.8413 16.3428 14.1127 16.0714 14.6555 16.0714Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
+</svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 0
static/images/svg/female.svg


+ 4 - 0
static/images/svg/file.svg

@@ -0,0 +1,4 @@
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none">
+	<rect id="svg 57" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
+	<path id="矢量 56" d="M8.28678 1.31088C8.68377 1.31088 9.00559 1.63248 9.00559 2.02922L9.00559 5.22927C9.00559 5.52681 9.24695 5.76803 9.5447 5.76803L12.9618 5.76803C13.3588 5.76803 13.6806 6.08964 13.6806 6.48637L13.6806 13.0559C13.6806 14.1469 12.7956 15.0313 11.7039 15.0313L3.97672 15.0313C2.885 15.0313 2 14.1469 2 13.0559L2 3.28633C2 2.19531 2.885 1.31088 3.97672 1.31088L8.28678 1.31088L8.28678 1.31088ZM10.1502 7.39198C9.61177 6.85144 8.74022 6.8503 8.20041 7.38945L5.39986 10.1866L5.37778 10.209C4.65611 10.9536 4.65928 12.1456 5.39044 12.8862L5.41694 12.9125C6.16061 13.6373 7.34766 13.6305 8.08295 12.8915L10.7929 10.1624L10.7982 10.1569C10.9055 10.0431 10.9036 9.86341 10.7926 9.75194C10.6799 9.63866 10.4972 9.63878 10.3846 9.75219L7.67611 12.4799L7.65947 12.4964C7.14109 13.0007 6.31439 12.9952 5.80275 12.4801L5.79992 12.4772L5.78466 12.4615C5.28606 11.9398 5.29405 11.1103 5.80647 10.5985L8.60703 7.80133L8.61652 7.792C8.93153 7.48739 9.43209 7.49116 9.74252 7.80281C10.0556 8.11714 10.0566 8.62706 9.74475 8.94263L7.19408 11.5236L7.18834 11.5293C7.08066 11.6322 6.91042 11.6306 6.80466 11.5244C6.69428 11.4136 6.69262 11.2342 6.80095 11.1214L8.96523 8.86639L8.97042 8.86086C9.07578 8.74527 9.07089 8.56559 8.95805 8.45603C8.84341 8.34472 8.66075 8.34795 8.55008 8.46327L6.38578 10.7182L6.37606 10.7285C6.05884 11.0698 6.06703 11.604 6.397 11.9352C6.73008 12.2696 7.26962 12.2691 7.60209 11.9341L10.154 9.3518L10.1699 9.33542C10.6901 8.79172 10.6831 7.92705 10.1502 7.39198L10.1502 7.39198ZM9.76308 1.26563C9.84004 1.26562 9.90631 1.29223 9.96191 1.34545L13.6298 4.85694C13.7445 4.96675 13.7484 5.14873 13.6386 5.26344C13.6115 5.29176 13.5799 5.31362 13.5439 5.32901C13.5078 5.34441 13.4702 5.35211 13.431 5.35211L9.9787 5.35211C9.70084 5.35211 9.47558 5.12686 9.47558 4.84898L9.47558 1.55313C9.47558 1.39434 9.6043 1.26562 9.76308 1.26562L9.76308 1.26563Z" fill="rgb(1,107,246)" fill-rule="nonzero" />
+</svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 0
static/images/svg/gray-briefcase.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
static/images/svg/heart.svg


+ 5 - 0
static/images/svg/male.svg

@@ -0,0 +1,5 @@
+<svg viewBox="0 0 11 11" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11.000000" height="11.000000" fill="none">
+	<rect id="svg 49" width="11.000000" height="11.000000" x="0.000000" y="0.000000" />
+	<circle id="椭圆 10" cx="5.5" cy="5.5" r="5.5" fill="rgb(255,255,255)" />
+	<path id="矢量 48" d="M8.84505 4.47989L8.84505 3.02702C8.55674 3.30779 7.69086 4.15012 7.24238 4.58636C7.68332 5.12529 7.94808 5.80839 7.94808 6.55272C7.94808 8.28448 6.51783 9.69401 4.75969 9.69401C3.00155 9.69401 1.57129 8.28448 1.57129 6.55272C1.57129 4.82096 3.00154 3.41144 4.75969 3.41144C5.44749 3.41144 6.08347 3.62908 6.60545 3.9956C7.04828 3.57444 7.9396 2.72834 8.24299 2.43909L6.64973 2.43909L6.64973 1.57227L9.68832 1.57227L9.68832 4.47895L8.84506 4.47895L8.84505 4.47989ZM2.4513 6.55272C2.4513 7.80679 3.48678 8.82719 4.76063 8.82719C6.03448 8.82719 7.06995 7.80679 7.06995 6.55272C7.06995 5.29866 6.03259 4.27826 4.75969 4.27826C3.48678 4.27826 2.4513 5.29866 2.4513 6.55272L2.4513 6.55272Z" fill="rgb(16,0,255)" fill-rule="nonzero" />
+</svg>

+ 4 - 0
static/images/svg/search.svg

@@ -0,0 +1,4 @@
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
+	<rect id="icon_search_gray_16" width="16.000000" height="16.000000" x="0.000000" y="0.000000" fill="rgb(255,255,255)" fill-opacity="0" />
+	<path id="形状" d="M15.8247 14.9755L12.502 11.6459C13.5712 10.3712 14.1539 8.77657 14.1539 7.09177C14.1539 5.19743 13.4177 3.41646 12.0812 2.0771C10.7444 0.737517 8.96735 0 7.07697 0C5.18658 0 3.40932 0.737741 2.07276 2.0771C0.7362 3.41646 0 5.19743 0 7.09177C0 8.98611 0.7362 10.7671 2.07276 12.1064C3.40932 13.4458 5.18658 14.1835 7.07697 14.1835C8.77428 14.1835 10.3801 13.5884 11.6581 12.4974L14.9779 15.8242C15.09 15.9369 15.2424 16.0002 15.4012 16C15.5544 16 15.7076 15.9413 15.8245 15.8242C15.937 15.7118 16.0002 15.5591 16 15.3999C16 15.2462 15.9417 15.0927 15.8247 14.9755ZM7.07697 1.20012C3.8351 1.20012 1.19761 3.84313 1.19761 7.09178C1.19761 10.3404 3.8351 12.9834 7.07697 12.9834C10.3188 12.9834 12.9563 10.3404 12.9563 7.09178C12.9563 3.84313 10.3188 1.20012 7.07697 1.20012Z" fill="rgb(180,179,177)" fill-rule="evenodd" />
+</svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
static/images/svg/toolbox.svg


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů