yezhihao 4 mesi fa
parent
commit
d125821466

+ 1 - 1
.hbuilderx/launch.json

@@ -2,7 +2,7 @@
     "version" : "1.0",
     "version" : "1.0",
     "configurations" : [
     "configurations" : [
         {
         {
-            "customPlaygroundType" : "device",
+            "customPlaygroundType" : "local",
             "localRepoPath" : "E:/projects/yizhizan-h5",
             "localRepoPath" : "E:/projects/yizhizan-h5",
             "packageName" : "uni.app.UNI0B0096D",
             "packageName" : "uni.app.UNI0B0096D",
             "playground" : "custom",
             "playground" : "custom",

+ 1 - 1
common/config.js

@@ -6,7 +6,7 @@ const productionChatUrl = 'wss://www.bosszan.com/wss/chatSocket/'
 const testApiUrl = 'https://yizhizan.edccc.cn/sqx_fast'
 const testApiUrl = 'https://yizhizan.edccc.cn/sqx_fast'
 const testWssUrl = 'wss://yizhizan.edccc.cn/wss/websocket/'
 const testWssUrl = 'wss://yizhizan.edccc.cn/wss/websocket/'
 const testChatUrl = 'wss://yizhizan.edccc.cn/wss/chatSocket/'
 const testChatUrl = 'wss://yizhizan.edccc.cn/wss/chatSocket/'
-let isProduction = true // 判断是否是生产环境
+let isProduction = false // 判断是否是生产环境
 if (isProduction) {
 if (isProduction) {
 	//正式环境
 	//正式环境
 	const ROOTPATH = productionApiUrl;
 	const ROOTPATH = productionApiUrl;

+ 1 - 1
common/httpRequest.js

@@ -18,7 +18,7 @@ function ensureDomainReady() {
 	// 3)第一次:去后端拉取域名配置
 	// 3)第一次:去后端拉取域名配置
 	domainReadyPromise = new Promise((resolve) => {
 	domainReadyPromise = new Promise((resolve) => {
 		uni.request({
 		uni.request({
-			url: 'https://www.bosszan.com/sqx_fast/app/dict/list',
+			url: configdata.isProduction ? 'https://www.bosszan.com/sqx_fast/app/dict/list' : 'https://yizhizan.edccc.cn/sqx_fast/app/dict/list',
 			data: {
 			data: {
 				type: '路由'
 				type: '路由'
 			},
 			},

+ 20 - 0
constants/common.js

@@ -96,3 +96,23 @@ export const companyWelfare = [
 		]
 		]
 	},
 	},
 ]
 ]
+
+// 线上面试类型
+export const onlineInterviewType = [
+	{
+		name: '腾讯会议',
+		value: 0
+	},
+	{
+		name: '钉钉',
+		value: 1
+	},
+	{
+		name: '微信视频',
+		value: 2
+	},
+	{
+		name: '电话面试',
+		value: 3
+	},
+]

+ 5 - 5
constants/userInfo.js

@@ -21,9 +21,9 @@ export const jobStatus = [
         text: '在职-暂不考虑',
         text: '在职-暂不考虑',
         recommended: false
         recommended: false
     },
     },
-    {
-        value: '4',
-        text: '实习',
-        recommended: false
-    }
+    // {
+    //     value: '4',
+    //     text: '实习',
+    //     recommended: false
+    // }
 ];
 ];

+ 1 - 1
manifest.json

@@ -196,7 +196,7 @@
                 "JPUSH_GOOGLE_STORAGE_BUCKET" : "",
                 "JPUSH_GOOGLE_STORAGE_BUCKET" : "",
                 "JPUSH_HONOR_APPID" : "104533692",
                 "JPUSH_HONOR_APPID" : "104533692",
                 "JPUSH_HUAWEI_APPID" : "116155907",
                 "JPUSH_HUAWEI_APPID" : "116155907",
-                "JPUSH_ISPRODUCTION_IOS" : "true",
+                "JPUSH_ISPRODUCTION_IOS" : "",
                 "JPUSH_MEIZU_APPID" : "",
                 "JPUSH_MEIZU_APPID" : "",
                 "JPUSH_MEIZU_APPKEY" : "",
                 "JPUSH_MEIZU_APPKEY" : "",
                 "JPUSH_OPPO_APPID" : "36598376",
                 "JPUSH_OPPO_APPID" : "36598376",

+ 30 - 3
my/jilu/bossMianshiDetail.vue

@@ -57,6 +57,10 @@
       <view class="detail-item">
       <view class="detail-item">
         <view class="user-title"> 面试信息 </view>
         <view class="user-title"> 面试信息 </view>
         <view class="msg-box">
         <view class="msg-box">
+			<view class="msg-item">
+			  <view class="msg-label">面试类型</view>
+			  <view class="msg-value">{{onlineText}}</view>
+			</view>
           <view class="msg-item">
           <view class="msg-item">
             <view class="msg-label">时间</view>
             <view class="msg-label">时间</view>
             <view class="msg-value">{{info.interviewDateTime}}</view>
             <view class="msg-value">{{info.interviewDateTime}}</view>
@@ -73,10 +77,18 @@
             <view class="msg-label">备注</view>
             <view class="msg-label">备注</view>
             <view class="msg-value">{{info.remarks}}</view>
             <view class="msg-value">{{info.remarks}}</view>
           </view>
           </view>
-          <view class="msg-item">
+          <view class="msg-item" v-if="!isOnline">
             <view class="msg-label">地址</view>
             <view class="msg-label">地址</view>
             <view class="msg-value">{{info.address}} {{info.detailedAddress}}</view>
             <view class="msg-value">{{info.address}} {{info.detailedAddress}}</view>
           </view>
           </view>
+		  <view class="msg-item" v-if="isOnline">
+		    <view class="msg-label">面试方式</view>
+		    <view class="msg-value">{{interviewTypeText}}</view>
+		  </view>
+		  <view class="msg-item" v-if="isOnline">
+		    <view class="msg-label">面试地址</view>
+		    <view class="msg-value">{{info.onlineMsg}}</view>
+		  </view>
         </view>
         </view>
       </view>
       </view>
       <view class="detail-item" v-if="currentStep == 4">
       <view class="detail-item" v-if="currentStep == 4">
@@ -257,6 +269,7 @@
 </template>
 </template>
 <script>
 <script>
 import navBar from "@/components/nav-bar/index.vue";
 import navBar from "@/components/nav-bar/index.vue";
+import { onlineInterviewType } from "@/constants/common";
 
 
 export default {
 export default {
   data() {
   data() {
@@ -282,12 +295,25 @@ export default {
 	  info:{},
 	  info:{},
 	  recordId:'',
 	  recordId:'',
 	  resultType:0,
 	  resultType:0,
-	  isWork:false
+	  isWork:false,
+	  interviewType: 0, // 面试类型:0线下、1线上
     };
     };
   },
   },
   components: {
   components: {
     navBar,
     navBar,
   },
   },
+  computed: {
+	  isOnline() {
+		  return this.interviewType == 1
+	  },
+	  onlineText() {
+		  return this.interviewType == 1 ? '线上面试' : '线下面试'
+	  },
+	  interviewTypeText() {
+		  console.log(onlineInterviewType)
+		  return onlineInterviewType[this?.info?.onlineType]?.name ?? ''
+	  }
+  },
   onLoad(options){
   onLoad(options){
   		this.recordId=options&&options.recordId?options.recordId:''
   		this.recordId=options&&options.recordId?options.recordId:''
   		this.getData()
   		this.getData()
@@ -308,7 +334,8 @@ export default {
 	  		  that.info=res.data
 	  		  that.info=res.data
 	  			  console.log(that.info)
 	  			  console.log(that.info)
 	  			  that.currentStep=!res.data.interviewProcesses||res.data.interviewProcesses==0?res.data.interviewProcesses+1:res.data.interviewProcesses
 	  			  that.currentStep=!res.data.interviewProcesses||res.data.interviewProcesses==0?res.data.interviewProcesses+1:res.data.interviewProcesses
-	  			  /* that.covers.push({
+	  			  this.interviewType = res.data?.type
+				  /* that.covers.push({
 	  				  id:1,
 	  				  id:1,
 	  				latitude: res.data.lat,
 	  				latitude: res.data.lat,
 	  				longitude: res.data.lng,
 	  				longitude: res.data.lng,

+ 26 - 1
my/jilu/mianshiDetail.vue

@@ -42,6 +42,10 @@
           </view>
           </view>
         </view>
         </view>
         <view class="msg-box">
         <view class="msg-box">
+			<view class="msg-item">
+			  <view class="msg-label">面试类型</view>
+			  <view class="msg-value">{{onlineText}}</view>
+			</view>
           <view class="msg-item">
           <view class="msg-item">
             <view class="msg-label">时间</view>
             <view class="msg-label">时间</view>
             <view class="msg-value">{{info.interviewDateTime}}</view>
             <view class="msg-value">{{info.interviewDateTime}}</view>
@@ -58,11 +62,19 @@
             <view class="msg-label">备注</view>
             <view class="msg-label">备注</view>
             <view class="msg-value">{{info.remarks}}</view>
             <view class="msg-value">{{info.remarks}}</view>
           </view>
           </view>
-          <view class="msg-item" @tap.stop="gotoMap()">
+          <view class="msg-item" v-if="!isOnline" @tap.stop="gotoMap()">
             <view class="msg-label">地址</view>
             <view class="msg-label">地址</view>
             <view class="msg-value">{{info.address}} {{info.detailedAddress}}</view>
             <view class="msg-value">{{info.address}} {{info.detailedAddress}}</view>
 			<u-icon name="arrow-right"></u-icon>
 			<u-icon name="arrow-right"></u-icon>
           </view>
           </view>
+		  <view class="msg-item" v-if="isOnline">
+		    <view class="msg-label">面试方式</view>
+		    <view class="msg-value">{{interviewTypeText}}</view>
+		  </view>
+		  <view class="msg-item" v-if="isOnline">
+		    <view class="msg-label">面试地址</view>
+		    <view class="msg-value">{{info.onlineMsg}}</view>
+		  </view>
         </view>
         </view>
         <view class="map-box">
         <view class="map-box">
           <map v-if="info.lng" name="map" class="map" :longitude="parseFloat(info.lng)" :latitude="parseFloat(info.lat)" :markers="covers"></map>
           <map v-if="info.lng" name="map" class="map" :longitude="parseFloat(info.lng)" :latitude="parseFloat(info.lat)" :markers="covers"></map>
@@ -218,6 +230,7 @@
 </template>
 </template>
 <script>
 <script>
 import navBar from "@/components/nav-bar/index.vue";
 import navBar from "@/components/nav-bar/index.vue";
+import { onlineInterviewType } from "@/constants/common";
 
 
 export default {
 export default {
   data() {
   data() {
@@ -232,6 +245,18 @@ export default {
   components: {
   components: {
     navBar,
     navBar,
   },
   },
+  computed: {
+	  isOnline() {
+	  		  return this?.info?.type == 1
+	  },
+	  onlineText() {
+	  		  return this?.info?.type == 1 ? '线上面试' : '线下面试'
+	  },
+	  interviewTypeText() {
+	  		  console.log(onlineInterviewType)
+	  		  return onlineInterviewType[this?.info?.onlineType]?.name ?? ''
+	  }
+  },
   onLoad(options){
   onLoad(options){
 		this.recordId=options&&options.recordId?options.recordId:''
 		this.recordId=options&&options.recordId?options.recordId:''
 		this.companyId=options&&options.companyId?options.companyId:''
 		this.companyId=options&&options.companyId?options.companyId:''

+ 1 - 1
package/jobIntention/basicInfo.vue

@@ -100,7 +100,7 @@
 		<!-- 保存按钮 -->
 		<!-- 保存按钮 -->
 		<view class="button-section">
 		<view class="button-section">
 			<view class="link-btn" v-if="!hasUserType" @click="handleIgnore">稍后填写</view>
 			<view class="link-btn" v-if="!hasUserType" @click="handleIgnore">稍后填写</view>
-			<view class="btn" @click="messagebtn">继续完善</view>
+			<view class="btn" @click="messagebtn">保存</view>
 		</view>
 		</view>
 
 
 		<!-- 求职状态选择器 -->
 		<!-- 求职状态选择器 -->

+ 10 - 14
pages/index/index.vue

@@ -73,7 +73,7 @@
 									<view class="positions flex align-center">
 									<view class="positions flex align-center">
 										<image src="/static/images/svg/tie.svg" class="position-icon"></image>
 										<image src="/static/images/svg/tie.svg" class="position-icon"></image>
 										<view class="position-text">
 										<view class="position-text">
-											<text>{{ company.postPushRuleNames }}</text>
+											{{ company.postPushRuleNames }}
 										</view>
 										</view>
 									</view>
 									</view>
 								</view>
 								</view>
@@ -969,11 +969,6 @@ export default {
 				name: '全部',
 				name: '全部',
 			}]
 			}]
 		}
 		}
-		if (uni.getStorageSync('city')) {
-			this.city = uni.getStorageSync('city')
-		} else {
-			this.city = ''
-		}
 		if (this.city || true) {
 		if (this.city || true) {
 			if (this.userType == 1) {
 			if (this.userType == 1) {
 				if (this.current != this.typeList.length - 1) {
 				if (this.current != this.typeList.length - 1) {
@@ -1114,16 +1109,15 @@ export default {
 		// 
 		// 
 		async getLocalJobs(go = 'go', isBusiness = false) {
 		async getLocalJobs(go = 'go', isBusiness = false) {
 			// isBusiness:判断是否是招聘端,如果是则限制选择城市,以公司城市为准
 			// isBusiness:判断是否是招聘端,如果是则限制选择城市,以公司城市为准
-			let that = this;
 			// #ifdef APP
 			// #ifdef APP
 			const hasLocation = await this.$queue.checkPermission(
 			const hasLocation = await this.$queue.checkPermission(
 				'location',
 				'location',
 				'获取位置需要定位权限,用于推荐同城的求职岗位或牛人',
 				'获取位置需要定位权限,用于推荐同城的求职岗位或牛人',
 				this
 				this
 			);
 			);
-			if (!hasLocation) return that.goNav('/package/screen/city?city=' + that.city + '&county=' + that.county);
+			if (!hasLocation) return this.goNav('/package/screen/city?city=' + this.city + '&county=' + this.county);
 			// #endif
 			// #endif
-			that.getCity(go, isBusiness)
+			this.getCity(go, isBusiness)
 		},
 		},
 
 
 		getCity(go = '', isBusiness = false) {
 		getCity(go = '', isBusiness = false) {
@@ -1166,7 +1160,7 @@ export default {
 						return
 						return
 						// #endif
 						// #endif
 					} else {
 					} else {
-						that.city = uni.getStorageSync('city')
+						that.city = that.city ?? uni.getStorageSync('city')
 						if (go == 'go') {
 						if (go == 'go') {
 							that.goNav(`/package/screen/city?city=${that.city}&county=${that.county}&type=search&onlyShowOneCity=${ this.userType == 2 ? 'true' : '' }`)
 							that.goNav(`/package/screen/city?city=${that.city}&county=${that.county}&type=search&onlyShowOneCity=${ this.userType == 2 ? 'true' : '' }`)
 						}
 						}
@@ -1597,8 +1591,10 @@ export default {
 							ruleClassifyId: item.ruleClassifyId,
 							ruleClassifyId: item.ruleClassifyId,
 							city: item.city
 							city: item.city
 						}
 						}
+						
 						if (!this.currentPostionCity) {
 						if (!this.currentPostionCity) {
 							this.currentPostionCity = item.city
 							this.currentPostionCity = item.city
+							this.city = item.city
 						}
 						}
 						arr.push(obj)
 						arr.push(obj)
 
 
@@ -1686,8 +1682,10 @@ export default {
 			this.$Request.get('/app/Login/selectCity?lat=' + latitude + '&lng=' + longitude).then(res => {
 			this.$Request.get('/app/Login/selectCity?lat=' + latitude + '&lng=' + longitude).then(res => {
 				if (res.code == 0) {
 				if (res.code == 0) {
 					// console.log(res, '获取地址信息')
 					// console.log(res, '获取地址信息')
-					this.city = res.data.city ? res.data.city : '区域'
-					uni.setStorageSync('city', res.data.city)
+					if (!this.city) {
+						this.city = res.data.city ? res.data.city : '区域'
+						uni.setStorageSync('city', res.data.city)						
+					}
 					if (go == 'go')
 					if (go == 'go')
 						this.goNav('/package/screen/city?city=' + this.city + '&county=' + this.county + '&type=' + 'search')
 						this.goNav('/package/screen/city?city=' + this.city + '&county=' + this.county + '&type=' + 'search')
 					if (this.userType == 1) {
 					if (this.userType == 1) {
@@ -2937,8 +2935,6 @@ page {
 					overflow: hidden;
 					overflow: hidden;
 					text-overflow: ellipsis;
 					text-overflow: ellipsis;
 					white-space: nowrap;
 					white-space: nowrap;
-				}
-				text {
 					font-size: 24rpx;
 					font-size: 24rpx;
 					color: rgba(1, 107, 246, 1);
 					color: rgba(1, 107, 246, 1);
 				}
 				}

+ 29 - 3
pages/msg/im.vue

@@ -743,6 +743,14 @@
 			</view>
 			</view>
 			<view class="avatorm flex justify-center">
 			<view class="avatorm flex justify-center">
 				<view class="avatorm-box">
 				<view class="avatorm-box">
+					<view class="avatorm-box-item flex">
+						<view class="avatorm-box-item-t">
+							面试类型:
+						</view>
+						<view class="avatorm-box-item-r">
+							{{ records.type == 1 ? '线上面试' : '线下面试' }}
+						</view>
+					</view>
 					<view class="avatorm-box-item flex">
 					<view class="avatorm-box-item flex">
 						<view class="avatorm-box-item-t">
 						<view class="avatorm-box-item-t">
 							面试岗位:
 							面试岗位:
@@ -759,15 +767,31 @@
 							{{records.interviewDateTime&&records.interviewDateTime.substring(0, 10)||''}} {{records.detailTime}}
 							{{records.interviewDateTime&&records.interviewDateTime.substring(0, 10)||''}} {{records.detailTime}}
 						</view>
 						</view>
 					</view>
 					</view>
-					<view class="avatorm-box-item flex" @click="goMapDap(records)">
+					<view class="avatorm-box-item flex" @click="goMapDap(records)" v-if="records.type != 1">
 						<view class="avatorm-box-item-t">
 						<view class="avatorm-box-item-t">
 							面试地点:
 							面试地点:
 						</view>
 						</view>
 						<view class="avatorm-box-item-r">
 						<view class="avatorm-box-item-r">
-							{{records.detailedAddress}}
+							{{records.address}}
 							<u-icon name="map-fill" color="#016BF6" size="28"></u-icon>
 							<u-icon name="map-fill" color="#016BF6" size="28"></u-icon>
 						</view>
 						</view>
 					</view>
 					</view>
+					<view class="avatorm-box-item flex" v-if="records.type == 1">
+						<view class="avatorm-box-item-t">
+							面试方式:
+						</view>
+						<view class="avatorm-box-item-r">
+							{{onlineInterviewType[records.onlineType] ? onlineInterviewType[records.onlineType].name : '暂无'}}
+						</view>
+					</view>
+					<view class="avatorm-box-item flex" v-if="records.type == 1">
+						<view class="avatorm-box-item-t">
+							面试地址:
+						</view>
+						<view class="avatorm-box-item-r">
+							{{records.onlineMsg}}
+						</view>
+					</view>
 					<view class="avatorm-box-item flex">
 					<view class="avatorm-box-item flex">
 						<view class="avatorm-box-item-t">
 						<view class="avatorm-box-item-t">
 							面试备注:
 							面试备注:
@@ -873,6 +897,7 @@
 	import positionCard from '@/components/resume/position-card.vue'
 	import positionCard from '@/components/resume/position-card.vue'
 	import resumeCard from '@/components/resume/resume-card.vue'
 	import resumeCard from '@/components/resume/resume-card.vue'
 	import { logoutJP } from '@/utils/login.js';
 	import { logoutJP } from '@/utils/login.js';
+	import { onlineInterviewType } from "@/constants/common";
 	export default {
 	export default {
 		components: {
 		components: {
 			attachment,
 			attachment,
@@ -1036,7 +1061,8 @@
 				attachmentContent:[],
 				attachmentContent:[],
 				showMask: false, // 更多操作按钮弹窗
 				showMask: false, // 更多操作按钮弹窗
 				updating: false,
 				updating: false,
-				isTop: false
+				isTop: false,
+				onlineInterviewType: onlineInterviewType
 			};
 			};
 		},
 		},
 		onUnload() {
 		onUnload() {

+ 407 - 96
pages/my/attachment.vue

@@ -33,15 +33,38 @@
 			</scroll-view>
 			</scroll-view>
 		</view>
 		</view>
 		<view class="footer-btn">
 		<view class="footer-btn">
-			<fileSelector title="上传简历" allowType=".doc,.docx,.xls,.xlsx,.pdf" @fileSelected="uploadResumes"
+			<view class="white-btn" @click="handlUploadFile">附件简历一键识别</view>
+			<fileSelector title="简历上传" allowType=".doc,.docx,.xls,.xlsx,.pdf" @fileSelected="uploadResumes"
 				@filesChanged="onFilesChanged" />
 				@filesChanged="onFilesChanged" />
 		</view>
 		</view>
+		<!-- 简历解析加载 -->
+		<view class="load-container" v-if="showLoadCard">
+			<image src="@/static/loading.gif" class="loading-image" mode="aspectFit"></image>
+		</view>
 		<!-- 权限说明弹窗 -->
 		<!-- 权限说明弹窗 -->
 		<u-popup mode="top" ref="permission">
 		<u-popup mode="top" ref="permission">
 			<view class="popup-content">
 			<view class="popup-content">
 				<view class="popup-text-permission">选择/拍摄照片需要相机/相册权限,用于上传用户头像</view>
 				<view class="popup-text-permission">选择/拍摄照片需要相机/相册权限,用于上传用户头像</view>
 			</view>
 			</view>
 		</u-popup>
 		</u-popup>
+		<!-- 同步解析简历数据 -->
+		<u-popup v-model="showResumesAnalysis" mode="bottom" border-radius="14" :mask-close-able="false">
+			<view class="resume-popup">
+				<view class="close-button flex align-center justify-center" @click="showResumesAnalysis = false">
+					<u-icon name="close" color="#fff" size="22" />
+				</view>
+				<view class="title">从附件简历中解析出<text>{{ validInfoCount }}段</text>有效信息</view>
+				<view class="tip">无需手动填写,可直接添加到在线简历中</view>
+				<view class="info-list">
+					<view class="info-item flex align-center" v-for="(item, index) in analysisList" :key="index">
+						<view class="label">{{ item.title }}</view>
+						<view class="border"></view>
+						<view class="content">{{ item.value }}</view>
+					</view>
+				</view>
+				<view class="button" @click="handleSync">立即同步</view>
+			</view>
+		</u-popup>
 	</view>
 	</view>
 </template>
 </template>
 
 
@@ -51,6 +74,10 @@ import navBar from "@/components/nav-bar/index.vue";
 // 引入组件
 // 引入组件
 import fileSelector from '@/uni_modules/zhouquan-fileSelector/components/zhouquan-fileSelector/file-selector.vue';
 import fileSelector from '@/uni_modules/zhouquan-fileSelector/components/zhouquan-fileSelector/file-selector.vue';
 import empty from '../../components/empty.vue'
 import empty from '../../components/empty.vue'
+// #ifdef APP-PLUS
+import { chooseFileFromModule } from '@/uni_modules/sr-file-choose'
+// #endif
+let AIResumeData = {}
 export default {
 export default {
 	components: {
 	components: {
 		navBar,
 		navBar,
@@ -81,7 +108,29 @@ export default {
 			zhiFuBaoName: '',
 			zhiFuBaoName: '',
 			sex: 1,
 			sex: 1,
 			age: 0,
 			age: 0,
-			content: []
+			content: [],
+			showLoadCard: false,
+			showResumesAnalysis: false,
+			validInfoCount: 0, // 有效信息数量
+			analysisList: [
+				{
+					title: '基本信息',
+					value: '',
+				},
+				{
+					title: '工作经历',
+					value: '',
+				},
+				{
+					title: '教育经历',
+					value: '',
+				},
+				{
+					title: '个人优势',
+					value: '',
+				},
+			],
+			loading: false
 		};
 		};
 	},
 	},
 	computed: {
 	computed: {
@@ -130,7 +179,7 @@ export default {
 			let that = this;
 			let that = this;
 			let token = uni.getStorageSync('token');
 			let token = uni.getStorageSync('token');
 			uni.uploadFile({
 			uni.uploadFile({
-				url: that.config("APIHOST1") +
+				url: this.$Request.config("APIHOST1") +
 					'/alioss/upload', //真实的接口地址
 					'/alioss/upload', //真实的接口地址
 				filePath: e.detail.avatarUrl,
 				filePath: e.detail.avatarUrl,
 				header: {
 				header: {
@@ -150,95 +199,95 @@ export default {
 				url: '../jifen/myaddress'
 				url: '../jifen/myaddress'
 			});
 			});
 		},
 		},
-		uploadImg() {
-			let token = uni.getStorageSync('token')
-
-			if (!token) {
-				this.goLoginInfo();
-				return;
-			}
-			let that = this;
-			var url = null;
-			uni.showActionSheet({
-				// itemList按钮的文字接受的是数组
-				itemList: ["查看头像", "从相册选择图片"],
-				async success(e) {
-					var index = e.tapIndex
-					if (index === 0) {
-						// 用户点击了预览当前图片
-						// 可以自己实现当前头像链接的读取
-						let url = that.avatar;
-						let arr = []
-						arr.push(url)
-						uni.previewImage({
-							// 预览功能图片也必须是数组的
-							urls: arr
-						})
-					} else if (index === 1) {
-						// 1. 检查权限状态
-						const hasPermission = await this.$queue.checkPermission(
-							'camera',
-							'选择/拍摄照片需要相机/相册权限,用于上传用户头像',
-							this
-						);
-
-						// 2. 如果未授权或者用户拒绝,显示提示
-						if (!hasPermission) {
-							return;
-						}
-						uni.chooseImage({
-							count: 1, //默认9
-							sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
-							sourceType: ['album'], //从相册选择
-							success: function (res) {
-								uni.showLoading({
-									title: '上传中...'
-								});
-								let token = uni.getStorageSync('token');
-								let userId = uni.getStorageSync('userId');
-								uni.uploadFile({
-									url: that.config("APIHOST1") +
-										'/alioss/upload', //真实的接口地址
-
-									filePath: res.tempFilePaths[0],
-									header: {
-										token: token
-									},
-									name: 'file',
-									success: uploadFileRes => {
-										url = JSON.parse(uploadFileRes.data);
-										that.avatar = url.data
-										uni.hideLoading();
-									}
-								});
-							}
-						});
-					}
-				}
-			})
-		},
-		config: function (name) {
-			var info = null;
-			if (name) {
-				var name2 = name.split("."); //字符分割
-				if (name2.length > 1) {
-					info = configdata[name2[0]][name2[1]] || null;
-				} else {
-					info = configdata[name] || null;
-				}
-				if (info == null) {
-					let web_config = cache.get("web_config");
-					if (web_config) {
-						if (name2.length > 1) {
-							info = web_config[name2[0]][name2[1]] || null;
-						} else {
-							info = web_config[name] || null;
-						}
-					}
-				}
-			}
-			return info;
-		},
+		// uploadImg() {
+		// 	let token = uni.getStorageSync('token')
+
+		// 	if (!token) {
+		// 		this.goLoginInfo();
+		// 		return;
+		// 	}
+		// 	let that = this;
+		// 	var url = null;
+		// 	uni.showActionSheet({
+		// 		// itemList按钮的文字接受的是数组
+		// 		itemList: ["查看头像", "从相册选择图片"],
+		// 		async success(e) {
+		// 			var index = e.tapIndex
+		// 			if (index === 0) {
+		// 				// 用户点击了预览当前图片
+		// 				// 可以自己实现当前头像链接的读取
+		// 				let url = that.avatar;
+		// 				let arr = []
+		// 				arr.push(url)
+		// 				uni.previewImage({
+		// 					// 预览功能图片也必须是数组的
+		// 					urls: arr
+		// 				})
+		// 			} else if (index === 1) {
+		// 				// 1. 检查权限状态
+		// 				const hasPermission = await this.$queue.checkPermission(
+		// 					'camera',
+		// 					'选择/拍摄照片需要相机/相册权限,用于上传用户头像',
+		// 					this
+		// 				);
+
+		// 				// 2. 如果未授权或者用户拒绝,显示提示
+		// 				if (!hasPermission) {
+		// 					return;
+		// 				}
+		// 				uni.chooseImage({
+		// 					count: 1, //默认9
+		// 					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+		// 					sourceType: ['album'], //从相册选择
+		// 					success: function (res) {
+		// 						uni.showLoading({
+		// 							title: '上传中...'
+		// 						});
+		// 						let token = uni.getStorageSync('token');
+		// 						let userId = uni.getStorageSync('userId');
+		// 						uni.uploadFile({
+		// 							url: this.$Request.config("APIHOST1") +
+		// 								'/alioss/upload', //真实的接口地址
+
+		// 							filePath: res.tempFilePaths[0],
+		// 							header: {
+		// 								token: token
+		// 							},
+		// 							name: 'file',
+		// 							success: uploadFileRes => {
+		// 								url = JSON.parse(uploadFileRes.data);
+		// 								that.avatar = url.data
+		// 								uni.hideLoading();
+		// 							}
+		// 						});
+		// 					}
+		// 				});
+		// 			}
+		// 		}
+		// 	})
+		// },
+		// config: function (name) {
+		// 	var info = null;
+		// 	if (name) {
+		// 		var name2 = name.split("."); //字符分割
+		// 		if (name2.length > 1) {
+		// 			info = configdata[name2[0]][name2[1]] || null;
+		// 		} else {
+		// 			info = configdata[name] || null;
+		// 		}
+		// 		if (info == null) {
+		// 			let web_config = cache.get("web_config");
+		// 			if (web_config) {
+		// 				if (name2.length > 1) {
+		// 					info = web_config[name2[0]][name2[1]] || null;
+		// 				} else {
+		// 					info = web_config[name] || null;
+		// 				}
+		// 			}
+		// 		}
+		// 	}
+		// 	return info;
+		// },
 		getUserInfo() {
 		getUserInfo() {
 			this.$Request.get("/app/resumes/getAttachment").then(res => {
 			this.$Request.get("/app/resumes/getAttachment").then(res => {
 				if (res.code == 0) {
 				if (res.code == 0) {
@@ -362,6 +411,173 @@ export default {
 			uni.navigateTo({
 			uni.navigateTo({
 				url: '/pages/index/webView?url=' + it.attachmentAddress + '&title=' + it.attachmentName
 				url: '/pages/index/webView?url=' + it.attachmentAddress + '&title=' + it.attachmentName
 			});
 			});
+		},
+		// 附件一键识别
+		handlUploadFile() {
+			if (this.content.length >= 3) {
+				this.$queue.showToast('最多保存三张附件简历,请删除后再试')
+				return
+			}
+			
+			// #ifdef APP-PLUS
+			chooseFileFromModule({
+				complete: res => {
+					let path = res.path
+					let name = res.name
+					let fileType = ''
+					// 如果没有name,默认为:截取最后一个/之后的内容
+					if (!name) {
+						let lastIndex = path.lastIndexOf('/');
+						if (lastIndex !== -1) {
+							name = path.substring(lastIndex + 1);
+						} else {
+							name = Math.random().toString(36).substr(2) + Date.now();
+						}
+					}
+					// 使用 lastIndexOf 方法找到最后一个 . 的位置
+					let lastDotIndex = name.lastIndexOf('.');
+					if (lastDotIndex !== -1) {
+						fileType = name.substring(lastDotIndex + 1);
+					} else {
+						console.log('文件路径中没有 .');
+					}
+					let file = {
+						size: res.size,
+						path,
+						fileType,
+						name
+					}
+					this.uploadFile(file)
+				}
+			})
+			// #endif
+			// #ifdef H5
+			uni.chooseFile({
+				count: 1,
+				success: res => {
+					this.uploadFile({
+						path: res.tempFilePaths[0],
+						name: 'file'
+					})
+				}
+			})
+			// #endif
+		},
+		// 上传文件
+		uploadFile(file) {
+			this.$queue.uploadFiles({
+				url: '/app/resumes/aiResumesUpload',
+				path: file.path,
+				name: 'file'
+			}, (res) => {
+				if (res && res.code === 0) {
+					const id = res.data?.id
+					const resumesAttachmentId = res.data?.resumesAttachmentId || ''
+					if (id) {
+						this.getAiResumesAnalysis(id, resumesAttachmentId)
+					}
+					
+					// 上传成功,获取简历列表数据
+					this.getUserInfo()
+				} else {
+					this.$queue.showToast(res ? res.msg : '文件上传失败')
+				}
+			})
+		},
+		// 获取简历解析数据
+		getAiResumesAnalysis(fileId, resumesAttachmentId) {
+			this.showLoadCard = true
+			uni.request({
+				url: this.$Request.config('APIHOST') + '/app/resumes/aiResumesAnalysis',
+				header: {
+					'content-type': 'application/x-www-form-urlencoded', // 模拟 form-data
+					token: uni.getStorageSync('token'),
+				},
+				method: 'post',
+				data: {
+					workflowId: '7594327567932309547',
+					fileId,
+					resumesAttachmentId
+				},
+				timeout: 180000,
+				success: (res) => {
+					this.stopLoadStatus()
+					
+					if (res.data?.code == 0) {
+						const data = res.data.data.data
+						this.setAiResumesAnalysis(data.output)
+					}
+				},
+				fail: (err) => {
+					this.$queue.showToast('解析失败,请稍后重试')
+					this.stopLoadStatus()
+				}
+			})
+		},
+		stopLoadStatus() {
+			this.showLoadCard = false
+		},
+		// 获取简历解析数据
+		setAiResumesAnalysis(data) {
+			AIResumeData = data || {}
+			if (data) {
+				this.showResumesAnalysis = true
+				// 基本信息
+				if (data.name || data.age || data.email) {
+					this.validInfoCount++
+					let dataArray = []
+					if (data.name) {
+						dataArray.push(data.name)
+					}
+					if (data.age) {
+						dataArray.push(data.age)
+					}
+					if (data.email) {
+						dataArray.push(data.email)
+					}
+					this.analysisList[0].value = dataArray.join('、')
+				}
+				
+				// 工作经历
+				if (data.workExperience?.length) {
+					this.validInfoCount++
+					let dataArray = data.workExperience.map(item => item.company)
+					this.analysisList[1].value = dataArray.join('、')
+				}
+				
+				// 教育经历
+				if (data.education?.length) {
+					this.validInfoCount++
+					let dataArray = data.education.map(item => item.school)
+					this.analysisList[2].value = dataArray.join('、')
+				}
+				
+				// 个人优势
+				if (data.selfEvaluation) {
+					this.validInfoCount++
+					this.analysisList[3].value = data.selfEvaluation
+				}
+			}
+		},
+		
+		// 同步简历数据
+		handleSync() {
+			if (this.loading) return
+			
+			uni.showLoading({ title: '同步中' })
+			this.loading = true
+			this.$Request
+				.postJson('/app/resumes/syncResumess', AIResumeData)
+				.then(res => {
+					if (res.code === 0) {
+						this.showResumesAnalysis = false
+						this.$queue.showToast('同步成功')
+					}
+				})
+				.finally(() => {
+					this.loading = false
+					uni.hideLoading()
+				})
 		}
 		}
 	},
 	},
 	// userphone(){
 	// userphone(){
@@ -616,10 +832,6 @@ button {
 	border: none;
 	border: none;
 }
 }
 
 
-.footer-btn {
-	margin-top: 40rpx;
-}
-
 .footer-btn .usermain-btn {
 .footer-btn .usermain-btn {
 	color: rgba(255, 255, 255, 1);
 	color: rgba(255, 255, 255, 1);
 	background: rgba(1, 107, 246, 1);
 	background: rgba(1, 107, 246, 1);
@@ -674,4 +886,103 @@ button {
 	background: #f5f7fa !important;
 	background: #f5f7fa !important;
 	transform: scale(0.99);
 	transform: scale(0.99);
 }
 }
+
+.white-btn {
+	width: 600rpx;
+	font-size: 32rpx;
+	text-align: center;
+	color: #016bf6;
+	background-color: #fff;
+	border-radius: 88rpx;
+	margin: 32rpx auto 0;
+}
+
+.load-container {
+	position: fixed;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	background: rgba(0, 0, 0, 1);
+	.loading-image {
+		width: 100%;
+		height: 100%;
+	}
+}
+// 解析简历popup
+.resume-popup {
+	position: relative;
+	padding: 70rpx 40rpx 40rpx;
+	.title {
+		font-size: 40rpx;
+		font-weight: 700;
+		line-height: 52rpx;
+		color: #333;
+		margin-bottom: 12rpx;
+		text {
+			color: #016bf6;
+		}
+	}
+	.tip {
+		font-size: 28rpx;
+		line-height: 36rpx;
+		color: #999999;
+	}
+	.info-list {
+		.info-item {
+			box-sizing: border-box;
+			border: 1px solid rgba(242, 242, 242, 1);
+			border-radius: 6px;
+			background: rgba(250, 250, 250, 1);
+			padding: 26rpx 24rpx;
+			margin-top: 40rpx;
+			.label {
+				font-size: 28rpx;
+				font-weight: 500;
+				line-height: 1;
+				color: rgba(51, 51, 51, 1);
+			}
+			.border {
+				width: 1px;
+				height: 20rpx;
+				margin: 0 20rpx;
+				background: rgba(234, 234, 234, 1);
+			}
+			.content {
+				flex: 1;
+				width: 0;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+				color: rgba(153, 153, 153, 1);
+				font-size: 28rpx;
+				line-height: 1;
+			}
+		}
+	}
+	.button {
+		width: 600rpx;
+		height: 88rpx;
+		border-radius: 88rpx;
+		background: linear-gradient(90.00deg, rgba(13, 39, 247, 1),rgba(19, 193, 234, 1));
+		font-size: 32rpx;
+		font-weight: 500;
+		line-height: 88rpx;
+		text-align: center;
+		color: #fff;
+		margin: 60rpx auto 0;
+	}
+	.close-button {
+		position: absolute;
+		top: 30rpx;
+		right: 40rpx;
+		width: 40rpx;
+		height: 40rpx;
+		border-radius: 40rpx;
+		background: rgba(230, 230, 230, 1);
+	}
+}
 </style>
 </style>

+ 3 - 3
pages/my/index.vue

@@ -66,19 +66,19 @@
 									<view class="info-box-num-td-num">
 									<view class="info-box-num-td-num">
 										{{ deliveryCount }}
 										{{ deliveryCount }}
 									</view>
 									</view>
-									<view class="info-box-num-td-name"> 已投简历 </view>
+									<view class="info-box-num-td-name"> 已投 </view>
 								</view>
 								</view>
 								<view class="info-box-num-td" @click="gojiLuList('/package/records/records', '面试记录')">
 								<view class="info-box-num-td" @click="gojiLuList('/package/records/records', '面试记录')">
 									<view class="info-box-num-td-num">
 									<view class="info-box-num-td-num">
 										{{ interviewCount }}
 										{{ interviewCount }}
 									</view>
 									</view>
-									<view class="info-box-num-td-name"> 面试 </view>
+									<view class="info-box-num-td-name"> 面试 </view>
 								</view>
 								</view>
 								<view class="info-box-num-td" @click="gojiLuList('/package/records/records', '我的收藏')">
 								<view class="info-box-num-td" @click="gojiLuList('/package/records/records', '我的收藏')">
 									<view class="info-box-num-td-num">
 									<view class="info-box-num-td-num">
 										{{ collectionCount }}
 										{{ collectionCount }}
 									</view>
 									</view>
-									<view class="info-box-num-td-name"> 收藏 </view>
+									<view class="info-box-num-td-name"> 收藏职位 </view>
 								</view>
 								</view>
 							</view>
 							</view>
 						</view>
 						</view>

+ 11 - 5
pages/my/onlineResume.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
 	<view class="online-resume" :class="{ pb : scene == 1 }">
 	<view class="online-resume" :class="{ pb : scene == 1 }">
-		<navBar title="完善在线简历" />
+		<navBar title="在线简历" />
 		<view class="page-content">
 		<view class="page-content">
 			<!-- 用户信息区域 -->
 			<!-- 用户信息区域 -->
 			<view class="user-profile">
 			<view class="user-profile">
@@ -154,9 +154,12 @@
 					<view class="experience-list">
 					<view class="experience-list">
 						<template v-if="showExperienceData.length">
 						<template v-if="showExperienceData.length">
 							<view class="experience-item" v-for="item in showExperienceData">
 							<view class="experience-item" v-for="item in showExperienceData">
-								<view class="company-title">
-									<text class="company-name">{{ item.companyName }}</text>
-									<text class="company-type"> • {{ setCompanyType(item.type) }}</text>
+								<view class="company-title flex justify-between">
+									<view>
+										<text class="company-name">{{ item.companyName }}</text>
+										<text class="company-type"> • {{ setCompanyType(item.type) }}</text>										
+									</view>
+									<text style="width: 60px; text-align: right;">编辑</text>
 								</view>
 								</view>
 								
 								
 								<view class="experience-content">
 								<view class="experience-content">
@@ -225,7 +228,10 @@
 							<view class="education-item" @click.stop="goToEducationExperience(item.eduId)"
 							<view class="education-item" @click.stop="goToEducationExperience(item.eduId)"
 								v-for="(item, index) in detail.eduList">
 								v-for="(item, index) in detail.eduList">
 								<view class="education-content">
 								<view class="education-content">
-									<view class="school-name">{{ item.school }}</view>
+									<view class="school-name flex justify-between">
+										<text>{{ item.school }}</text>
+										<text style="width: 60px; text-align: right;">编辑</text>
+									</view>
 									<view class="degree-info">{{ item.degree }} • {{ item.profession }} •
 									<view class="degree-info">{{ item.degree }} • {{ item.profession }} •
 										{{ new Date(item.startTime).getFullYear() }}-{{ new Date(item.endTime).getFullYear() }}
 										{{ new Date(item.startTime).getFullYear() }}-{{ new Date(item.endTime).getFullYear() }}
 									</view>
 									</view>

+ 11 - 1
pages/my/workExperience.vue

@@ -141,7 +141,10 @@
 
 
 				<!-- 工作内容 -->
 				<!-- 工作内容 -->
 				<view class="form-item">
 				<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">
 					<view class="form-input">
 						<textarea v-model="resume.workContent" placeholder="请输入工作内容" auto-height
 						<textarea v-model="resume.workContent" placeholder="请输入工作内容" auto-height
 							@input="handleTextareaInput($event, 'workContent', index)" class="form-textarea"></textarea>
 							@input="handleTextareaInput($event, 'workContent', index)" class="form-textarea"></textarea>
@@ -729,6 +732,13 @@ export default {
 					this.$queue.showToast('岗位技能不能为空')
 					this.$queue.showToast('岗位技能不能为空')
 					return false;
 					return false;
 				}
 				}
+				if (!item.workContent) {
+					this.$queue.showToast('请输入工作内容')
+					return false;
+				} else if (item.workContent.length < 80) {
+					this.$queue.showToast('工作内容至少输入80个字')
+					return false;
+				}
 			}
 			}
 			let postData = this.formData.resumes.map(({
 			let postData = this.formData.resumes.map(({
 				employmentTime,
 				employmentTime,

+ 6 - 25
pages/public/improvePrompt.vue

@@ -31,10 +31,7 @@
 		</view>
 		</view>
 		
 		
 		<view class="load-container" v-if="showLoadCard">
 		<view class="load-container" v-if="showLoadCard">
-			<view class="video-container">
-				<view class="title">简历解析中</view>
-				<video src="https://bossweb.edccc.cn/video_260307_151616.mp4" :muted="true" :autoplay="true" :controls="false" :loop="true" object-fit="fill"></video>
-			</view>
+			<image src="@/static/loading.gif" class="loading-image" mode="aspectFit"></image>
 		</view>
 		</view>
 		
 		
 		<!-- <load-card :progress="progress" v-if="showLoadCard"></load-card> -->
 		<!-- <load-card :progress="progress" v-if="showLoadCard"></load-card> -->
@@ -137,7 +134,7 @@
 				}, (res) => {
 				}, (res) => {
 					if (res && res.code === 0) {
 					if (res && res.code === 0) {
 						const id = res.data?.id
 						const id = res.data?.id
-						const resumesAttachmentId = res.data?.resumesAttachmentId || null
+						const resumesAttachmentId = res.data?.resumesAttachmentId || ''
 						if (id) {
 						if (id) {
 							this.getAiResumesAnalysis(id, resumesAttachmentId)
 							this.getAiResumesAnalysis(id, resumesAttachmentId)
 						}
 						}
@@ -273,26 +270,10 @@
 		display: flex;
 		display: flex;
 		align-items: center;
 		align-items: center;
 		justify-content: center;
 		justify-content: center;
-		background: rgba(0, 0, 0, 0.5);
-		.video-container {
-			width: 600rpx;
-			// height: 600rpx;
-			background: #fff;
-			border-radius: 20rpx;
-			padding: 40rpx;
-			.title {
-				font-size: 36rpx;
-				font-weight: bold;
-				text-align: center;
-				line-height: 1;
-				padding-bottom: 40rpx;
-			}
-		}
-		video {
-			display: block;
-			width: 520rpx;
-			height: 320rpx;
-			margin: 0 auto;
+		background: rgba(0, 0, 0, 1);
+		.loading-image {
+			width: 100%;
+			height: 100%;
 		}
 		}
 	}
 	}
 </style>
 </style>

BIN
static/loading.gif