htc 1 周之前
父節點
當前提交
179e4a9faf

+ 2 - 2
components/pages/nonprofitActivety/index.vue

@@ -112,7 +112,7 @@
 				.tip{
 					margin-top: 25rpx;
 					&-left{
-						width: 150rpx;
+						width: 160rpx;
 						image{
 							width: 24rpx;
 							height: 24rpx;
@@ -128,7 +128,7 @@
 						}
 					}
 					&-right{
-						width: calc(100% - 150rpx);
+						width: calc(100% - 160rpx);
 						font-family: PingFangSC, PingFang SC;
 						font-weight: 400;
 						font-size: 24rpx;

+ 3 - 3
components/pages/nonprofitItem/index.vue

@@ -2,7 +2,7 @@
 	<view class="ni" v-if="item" @click="toDetail(item)">
 		<view class="ni-top adfacjb">
 			<view class="ni-top-left adfac">
-				<image class="avatar" src="https://oss.familydaf.cn/sxsnfile/20251218/2b822605d8d04cffb53b8521478ec2f9.png"></image>
+				<image class="avatar" src="https://oss.familydaf.cn/sxsnfile/20251218/3821654e080945998d464f3c3aa64122.png"></image>
 				<view class="name">{{item?.memberName||''}}</view>
 				<image class="sex" v-if="item?.gender==1" src="https://oss.familydaf.cn/sxsnfile/20251218/473d5677fbdb4106acdb9a163377d27f.png"></image>
 				<image class="sex" v-else-if="item?.gender==0" src="https://oss.familydaf.cn/sxsnfile/20251218/02bc40a1c47b40f1a36b55cd0553211c.png"></image>
@@ -158,7 +158,7 @@
 					align-items: flex-start;
 					margin-top: 25rpx;
 					&-left{
-						width: 150rpx;
+						width: 160rpx;
 						image{
 							width: 24rpx;
 							height: 24rpx;
@@ -174,7 +174,7 @@
 						}
 					}
 					&-right{
-						width: calc(100% - 150rpx);
+						width: calc(100% - 160rpx);
 						font-family: PingFangSC, PingFang SC;
 						font-weight: 400;
 						font-size: 24rpx;

+ 76 - 0
pagesHome/activityApply.vue

@@ -137,6 +137,22 @@
 	
 	const handleApply = async () => {
 		if(selectMemberList.value.length===0) return proxy.$showToast('请至少添加一位报名人员')
+		
+		//判断人数和年龄符不符合限制
+		if(activity.value.recruitmentMax!==0){
+			const nextUserCount = activity.value.recruitmentMax-activity.value.recruitmentNow;
+			if(selectMemberList.value.length>nextUserCount){
+				return proxy.$showModal(`很抱歉,当前活动最大招募人数为${activity.value.recruitmentMax}人,剩余可招募人数为${nextUserCount}人,您的报名人数共${selectMemberList.value.length}人,超出人数限制,不可报名。`)
+			}
+		}
+		if(activity.value.userAgeMax!==0){
+			const limitUser = selectMemberList.value.filter(m=>getAgeFromIdCard(m.idCard)>activity.value.userAgeMax||getAgeFromIdCard(m.idCard)<activity.value.userAgeMin)
+			if(limitUser.length){
+				const limitUserText = limitUser.length>0&&limitUser.map(u=>`${u.name}[${getAgeFromIdCard(u.idCard)}岁]`)
+				return proxy.$showModal(`很抱歉,当前活动限制招募年龄为${activity.value.userAgeMin}至${activity.value.userAgeMax}岁,您的报名人员中:${limitUserText},超出了年龄限制,不可报名。`)
+			}
+		}
+		
 		if(!submitDto.value.contact) return proxy.$showToast('请输入联系人姓名')
 		if(!proxy.$reg.mobile(submitDto.value.contactPhone)) return proxy.$showToast('请输入正确的联系电话')
 		submitDto.value.memberIds = selectMemberList.value.map(m=>m.id);
@@ -158,6 +174,66 @@
 		})
 	}
 	
+	const getAgeFromIdCard = (idCardNumber) => {
+		  // 1. 基本校验:检查输入是否为字符串且长度是否为18位
+		  if (typeof idCardNumber !== 'string' || idCardNumber.length !== 18) {
+			console.error("无效的身份证号码格式,长度必须是18位字符串。");
+			return null;
+		  }
+
+		  // 2. 提取出生日期部分 (YYYYMMDD)
+		  // 中国大陆18位身份证号码的出生日期信息位于第7位到第14位(索引6到13)
+		  const birthDateStr = idCardNumber.substring(6, 14); // 例如 "19900101"
+
+		  // 3. 解析年、月、日
+		  const year = parseInt(birthDateStr.substring(0, 4), 10);
+		  const month = parseInt(birthDateStr.substring(4, 6), 10);
+		  const day = parseInt(birthDateStr.substring(6, 8), 10);
+
+		  // 4. 校验日期有效性
+		  // 简单校验年份、月份、日期范围
+		  if (isNaN(year) || isNaN(month) || isNaN(day) ||
+			  year < 1900 || year > new Date().getFullYear() || // 假设最小年份1900,最大为当前年
+			  month < 1 || month > 12 ||
+			  day < 1 || day > 31) {
+			console.error("身份证号码中包含无效的出生日期信息。", idCardNumber);
+			return null;
+		  }
+
+		  // 更严谨的日期校验:使用Date对象进行验证
+		  // 注意:Date对象的月份是0-11,所以需要 month - 1
+		  const birthDate = new Date(year, month - 1, day);
+		  // 检查解析后的日期是否与输入匹配,以排除像 "20000230" 这样的无效日期(会自动转换为 2000-03-01)
+		  if (birthDate.getFullYear() !== year ||
+			  birthDate.getMonth() !== month - 1 ||
+			  birthDate.getDate() !== day) {
+			console.error("身份证号码中的出生日期不是一个有效的日历日期。", idCardNumber);
+			return null;
+		  }
+
+		  // 5. 获取当前日期
+		  const today = new Date();
+		  const currentYear = today.getFullYear();
+		  const currentMonth = today.getMonth() + 1; // getMonth() 返回 0-11,所以加1
+		  const currentDay = today.getDate();
+
+		  // 6. 计算年龄
+		  let age = currentYear - year;
+
+		  // 如果当前月份小于出生月份,或者当前月份等于出生月份但当前日期小于出生日期,则年龄减1
+		  if (currentMonth < month || (currentMonth === month && currentDay < day)) {
+			age--;
+		  }
+		  
+		  // 确保年龄不为负数(如果身份证日期是未来日期,虽然前面有校验,但以防万一)
+		  if (age < 0) {
+			  console.warn("身份证号码中的出生日期晚于当前日期,返回年龄为0。", idCardNumber);
+			  return 0; // 或者 null,取决于业务需求
+		  }
+
+		  return age;
+		}
+	
 	const getUserLoveTicket = () => {
 		let userId = JSON.parse(uni.getStorageSync('userInfo'))?.id;
 		proxy.$api.get(`/core/activity/signup/userAsset/${userId}/${activity.value?.id}`).then(({data:res})=>{

+ 4 - 0
pagesHome/activityDetail.vue

@@ -134,6 +134,7 @@
 				
 				<view class="right end" v-else-if="activityInfo?.activeState==0">活动未开始</view>
 				<view class="right end" v-else-if="activityInfo?.activeState==1&&activityInfo?.signupState==2">活动已签到</view>
+				<view class="right end" v-else-if="activityInfo?.activeState==2&&activityInfo?.signupState==2">活动已签到</view>
 				<view class="right end" v-else-if="activityInfo?.activeState==2&&activityInfo?.signupState==0">活动进行中不可报名</view>
 				<view class="right end" v-else-if="activityInfo?.activeState==3">活动已结束</view>
 				<view class="right end" v-else-if="activityInfo?.activeState==4">已报满暂无活动名额</view>
@@ -296,6 +297,9 @@
 	
 	//立即报名
 	const handleApply = async () => {
+		let level = JSON.parse(uni.getStorageSync('userInfo'))?.userLevel;
+		if(level<activityInfo.value.userLevel) return proxy.$showModal(`很抱歉,当前活动限制报名等级为${activityInfo.value.userLevel}级,您当前等级为${level}级,不满足报名条件。`)
+		
 		let { loveValue, couponIds } = await getUserLoveTicket();
 		let url = `/pagesHome/activityApply?activity=${encodeURIComponent(JSON.stringify(activityInfo.value))}`;
 		

+ 5 - 2
pagesNonprofit/nonprofitDetail.vue

@@ -190,8 +190,11 @@
 			uni.scanCode({
 				success: (res) => {
 					if(res.errMsg=='scanCode:ok'){
-						let { id } = JSON.parse(res.result)
-						console.log(id,'id');
+						let r = res.result.replace(/^\uFEFF/, '');
+						let d = JSON.parse(r);
+						if(!d.hasOwnProperty('id')||!d) return proxy.$showToast('请扫描正确的活动签到码');
+						
+						let { id } = d;
 						proxy.$api.post('/core/activity/signup/signinBySingle',{
 							activityId:id??'',
 							memberSignupId:memberSignupId.value,