liujiaxin 3 روز پیش
والد
کامیت
dd86c798ad

+ 2 - 0
common/request.js

@@ -3,6 +3,8 @@ export default class Request {
 	http(router, data = {}, method,contentType) {
 		let that = this;
 		let path = 'http://132.232.83.221:7771';
+		// let path = 'https://user.his.ifeiyu100.com/';
+
 		
 		// let path = 'https://api.homemdt.net'; //正式
 		

+ 3 - 1
main.js

@@ -30,7 +30,9 @@ function checkNeedLogin(targetPath) {
     'auth/changePassword',
     'auth/wxLogin',
     'auth/setting',
-    'common/launch'
+    'common/launch',
+    'pages_user/userAgreement',
+    'pages_user/privacyPolicy'
   ]
   
   // 移除路径中的斜杠和协议,只保留核心路径部分

+ 11 - 0
pages.json

@@ -213,7 +213,18 @@
 					"style": {
 						"navigationBarTitleText": "个人信息"
 					}
+				},{
+					"path": "userAgreement",
+					"style": {
+						"navigationBarTitleText": "用户协议"
+					}
+				},{
+					"path": "privacyPolicy",
+					"style": {
+						"navigationBarTitleText": "隐私政策"
+					}
 				}
+				
 			]
 		},
 		{

+ 15 - 9
pages/auth/login.vue

@@ -4,10 +4,10 @@
 		<image class="bg" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/bg_login.png" mode="widthFix"></image>
 		<view class="force-login-wrap">
 			<view :style="{height:menuButtonInfo.height,marginTop:menuButtonInfo.top}" class="backImg">
-				<image @tap="goBack()" src="/static/images/back.png"></image>
+				<image @tap="goBack()" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/back_white.png"></image>
 			</view>
 			<view class="top-title">
-				<view class="title-text">欢迎登录<text class="blue">小蜜蜂</text></view>
+				<view class="title-text">欢迎登录<text class="blue">一咻学术</text></view>
 				<view class="login-notice">新用户首次登录即视为注册</view>
 			</view>
 			<view class="force-login__content">
@@ -48,11 +48,11 @@
 				</view>
 
 				<view class="tips">
-					<checkbox :checked="isAgreement" @click="handleAgreement()" />
-					<view class="tips-text" @click="handleAgreement()">已阅读并接受</view>
-					<view class="btn" @click="openH5('/web/userAgreement')">《用户注册协议》</view>
-					<view class="btn" @click="openH5('/web/privacyPolicy')">《隐私保护政策》</view>
-				</view>
+				<checkbox :checked="isAgreement" @click="handleAgreement()" />
+				<view class="tips-text" @click="handleAgreement()">已阅读并接受</view>
+				<view class="btn" @click.stop="navTo('/pages_user/userAgreement')">《用户注册协议》</view>
+				<view class="btn" @click.stop="navTo('/pages_user/privacyPolicy')">《隐私保护政策》</view>
+			</view>
 			</view>
 		</view>
 		<!-- #endif -->
@@ -124,6 +124,12 @@
 
 		},
 		methods: {
+			navTo(path) {
+				console.log("地址",path)
+				uni.navigateTo({
+					url: path
+				})
+			},
 			closePwd() {
 				this.showPassword = !this.showPassword
 			},
@@ -293,7 +299,7 @@
 					} else {
 						uni.showToast({
 							icon: 'none',
-							title: res.message || "登录失败",
+							title: res.msg || "登录失败",
 						});
 					}
 				})
@@ -329,7 +335,7 @@
 						} else {
 							uni.showToast({
 								icon: 'none',
-								title: res.message || "登录失败",
+								title: res.msg || "登录失败",
 							});
 						}
 					})

+ 0 - 2
pages/auth/setting.vue

