Browse Source

实名认证,问诊单,首页修改,登录优化

master
ZhaoYang 2 weeks ago
parent
commit
0d80ca8f4d
  1. 115
      pages/home/home.js
  2. 37
      pages/home/home.wxml
  3. 153
      pages/home/home.wxss
  4. BIN
      pagesA/images/duig.png
  5. BIN
      pagesA/images/name.png
  6. BIN
      pagesA/images/sfz.png
  7. 16
      pagesA/pages/askingSy/askingSy.js
  8. 74
      pagesA/pages/askingSyAdd/askingSyAdd.js
  9. 10
      pagesA/pages/askingSyAdd/askingSyAdd.wxml
  10. 57
      pagesA/pages/askingSyAdd/askingSyAdd.wxss
  11. 414
      pagesA/pages/attestation/attestation.js
  12. 308
      pagesA/pages/attestation/attestation.wxml
  13. 1397
      pagesA/pages/attestation/attestation.wxss
  14. 4
      utils/baseUrl.js
  15. 20
      utils/http.js

115
pages/home/home.js

@ -9,10 +9,13 @@ Page({
// 通知公告数据
currentNotice: 0,
noticeList: [],
forum:[]
forum: [],
suffer: [],
// 添加用户数据
user: {},
county: ''
},
// 查询用户信息
getUserInfo() {
http.UserInfo({
@ -54,8 +57,6 @@ Page({
})
},
// 轮播
getCarousel() {
http.carousel({
@ -68,18 +69,34 @@ Page({
})
},
// 灾害
// 灾害/通知公告
getDisaster() {
http.disaster({
data: {},
success: res => {
// 处理通知数据,添加时间戳
const notices = res.rows.map(item => {
return {
...item,
// // 判断是否是24小时内的通知
// isNew: this.isNewNotification(item.createdTime)
}
})
this.setData({
noticeList: res.rows
noticeList: notices
})
}
})
},
// // 判断通知是否在24小时内
// isNewNotification(createdTime) {
// if (!createdTime) return false
// const noticeTime = new Date(createdTime.replace(/-/g, '/')).getTime()
// const now = new Date().getTime()
// const twentyFourHours = 24 * 60 * 60 * 1000
// return now - noticeTime < twentyFourHours
// },
// 区域划分跳转
bindXzqh() {
@ -168,6 +185,17 @@ Page({
})
},
// 查看所有通知
viewAllNotices() {
wx.navigateTo({
url: '/pagesB/pages/noticeList/noticeList',
})
},
// 查看所有问题
viewAllQuestions() {
this.bindwdlist()
},
// 获取当前位置信息
getLocation() {
@ -202,25 +230,44 @@ Page({
},
onShow() {
// 页面显示时重置轮播图(解决某些手机上的轮播问题)
this.resetSwiper()
},
// 重置轮播图(解决轮播不自动播放的问题)
resetSwiper() {
setTimeout(() => {
if (this.data.swiperList.length > 0) {
this.setData({
currentSwiper: this.data.currentSwiper
})
}
}, 300)
},
// 轮播图变化事件
onSwiperChange(e) {
const current = e.detail.current;
const swiperList = this.data.swiperList.map((item, index) => ({
...item,
}));
this.setData({
currentSwiper: current,
swiperList
currentSwiper: current
});
},
// 轮播图指示器点击
onIndicatorTap(e) {
const index = e.currentTarget.dataset.index;
this.setData({
currentSwiper: index
});
},
// 通知轮播变化事件
onNoticeSwiperChange(e) {
const current = e.detail.current;
this.setData({
currentNotice: current
});
},
// 轮播图点击
onSwiperTap(e) {
@ -231,11 +278,9 @@ Page({
icon: 'none',
duration: 1000
});
},
// 通知点击 - 使用catchtap防止事件冒泡
// 通知点击
onNoticeTap(e) {
const id = e.currentTarget.dataset.id;
console.log('通知点击:', id);
@ -244,15 +289,15 @@ Page({
const notice = this.data.noticeList.find(item => item.id === id);
if (notice) {
wx.showModal({
title: notice.typeName,
content: notice.content,
title: notice.warningLevel || '通知详情',
content: notice.title,
showCancel: true,
cancelText: '关闭',
confirmText: '查看详情',
success: (res) => {
if (res.confirm) {
wx.navigateTo({
url: '/pages/notice/detail?id=' + id
url: '/pagesB/pages/noticeDetail/noticeDetail?id=' + id
});
}
}
@ -260,18 +305,12 @@ Page({
}
},
// 更多通知
gotoNotices() {
wx.navigateTo({
url: ''
});
},
onReady() {
// 当前网络状态
wx.getNetworkType({
success: function (res) { // 返回网络类型, 有效值:// wifi/2g/3g/4g/unknown(Android下不常见的网络类型)/none(无网络)
success: function (res) {
// 返回网络类型, 有效值:
// wifi/2g/3g/4g/unknown(Android下不常见的网络类型)/none(无网络)
console.log(res);
var networkType = res.networkType
if (networkType !== 'unknown') {
@ -285,11 +324,18 @@ Page({
})
},
// 下拉刷新
onPullDownRefresh() {
wx.showNavigationBarLoading()
setTimeout(function () {
// 重新加载所有数据
Promise.all([
new Promise(resolve => this.getUserInfo(resolve)),
new Promise(resolve => this.getDisaster(resolve)),
new Promise(resolve => this.getCarousel(resolve)),
new Promise(resolve => this.getforumList(resolve)),
new Promise(resolve => this.getexperience(resolve))
]).then(() => {
wx.showToast({
title: '刷新成功',
icon: 'none',
@ -297,11 +343,14 @@ Page({
})
wx.hideNavigationBarLoading()
wx.stopPullDownRefresh()
}, 1000)
}).catch(() => {
wx.hideNavigationBarLoading()
wx.stopPullDownRefresh()
})
},
// 页面滚动
onPageScroll(e) {
// 可以根据需要添加滚动效果
}
});

37
pages/home/home.wxml

@ -24,7 +24,17 @@
<!-- 轮播图区域-->
<view class="swiper-container">
<swiper class="custom-swiper" indicator-dots="{{false}}" indicator-color="rgba(255,255,255,0.4)" indicator-active-color="#4CAF50" autoplay="{{true}}" interval="5000" duration="500" circular="{{true}}" current="{{currentSwiper}}" bindchange="onSwiperChange" style="height: 360rpx;">
<swiper class="custom-swiper"
indicator-dots="{{false}}"
indicator-color="rgba(255,255,255,0.4)"
indicator-active-color="#4CAF50"
autoplay="{{true}}"
interval="5000"
duration="500"
circular="{{true}}"
current="{{currentSwiper}}"
bindchange="onSwiperChange"
style="height: 360rpx;">
<block wx:for="{{swiperList}}" wx:key="id">
<swiper-item>
<view class="swiper-item {{item.isActive ? 'active' : ''}}" data-value="{{item}}" catchtap="onSwiperTap">
@ -87,20 +97,43 @@
<!-- 通知公告区域 -->
<view class="notice-section">
<view class="notice-header">
<view class="notice-title">
<text class="notice-icon">📢</text>
<text class="notice-title-text">通知公告</text>
</view>
<view class="notice-more" bindtap="viewAllNotices">
更多 >
</view>
</view>
<view class="notice-content">
<swiper class="notice-swiper" vertical="{{true}}" autoplay="{{true}}" interval="4000" duration="800" circular="{{true}}" style="height: 200rpx;">
<swiper class="notice-swiper"
vertical="{{true}}"
autoplay="{{true}}"
interval="4000"
duration="800"
circular="{{true}}"
style="height: 160rpx;"
bindchange="onNoticeSwiperChange">
<block wx:for="{{noticeList}}" wx:key="id">
<swiper-item>
<view class="notice-item {{index === currentNotice ? 'highlight' : ''}}" data-id="{{item.id}}" catchtap="onNoticeTap">
<view class="notice-item-header">
<view class="notice-type-container">
<text class="notice-type {{tool.type(item.warningLevel)}}">{{item.warningLevel}}</text>
<text class="notice-badge" wx:if="{{item.isNew}}">NEW</text>
</view>
<text class="notice-time">{{item.createdTime}}</text>
</view>
<view class="notice-text-container">
<text class="notice-text">{{item.title}}</text>
<text class="notice-arrow">→</text>
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>

153
pages/home/home.wxss

@ -6,7 +6,6 @@
padding-top: env(safe-area-inset-top);
}
/* 主要内容区域 */
.box {
width: 93%;
@ -29,7 +28,6 @@
border-radius: 50%;
}
.orientation{
display: flex;
align-items: center;
@ -59,7 +57,7 @@
color: #fff;
}
/* 轮播图区域 */
/* 轮播图区域 - 已修复 */
.swiper-container {
position: relative;
border-radius: 20rpx;
@ -175,13 +173,12 @@
}
.indicator-dot.active {
width: 30rpx;
width: 40rpx;
background: #96DBD4;
border-radius: 6rpx;
}
/* 卡片类型 */
.kap {
animation: kapIn 0.5s ease-out 0.5s both;
}
@ -196,8 +193,6 @@
}
}
.card {
width: 100%;
display: grid;
@ -307,39 +302,99 @@
margin: 20rpx 0;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.05);
animation: fadeIn 0.6s ease-out 0.6s both;
position: relative;
overflow: hidden;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 通知标题区域 */
.notice-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 1px solid rgba(150, 219, 212, 0.2);
}
.notice-title {
display: flex;
align-items: center;
gap: 12rpx;
}
.notice-icon {
font-size: 32rpx;
}
.notice-title-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 16rpx;
}
.notice-title-text::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: linear-gradient(135deg, #FF9800, #F44336);
border-radius: 3rpx;
}
.notice-more {
font-size: 24rpx;
color: #96DBD4;
padding: 8rpx 16rpx;
background: rgba(150, 219, 212, 0.1);
border-radius: 20rpx;
transition: all 0.3s ease;
}
.notice-more:active {
background: rgba(150, 219, 212, 0.2);
transform: scale(0.95);
}
/* 通知内容区域 */
.notice-content {
position: relative;
}
.notice-swiper {
height: 150rpx;
height: 160rpx;
}
.notice-item {
padding: 20rpx 0;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
cursor: pointer;
}
.notice-item.highlight {
background: rgba(76, 175, 80, 0.05);
border-radius: 12rpx;
background: rgba(150, 219, 212, 0.08);
border-radius: 16rpx;
padding: 20rpx;
margin: -10rpx -10rpx 0;
margin: 0 -10rpx;
}
.notice-item-header {
@ -349,47 +404,90 @@
margin-bottom: 16rpx;
}
.notice-type-container {
display: flex;
align-items: center;
gap: 10rpx;
}
.notice-type {
padding: 4rpx 16rpx;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 22rpx;
font-weight: 500;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 80rpx;
}
/* 优化通知类型样式 */
.notice-type.urgent {
background: rgba(244, 67, 54, 0.1);
color: #F44336;
background: linear-gradient(135deg, #FF5252, #FF1744);
color: white;
box-shadow: 0 4rpx 12rpx rgba(244, 67, 54, 0.2);
}
.notice-type.important {
background: rgba(255, 152, 0, 0.1);
color: #FF9800;
background: linear-gradient(135deg, #FF9800, #FF9100);
color: white;
box-shadow: 0 4rpx 12rpx rgba(255, 152, 0, 0.2);
}
.notice-type.normal {
background: rgba(33, 150, 243, 0.1);
color: #2196F3;
background: linear-gradient(135deg, #96DBD4, #60C0B9);
color: white;
box-shadow: 0 4rpx 12rpx rgba(33, 150, 243, 0.2);
}
.notice-badge {
background: #FF4081;
color: white;
font-size: 18rpx;
padding: 2rpx 8rpx;
border-radius: 10rpx;
margin-left: 4rpx;
}
.notice-time {
font-size: 22rpx;
color: #999999;
color: #888;
font-family: 'Arial', sans-serif;
}
.notice-text-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.notice-text {
font-size: 28rpx;
color: #333333;
color: #333;
line-height: 1.5;
flex: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
font-weight: 500;
padding-right: 20rpx;
}
.notice-arrow {
font-size: 24rpx;
color: #96DBD4;
opacity: 0.7;
transition: all 0.3s ease;
}
.notice-item.highlight .notice-arrow {
opacity: 1;
transform: translateX(4rpx);
}
/* 用户提问板块 - 优化样式 */
/* 用户提问板块 */
.user-question-section {
background: #FFFFFF;
border-radius: 24rpx;
@ -447,7 +545,6 @@
border-radius: 4rpx;
}
.title-text1_1 {
font-size: 38rpx;
font-weight: bold;
@ -457,7 +554,6 @@
padding-left: 20rpx;
}
.title-text1_1::before {
content: '';
position: absolute;
@ -476,8 +572,6 @@
padding-left: 20rpx;
}
.view-all {
display: flex;
align-items: center;
@ -494,7 +588,6 @@
transform: scale(0.98);
}
.view-all1_1{
display: flex;
align-items: center;
@ -511,9 +604,6 @@
transform: scale(0.98);
}
/* 问题元信息 */
.question-meta {
display: flex;
@ -540,7 +630,6 @@
overflow: hidden;
}
/* 用户信息 */
.question-info {
display: flex;
@ -577,7 +666,6 @@
margin-bottom: 6rpx;
}
.time-info {
font-size: 22rpx;
color: #999;
@ -586,7 +674,6 @@
border-radius: 16rpx;
}
.post-footer {
display: flex;
align-items: center;

BIN
pagesA/images/duig.png

After

Width: 200  |  Height: 200  |  Size: 2.5 KiB

BIN
pagesA/images/name.png

After

Width: 200  |  Height: 200  |  Size: 4.2 KiB

BIN
pagesA/images/sfz.png

After

Width: 200  |  Height: 200  |  Size: 3.4 KiB

16
pagesA/pages/askingSy/askingSy.js

@ -5,6 +5,10 @@ Page({
},
onLoad: function () {
},
onShow:function(){
this.getwzd()
},
@ -59,22 +63,10 @@ Page({
// 查看详情
viewDetail: function (e) {
console.log(1111,e);
const status = e.currentTarget.dataset.value.status
const data = e.currentTarget.dataset.value
console.log(data);
if(status=='已回复'){
wx.navigateTo({
url: `/pagesA/pages/askingSyDetails/askingSyDetails?data=${encodeURIComponent(JSON.stringify(data))}`,
});
}else{
wx.showToast({
title: `无回复内容`,
icon: 'none',
duration: 1000
});
}
},

74
pagesA/pages/askingSyAdd/askingSyAdd.js

@ -1,5 +1,6 @@
import http from '../../../utils/api'
const baseUrl = require('../../../utils/baseUrl')
Page({
/**
* 页面的初始数据
@ -16,7 +17,9 @@ Page({
isSubmitting: false,
isFormValid: false,
tempImages: [], // 新增:临时存储本地图片路径
isUploading: false // 新增:防止重复上传
isUploading: false, // 新增:防止重复上传
showLoadingMask: false, // 新增:显示加载遮罩层
loadingText: '提交中...' // 新增:加载提示文字
},
/**
@ -234,8 +237,11 @@ Page({
return;
}
// 显示加载遮罩层
this.setData({
isSubmitting: true
isSubmitting: true,
showLoadingMask: true,
loadingText: '提交中...'
});
// 准备提交数据
@ -248,29 +254,77 @@ Page({
data: submitData,
success: (res) => {
console.log('提交成功', res);
this.setData({
isSubmitting: false
});
if(res.code==200){
// 提交成功后的处理
this.setData({
loadingText: '提交成功'
});
setTimeout(() => {
this.setData({
isSubmitting: false,
showLoadingMask: false
});
wx.showToast({
title: '提交成功',
icon: 'success',
duration: 1500,
success: () => {
setTimeout(() => {
// 返回上一页
// wx.navigateBack();
}, 1500);
wx.navigateBack();
}
});
}, 1000);
} else {
this.setData({
loadingText: '提交失败'
});
setTimeout(() => {
this.setData({
isSubmitting: false,
showLoadingMask: false
});
wx.showToast({
title: '提交失败,请重试',
icon: 'none'
title: res.msg || '提交失败,请重试',
icon: 'none',
duration: 2000
});
}, 1000);
}
},
fail: (err) => {
this.setData({
loadingText: '网络错误'
});
setTimeout(() => {
this.setData({
isSubmitting: false,
showLoadingMask: false
});
wx.showToast({
title: '网络异常,请检查网络后重试',
icon: 'none',
duration: 2000
});
}, 1000);
}
});
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
// 页面卸载时重置状态
this.setData({
isSubmitting: false,
showLoadingMask: false
});
}
});

10
pagesA/pages/askingSyAdd/askingSyAdd.wxml

@ -104,11 +104,19 @@
<!-- 提交按钮 -->
<view class="submit-section">
<button class="submit-btn" type="primary" formType="submit" loading="{{isSubmitting}}" disabled="{{isSubmitting || !isFormValid}}">
<button class="submit-btn" type="primary" formType="submit" loading="{{isSubmitting}}" disabled="{{isSubmitting || !isFormValid || isUploading}}">
{{isSubmitting ? '提交中...' : '提交问诊单'}}
</button>
</view>
</form>
</scroll-view>
<!-- 加载遮罩层 -->
<view wx:if="{{showLoadingMask}}" class="loading-mask">
<view class="loading-content">
<view class="loading-spinner"></view>
<text class="loading-text">{{loadingText}}</text>
</view>
</view>
</view>

57
pagesA/pages/askingSyAdd/askingSyAdd.wxss

@ -318,6 +318,47 @@
box-shadow: none;
}
/* 加载遮罩层 */
.loading-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.loading-content {
background: #FFFFFF;
border-radius: 24rpx;
padding: 60rpx 80rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
animation: scaleIn 0.3s ease-out;
}
.loading-spinner {
width: 80rpx;
height: 80rpx;
border: 6rpx solid #F0F7FF;
border-top: 6rpx solid #4A90E2;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 32rpx;
}
.loading-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
/* 动画效果 */
@keyframes fadeIn {
from {
@ -330,6 +371,22 @@
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.form-section {
animation: fadeIn 0.4s ease-out forwards;
opacity: 0;

414
pagesA/pages/attestation/attestation.js

@ -1,25 +1,26 @@
// pages/real-name-auth/real-name-auth.js
import http from '../../../utils/api'
const baseUrl = require('../../../utils/baseUrl')
Page({
data: {
// 表单数据
name: '',
phone: '',
smsCode: '',
idNumber: '',
// 焦点状态
nameFocus: false,
phoneFocus: false,
codeFocus: false,
idNumberFocus: false,
// 错误提示
nameError: '',
phoneError: '',
smsCodeError: '',
idNumberError: '',
// 验证码相关
canSendCode: false,
countdown: 0,
countdownTimer: null,
// 提示显示控制 - 修复:初始为false
showNameHint: false,
showIdNumberHint: false,
// 验证状态
isNameValid: false,
isIdNumberValid: false,
// 协议状态
agreed: false,
@ -28,211 +29,262 @@ Page({
canSubmit: false,
isSubmitting: false,
// 弹窗
showSuccessModal: false
},
// 进度条
currentStep: 1,
lineProgress1: 0,
lineProgress2: 0,
onLoad() {
this.checkForm();
// 弹窗数据
showModal: false,
modalTitle: '',
modalContent: '',
// 成功弹窗数据
showSuccessModal: false,
maskedIdNumber: ''
},
onUnload() {
// 清除定时器
if (this.data.countdownTimer) {
clearInterval(this.data.countdownTimer);
}
onLoad() {
// 页面加载时启动进度条动画
setTimeout(() => {
this.setData({ lineProgress1: 50 });
}, 600);
},
// 姓名输入处理
// 姓名输入处理 - 修复:简化逻辑
onNameInput(e) {
const name = e.detail.value.trim();
let nameError = '';
if (name && !/^[\u4e00-\u9fa5]{2,10}$/.test(name)) {
nameError = '姓名应为2-10个汉字';
const value = e.detail.value.trim();
let error = '';
let showHint = true;
let isValid = false;
if (value) {
if (!/^[\u4e00-\u9fa5]{2,10}$/.test(value)) {
error = '姓名应为2-10个汉字';
} else {
isValid = true;
// 验证通过时保持提示显示,但无错误
}
} else {
// 内容为空时显示正常提示
error = '';
}
this.setData({
name: name,
nameError: nameError
name: value,
nameError: error,
showNameHint: showHint,
isNameValid: isValid
}, () => {
this.checkForm();
this.checkCanSendCode();
});
},
onNameFocus() {
this.setData({ nameFocus: true });
this.setData({
nameFocus: true,
showNameHint: true // 获得焦点时显示提示
});
},
onNameBlur() {
this.setData({ nameFocus: false });
},
const { name } = this.data;
// 手机号输入处理
onPhoneInput(e) {
const phone = e.detail.value.trim();
let phoneError = '';
if (phone && !/^1[3-9]\d{9}$/.test(phone)) {
phoneError = '请输入正确的手机号码';
}
this.setData({
nameFocus: false,
// 失去焦点时,如果内容为空或验证失败,保持提示显示
showNameHint: !!(name && !this.data.isNameValid)
});
},
// 清除姓名
clearName() {
this.setData({
phone: phone,
phoneError: phoneError
name: '',
nameError: '',
showNameHint: false,
isNameValid: false
}, () => {
this.checkForm();
this.checkCanSendCode();
});
},
onPhoneFocus() {
this.setData({ phoneFocus: true });
},
onPhoneBlur() {
this.setData({ phoneFocus: false });
},
// 验证码输入处理
onSmsCodeInput(e) {
const smsCode = e.detail.value.trim();
let smsCodeError = '';
if (smsCode && !/^\d{6}$/.test(smsCode)) {
smsCodeError = '请输入6位数字验证码';
// 身份证号输入处理 - 修复:简化逻辑
onIdNumberInput(e) {
const value = e.detail.value.trim().toUpperCase();
let error = '';
let showHint = true;
let isValid = false;
if (value) {
if (value.length < 18) {
error = '还需输入' + (18 - value.length) + '位';
} else if (value.length === 18) {
if (this.validateIdNumber(value)) {
isValid = true;
// 验证通过时保持提示显示,但无错误
} else {
error = '身份证号格式不正确';
}
}
} else {
// 内容为空时显示正常提示
error = '';
}
this.setData({
smsCode: smsCode,
smsCodeError: smsCodeError
idNumber: value,
idNumberError: error,
showIdNumberHint: showHint,
isIdNumberValid: isValid
}, () => {
this.checkForm();
});
},
onCodeFocus() {
this.setData({ codeFocus: true });
},
onCodeBlur() {
this.setData({ codeFocus: false });
},
// 检查是否可以发送验证码
checkCanSendCode() {
const { name, phone, nameError, phoneError } = this.data;
const canSendCode = name && phone && !nameError && !phoneError;
this.setData({ canSendCode });
onIdNumberFocus() {
this.setData({
idNumberFocus: true,
showIdNumberHint: true // 获得焦点时显示提示
});
},
// 发送验证码
async sendSmsCode() {
const { name, phone, countdown } = this.data;
onIdNumberBlur() {
const { idNumber } = this.data;
let error = '';
let isValid = false;
if (countdown > 0) return;
// 验证手机号格式
if (!/^1[3-9]\d{9}$/.test(phone)) {
this.setData({ phoneError: '请输入正确的手机号码' });
return;
// 最终验证
if (idNumber) {
if (idNumber.length < 18) {
error = '还需输入' + (18 - idNumber.length) + '位';
} else if (idNumber.length === 18) {
if (this.validateIdNumber(idNumber)) {
isValid = true;
} else {
error = '身份证号格式不正确';
}
}
}
// 显示加载
wx.showLoading({
title: '发送中...',
mask: true
this.setData({
idNumberFocus: false,
idNumberError: error,
isIdNumberValid: isValid,
// 失去焦点时,如果内容为空或验证失败,保持提示显示
showIdNumberHint: !!(idNumber && !isValid)
});
},
try {
// 模拟发送验证码请求
await new Promise(resolve => setTimeout(resolve, 1500));
wx.hideLoading();
// 发送成功
wx.showToast({
title: '验证码已发送',
icon: 'success',
duration: 2000
// 清除身份证号
clearIdNumber() {
this.setData({
idNumber: '',
idNumberError: '',
showIdNumberHint: false,
isIdNumberValid: false
}, () => {
this.checkForm();
});
},
// 开始倒计时
this.startCountdown();
// 身份证验证函数
validateIdNumber(idNumber) {
// 基础格式验证
if (!/^\d{17}[\dXx]$/.test(idNumber)) {
return false;
}
} catch (error) {
wx.hideLoading();
wx.showToast({
title: '发送失败,请重试',
icon: 'error',
duration: 2000
});
// 地区码验证(简化的验证,实际应该更严谨)
const areaCode = idNumber.substring(0, 2);
const validAreaCodes = ['11', '12', '13', '14', '15', '21', '22', '23',
'31', '32', '33', '34', '35', '36', '37', '41',
'42', '43', '44', '45', '46', '50', '51', '52',
'53', '54', '61', '62', '63', '64', '65'];
if (!validAreaCodes.includes(areaCode)) {
return false;
}
},
// 开始倒计时
startCountdown() {
this.setData({ countdown: 60 });
// 出生日期验证
const year = parseInt(idNumber.substring(6, 10));
const month = parseInt(idNumber.substring(10, 12));
const day = parseInt(idNumber.substring(12, 14));
const timer = setInterval(() => {
let { countdown } = this.data;
countdown--;
const currentYear = new Date().getFullYear();
if (year < 1900 || year > currentYear) return false;
if (month < 1 || month > 12) return false;
if (day < 1 || day > 31) return false;
if (countdown <= 0) {
clearInterval(timer);
this.setData({
countdown: 0,
countdownTimer: null
});
} else {
this.setData({
countdown: countdown,
countdownTimer: timer
});
// 校验码验证
const checkCode = idNumber.charAt(17).toUpperCase();
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idNumber.charAt(i)) * weights[i];
}
}, 1000);
const mod = sum % 11;
return checkCode === checkCodes[mod];
},
// 协议处理
toggleAgreement() {
const newAgreed = !this.data.agreed;
this.setData({
agreed: !this.data.agreed
agreed: newAgreed
}, () => {
this.checkForm();
});
},
viewAgreement() {
wx.navigateTo({
url: '/pages/web-view/web-view?url=' + encodeURIComponent('https://your-domain.com/agreement')
});
// 显示协议弹窗
showAgreementModal() {
const title = '用户服务协议';
const content = `欢迎您使用"与牧同行"服务!\n\n在使用我们的服务前,请您仔细阅读并同意以下协议:\n\n1. 服务条款\n您在使用与牧同行提供的各项服务时,应当遵守相关法律法规,不得从事任何非法行为。\n\n2. 用户责任\n您需要保证所提供信息的真实性、准确性和完整性。\n\n3. 服务变更\n我们保留随时修改、暂停或终止服务的权利。\n\n4. 免责声明\n在法律法规允许的最大范围内,我们对因使用服务而产生的任何间接损失不承担责任。\n\n5. 法律适用\n本协议的订立、执行和解释及争议的解决均适用中华人民共和国法律。\n\n请您确保已阅读并理解以上条款。`;
this.showModal(title, content);
},
// 显示隐私弹窗
showPrivacyModal() {
const title = '隐私保护协议';
const content = `我们非常重视您的隐私保护,请您仔细阅读以下隐私政策:\n\n1. 信息收集\n我们仅收集为您提供服务所必需的信息,包括姓名、身份证号等实名信息。\n\n2. 信息使用\n您的信息仅用于身份验证和服务提供,不会用于其他商业用途。\n\n3. 信息保护\n我们采用先进的安全技术保护您的信息,防止未经授权的访问、使用或泄露。\n\n4. 信息共享\n除非获得您的明确同意,我们不会向第三方共享您的个人信息。\n\n5. 您的权利\n您可以随时查看、更正或删除您的个人信息。\n\n6. 政策更新\n我们可能会不时更新本隐私政策,更新后的政策将在本页面公布。\n\n我们承诺严格遵守相关法律法规,保护您的个人信息安全。`;
this.showModal(title, content);
},
viewPrivacy() {
wx.navigateTo({
url: '/pages/web-view/web-view?url=' + encodeURIComponent('https://your-domain.com/privacy')
// 显示弹窗
showModal(title, content) {
this.setData({
modalTitle: title,
modalContent: content,
showModal: true
});
},
// 关闭弹窗
closeModal() {
this.setData({ showModal: false });
},
// 阻止事件冒泡
stopPropagation(e) {
// 阻止冒泡
},
// 检查表单
checkForm() {
const {
name,
phone,
smsCode,
nameError,
phoneError,
smsCodeError,
isNameValid,
isIdNumberValid,
agreed
} = this.data;
const isValid = name &&
phone &&
smsCode &&
!nameError &&
!phoneError &&
!smsCodeError &&
const isValid = isNameValid &&
isIdNumberValid &&
agreed;
this.setData({
@ -244,56 +296,70 @@ Page({
async submitAuth() {
if (!this.data.canSubmit || this.data.isSubmitting) return;
this.setData({ isSubmitting: true });
// 验证数据
const { name, phone, smsCode } = this.data;
// 最终验证
const { name, idNumber } = this.data;
if (!/^[\u4e00-\u9fa5]{2,10}$/.test(name)) {
this.setData({
nameError: '姓名应为2-10个汉字',
isSubmitting: false
showNameHint: true,
canSubmit: false
});
return;
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
if (!this.validateIdNumber(idNumber)) {
this.setData({
phoneError: '请输入正确的手机号码',
isSubmitting: false
idNumberError: '身份证号格式不正确',
showIdNumberHint: true,
canSubmit: false
});
return;
}
if (!/^\d{6}$/.test(smsCode)) {
this.setData({
smsCodeError: '请输入6位数字验证码',
isSubmitting: false
isSubmitting: true,
currentStep: 2,
lineProgress1: 100,
lineProgress2: 50
});
// 显示加载动画
wx.showLoading({
title: '正在验证...',
mask: true
});
return;
}
try {
// 模拟API请求
await new Promise(resolve => setTimeout(resolve, 2000));
await new Promise(resolve => setTimeout(resolve, 1500));
// 提交成功
this.setData({
isSubmitting: false,
showSuccessModal: true
});
wx.hideLoading();
// 处理身份证号脱敏显示
const maskedId = idNumber.substring(0, 4) + '**********' + idNumber.substring(14);
// 保存认证信息到本地
// 显示成功弹窗
this.showSuccessModal(maskedId);
// 保存认证信息
wx.setStorageSync('realNameAuth', {
name: name,
phone: phone,
idNumber: idNumber,
certified: true,
certifiedTime: new Date().getTime()
});
this.setData({
isSubmitting: false,
currentStep: 3,
lineProgress2: 100
});
} catch (error) {
wx.hideLoading();
this.setData({ isSubmitting: false });
wx.showToast({
title: '认证失败,请重试',
icon: 'error',
@ -302,7 +368,15 @@ Page({
}
},
// 成功弹窗处理
// 显示成功弹窗
showSuccessModal(maskedId) {
this.setData({
maskedIdNumber: maskedId,
showSuccessModal: true
});
},
// 关闭成功弹窗
closeSuccessModal() {
this.setData({ showSuccessModal: false });
},
@ -311,7 +385,7 @@ Page({
goToHome() {
this.closeSuccessModal();
wx.switchTab({
url: '/pages/index/index'
url: '/pages/personal/personal'
});
}
});

308
pagesA/pages/attestation/attestation.wxml

@ -1,185 +1,261 @@
<!-- pages/real-name-auth/real-name-auth.wxml -->
<view class="auth-container">
<!-- 顶部装饰 -->
<view class="top-decoration">
<view class="decoration-circle circle-1"></view>
<view class="decoration-circle circle-2"></view>
<view class="decoration-circle circle-3"></view>
<!-- 背景装饰 -->
<view class="background-design">
<view class="bg-circle circle-1"></view>
<view class="bg-circle circle-2"></view>
<view class="bg-wave"></view>
</view>
<!-- 头部 -->
<view class="header">
<image class="logo" src="/assets/icons/sheep-logo.svg" mode="aspectFit"></image>
<!-- 头部区域 -->
<view class="header-section">
<view class="brand-header">
<view class="brand-text">
<view class="brand-name">与牧同行</view>
<view class="page-title">实名认证</view>
<view class="page-subtitle">开启您的牧业伙伴之旅</view>
<view class="brand-slogan">专业牧业,贴心同行</view>
</view>
</view>
<view class="auth-header">
<view class="auth-title">
<text class="title-text">实名认证</text>
<view class="title-badge">必填</view>
</view>
<view class="auth-description">
为了更好的服务体验,请完成实名认证
</view>
</view>
</view>
<!-- 进度指示 -->
<view class="progress-indicator">
<view class="progress-step active">
<view class="step-bubble">
<view class="step-number">1</view>
</view>
<view class="step-label">填写信息</view>
</view>
<view class="progress-line">
<view class="line-progress" style="width: {{lineProgress1}}%;"></view>
</view>
<!-- 表单卡片 -->
<view class="form-card">
<!-- 表单标题 -->
<view class="card-header">
<view class="card-title">
<image class="title-icon" src="/assets/icons/id-card.svg" mode="aspectFit"></image>
<text>身份信息</text>
<view class="progress-step {{currentStep >= 2 ? 'active' : ''}}">
<view class="step-bubble">
<view class="step-number">2</view>
</view>
<view class="card-hint">请填写您的真实信息</view>
<view class="step-label">信息验证</view>
</view>
<view class="progress-line">
<view class="line-progress" style="width: {{lineProgress2}}%;"></view>
</view>
<view class="progress-step {{currentStep >= 3 ? 'active' : ''}}">
<view class="step-bubble">
<view class="step-number">3</view>
</view>
<view class="step-label">完成认证</view>
</view>
</view>
<!-- 表单区域 -->
<view class="form-section">
<!-- 姓名输入 -->
<view class="input-group">
<view class="input-card">
<view class="input-label">
<image class="label-icon" src="/assets/icons/user.svg" mode="aspectFit"></image>
<text>真实姓名</text>
<image class="label-icon" src="/pagesA/images/name.png" mode="aspectFit"></image>
<text class="label-text">真实姓名</text>
<text class="required-star">*</text>
</view>
<view class="input-wrapper">
<view class="input-container">
<input
class="name-input"
class="input-field {{nameFocus ? 'focused' : ''}} {{nameError ? 'error' : ''}} {{name ? 'has-value' : ''}} {{isNameValid ? 'valid' : ''}}"
placeholder="请输入您的真实姓名"
placeholder-class="placeholder"
value="{{name}}"
bindinput="onNameInput"
focus="{{nameFocus}}"
bindfocus="onNameFocus"
bindblur="onNameBlur"
maxlength="10"
/>
<view class="input-border"></view>
<view class="input-focus-border {{nameFocus ? 'active' : ''}}"></view>
</view>
<view class="input-hint {{nameError ? 'error' : ''}}">
{{nameError || '请务必使用真实姓名'}}
<!-- 删除按钮 -->
<view class="clear-wrapper" wx:if="{{name}}">
<button class="clear-btn" bindtap="clearName" hover-class="btn-hover">
<image class="clear-icon" src="/pagesA/images/ch.png" mode="aspectFit"></image>
</button>
</view>
<!-- 输入框下划线 -->
<view class="input-underline">
<view class="underline-bg"></view>
<view class="underline-progress {{nameFocus ? 'active' : ''}}"></view>
</view>
<!-- 手机号输入 -->
<view class="input-group">
<view class="input-label">
<image class="label-icon" src="/assets/icons/phone.svg" mode="aspectFit"></image>
<text>手机号码</text>
<!-- 字符计数 -->
<view class="char-count {{name.length > 8 ? 'warning' : ''}}">
{{name.length}}/10
</view>
<view class="input-wrapper">
<input
class="phone-input"
placeholder="请输入您的手机号码"
placeholder-class="placeholder"
value="{{phone}}"
bindinput="onPhoneInput"
type="number"
maxlength="11"
focus="{{phoneFocus}}"
bindfocus="onPhoneFocus"
bindblur="onPhoneBlur"
/>
<view class="input-border"></view>
<view class="input-focus-border {{phoneFocus ? 'active' : ''}}"></view>
</view>
<view class="input-hint {{phoneError ? 'error' : ''}}">
{{phoneError || '用于接收重要通知'}}
<!-- 提示信息 -->
<view class="hint-container" wx:if="{{showNameHint || nameError}}">
<text class="hint-text {{nameError ? 'error' : 'normal'}}">
{{nameError || '请输入与身份证一致的姓名(2-10个汉字)'}}
</text>
</view>
</view>
<!-- 验证码 -->
<view class="input-group">
<!-- 身份证号输入 -->
<view class="input-card">
<view class="input-label">
<image class="label-icon" src="/assets/icons/sms.svg" mode="aspectFit"></image>
<text>验证码</text>
<image class="label-icon" src="/pagesA/images/sfz.png" mode="aspectFit"></image>
<text class="label-text">身份证号</text>
<text class="required-star">*</text>
</view>
<view class="code-input-wrapper">
<view class="code-input-container">
<view class="input-container">
<input
class="code-input"
placeholder="请输入验证码"
class="input-field {{idNumberError ? 'error' : ''}} {{isIdNumberValid ? 'valid' : ''}} {{idNumber ? 'has-value' : ''}}"
placeholder="请输入18位身份证号码"
placeholder-class="placeholder"
value="{{smsCode}}"
bindinput="onSmsCodeInput"
type="number"
maxlength="6"
focus="{{codeFocus}}"
bindfocus="onCodeFocus"
bindblur="onCodeBlur"
value="{{idNumber}}"
bindinput="onIdNumberInput"
bindfocus="onIdNumberFocus"
bindblur="onIdNumberBlur"
maxlength="18"
type="idcard"
/>
<view class="input-border"></view>
<view class="input-focus-border {{codeFocus ? 'active' : ''}}"></view>
<!-- 删除按钮 -->
<view class="clear-wrapper" wx:if="{{idNumber}}">
<button class="clear-btn" bindtap="clearIdNumber" hover-class="btn-hover">
<image class="clear-icon" src="/pagesA/images/ch.png" mode="aspectFit"></image>
</button>
</view>
<button
class="send-code-btn {{!canSendCode ? 'disabled' : ''}} {{countdown > 0 ? 'counting' : ''}}"
bindtap="sendSmsCode"
disabled="{{!canSendCode || countdown > 0}}"
hover-class="btn-hover"
>
<view class="btn-content">
<image wx:if="{{countdown === 0}}" class="sms-icon" src="/assets/icons/send.svg" mode="aspectFit"></image>
<!-- <text>{{countdown > 0 ? `${countdown}s后重发` : '发送验证码'}}</text> -->
<!-- 输入框下划线 -->
<view class="input-underline">
<view class="underline-bg"></view>
<view class="underline-progress {{idNumberFocus ? 'active' : ''}}"></view>
</view>
</button>
<!-- 分段显示 -->
<view class="id-segments {{idNumberFocus || idNumber ? 'show' : ''}}">
<view class="id-segment {{idNumber.length >= 6 ? 'filled' : ''}}">{{idNumber.substring(0, 6) || '地区'}}</view>
<view class="id-segment {{idNumber.length >= 14 ? 'filled' : ''}}">{{idNumber.substring(6, 14) || '出生'}}</view>
<view class="id-segment {{idNumber.length >= 17 ? 'filled' : ''}}">{{idNumber.substring(14, 17) || '顺序'}}</view>
<view class="id-segment last {{idNumber.length === 18 ? 'filled' : ''}}">{{idNumber.substring(17) || '校验'}}</view>
</view>
<view class="input-hint {{smsCodeError ? 'error' : ''}}">
{{smsCodeError || '输入6位数字验证码'}}
</view>
<!-- 提示信息 -->
<view class="hint-container" wx:if="{{showIdNumberHint || idNumberError}}">
<text class="hint-text {{idNumberError ? 'error' : 'normal'}}">
{{idNumberError || '请输入有效的18位身份证号码'}}
</text>
</view>
</view>
<!-- 协议 -->
<!-- 协议条款 -->
<view class="agreement-card">
<label class="agreement-item" bindtap="toggleAgreement">
<view class="checkbox {{agreed ? 'checked' : ''}}">
<image wx:if="{{agreed}}" class="check-icon" src="/assets/icons/check.svg" mode="aspectFit"></image>
</view>
<view class="agreement-text">
我已阅读并同意
<text class="link" bindtap="viewAgreement">《用户服务协议》</text>
<text class="link" bindtap="viewPrivacy">《隐私政策》</text>
<view class="agreement-checkbox {{agreed ? 'checked' : ''}}">
<image
wx:if="{{agreed}}"
class="checkmark"
src="/pagesA/images/duig.png"
mode="aspectFit"
></image>
</view>
<view class="agreement-content">
<text>我已阅读并同意</text>
<text class="link-text" bindtap="showAgreementModal">《用户服务协议》</text>
<text>和</text>
<text class="link-text" bindtap="showPrivacyModal">《隐私保护协议》</text>
</view>
</label>
</view>
</view>
<!-- 提交按钮 -->
<!-- 提交区域 -->
<view class="submit-section">
<button
class="submit-btn {{canSubmit ? 'active' : 'disabled'}}"
class="submit-button {{canSubmit ? 'active' : 'disabled'}}"
bindtap="submitAuth"
disabled="{{!canSubmit}}"
hover-class="submit-btn-hover"
hover-class="button-hover"
loading="{{isSubmitting}}"
>
<view class="btn-inner">
<text>{{isSubmitting ? '提交中...' : '完成认证'}}</text>
<image wx:if="{{!isSubmitting}}" class="arrow-icon" src="/assets/icons/arrow-right.svg" mode="aspectFit"></image>
</view>
验证
</button>
</view>
<view class="submit-hint">
认证成功后,您将享受与牧同行的专属服务
<!-- 协议弹窗 -->
<view class="modal-overlay {{showModal ? 'show' : ''}}" bindtap="closeModal">
<view class="modal-container" catchtap="stopPropagation">
<view class="modal-header">
<view class="modal-title">{{modalTitle}}</view>
<button class="modal-close" bindtap="closeModal">
<image class="close-icon" src="/pagesA/images/ch.png" mode="aspectFit"></image>
</button>
</view>
<scroll-view class="modal-content" scroll-y>
<view class="modal-text">
{{modalContent}}
</view>
</scroll-view>
<!-- 底部装饰 -->
<view class="bottom-decoration">
<image class="sheep-illustration" src="/assets/illustrations/sheep.svg" mode="aspectFit"></image>
<view class="decoration-text">
<text class="highlight">与牧同行</text>,伴您每一次成长
<view class="modal-footer">
<button class="modal-confirm" bindtap="closeModal">
我已阅读并理解
</button>
</view>
</view>
</view>
<!-- 成功弹窗 -->
<view class="success-modal {{showSuccessModal ? 'show' : ''}}">
<view class="modal-mask" bindtap="closeSuccessModal"></view>
<view class="modal-content">
<view class="modal-icon">
<image class="success-icon" src="/assets/icons/success.svg" mode="aspectFit"></image>
<view class="success-overlay" bindtap="closeSuccessModal"></view>
<view class="success-container">
<view class="success-icon">
<image class="success-badge" src="/pagesA/images/duig.png" mode="aspectFit"></image>
<view class="success-ring ring-1"></view>
<view class="success-ring ring-2"></view>
</view>
<view class="modal-title">认证成功!</view>
<view class="modal-message">
欢迎加入<text class="brand-highlight">与牧同行</text>大家庭
<view class="success-body">
<view class="success-title">认证成功!</view>
<view class="success-message">
欢迎加入<text class="brand">与牧同行</text>大家庭
</view>
<view class="modal-subtitle">
您已成功完成实名认证,开始享受专属服务吧!
<view class="success-details">
<view class="detail-item">
<view class="detail-label">
<image class="detail-icon" src="/pagesA/images/name.png" mode="aspectFit"></image>
<text>姓名</text>
</view>
<view class="detail-value">{{name}}</view>
</view>
<button class="modal-btn" bindtap="goToHome">
<image class="home-icon" src="/assets/icons/home.svg" mode="aspectFit"></image>
<text>前往首页</text>
<view class="detail-item">
<view class="detail-label">
<image class="detail-icon" src="/pagesA/images/sfz.png" mode="aspectFit"></image>
<text>身份证号</text>
</view>
<view class="detail-value">{{maskedIdNumber}}</view>
</view>
</view>
</view>
<view class="success-footer">
<button class="success-button" bindtap="goToHome">
<text>开始使用</text>
</button>
</view>
</view>
</view>
</view>

1397
pagesA/pages/attestation/attestation.wxss
File diff suppressed because it is too large
View File

4
utils/baseUrl.js

@ -1,5 +1,5 @@
// var baseUrl = 'https://wx.chenhaitech.com/ymtx-prod-api'
var baseUrl = 'https://wx.chenhaitech.com/ymtx-prod-api'
// var baseUrl = 'http://192.168.101.109:8080'
var baseUrl = 'http://192.168.101.105:8082'
// var baseUrl = 'http://192.168.101.105:8082'
// var baseUrl = 'http://192.168.101.111:8081'
module.exports = baseUrl

20
utils/http.js

@ -1,5 +1,7 @@
var baseUrl = require('../utils/baseUrl')
var ajaxtimes = 0
var isShowingTokenExpiredModal = false // 新增:标记是否正在显示token过期弹窗
module.exports = {
http(url, method, params) {
//发送一次请求就加1
@ -52,19 +54,35 @@ module.exports = {
success(res) {
// console.log(res);
if(res.data.code == 401){
// 只在没有显示弹窗时才显示
if (!isShowingTokenExpiredModal) {
isShowingTokenExpiredModal = true
wx.showModal({
title: '提示',
content: '登录已过期,请重新登录',
success (res) {
if (res.confirm) {
// 重置标记
isShowingTokenExpiredModal = false
wx.reLaunch({
url: '/pages/login/login',
})
} else if (res.cancel) {
// 重置标记
isShowingTokenExpiredModal = false
}
},
// 确保在模态框关闭时重置标记
complete: function() {
// 如果success回调没有执行(例如直接点击蒙层关闭),在这里重置标记
setTimeout(() => {
isShowingTokenExpiredModal = false
}, 300)
}
})
}
// 401错误时,不调用params.success,直接返回
return
} else {
params.success && params.success(res.data)
}

Loading…
Cancel
Save