Browse Source

Merge branch 'master' of http://150.158.33.144:3000/lalalashen/MoeNovaClient

lalalashen 3 months ago
parent
commit
dc054489a7

+ 11 - 3
components/tabbar/tabbar.vue

@@ -14,7 +14,9 @@
 		<view class="midButton">
 			<image class="image" src="../../static/tabbar-icon/center.png" mode=""></image>
 		</view>
-		<uv-safe-bottom></uv-safe-bottom>
+		<view class="safe-bottom-area" style="background-color: #fff;">
+			<uv-safe-bottom></uv-safe-bottom>
+		</view>
 	</view>
 </template>
 <script>
@@ -120,12 +122,13 @@
 		// #ifndef APP-NVUE
 		box-sizing: border-box;
 		// #endif
-
+		display: flex;
+		flex-direction: column;
 	}
 
 	.tabbar-bottom {
 		width: 750rpx;
-		height: 120rpx;
+		flex: 1;
 		// #ifndef APP-NVUE
 		display: flex;
 		// #endif
@@ -188,4 +191,9 @@
 		justify-content: center;
 		align-items: center;
 	}
+
+	.safe-bottom-area {
+		width: 750rpx;
+		background-color: #fff;
+	}
 </style>

+ 6 - 0
pages.json

@@ -177,6 +177,12 @@
 				"navigationBarTitleText": "设置",
 				"navigationBarBackgroundColor": "#ffffff"
 			}