@@ -27,8 +27,6 @@
 		},
 		onLoad() {
 			this.getVersion()
-			this.version = uni.getSystemInfoSync().version; // 注意:这里实际上是获取系统信息,而非应用版本号。对于应用版本号,通常需要在 manifest.json 中定义或在代码中硬编码。
-
 		},
 		methods: {
 			getVersion() {

+ 11 - 7
pages/home/index.vue

@@ -5,30 +5,34 @@
 		<view class="content">
 			<view class="title">工作台</view>
 			<view class="summary-section ">
-				<view class="summary-header">
+				<!-- <view class="summary-header">
 					<view class="summary-indicator"></view>
 					<text class="summary-title">互联网</text>
-				</view>
+				</view> -->
 				<view class="list">
 					<view class="item" @click="navTo('/pages_task/xlTask')">
 						<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/xl.png"></image>
-						<text>XL任务</text>
+						<text>任务申请</text>
 					</view>
 					<view class="item" @click="navTo('/pages_speaker/index')">
 						<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/speaker.png" ></image>
 						<text>讲者管理</text>
 					</view>
+					<view class="item" @click="navTo('/pages_task/approvalCenter')">
+						<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/approval.png"></image>
+						<text>审批中心</text>
+					</view>
 				</view>
-				<view class="summary-header">
+				<!-- <view class="summary-header">
 					<view class="summary-indicator"></view>
 					<text class="summary-title">行政管理</text>
-				</view>
-				<view class="list">
+				</view> -->
+				<!-- <view class="list">
 					<view class="item" @click="navTo('/pages_task/approvalCenter')">
 						<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/approval.png"></image>
 						<text>审批中心</text>
 					</view>
-				</view>
+				</view> -->
 			</view>
 		</view>
 

+ 20 - 7
pages/user/index.vue

@@ -8,22 +8,19 @@
 				<view class="content">
 					<view class="user-info">
 						<view class="left">
-							<view class="head-img">
+							<view class="head-img" @click="isLogin">
 								<image :src="userInfo.avatar?userInfo.avatar:'https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/my_heads_icon.png'"
 									mode="aspectFill">
 								</image>
-								<image class="gender"
-									:src="isGirl==null?'https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_girl.png':'https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_boy.png'"
-									mode="aspectFill"></image>
 							</view>
 							<view class="name-phone">
 								<view class="x-f">
-									<view class="name" v-if="UserInfo">{{userInfo.nickName||'未命名'}}</view>
+									<view class="name" v-if="userInfo && userInfo.userId">{{userInfo.nickName||'未命名'}}</view>
 									<view class="name" v-else>请先登录</view>
-									<view class="lable" v-if="UserInfo.deptName">{{userInfo.deptName}}</view>
+									<view class="lable" v-if="userInfo && userInfo.deptName">{{userInfo.deptName}}</view>
 								</view>
 							</view>
-							<view class="txt" v-if="UserInfo">您已加入小蜜蜂{{joinDays||'0'}}天了~</view>
+							<view class="txt" v-if="userInfo && userInfo.userId">您已加入小蜜蜂{{joinDays||'0'}}天了~</view>
 						</view>
 					</view>
 
@@ -108,6 +105,22 @@
 			}
 		},
 		methods: {
+				
+			isLogin(){
+				console.log("是否登录")
+				console.log("是否登录222",this.userInfo)
+				if(!this.userInfo || !this.userInfo.userId){
+					console.log("未登录,跳转到登录页面")
+					uni.navigateTo({
+						url:'/pages/auth/login'
+					})
+				} else {
+					console.log("已登录,跳转到个人信息页面")
+					uni.navigateTo({
+						url:'/pages_user/userInfo'
+					})
+				}
+			},
 			seeChange() {
 				this.isShow = !this.isShow
 			},

+ 15 - 7
pages_speaker/speakerInvitation.vue

@@ -30,7 +30,7 @@
 					<image class="qrcode-img" :src="qscode" @longpress="saveQrcode"></image>
 				</view>
 				<!-- 扫码提示文字 -->
-				<view class="scan-tip">扫一扫,注册学苑</view>
+				<view class="scan-tip">扫一扫,注册一咻学苑</view>
 			</view>
 		</view>
 	</view>
@@ -181,16 +181,24 @@ import { inviteDoctor } from '@/api/speaker.js'
 			inviteDoctor() {
 				inviteDoctor(this.userInfo.userId,this.userInfo.companyId).then(res => {
 					console.log('inviteDoctor返回数据:', res);
-					if (res.code === 200) {
-						// 将arraybuffer转换为base64
+					// 检查返回数据的类型
+					if (res && typeof res === 'object' && res.code === 200 && res.data) {
+						// 如果是标准的API返回格式
 						const arrayBuffer = res.data;
 						const base64 = uni.arrayBufferToBase64(arrayBuffer);
 						this.qscode = 'data:image/png;base64,' + base64;
 					} else {
-						uni.showToast({
-							icon: 'none',
-							title: res.msg || '获取二维码失败'
-						});
+						// 如果直接返回arraybuffer
+						try {
+							const base64 = uni.arrayBufferToBase64(res);
+							this.qscode = 'data:image/png;base64,' + base64;
+						} catch (e) {
+							console.error('二维码转换失败:', e);
+							uni.showToast({
+								icon: 'none',
+								title: '二维码转换失败'
+							});
+						}
 					}
 				}).catch(err => {
 					console.error('获取二维码失败:', err);

+ 136 - 12
pages_task/approvalCenter.vue

@@ -20,21 +20,47 @@
 		<view class="sub-tabs-wrapper">
 			<!-- 动态子标签 -->
 			<view class="sub-tabs">
-				<view class="sub-tab-item" :class="{ active: currentSubTab === item.value }" @click="popShow = !popShow"
-					v-for="(item, index) in currentSubTabsList" :key="index">
-					<text>{{ item.label }}</text>
+				<view class="sub-tab-item" :class="{ active: currentSubTab === 'all' || currentSubTab === 'taskCreate' }" @click="openSubTabPopup('all')">
+					<text>{{ selectedSubTabOption === 'all' || selectedSubTabOption === 'taskCreate' ? (selectedSubTabOption === 'all' ? '全部审核' : '任务创建') : '全部审核' }}</text>
 					<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_expand.png" mode="widthFix"></image>
 				</view>
+				<view class="sub-tab-item" :class="{ active: currentSubTab === 'unfinished' || currentSubTab === 'finished' }" @click="openSubTabPopup('unfinished')">
+					<text>{{ selectedSubTabOption === 'unfinished' || selectedSubTabOption === 'finished' ? (selectedSubTabOption === 'unfinished' ? '最新发起' : '最早发起') : '最新发起' }}</text>
+					<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_expand.png" mode="widthFix"></image>
+				</view>
+			</view>
+			<!-- 子标签弹窗 -->
+			<view class="sub-tab-popup-overlay" v-if="showSubTabPopup" @click="showSubTabPopup = false"></view>
+			<view class="sub-tab-popup" v-if="showSubTabPopup">
+				<view class="sub-tab-options">
+					<!-- 全部审核选项 -->
+					<template v-if="currentPopupType === 'all'">
+						<view class="sub-tab-option" :class="{ active: selectedSubTabOption === 'all' }" @click="selectSubTabOption('all', '全部审核')">
+							<text>全部审核</text>
+						</view>
+						<view class="sub-tab-option" :class="{ active: selectedSubTabOption === 'taskCreate' }" @click="selectSubTabOption('taskCreate', '任务创建')">
+							<text>任务创建</text>
+						</view>
+					</template>
+					<!-- 最新发起选项 -->
+					<template v-else-if="currentPopupType === 'unfinished'">
+						<view class="sub-tab-option" :class="{ active: selectedSubTabOption === 'unfinished' }" @click="selectSubTabOption('unfinished', '最新发起')">
+							<text>最新发起</text>
+						</view>
+						<view class="sub-tab-option" :class="{ active: selectedSubTabOption === 'finished' }" @click="selectSubTabOption('finished', '最早发起')">
+							<text>最早发起</text>
+						</view>
+					</template>
+				</view>
 			</view>
-			<!-- 使用tab-popup组件 -->
-			<tab-popup v-model:show="popShow" :items="tabsList" :selected-item="selectedTabItem" @select="selectTabItem" />
 		</view>
 		<!-- 列表内容 -->
-		<scroll-view class="content" scroll-y>
+		<scroll-view class="content" scroll-y refresher-enabled :refresher-triggered="refreshing" @refresherrefresh="onRefresh" @refresherrestore="onRestore">
 			<view class="task-card" v-for="(item, index) in currentList" :key="index" @click="goDetails(item)">
 				<!-- 任务/审核标题+状态 -->
 				<view class="card-top">
-					<text class="card-task-title">{{ item.auditName || '未设置' }}</text>
+					<text class="card-task-title">{{ getAuditNameDisplay(item.auditName) }}</text>
+
 					<view class="status-tag" :class="item.statusClass">{{ item.statusText }}</view>
 				</view>
 
@@ -175,6 +201,11 @@ import utils from '@/utils/common.js'
 						finishStatus: '',
 						belongType: ''
 					},
+					refreshing: false,
+					showSubTabPopup: false,
+					currentPopupType: 'all',
+					selectedSubTabOption: 'all',
+					selectedSubTabLabel: '全部审核',
 					// 顶部选项卡数组
 					topTabs: [{
 								label: '待办',
@@ -250,6 +281,29 @@ import utils from '@/utils/common.js'
 				});
 			},
 		methods: {
+			onRefresh() {
+				this.refreshing = true;
+				this.loadData().finally(() => {
+					setTimeout(() => {
+						this.refreshing = false;
+					}, 500);
+				});
+			},
+			onRestore() {
+				this.refreshing = false;
+			},
+			openSubTabPopup(type) {
+				this.currentPopupType = type;
+				this.showSubTabPopup = true;
+			},
+			selectSubTabOption(value, label) {
+				this.selectedSubTabOption = value;
+				this.selectedSubTabLabel = label;
+				this.currentSubTab = value;
+				this.showSubTabPopup = false;
+				// 这里可以添加根据选择的子标签过滤数据的逻辑
+				this.loadData();
+			},
 			selectTabItem(item) {
 				this.selectedTabItem = item;
 				this.popShow = false;
@@ -263,7 +317,10 @@ import utils from '@/utils/common.js'
 			switchTopTab(index) {
 				this.currentTopTab = index;
 				this.currentSubTab = 'all';
+				this.selectedSubTabOption = 'all';
+				this.selectedSubTabLabel = '全部审核';
 				this.popShow = false;
+				this.showSubTabPopup = false;
 				// 切换标签时重新加载数据
 				this.loadData();
 			},
@@ -284,11 +341,24 @@ import utils from '@/utils/common.js'
 				}
 			},
 			confirmFilters() {
-										this.showFilter = false
-										console.log('筛选条件:', this.filters)
-										// 筛选后重新加载数据
-										this.loadData()
-									},
+				this.showFilter = false
+				console.log('筛选条件:', this.filters)
+				// 筛选后重新加载数据
+				this.loadData()
+				},
+				getAuditNameDisplay(auditName) {
+					if (!auditName) return '未设置'
+					switch (auditName) {
+						case '完成任务审核':
+							return '"完成任务"审核'
+						case '定级审核':
+							return '"讲者定级"审核'
+						default:
+							// 对于其他审核类型,在最开始和审核前都加双引号
+							const prefix = auditName.replace('审核', '')
+							return '"' + prefix + '"审核'
+					}
+				},
 								handleShare(item) {
 									uni.showToast({
 										title: '分享功能待实现',
@@ -602,6 +672,60 @@ import utils from '@/utils/common.js'
 			}
 		}
 
+		/* 子标签弹窗样式 */
+		.sub-tab-popup-overlay {
+			position: absolute;
+			top: 100%;
+			height: 100vh;
+			left: 0;
+			right: 0;
+			bottom: -1000rpx;
+			background: rgba(0, 0, 0, 0.5);
+			z-index: 8;
+		}
+
+		.sub-tab-popup {
+			position: absolute;
+			top: 100%;
+			left: 0;
+			right: 0;
+			background: #fff;
+			border-radius: 0;
+			padding: 32rpx;
+			width: 100%;
+			box-sizing: border-box;
+			box-shadow: none;
+			z-index: 9;
+		}
+
+		.sub-tab-options {
+			display: flex;
+			flex-wrap: wrap;
+			gap: 24rpx;
+			border-radius: 70rpx 70rpx 70rpx 70rpx;
+			justify-content: flex-start;
+		}
+
+		.sub-tab-option {
+			padding: 24rpx 14rpx;
+			border-radius: 70rpx;
+			font-size: 28rpx;
+			color: #666666;
+			background: #ffffff;
+			border: 1rpx solid #e8e8e8;
+			transition: all 0.2s ease;
+			text-align: center;
+			min-width: 214rpx;
+			box-sizing: border-box;
+
+			&.active {
+				background: rgba(56,139,255,0.15);
+				color: #ffffff;
+				color: #388BFF;
+				border: 1rpx solid #388BFF ;
+			}
+		}
+
 		// 列表区域
 		.content {
 			padding: 24rpx;

+ 10 - 10
pages_task/approvalTaskDetail.vue

@@ -224,10 +224,10 @@
 					<text class="section-title">任务信息</text>
 				</view>
 				<view class="info-list">
-					<view class="info-item">
+					<!-- <view class="info-item">
 							<text class="info-label">费用分摊ID</text>
 							<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.costShareId||'-'}}</text>
-					</view>
+					</view> -->
 					<view class="info-item">
 						<text class="info-label">费用分摊名字</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.costShareName||'-'}}</text>
@@ -240,18 +240,18 @@
 						<text class="info-label">任务数量</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.taskCount||'-'}}</text>
 					</view>
-					<view class="info-item">
+					<!-- <view class="info-item">
 						<text class="info-label">任务单位(字典ID)</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.taskUnit||'-'}}</text>
-					</view>
+					</view> -->
 					<view class="info-item">
 						<text class="info-label">任务单位名称</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.taskUnitName||'-'}}</text>
 					</view>
-					<view class="info-item">
+					<!-- <view class="info-item">
 						<text class="info-label">归属类型(字典ID)</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.belongType||'-'}}</text>
-					</view>
+					</view> -->
 					<view class="info-item">
 						<text class="info-label">归属名字</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.belongTypeName||'-'}}</text>
@@ -264,22 +264,22 @@
 						<text class="info-label">计划结束时间</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.planEndTime||'-'}}</text>
 					</view>
-					<view class="info-item">
+					<!-- <view class="info-item">
 						<text class="info-label">归属项目ID</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.projectId||'-'}}</text>
-					</view>
+					</view> -->
 					<view class="info-item">
 						<text class="info-label">项目名称</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.projectName||'-'}}</text>
 					</view>
-					<view class="info-item">
+					<!-- <view class="info-item">
 						<text class="info-label">医生id</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.doctorId||'-'}}</text>
 					</view>
 					<view class="info-item">
 						<text class="info-label">归属部门ID</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.deptId||'-'}}</text>