+		}, {
+			"path": "pages/my/task",
+			"style": {
+				"navigationBarTitleText": "任务中心",
+				"navigationBarBackgroundColor": "#ffffff"
+			}
 		}, {
 			"path": "pages/AboutUs/xieyi",
 			"style": {

+ 9 - 0
pages/message/mailMessage.scss

@@ -221,4 +221,13 @@ page {
 }
 .blankHeight {
 	height:300rpx;
+}
+.loading-more {
+	width: 100%;
+	height: 80rpx;
+	text-align: center;
+	color: #999;
+	font-size: 24rpx;
+	line-height: 80rpx;
+	margin-bottom: 20rpx;
 }

+ 106 - 36
pages/message/mailMessage.vue

@@ -2,7 +2,7 @@
 	<view class="page">
 		<view class="mainBody">
 			<scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="0">
-<!-- 				<view class="item" :class="{'active':tab===0}" @click="checkTab(0)">
+				<!-- 				<view class="item" :class="{'active':tab===0}" @click="checkTab(0)">
 					<text class="left">全部</text>
 					<view class="line"></view>
 				</view> -->
@@ -22,37 +22,42 @@
 					</view>
 					<view class="content">
 						<view class="tit">
-							<view class="name">{{item.name}}</view>
-							<view class="time">{{item.time}}</view>
-							<view class="desc">{{item.desc}}</view>
-						</view>
-						<view class="thumbnail">
-							<image :src="item.thumbnail" mode="aspectFill"></image>
+							<view class="name">{{item.title}}</view>
+							<view class="time">{{item.create_time}}</view>
+							<view class="desc">{{item.content}}</view>
 						</view>
 					</view>
 				</view>
 			</block>
 			<view class="blankHeight"></view>
+			<view class="loading-more" v-if="tab === 2">
+				<text v-if="isLoading">正在加载更多...</text>
+				<text v-else-if="!hasMore">没有更多内容了</text>
+			</view>
 		</view>
 
 		<view class="list_article" v-if="tab === 1">
 			<block v-for="(item,index) in list2" :key="index">
 				<view class="item" @click="goDetail(item)">
 					<view class="thumbnail">
-						<image :src="item.thumbnail" mode="aspectFill"></image>
+						<image :src="item.image" mode="aspectFill"></image>
 					</view>
 					<view class="title">{{item.title}}</view>
 					<view class="content">{{item.content}}</view>
 					<view class="divider"></view>
-					<view class="time">{{item.time}}</view>
+					<view class="time">{{item.create_time}}</view>
 				</view>
 			</block>
 			<view class="blankHeight"></view>
+			<view class="loading-more" v-if="tab === 1">
+				<text v-if="isLoading">正在加载更多...</text>
+				<text v-else-if="!hasMore">没有更多内容了</text>
+			</view>
 		</view>
 
 		<DialogBox ref="DialogBox"></DialogBox>
 		<ToastW3 ref="ToastW3"></ToastW3>
-		
+
 		<tabbar-view :tabbars="tabbars" :currentIndex="3" ref="tabbar"></tabbar-view>
 	</view>
 </template>
@@ -72,37 +77,39 @@
 				old: {
 					scrollTop: 0
 				},
-				list: [{
-					image: '/static/images/avatar.png',
-					name: '张三',
-					time: '2024-03-20 12:30',
-					desc: '给你点赞了一下作品',
-					thumbnail: '/static/images/thumb1.png'
+				list: [],
+				list2: [],
+				cate: [{
+					"name": "消息",
+					id: 1
 				}, {
-					image: '/static/images/avatar2.png',
-					name: '李四',
-					time: '2024-03-19 15:45',
-					desc: '评论了你的作品:真不错!',
-					thumbnail: '/static/images/thumb2.png'
+					"name": "点赞和评论",
+					id: 2
 				}],
-				list2: [{
-					thumbnail: '/static/images/article1.png',
-					title: '2024年最新艺术设计趋势',
-					content: '近期艺术设计领域出现了许多新的趋势,本文将为您详细解析这些新趋势带来的机遇与挑战...',
-					time: '2024-03-20 10:00'
-				}, {
-					thumbnail: '/static/images/article2.png',
-					title: '如何提升作品质量',
-					content: '作品质量是艺术创作中最重要的环节,本文将分享一些实用的技巧和方法...',
-					time: '2024-03-19 14:30'
-				}],
-				cate: [{"name": "消息",id: 1},{"name": "点赞和评论",id: 2}],
+				offset: 0,
+				isLoading: false,
+				hasMore: true,
+				pageSize: 20,
+				typeMap: {
+					1: 'sms',
+					2: 'hudong'
+				}
 			}
 		},
-		onLoad() {},
-		onShow() {
+		onLoad() {
 			this.loadData();
 		},
+		onShow() {
+			this.refreshData();
+		},
+		onPullDownRefresh() {
+			this.refreshData();
+		},
+		onReachBottom() {
+			if (this.hasMore && !this.isLoading) {
+				this.loadMore();
+			}
+		},
 		onNavigationBarButtonTap(e) {
 			if (e.index === 0) {
 				// uni.navigateTo({
@@ -114,7 +121,7 @@
 			onBack() {},
 			checkTab(tab) {
 				this.tab = tab;
-				this.loadData();
+				this.refreshData();
 			},
 			scroll: function(e) {
 				console.log(e)
@@ -122,9 +129,72 @@
 			},
 			goDetail(item) {
 
+			},
+			refreshData() {
+				this.offset = 0;
+				this.hasMore = true;
+				if (this.tab === 1) {
+					this.list2 = [];
+				} else {
+					this.list = [];
+				}
+				this.loadData();
+			},
+			loadMore() {
+				this.offset += this.pageSize;
+				this.loadData();
 			},
 			loadData() {
+				if (this.isLoading) return;
+				this.isLoading = true;
+
+				const type = this.typeMap[this.tab];
+				if (!type) {
+					this.isLoading = false;
+					return;
+				}
+
+				uni.request({
+					url: this.$apiHost + '/Sms/getlist',
+					method: 'GET',
+					data: {
+						uuid: getApp().globalData.uuid,
+						skey: getApp().globalData.skey,
+						type: type,
+						offset: this.offset
+					},
+					header: {
+						"content-type": "application/json",
+						'sign': getApp().globalData.headerSign
+					},
+					success: (res) => {
+						console.log('xx1', res.data);
+						if (res.data && res.data.success == 'yes' && res.data.list) {
+							const newData = res.data.list || [];
+
+							if (newData.length < this.pageSize) {
+								this.hasMore = false;
+							}
 
+							if (this.tab === 1) {
+								this.list2 = this.offset === 0 ? newData : [...this.list2, ...newData];
+							} else {
+								this.list = this.offset === 0 ? newData : [...this.list, ...newData];
+							}
+						} else {
+							this.hasMore = false;
+							this.$refs.ToastW3.show('加载失败,请稍后重试');
+						}
+					},
+					fail: () => {
+						this.hasMore = false;
+						this.$refs.ToastW3.show('网络错误,请检查网络连接');
+					},
+					complete: () => {
+						this.isLoading = false;
+						uni.stopPullDownRefresh();
+					}
+				});
 			},
 		}
 	}

+ 1 - 1
pages/my/idcheck.scss

@@ -34,7 +34,7 @@ page {
 		// position: relative;
 		width: 610rpx;
 		height: 84rpx;
-		background: #282828;
+		background: #f0f0f0;
 		border-radius: 24rpx 24rpx 24rpx 24rpx;
 		margin-top: 48rpx;
 		.left {

+ 3 - 3
pages/my/idcheck.vue

@@ -22,14 +22,14 @@
 				<image style="margin-top: 150rpx;height: 120rpx;" src="../../static/me/img_checkMark.png"
 					mode="heightFix" />
 				<text
-					style="margin-top: 60rpx;margin-bottom: 30rpx;color:#FFFFFF;font-size: 28rpx;">{{$t('txt.恭喜您已完成实名认证')}}</text>
+					style="margin-top: 60rpx;margin-bottom: 30rpx;color:#333;font-size: 28rpx;">{{$t('txt.恭喜您已完成实名认证')}}</text>
 
 				<view class="idList">
 					<view class="left">
 						<text style="font-size: 28rpx;color: #999999;">{{$t('txt.姓名')}}</text>
 					</view>
 					<view class="right">
-						<text style="font-size: 28rpx;color: #ffffff;">{{myinfo.realname}}</text>
+						<text style="font-size: 28rpx;color: #333;">{{myinfo.realname}}</text>
 					</view>
 				</view>
 
@@ -38,7 +38,7 @@
 						<text style="font-size: 28rpx;color: #999999;">{{$t('txt.身份证号')}}</text>
 					</view>
 					<view class="right">
-						<text style="font-size: 28rpx;color: #ffffff;">{{myinfo.idcard}}</text>
+						<text style="font-size: 28rpx;color: #333;">{{myinfo.idcard}}</text>
 					</view>
 				</view>
 

+ 15 - 3
pages/my/my.scss

@@ -22,7 +22,7 @@ page {
 	.topBg {
 		width:750rpx;
 		height:250rpx;
-		background: #FFA54F;
+		background: #90d369;
 		border-radius: 0 0 50% 50% / 0 0 20% 20%;
 		z-index: 0;
 		position: absolute;
@@ -49,12 +49,12 @@ page {
 			margin-left: 20rpx;
 			
 			text:first-child {
-				font-size: 24rpx;
+				font-size: 24rpx;line-height: 32rpx;
 				color: #666;
 			}
 			
 			text:last-child {
-				font-size: 32rpx;
+				font-size: 32rpx;line-height: 32rpx;
 				font-weight: bold;
 				color: #333;
 			}
@@ -355,4 +355,16 @@ page {
 }
 .blankHeight {
 	height:100rpx;
+}
+.loading-more {
+	text-align: center;
+	padding: 20rpx 0;
+	color: #999;
+	font-size: 28rpx;
+}
+.no-more {
+	text-align: center;
+	padding: 20rpx 0;
+	color: #999;
+	font-size: 28rpx;
 }

+ 65 - 18
pages/my/my.vue

@@ -71,14 +71,19 @@
 					</view>
 				</view>
 				<view class="numlist2" style="margin-top: 60rpx;">
-					<view class="item" v-for="(item,index) in data_list">
+					<view class="item" v-for="(item,index) in worksList" :key="index">
 						<view class="num">
-							<image class="icon" :src="item.url" mode="widthFix" />
-							<view class="name">作品1号</view>
+							<image class="icon" :src="item.images" mode="widthFix" />
+							<view class="name">{{item.title || '作品'+index}}</view>
 						</view>
 					</view>
 				</view>
 
+				<!-- 加载更多提示 -->
+				<view class="loading-more" v-if="isLoading">加载中...</view>
+				<view class="no-more" v-if="!hasMore && worksList.length > 0">没有更多作品了</view>
+				<view class="no-more" v-if="!hasMore && worksList.length === 0">暂无作品</view>
+
 			</view>
 
 			<view class="blankHeight"></view>
@@ -157,7 +162,11 @@
 
 
 				],
-				activeTab: 0
+				activeTab: 0,
+				offset: 0,
+				hasMore: true,
+				isLoading: false,
+				worksList: []
 			}
 		},
 		onLoad() {
@@ -177,6 +186,12 @@
 			// this.loadData();
 			// this.loadMenu();
 			this.loadInfo();
+			this.loadWorksList();
+		},
+		onReachBottom() {
+			if (this.hasMore && !this.isLoading) {
+				this.loadMoreWorks();
+			}
 		},
 		methods: {
 			onBack() {},
@@ -297,38 +312,70 @@
 			},
 			switchTab(index) {
 				this.activeTab = index;
-				this.loadData();
+				this.offset = 0;
+				this.hasMore = true;
+				this.worksList = [];
+				this.loadWorksList();
 			},
-			loadData() {
-				console.log({
-					uuid: getApp().globalData.uuid,
-					skey: getApp().globalData.skey
-				});
+			loadWorksList() {
+				if (this.isLoading) return;
+				this.isLoading = true;
+
+				const status = this.activeTab === 0 ? 1 : 2; // 0=我的作品(已生成),1=生成中
+
 				uni.request({
-					url: this.$apiHost + '/My/getdata',
+					url: this.$apiHost + '/Work/getlist',
 					data: {
 						uuid: getApp().globalData.uuid,
-						skey: getApp().globalData.skey
+						skey: getApp().globalData.skey,
+						ismy: 1, // 固定为1,表示获取自己的作品
+						offset: this.offset,
+						status: status
 					},
 					header: {
 						"content-type": "application/json",
 						'sign': getApp().globalData.headerSign
 					},
 					success: (res) => {
-						console.log("----:", res.data);
-						if (res.data.success == 'yes') {
+						console.log("作品列表数据:", res.data);
+						if (res.data.success == 'yes' && res.data.list) {
+							if (res.data.list.length > 0) {
+								this.worksList = [...this.worksList, ...res.data.list];
+								this.offset += res.data.list.length;
+							}
 
+							if (res.data.list.length < 20) {
+								this.hasMore = false;
+							}
+						} else {
+							this.hasMore = false;
 						}
-						// this.myinfo = res.data;
+
+						this.updateDataList();
 					},
-					complete: (com) => {
-						// uni.hideLoading();
+					complete: () => {
+						this.isLoading = false;
 					},
 					fail: (e) => {
-						console.log("----e:", e);
+						console.log("请求作品列表失败:", e);
+						this.isLoading = false;
 					}
 				});
 			},
+			loadMoreWorks() {
+				if (this.hasMore && !this.isLoading) {
+					this.loadWorksList();
+				}
+			},
+			updateDataList() {
+				this.data_list = this.worksList.map(item => {
+					return {
+						url: item.img_url || item.url || '../../static/logo.png',
+						title: item.title || '作品',
+						id: item.id
+					};
+				});
+			},
 		}
 	}
 </script>

+ 1 - 1
pages/my/normal.scss

@@ -220,7 +220,7 @@ page {
 	display: flex;flex-direction: row;justify-content: space-between;align-items: center;
 	.btn_submit1 {
 		width: 326rpx;height: 96rpx;border: 2rpx solid #D0D0D0;
-		border-radius: 28rpx;font-weight: normal;font-size: 32rpx;color: #FFFFFF;
+		border-radius: 28rpx;font-weight: normal;font-size: 32rpx;color: #959595;
 		display: flex;flex-direction: row;justify-content: center;align-items: center;
 	}
 	.btn_submit2 {

+ 593 - 0
pages/my/task.scss

@@ -0,0 +1,593 @@
+page {
+	background-color: #fff;
+}
+
+.page {
+	background-color: #fff;
+	position: relative;
+}
+
+// 顶部黄色背景
+.top-bg {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 200rpx;
+	background-color: #90d369;
+	z-index: 0;
+}
+
+// 内容区域
+.content-area {
+	position: relative;
+	z-index: 1;
+	padding: 30rpx;
+}
+
+.topbg {
+}
+
+.topBody {
+	width:750rpx;
+}
+
+.header {
+	display: flex;flex-direction: row;justify-content: space-between;align-items: center;color:$title;
+
+	.title {
+		font-size: 34rpx;
+	}
+}
+
+.thread {
+	height:210rpx;
+	padding:50rpx;font-size: 52rpx;color:#6E6A6A;padding-top: 80rpx;
+}
+
+.mainInfo {
+	width: 690rpx;
+	margin:30rpx 30rpx 60rpx;
+	display:flex;flex-direction: column;justify-content: space-around;
+	align-items: center;
+	// background: #FFFFFF;
+	
+	
+	.idList {
+		display: flex;flex-direction: row;justify-content: space-between;align-items: center;
+		// position: relative;
+		width: 610rpx;
+		height: 84rpx;
+		background: #282828;
+		border-radius: 24rpx 24rpx 24rpx 24rpx;
+		margin-top: 48rpx;
+		.left {
+			display: flex;flex-direction: row;justify-content: flex-start;align-items: center;
+			padding-left:24rpx;
+
+
+		}
+		.right{
+			display: flex;flex-direction: row;justify-content: flex-start;align-items: center;
+			padding-right:24rpx;
+
+
+		}
+
+	}
+	
+	.reCheckBtn{
+		width: 610rpx;
+		height: 96rpx;
+		border-radius: 28rpx 28rpx 28rpx 28rpx;
+		border: 2rpx solid #404040;
+		display:flex;flex-direction: column;justify-content: space-around;
+		align-items: center;
+		margin-top: 74rpx;
+	}
+	
+}
+
+.blankHeight {
+	height:100rpx;
+}
+
+// 彩豆余额展示区
+.bean-balance {
+	width: 690rpx;
+	background-color: #FFFFFF;
+	border-radius: 24rpx;
+	padding: 30rpx;
+	margin-bottom: 30rpx;
+	box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
+	
+	.balance-header {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		
+		.title-area {
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			
+			.yellow-dot {
+				width: 16rpx;
+				height: 16rpx;
+				border-radius: 50%;
+				background-color: #90d369;
+				margin-right: 10rpx;
+			}
+			
+			.my-bean-title {
+				font-size: 32rpx;
+				color: #333;
+				font-weight: bold;
+			}
+		}
+		
+		.exchange-btn {
+			width: 120rpx;
+			height: 60rpx;
+			background-color: #90d369;
+			border-radius: 30rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			font-size: 28rpx;
+			color: #fff;
+			font-weight: bold;
+		}
+	}
+	
+	.bean-number {
+		font-size: 80rpx;
+		font-weight: bold;
+		color: #333;
+		margin-top: 20rpx;
+	}
+}
+
+// 星愿打卡区域
+.sign-cards {
+	display: flex;
+	flex-direction: row;
+	justify-content: space-between;
+	margin-bottom: 30rpx;
+	
+	.card {
+		width: 330rpx;
+		height: 240rpx;
+		border-radius: 24rpx;
+		padding: 24rpx;
+		display: flex;
+		flex-direction: column;
+		box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
+		
+		.card-title {
+			font-size: 34rpx;
+			font-weight: bold;
+			color: #FFFFFF;
+			margin-bottom: 10rpx;
+		}
+		
+		.card-desc {
+			font-size: 24rpx;
+			color: rgba(255, 255, 255, 0.8);
+			margin-bottom: 30rpx;
+		}
+		
+		.card-reward {
+			font-size: 30rpx;
+			color: #FFFFFF;
+			font-weight: bold;
+		}
+		
+		.card-progress {
+			font-size: 36rpx;
+			color: #FFFFFF;
+			font-weight: bold;
+			margin-top: auto;
+		}
+		
+		.sign-btn {
+			width: 180rpx;
+			height: 70rpx;
+			background-color: #FFFFFF;
+			border-radius: 35rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			font-size: 28rpx;
+			color: #333;
+			font-weight: bold;
+			margin-top: auto;
+		}
+	}
+	
+	.purple-card {
+		background-color: #9C27B0;
+	}
+	
+	.yellow-card {
+		background-color: #90d369;
+	}
+}
+
+// 任务列表
+.task-list {
+	background-color: #FFFFFF;
+	border-radius: 24rpx;
+	padding: 30rpx;
+	box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
+	
+	.task-header {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		margin-bottom: 30rpx;
+		
+		.task-title {
+			font-size: 34rpx;
+			color: #333;
+			font-weight: bold;
+			margin-right: 20rpx;
+		}
+		
+		.task-subtitle {
+			font-size: 24rpx;
+			color: #999;
+		}
+	}
+	
+	.task-item {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		padding: 20rpx 0;
+		border-bottom: 1px solid #F0F0F0;
+		
+		.task-info {
+			flex: 1;
+			
+			.task-name {
+				font-size: 30rpx;
+				color: #333;
+				margin-bottom: 6rpx;
+			}
+			
+			.task-desc {
+				font-size: 24rpx;
+				color: #999;
+			}
+		}
+		
+		.task-reward {
+			font-size: 30rpx;
+			color: #90d369;
+			font-weight: bold;
+			margin-right: 20rpx;
+		}
+		
+		.task-btn {
+			width: 120rpx;
+			height: 60rpx;
+			background-color: #90d369;
+			border-radius: 30rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			font-size: 26rpx;
+			color: #fff;
+			font-weight: bold;
+		}
+		
+		.task-completed {
+			background-color: #F0F0F0;
+			color: #999;
+		}
+	}
+}
+
+// 彩豆兑换弹窗
+.exchange-popup {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 999;
+	
+	.popup-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		background-color: rgba(0, 0, 0, 0.5);
+	}
+	
+	.popup-content {
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		background-color: #F5F5F5;
+		border-radius: 24rpx 24rpx 0 0;
+		padding-bottom: 50rpx;
+		
+		.popup-header {
+			display: flex;
+			flex-direction: row;
+			justify-content: space-between;
+			align-items: center;
+			padding: 30rpx;
+			
+			.available-balance {
+				font-size: 28rpx;
+				color: #333;
+			}
+			
+			.exchange-title {
+				font-size: 28rpx;
+				color: #333;
+				font-weight: bold;
+			}
+		}
+		
+		.exchange-area {
+			background-color: #FFFFFF;
+			margin: 0 30rpx;
+			border-radius: 20rpx;
+			padding: 30rpx;
+			
+			.exchange-title-area {
+				margin-bottom: 40rpx;
+				
+				.exchange-main-title {
+					font-size: 34rpx;
+					color: #333;
+					font-weight: bold;
+					display: block;
+					margin-bottom: 10rpx;
+				}
+				
+				.exchange-subtitle {
+					font-size: 24rpx;
+					color: #999;
+				}
+			}
+			
+			.input-area {
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+				padding: 20rpx 0;
+				border-bottom: 1px solid #F0F0F0;
+				margin-bottom: 50rpx;
+				
+				.bean-icon {
+					width: 40rpx;
+					height: 40rpx;
+					border-radius: 50%;
+					background-color: #FFE156;
+					margin-right: 20rpx;
+				}
+				
+				.exchange-input {
+					flex: 1;
+					height: 60rpx;
+					font-size: 30rpx;
+				}
+			}
+			
+			.action-area {
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				
+				.exchange-btn-large {
+					width: 100%;
+					height: 90rpx;
+					background-color: #DDDDDD;
+					border-radius: 45rpx;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					font-size: 32rpx;
+					color: #333;
+					font-weight: bold;
+					margin-bottom: 20rpx;
+				}
+				
+				.tips-text {
+					font-size: 24rpx;
+					color: #999;
+					text-align: center;
+				}
+			}
+		}
+	}
+}
+
+// 签到弹窗
+.sign-popup {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 1000;
+	
+	.popup-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		background-color: rgba(0, 0, 0, 0.5);
+	}
+	
+	.sign-popup-content {
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		background: #FFFFFF;
+		border-radius: 24rpx 24rpx 0 0;
+		padding: 30rpx;
+		padding-bottom: 50rpx;
+		
+		.sign-popup-header {
+			position: relative;
+			padding-bottom: 30rpx;
+			
+			.sign-popup-title {
+				font-size: 36rpx;
+				color: #333333;
+				font-weight: bold;
+				margin-bottom: 30rpx;
+				display: block;
+			}
+			
+			.sign-notify-switch {
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+				position: absolute;
+				top: 0;
+				right: 0;
+				
+				.sign-notify-text {
+					font-size: 24rpx;
+					color: #666666;
+					margin-right: 10rpx;
+				}
+				
+				.sign-switch {
+					transform: scale(0.7);
+				}
+			}
+			
+			.sign-days-tag {
+				display: inline-block;
+				padding: 6rpx 20rpx;
+				background-color: #FFD54F;
+				border-radius: 24rpx;
+				font-size: 24rpx;
+				color: #333;
+				font-weight: bold;
+			}
+		}
+		
+		.vip-area {
+			display: flex;
+			flex-direction: row;
+			justify-content: space-between;
+			align-items: center;
+			background-color: #F5F5F5;
+			border-radius: 12rpx;
+			padding: 20rpx;
+			margin-bottom: 30rpx;
+			
+			.vip-left {
+				.vip-text {
+					font-size: 26rpx;
+					color: #333333;
+				}
+			}
+			
+			.vip-right {
+				.vip-offer {
+					font-size: 24rpx;
+					color: #9C27B0;
+				}
+			}
+		}
+		
+		.sign-grid {
+			display: flex;
+			flex-direction: row;
+			flex-wrap: wrap;
+			margin: 0 -10rpx;
+			margin-bottom: 40rpx;
+			
+			.sign-grid-item {
+				width: calc(33.33% - 20rpx);
+				background-color: #F5F5F5;
+				border-radius: 12rpx;
+				padding: 20rpx;
+				margin: 10rpx;
+				position: relative;
+				height: 180rpx;
+				display: flex;
+				flex-direction: column;
+				
+				.sign-day-num {
+					font-size: 24rpx;
+					color: #666666;
+					margin-bottom: 10rpx;
+				}
+				
+				.sign-item-img {
+					width: 70rpx;
+					height: 70rpx;
+					background-color: #DDDDDD;
+					border-radius: 50%;
+					margin: 10rpx auto;
+				}
+				
+				.sign-item-name {
+					font-size: 24rpx;
+					color: #333333;
+					text-align: center;
+					margin-top: auto;
+				}
+				
+				.sign-vip-tag {
+					position: absolute;
+					top: 20rpx;
+					right: 20rpx;
+					padding: 4rpx 10rpx;
+					background-color: #9C27B0;
+					border-radius: 10rpx;
+					font-size: 20rpx;
+					color: #FFFFFF;
+				}
+				
+				.sign-received-mask {
+					position: absolute;
+					top: 0;
+					left: 0;
+					width: 100%;
+					height: 100%;
+					background-color: rgba(0, 0, 0, 0.5);
+					border-radius: 12rpx;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					
+					.received-text {
+						font-size: 28rpx;
+						color: #FFFFFF;
+						font-weight: bold;
+					}
+				}
+			}
+		}
+		
+		.sign-btn-large {
+			width: 100%;
+			height: 90rpx;
+			background-color: #9C27B0;
+			border-radius: 45rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			font-size: 32rpx;
+			color: #FFFFFF;
+			font-weight: bold;
+		}
+	}
+}

+ 364 - 0
pages/my/task.vue

@@ -0,0 +1,364 @@
+<template>
+	<view class="page">
+		<!-- 顶部黄色背景 -->
+		<view class="top-bg"></view>
+		
+		<!-- 内容区域 -->
+		<view class="content-area">
+			<!-- 彩豆余额展示区 -->
+			<view class="bean-balance">
+				<view class="balance-header">
+					<view class="title-area">
+						<view class="yellow-dot"></view>
+						<text class="my-bean-title">我的彩豆</text>
+					</view>
+					<view class="exchange-btn" @click="showExchangePopup">兑换</view>
+				</view>
+				<view class="bean-number">2560</view>
+			</view>
+
+			<!-- 星愿打卡区域 -->
+			<view class="sign-cards">
+				<view class="card purple-card">
+					<view class="card-title">初次见面礼</view>
+					<view class="card-desc">完善个人资料可得</view>
+					<view class="card-reward">奖励+100彩豆</view>
+					<view class="card-progress">80%</view>
+				</view>
+				<view class="card yellow-card">
+					<view class="card-title">每日签到</view>
+					<view class="card-desc">连续签到奖励更多</view>
+					<view class="sign-btn" @click="showSignPopup">立即签到</view>
+				</view>
+			</view>
+
+			<!-- 每日任务列表 -->
+			<view class="task-list">
+				<view class="task-header">
+					<text class="task-title">每日任务</text>
+					<text class="task-subtitle">获取免费彩豆</text>
+				</view>
+				
+				<!-- 任务项列表 -->
+				<view class="task-item" v-for="(item, index) in taskList" :key="index">
+					<view class="task-info">
+						<view class="task-name">{{item.name}}</view>
+						<view class="task-desc">{{item.desc}}</view>
+					</view>
+					<view class="task-reward">+{{item.reward}}彩豆</view>
+					<view class="task-btn" :class="{'task-completed': item.completed}" @click="claimReward(index)">
+						{{item.completed ? '已领取' : '领取'}}
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 彩豆兑换弹窗 -->
+		<view class="exchange-popup" v-if="showExchange">
+			<view class="popup-mask" @click="hideExchangePopup"></view>
+			<view class="popup-content">
+				<!-- 弹窗顶部信息栏 -->
+				<view class="popup-header">
+					<text class="available-balance">可用M币: 14500</text>
+					<text class="exchange-title">兑换彩豆</text>
+				</view>
+				
+				<!-- 兑换区域主体 -->
+				<view class="exchange-area">
+					<view class="exchange-title-area">
+						<text class="exchange-main-title">M币兑换彩豆数</text>
+						<text class="exchange-subtitle">兑换彩豆数必须是10的倍数</text>
+					</view>
+					
+					<view class="input-area">
+						<view class="bean-icon"></view>
+						<input type="number" class="exchange-input" placeholder="请输入兑换彩豆数量" v-model="exchangeAmount" />
+					</view>
+					
+					<!-- 操作按钮 -->
+					<view class="action-area">
+						<view class="exchange-btn-large" @click="confirmExchange">立即兑换彩豆</view>
+						<text class="tips-text">彩豆可用于创作(生成图片、音乐等AI创作功能)</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		
+		<!-- 签到弹窗 -->
+		<view class="sign-popup" v-if="showSign">
+			<view class="popup-mask" @click="hideSignPopup"></view>
+			<view class="sign-popup-content">
+				<!-- 弹窗顶部 -->
+				<view class="sign-popup-header">
+					<text class="sign-popup-title">每日签到领好礼</text>
+					<view class="sign-notify-switch">
+						<text class="sign-notify-text">签到消息提醒</text>
+						<switch class="sign-switch" color="#9C27B0" :checked="signNotify" @change="toggleSignNotify" />
+					</view>
+					<view class="sign-days-tag">已签到1天</view>
+				</view>
+				
+				<!-- VIP特权区域 -->
+				<view class="vip-area">
+					<view class="vip-left">
+						<text class="vip-text">VIP十通会员,签到享专属好礼</text>
+					</view>
+					<view class="vip-right">
+						<text class="vip-offer">限时优惠 ></text>
+					</view>
+				</view>
+				
+				<!-- 签到奖励网格布局 -->
+				<view class="sign-grid">
+					<view class="sign-grid-item" v-for="(item, index) in signRewards" :key="index"
+						:class="{'sign-received': index === 0}">
+						<view class="sign-day-num">{{item.dayNum}}</view>
+						<view class="sign-item-img"></view>
+						<view class="sign-item-name">{{item.reward}}</view>
+						<view class="sign-vip-tag" v-if="item.isVip">VIP</view>
+						<view class="sign-received-mask" v-if="index === 0">
+							<text class="received-text">已领取</text>
+						</view>
+					</view>
+				</view>
+				
+				<!-- 底部签到按钮 -->
+				<view class="sign-btn-large" @click="confirmSign">签到领取奖励</view>
+			</view>
+		</view>
+
+		<!-- 提示框 -->
+		<DialogBox ref="DialogBox"></DialogBox>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {},
+		data() {
+			return {
+				title: '任务中心',
+				myinfo: {},
+				realname: '',
+				idcard: '',
+				beanBalance: 2560,
+				showExchange: false,
+				exchangeAmount: '',
+				mCoinBalance: 14500,
+				showSign: false,
+				signNotify: true,
+				signRewards: [
+					{ dayNum: '01', reward: '海浪*3天', isVip: false },
+					{ dayNum: '02', reward: '红玫瑰*3', isVip: false },
+					{ dayNum: '03', reward: '樱花*3', isVip: false },
+					{ dayNum: '04', reward: '星辰*7天', isVip: false },
+					{ dayNum: '05', reward: '红玫瑰*5', isVip: false },
+					{ dayNum: '06', reward: '樱花*5', isVip: true },
+					{ dayNum: '07', reward: '特别奖励', isVip: true }
+				],
+				taskList: [
+					{
+						name: '每日首次发布作品',
+						desc: '当日首次发布作品即可获得奖励',
+						reward: 20,
+						completed: false
+					},
+					{
+						name: '分享作品领彩豆',
+						desc: '分享作品到社交平台即可获得奖励',
+						reward: 20,
+						completed: false
+					},
+					{
+						name: '邀请好友领彩豆',
+						desc: '成功邀请一位好友注册',
+						reward: 50,
+						completed: false
+					},
+					{
+						name: '充值赠礼',
+						desc: '首次充值即可获得额外奖励',
+						reward: 30,
+						completed: false
+					},
+					{
+						name: '口碑缔造者',
+						desc: '给他人作品评论5次',
+						reward: 20,
+						completed: false
+					}
+				]
+			}
+		},
+		onLoad() {
+			this.loadInfo();
+		},
+		onShow() {},
+		methods: {
+			onBack() {},
+
+			loadInfo() {
+				uni.request({
+					url: this.$apiHost + '/My/idcheck',
+					data: {
+						uuid: getApp().globalData.uuid
+					},
+					header: {
+						"content-type": "application/json",
+						'sign': getApp().globalData.headerSign
+					},
+					success: (res) => {
+						console.log("----:", res.data);
+						this.myinfo = res.data;
+					},
+					complete: (com) => {
+						// uni.hideLoading();
+					},
+					fail: (e) => {
+						console.log("----e:", e);
+					}
+				});
+			},
+			
+			// 显示兑换弹窗
+			showExchangePopup() {
+				this.showExchange = true;
+			},
+			
+			// 隐藏兑换弹窗
+			hideExchangePopup() {
+				this.showExchange = false;
+			},
+			
+			// 显示签到弹窗
+			showSignPopup() {
+				this.showSign = true;
+			},
+			
+			// 隐藏签到弹窗
+			hideSignPopup() {
+				this.showSign = false;
+			},
+			
+			// 切换签到通知开关
+			toggleSignNotify(e) {
+				this.signNotify = e.detail.value;
+			},
+			
+			// 确认签到
+			confirmSign() {
+				uni.showToast({
+					title: "签到成功,获得今日奖励",
+					icon: 'none'
+				});
+				this.hideSignPopup();
+			},
+			
+			// 确认兑换
+			confirmExchange() {
+				if (!this.exchangeAmount) {
+					uni.showToast({
+						title: "请输入兑换数量",
+						icon: 'none'
+					});
+					return;
+				}
+				
+				const amount = parseInt(this.exchangeAmount);
+				
+				if (isNaN(amount) || amount <= 0) {
+					uni.showToast({
+						title: "请输入有效数量",
+						icon: 'none'
+					});
+					return;
+				}
+				
+				if (amount % 10 !== 0) {
+					uni.showToast({
+						title: "兑换数量必须是10的倍数",
+						icon: 'none'
+					});
+					return;
+				}
+				
+				// 模拟兑换处理
+				uni.showToast({
+					title: "兑换成功,获得" + amount + "彩豆",
+					icon: 'none'
+				});
+				
+				this.beanBalance += amount;
+				this.hideExchangePopup();
+				this.exchangeAmount = '';
+			},
+			
+			claimReward(index) {
+				if(this.taskList[index].completed) {
+					uni.showToast({
+						title: "已领取该奖励",
+						icon: 'none'
+					});
+					return;
+				}
+				
+				// 模拟领取奖励
+				this.taskList[index].completed = true;
+				this.beanBalance += this.taskList[index].reward;
+				
+				uni.showToast({
+					title: "成功领取" + this.taskList[index].reward + "彩豆",
+					icon: 'none'
+				});
+			},
+			setSFZ() {
+				if (this.realname == '') {
+					uni.showToast({
+						title: "请填写姓名",
+						icon: 'none'
+					});
+					return;
+				}
+				if (this.idcard.length < 15) {
+					uni.showToast({
+						title: "请填写身份证号",
+						icon: 'none'
+					});
+					return;
+				}
+				uni.request({
+					url: this.$apiHost + '/My/setsfz',
+					data: {
+						uuid: getApp().globalData.uuid,
+						realname: this.realname,
+						idcard: this.idcard
+					},
+					header: {
+						"content-type": "application/json",
+						'sign': getApp().globalData.headerSign
+					},
+					success: (res) => {
+						console.log("----:", res.data);
+						uni.showToast({
+							title: res.data.str,
+							icon: 'none'
+						})
+						if (res.data.success == 'yes') {
+							this.loadInfo();
+						}
+					},
+					complete: (com) => {
+						// uni.hideLoading();
+					},
+					fail: (e) => {
+						console.log("----e:", e);
+					}
+				});
+			},
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	@import 'task.scss';
+</style>