-					</view>
+					</view> -->
 					<view class="info-item">
 						<text class="info-label">部门名称</text>
 						<text class="info-value">{{ auditData.businessData.auditTaskInfoVO.deptName||'-'}}</text>

+ 22 - 15
pages_task/pointsSettings.vue

@@ -143,18 +143,25 @@
 			},
 			onLoad() {
 				// 从本地存储中获取选中的客户数据
-				const selectedCustomersStr = uni.getStorageSync('selectedCustomers')
-				if (selectedCustomersStr) {
-					const selectedCustomers = JSON.parse(selectedCustomersStr)
-					// 将选中的客户数据转换为积分设置需要的格式
-					this.customerList = selectedCustomers.map(customer => ({
-						id: customer.id,
-						name: customer.doctorName || '未知姓名',
-						doctorName: customer.doctorName || '未知姓名',
-						integral: '',
-						placeholder: '请输入积分',
-						disabled: false
-					}))
+				const selectedCustomersData = uni.getStorageSync('selectedCustomers')
+				if (selectedCustomersData) {
+					try {
+						const selectedCustomers = typeof selectedCustomersData === 'string' ? JSON.parse(selectedCustomersData) : selectedCustomersData
+						// 确保selectedCustomers是数组
+						if (Array.isArray(selectedCustomers)) {
+							// 将选中的客户数据转换为积分设置需要的格式
+							this.customerList = selectedCustomers.map(customer => ({
+								id: customer.id,
+								name: customer.doctorName || '未知姓名',
+								doctorName: customer.doctorName || '未知姓名',
+								integral: '',
+								placeholder: '请输入积分',
+								disabled: false
+							}))
+						}
+					} catch (e) {
+						console.error('解析客户数据失败:', e)
+					}
 				}
 			},
 		computed: {
@@ -224,8 +231,8 @@
 					const selectedCustomers = selectedCustomersStr ? JSON.parse(selectedCustomersStr) : []
 					
 					// 获取用户信息
-					const userInfoStr = uni.getStorageSync('userInfo')
-					const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {}
+					const userInfoData = uni.getStorageSync('userInfo')
+					const userInfo = typeof userInfoData === 'string' ? JSON.parse(userInfoData) : userInfoData || {}
 					
 					// 获取当前时间
 					const now = new Date()
@@ -277,7 +284,7 @@
 									// 延迟跳转,让用户看到成功提示
 									setTimeout(() => {
 										uni.navigateTo({
-											url: '/pages_task/taskList'
+											url: '/pages_task/success'
 										})
 									}, 1500)
 								}

+ 1 - 1
pages_task/success.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="container">
 		<image class="img" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/img_admitsuccess.png"></image>
-		<view class="title">定级材料提交成功!</view>
+		<view class="title">任务创建申请已提交!</view>
 		<view class="txt">预计1-2个工作日完成审核,请耐心等待</view>
 		<view class="return" @click="goBack">返回</view>
 	</view>

+ 148 - 0
pages_user/privacyPolicy.vue

@@ -0,0 +1,148 @@
+<template>
+	<view class="container">
+		<scroll-view class="content" scroll-y>
+			<view class="agreement-body">
+				<view class="title">隐私政策</view>
+				<view class="update-time">更新日期:2026年2月24日</view>
+
+				<view class="section">
+					<view class="section-text">「研究型互联网医院」平台(以下简称「我们」)深知个人信息对您的重要性,我们将按照法律法规要求,采取相应的安全保护措施,尽力保护您的个人信息安全可控。请您在使用我们的产品与/或服务前,仔细阅读并理解本《隐私政策》全部内容。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">一、我们如何收集和使用您的个人信息</view>
+					<view class="section-text">1.1 为向您提供注册、登录、认证、任务参与、积分与提现、客服与通知等服务,我们可能收集以下信息:</view>
+					<view class="section-text">· 账号信息:手机号、密码、昵称等;</view>
+					<view class="section-text">· 身份与职业信息:姓名、身份证号、执业证/职称证图片、职称、科室、机构、公司等(用于医生/药剂师认证);</view>
+					<view class="section-text">· 财务信息:银行卡号、开户行、支行等(用于提现);</view>
+					<view class="section-text">· 任务与行为信息:任务完成记录、上传内容、问卷与案例填写数据、浏览与操作日志等;</view>
+					<view class="section-text">· 设备与日志信息:设备型号、操作系统、唯一设备标识、IP 地址、访问时间等,用于保障账号安全与服务稳定。</view>
+					<view class="section-text">1.2 我们仅在法律允许及实现本政策所述目的所必需的范围内使用您的个人信息,包括:向您提供与改进服务、身份验证、安全与风控、争议处理、履行法定义务及经您同意的其他用途。</view>
+					<view class="section-text">1.3 我们不会将您的个人信息用于本政策未载明的其他目的;若需用于其他目的,我们会另行取得您的同意。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">二、我们如何使用 Cookie 与同类技术</view>
+					<view class="section-text">2.1 我们可能通过 Cookie、本地存储、SDK 等技术与手段收集与存储您的偏好、登录状态及设备相关信息,以便您获得更顺畅的访问体验、保障账号安全及进行数据统计。</view>
+					<view class="section-text">2.2 您可根据浏览器或设备设置管理或删除 Cookie/本地数据,但可能影响部分功能的使用。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">三、我们如何共享、转让、公开披露您的个人信息</view>
+					<view class="section-text">3.1 共享:我们不会与第三方共享您的个人信息,除非:经您明确同意;为完成合并、分立、收购或资产转让;与授权合作伙伴(如云服务、支付、实名认证服务商)在严格保密与约定范围内共享,且仅用于实现本政策所述目的。</view>
+					<view class="section-text">3.2 转让:我们不会将您的个人信息转让给任何公司、组织或个人,但以下情况除外:事先获得您的明确同意;在涉及合并、收购或破产清算时,如涉及个人信息转让,我们会要求受让方继续受本政策约束。</view>
+					<view class="section-text">3.3 公开披露:我们仅会在以下情况下公开披露您的个人信息:获得您明确同意;基于法律、法律程序、诉讼或政府主管部门强制性要求。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">四、我们如何存储与保护您的个人信息</view>
+					<view class="section-text">4.1 存储地点:我们在中华人民共和国境内收集和产生的个人信息,将存储在中国境内;如需跨境传输,我们会依法履行审批或告知义务。</view>
+					<view class="section-text">4.2 存储期限:我们仅在为实现目的所必需的期限内保留您的个人信息;当您删除账号或我们不再为您提供服务后,我们会在合理期限内删除或匿名化处理相关信息,法律法规另有规定的除外。</view>
+					<view class="section-text">4.3 安全措施:我们采取数据加密、访问控制、安全审计、脱敏处理等合理可行的措施,保护您的个人信息安全,防止未经授权的访问、公开、使用、修改或损坏。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">五、您如何管理您的个人信息</view>
+					<view class="section-text">5.1 您有权查询、更正、补充您的个人信息;您可通过「我的」-「个人信息」等入口进行查看与修改。</view>
+					<view class="section-text">5.2 在以下情形中,您可以向我们提出删除个人信息的请求:我们违反法律、行政法规或与您的约定收集、使用个人信息;我们违反法律、行政法规或与您的约定共享、转让、公开披露个人信息;您不再使用我们的产品或服务且您主动要求删除;我们不再为您提供产品或服务。</view>
+					<view class="section-text">5.3 您可改变授权范围或撤回同意(如关闭设备权限),我们将在权限变更后按新的授权范围处理您的信息;撤回同意可能导致部分功能无法使用。</view>
+					<view class="section-text">5.4 如您对上述权利或我们的处理有疑问,可通过本政策文末提供的联系方式与我们联系,我们将在法律规定期限内予以答复。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">六、未成年人保护</view>
+					<view class="section-text">6.1 我们的产品与/或服务主要面向医疗专业人士。若您为未成年人,请在监护人陪同下阅读本政策,并在取得监护人同意后使用我们的服务。</view>
+					<view class="section-text">6.2 若我们发现在未事先获得可证实的监护人同意的情况下收集了未成年人的个人信息,会尽快删除相关数据。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">七、本政策的更新与适用</view>
+					<view class="section-text">7.1 我们可能适时修订本政策,修订后的政策将在应用内或相关页面公布;若修订涉及重大权利义务变更,我们会通过弹窗、推送等方式另行提示。</view>
+					<view class="section-text">7.2 本政策适用于「研究型互联网医院」平台及其关联方提供的产品与/或服务;如某款产品或服务有单独的隐私说明,该说明与本政策不一致的,以该产品或服务的隐私说明为准。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">八、如何联系我们</view>
+					<view class="section-text">8.1 如您对本隐私政策或您的个人信息处理有任何疑问、意见或建议,您可通过应用内客服、或我们公示的其他联系方式与我们联系。</view>
+					<view class="section-text">8.2 我们将在收到您的反馈后,在法律法规规定的期限内予以回复。</view>
+				</view>
+
+				<view class="footer">感谢您对研究型互联网医院平台的信任与支持。</view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {}
+	},
+	onLoad() {}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	min-height: 100vh;
+	background: #fff;
+	display: flex;
+	flex-direction: column;
+}
+
+.content {
+	flex: 1;
+	height: 100vh;
+}
+
+.agreement-body {
+	padding: 32rpx 24rpx 48rpx;
+}
+
+.title {
+	font-size: 40rpx;
+	font-weight: bold;
+	color: #333;
+	text-align: center;
+	margin-bottom: 16rpx;
+}
+
+.update-time {
+	font-size: 24rpx;
+	color: #999;
+	text-align: center;
+	margin-bottom: 40rpx;
+}
+
+.section {
+	margin-bottom: 36rpx;
+
+	.section-title {
+		font-size: 30rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 16rpx;
+		line-height: 1.5;
+	}
+
+	.section-text {
+		font-size: 28rpx;
+		color: #666;
+		line-height: 1.75;
+		margin-bottom: 12rpx;
+		text-align: justify;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
+	}
+}
+
+.footer {
+	font-size: 26rpx;
+	color: #999;
+	text-align: center;
+	margin-top: 32rpx;
+	padding-top: 24rpx;
+}
+</style>

+ 159 - 0
pages_user/userAgreement.vue

@@ -0,0 +1,159 @@
+<template>
+	<view class="container">
+		<scroll-view class="content" scroll-y>
+			<view class="agreement-body">
+				<view class="title">用户协议</view>
+				<view class="update-time">更新日期:2026年2月24日</view>
+
+				<view class="section">
+					<view class="section-title">一、协议的接受与修订</view>
+					<view class="section-text">1.1 本协议是您与「研究型互联网医院」平台(以下简称「本平台」)之间关于使用本平台服务所订立的协议。请您仔细阅读本协议全部内容,未成年人应在法定监护人陪同下阅读。</view>
+					<view class="section-text">1.2 您使用本平台服务即视为已阅读并同意接受本协议约束。若您不同意本协议任何条款,请立即停止使用本平台服务。</view>
+					<view class="section-text">1.3 本平台有权根据需要修改本协议条款,修改后的协议将在平台内公布。若您继续使用服务,即视为接受修订后的协议。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">二、服务说明</view>
+					<view class="section-text">2.1 本平台面向医生、药剂师等医疗相关专业人士,提供医学教育、任务参与、积分与提现、认证管理、问卷与案例收集等相关服务。</view>
+					<view class="section-text">2.2 本平台提供的服务内容可能随业务调整而变更,具体以平台实际展示为准。本平台保留在不另行通知的情况下调整、中断或终止部分或全部服务的权利。</view>
+					<view class="section-text">2.3 您理解并同意,本平台仅提供信息与任务撮合服务,不替代任何医疗行为或专业判断,您在使用服务过程中应遵守国家法律法规及行业规范。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">三、账号注册与使用</view>
+					<view class="section-text">3.1 您应使用真实、准确的信息完成注册与认证。若您为医生或药剂师,需按要求提供执业证、职称证等材料,并保证所提交信息真实有效。</view>
+					<view class="section-text">3.2 您应妥善保管账号与密码,对使用该账号进行的一切行为负责。如发现账号被盗用或存在异常,请及时联系平台处理。</view>
+					<view class="section-text">3.3 您不得将账号出借、转让或以其他方式供他人使用;不得利用本平台从事违法违规活动或损害他人合法权益的行为。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">四、用户行为规范</view>
+					<view class="section-text">4.1 您在使用本平台服务时,应遵守中华人民共和国相关法律法规,不得发布违法、虚假、侵权或违背公序良俗的内容。</view>
+					<view class="section-text">4.2 您参与任务(如科普创作、短视频/长视频、问卷、用药调研、案例收集等)时,应保证所提交内容原创或已获授权,不得抄袭、剽窃或侵犯他人知识产权。</view>
+					<view class="section-text">4.3 您不得利用技术手段干扰平台正常运行、破坏数据或窃取他人信息;不得进行刷量、作弊等影响公平性的行为。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">五、积分与提现</view>
+					<view class="section-text">5.1 本平台积分规则以平台内公示为准。积分可用于兑换、提现等,具体规则以当时有效说明为准。</view>
+					<view class="section-text">5.2 提现需绑定真实有效的银行卡及身份信息,并可能需满足最低提现金额、实名认证等条件。因您提供信息有误导致的提现失败或延迟由您自行承担。</view>
+					<view class="section-text">5.3 如发现作弊、虚假任务完成等违规行为,本平台有权扣减或清零积分,并保留追究法律责任的权利。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">六、知识产权</view>
+					<view class="section-text">6.1 本平台所包含的商标、标识、界面设计、软件等知识产权归本平台或相关权利人所有。未经书面许可,您不得擅自使用、复制或修改。</view>
+					<view class="section-text">6.2 您在本平台上传、发布的内容,在您保留著作权的前提下,授予本平台在全球范围内、免费的、非独家的、可再许可的使用权,用于平台运营、展示、推广等目的。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">七、隐私与个人信息</view>
+					<view class="section-text">7.1 我们重视您的隐私。收集、使用、存储及保护个人信息的规则以《隐私政策》为准,请您一并阅读。</view>
+					<view class="section-text">7.2 为提供服务,我们可能收集您的账号信息、认证信息、任务完成记录、设备信息等,并可能依法向合作方或监管部门提供。我们不会在未经您同意的情况下向无关第三方出售您的个人信息。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">八、免责与责任限制</view>
+					<view class="section-text">8.1 因网络状况、不可抗力、政府行为等原因导致的服务中断或数据丢失,本平台将尽力恢复但不承担由此产生的责任。</view>
+					<view class="section-text">8.2 您通过本平台发布的内容由您自行负责。若因您的内容引发纠纷或给本平台或第三方造成损失,由您承担相应责任。</view>
+					<view class="section-text">8.3 在法律允许的范围内,本平台对因使用或无法使用服务而产生的间接、附带、惩罚性损失不承担责任。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">九、协议终止</view>
+					<view class="section-text">9.1 您可随时停止使用服务并注销账号(如有注销入口)。本平台也可在您违反本协议或法律法规时,暂停或终止向您提供服务。</view>
+					<view class="section-text">9.2 协议终止后,您使用服务的权利即行终止;本平台有权保留您的历史数据以履行法定义务或解决纠纷。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">十、法律适用与争议解决</view>
+					<view class="section-text">10.1 本协议的订立、执行与解释均适用中华人民共和国法律(不含冲突法)。</view>
+					<view class="section-text">10.2 因本协议产生的争议,双方应友好协商;协商不成的,任何一方可向本平台运营主体所在地有管辖权的人民法院提起诉讼。</view>
+				</view>
+
+				<view class="section">
+					<view class="section-title">十一、其他</view>
+					<view class="section-text">11.1 本协议条款如部分无效,不影响其余条款的效力。</view>
+					<view class="section-text">11.2 本平台未行使或延迟行使本协议项下权利,不构成对该权利的放弃。</view>
+					<view class="section-text">11.3 如您对本协议有任何疑问,可通过平台内客服或公示的联系方式与我们联系。</view>
+				</view>
+
+				<view class="footer">感谢您使用研究型互联网医院平台。</view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {}
+	},
+	onLoad() {}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	min-height: 100vh;
+	background: #fff;
+	display: flex;
+	flex-direction: column;
+}
+
+.content {
+	flex: 1;
+	height: 100vh;
+}
+
+.agreement-body {
+	padding: 32rpx 24rpx 48rpx;
+}
+
+.title {
+	font-size: 40rpx;
+	font-weight: bold;
+	color: #333;
+	text-align: center;
+	margin-bottom: 16rpx;
+}
+
+.update-time {
+	font-size: 24rpx;
+	color: #999;
+	text-align: center;
+	margin-bottom: 40rpx;
+}
+
+.section {
+	margin-bottom: 36rpx;
+
+	.section-title {
+		font-size: 30rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 16rpx;
+		line-height: 1.5;
+	}
+
+	.section-text {
+		font-size: 28rpx;
+		color: #666;
+		line-height: 1.75;
+		margin-bottom: 12rpx;
+		text-align: justify;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
+	}
+}
+
+.footer {
+	font-size: 26rpx;
+	color: #999;
+	text-align: center;
+	margin-top: 32rpx;
+	padding-top: 24rpx;
+}
+</style>

+ 2 - 2
pages_user/userInfo.vue

@@ -10,7 +10,7 @@
 					<view class="info-item">
 						<view class="label">头像</view>
 						<view class="right">
-							<image class="head" :src="formData.avatar||'https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/395926010.cos.ap-chengdu.myqcloud.com/image/my_heads_icon.png'"></image>
+							<image class="head" :src="formData.avatar||'https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/my_heads_icon.png'"></image>
 							<button class="wx-head" type="balanced" open-type="chooseAvatar"
 								@chooseavatar="onChooseAvatar"></button>
 						</view>
@@ -26,7 +26,7 @@
 						<view class="label">性别</view>
 						<view class="right">
 							<text class="txt">{{formData.sex==1?'男':'女'}}</text>
-							<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/395926010.cos.ap-chengdu.myqcloud.com/image/icon_my_more.png" mode=""></image>
+							<image class="icon" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_my_more.png" mode=""></image>
 						</view>
 					</view>
 				</view>