Forráskód Böngészése

【feat】【第二版开发】

1.修复领取按钮的展示异常
2.任务列表的增加打卡规则展示
3.增加登录凭据失效处理
4.安全区获取移到onShow阶段
ChenYL 1 éve
szülő
commit
809d31b93a
4 módosított fájl, 934 hozzáadás és 908 törlés
  1. 17 14
      src/App.vue
  2. 742 737
      src/pages/index/index.vue
  3. 149 151
      src/pages/login/login.vue
  4. 26 6
      src/utils/request.js

+ 17 - 14
src/App.vue

@@ -1,19 +1,22 @@
 <script setup>
-	import naviInterceptor from '@/interceptors/naviInterceptor.js';
-	import { useSafeAreaStore } from '@/stores/safeArea.js';
-	import { onLaunch } from '@dcloudio/uni-app';
-	import { getSafeArea } from '@/utils/system.js';
-	
-	onLaunch(() => {
-		// 导航拦截器初始化
-		naviInterceptor();
-		// 安全区初始化
-		const safeAreaStore = useSafeAreaStore();
-		safeAreaStore.$patch(getSafeArea());
-	});
-	
+import naviInterceptor from '@/interceptors/naviInterceptor.js';
+import { useSafeAreaStore } from '@/stores/safeArea.js';
+import { onLaunch, onShow } from '@dcloudio/uni-app';
+import { getSafeArea } from '@/utils/system.js';
+
+onLaunch(() => {
+	// 导航拦截器初始化
+	naviInterceptor();
+
+});
+
+onShow(() => {
+	// 安全区初始化
+	const safeAreaStore = useSafeAreaStore();
+	safeAreaStore.$patch(getSafeArea());
+});
 </script>
 
 <style>
-	/*每个页面公共css */
+/*每个页面公共css */
 </style>

+ 742 - 737
src/pages/index/index.vue

@@ -4,12 +4,13 @@
 		<view class="user-info">
 			<span class="nickname" v-if="!userInfoStore.isLogin" @click="goUserInfoPage">登录</span>
 			<view class="user-icon" v-if="userInfoStore.isLogin">
-				<uni-icons type="person" size="30"></uni-icons>	
+				<uni-icons type="person" size="30"></uni-icons>
 			</view>
-			<span class="nickname" v-if="userInfoStore.isLogin" @click="goUserInfoPage">{{userInfoStore.nickname}}</span>
+			<span class="nickname" v-if="userInfoStore.isLogin" @click="goUserInfoPage">{{ userInfoStore.nickname
+				}}</span>
 			<span class="user-btn" v-if="userInfoStore.isLogin" @click="goUserInfoPage">用户中心</span>
 		</view>
-		
+
 		<!-- 结算 -->
 		<view class="settle-container">
 			<!-- 刮刮乐、奖励数相关区域 -->
@@ -18,14 +19,14 @@
 					<view class="line-box">
 						<span>投入</span>
 						<span class="number-box" @click="addScratchRecord(SCRATCH_ACTION_TYPE_INVEST)">
-							¥{{userInfo.lotteryInvestAmount}}
+							¥{{ userInfo.lotteryInvestAmount }}
 							<uni-icons type="compose" color="#FFFFFF"></uni-icons>
 						</span>
 					</view>
 					<view class="under-line-box">
 						<span>中奖</span>
-						<span class="number-box"  @click="addScratchRecord(SCRATCH_ACTION_TYPE_WIN)">
-							¥{{userInfo.lotteryWinAmount}}
+						<span class="number-box" @click="addScratchRecord(SCRATCH_ACTION_TYPE_WIN)">
+							¥{{ userInfo.lotteryWinAmount }}
 							<uni-icons type="compose" color="#FFFFFF"></uni-icons>
 						</span>
 					</view>
@@ -33,33 +34,33 @@
 				<view class="split-box">
 					<view class="line-box">
 						<span>已领取</span>
-						<span class="number-box">{{userInfo.claimedRewardNum}}</span>
+						<span class="number-box">{{ userInfo.claimedRewardNum }}</span>
 					</view>
-					<view  class="under-line-box">
+					<view class="under-line-box">
 						<span>总奖励</span>
-						<span class="number-box">{{userInfo.totalRewardNum}}</span>
+						<span class="number-box">{{ userInfo.totalRewardNum }}</span>
 					</view>
-				</view>	
+				</view>
 			</view>
 			<!-- 待领取奖励区 -->
 			<view class="right-box">
 				<view class="reward-title">待领取奖励数</view>
-				<view class="reward-num">{{userInfo.unclaimedRewardNum}}</view>
+				<view class="reward-num">{{ userInfo.unclaimedRewardNum }}</view>
 				<view class="reward-btn-group">
-					<view class="reward-btn-left" @click="claimReward('all')">全部领取</view>
-					<view class="reward-btn-right" @click="claimReward('part')">部分领取</view>
+					<view class="reward-btn reward-btn-left" @click="claimReward('all')">全部领取</view>
+					<view class="reward-btn reward-btn-right" @click="claimReward('part')">部分领取</view>
 				</view>
 			</view>
 			<!-- 刷新按钮 -->
 			<view class="refresh-btn" @click="getUserInfo">
-				<uni-icons type="refreshempty" color="#406CE7"></uni-icons>	
+				<uni-icons type="refreshempty" color="#406CE7"></uni-icons>
 			</view>
 		</view>
-		
+
 		<!-- 打卡任务 -->
 		<view class="task-container">
 			<view class="task-header">
-				<view class="task-title" v-if="punchIns.length && punchIns.length > 0">任务({{punchIns.length}}个)
+				<view class="task-title" v-if="punchIns.length && punchIns.length > 0">任务({{ punchIns.length }}个)
 				</view>
 				<view class="task-title" v-else>任务</view>
 				<view class="task-add-btn" @click="goPunchInEditPage">
@@ -69,13 +70,25 @@
 			<view class="task-item" v-for="punchIn in punchIns" :key="punchIn.punchInId">
 				<view class="main-box" @click="goPunchInDetailPage(punchIn.punchInId)">
 					<view class="item-header">
-						<span class="item-title">{{punchIn.taskName}}</span>
-						<span class="item-reward">x{{punchIn.rewardNum}}</span>
+						<span class="item-title">{{ punchIn.taskName }}</span>
+						<span class="item-reward">x{{ punchIn.rewardNum }}</span>
 						<view class="item-tag" v-if="punchIn.fullAttendanceFlag">全勤奖励</view>
 						<view class="item-tag" v-if="punchIn.weekendDoubleFlag">周末双倍</view>
 					</view>
+					<view class="item-desc" v-if="punchIn.category == 1">
+						规则:打卡次数
+						<span v-if="punchIn.rule == 0">大于等于</span>
+						<span v-if="punchIn.rule == 1">小于等于</span>
+						{{ punchIn.countTrack }}次
+					</view>
+					<view class="item-desc" v-if="punchIn.category == 2">
+						规则:计时时间
+						<span v-if="punchIn.rule == 0">大于等于</span>
+						<span v-if="punchIn.rule == 1">小于等于</span>
+						{{ punchIn.timeTrack.slice(0, 5) }}
+					</view>
 					<view class="item-desc">
-						规则:{{punchIn.description}}
+						描述:{{ punchIn.description }}
 					</view>
 					<view class="item-detail-list">
 						<view class="item-detail" v-for="punchInRecord in punchIn.punchInRecords"
@@ -95,81 +108,83 @@
 						</view>
 					</view>
 				</view>
-				<view :class="punchIn.punchInStatus == 'punchIn'?'func-box func-box-finish':'func-box func-box-unfinish'" v-if="punchIn.category == 0" @click="doPunchIn(punchIn.punchInId)">
-					<span v-if="punchIn.punchInStatus == 'unPunchIn' || punchIn.punchInStatus == 'todayUnknown'">打卡</span>
+				<view
+					:class="punchIn.punchInStatus == 'punchIn' ? 'func-box func-box-finish' : 'func-box func-box-unfinish'"
+					v-if="punchIn.category == 0" @click="doPunchIn(punchIn.punchInId)">
+					<span
+						v-if="punchIn.punchInStatus == 'unPunchIn' || punchIn.punchInStatus == 'todayUnknown'">打卡</span>
 					<span v-else>已完成</span>
 				</view>
-				<view :class="punchIn.punchInStatus == 'punchIn'?'func-box func-box-finish':'func-box func-box-unfinish'" v-if="punchIn.category == 1" @click="doPunchIn(punchIn.punchInId)">
-					<span>{{punchIn.countTrack}}</span>
+				<view
+					:class="punchIn.punchInStatus == 'punchIn' ? 'func-box func-box-finish' : 'func-box func-box-unfinish'"
+					v-if="punchIn.category == 1" @click="doPunchIn(punchIn.punchInId)">
+					<span>{{ punchIn.countTrack }}</span>
 					<span>计数</span>
 				</view>
-				<view :class="punchIn.punchInStatus == 'punchIn'?'func-box func-box-finish':'func-box func-box-unfinish'" v-if="punchIn.category == 2" @click="doPunchInForTimeTrack(punchIn.punchInId, punchIn.timeTrack)">
+				<view
+					:class="punchIn.punchInStatus == 'punchIn' ? 'func-box func-box-finish' : 'func-box func-box-unfinish'"
+					v-if="punchIn.category == 2" @click="doPunchInForTimeTrack(punchIn.punchInId, punchIn.timeTrack)">
 					<span>
-						{{punchIn.timeTrack.slice(0, 5)}}
+						{{ punchIn.timeTrack.slice(0, 5) }}
 					</span>
 					<span>计时</span>
 				</view>
 			</view>
 		</view>
-		
+
 		<!-- 刮刮乐弹出框 -->
 		<uni-popup ref="scratchInputDialog" type="dialog" :is-mask-click="false">
-			<uni-popup-dialog 
-				mode="input" 
-				:before-close="true" 
-				:title="scratchFormData.actionType == SCRATCH_ACTION_TYPE_INVEST ? '投入金额' : '中奖金额'" 
-				confirmText="保存" 
-				@confirm="scratchFormConfirm"
-				@close="scratchFormClose">
+			<uni-popup-dialog mode="input" :before-close="true"
+				:title="scratchFormData.actionType == SCRATCH_ACTION_TYPE_INVEST ? '投入金额' : '中奖金额'" confirmText="保存"
+				@confirm="scratchFormConfirm" @close="scratchFormClose">
 				<view style="width: 100%;">
-					<uni-forms ref="scratchForm" :modelValue="scratchFormData" :rules="scratchFormRules" label-position="top" :label-width="150">
+					<uni-forms ref="scratchForm" :modelValue="scratchFormData" :rules="scratchFormRules"
+						label-position="top" :label-width="150">
 						<uni-forms-item label="刮刮乐来源" name="source" required>
-							<uni-data-select :localdata="scratchSourceRange" v-model="scratchFormData.source"></uni-data-select>
+							<uni-data-select :localdata="scratchSourceRange"
+								v-model="scratchFormData.source"></uni-data-select>
 						</uni-forms-item>
 						<uni-forms-item label="刮刮乐种类" name="category" required>
-							<uni-data-select :localdata="scratchCategoryRange" v-model="scratchFormData.category"></uni-data-select>
+							<uni-data-select :localdata="scratchCategoryRange"
+								v-model="scratchFormData.category"></uni-data-select>
 						</uni-forms-item>
-						<uni-forms-item :label="scratchFormData.actionType == SCRATCH_ACTION_TYPE_INVEST ? '投入金额' : '中奖金额'" name="amount" required>
-							<uni-easyinput type="digit" placeholder="请输入金额" v-model="scratchFormData.amount"></uni-easyinput>
+						<uni-forms-item
+							:label="scratchFormData.actionType == SCRATCH_ACTION_TYPE_INVEST ? '投入金额' : '中奖金额'"
+							name="amount" required>
+							<uni-easyinput type="digit" placeholder="请输入金额"
+								v-model="scratchFormData.amount"></uni-easyinput>
 						</uni-forms-item>
 					</uni-forms>
 				</view>
 			</uni-popup-dialog>
 		</uni-popup>
-		
+
 		<!-- 领取奖励弹出框 -->
 		<uni-popup ref="claimRewardInputDialog" type="dialog" :is-mask-click="false">
-			<uni-popup-dialog
-				mode="input" 
-				:before-close="true" 
-				title="领取奖励" 
-				confirmText="领取" 
-				@confirm="claimRewardFormConfirm"
-				@close="claimRewardFormClose">
+			<uni-popup-dialog mode="input" :before-close="true" title="领取奖励" confirmText="领取"
+				@confirm="claimRewardFormConfirm" @close="claimRewardFormClose">
 				<view style="width: 100%;">
-					<uni-forms ref="claimRewardForm" :modelValue="claimRewardFormData" :rules="claimRewardFormRules" label-position="top" :label-width="150">
+					<uni-forms ref="claimRewardForm" :modelValue="claimRewardFormData" :rules="claimRewardFormRules"
+						label-position="top" :label-width="150">
 						<uni-forms-item name="claimRewardNum">
-							<uni-easyinput type="digit" placeholder="请输入领取的奖励数" v-model="claimRewardFormData.claimRewardNum"></uni-easyinput>
+							<uni-easyinput type="digit" placeholder="请输入领取的奖励数"
+								v-model="claimRewardFormData.claimRewardNum"></uni-easyinput>
 						</uni-forms-item>
 					</uni-forms>
 				</view>
 			</uni-popup-dialog>
 		</uni-popup>
-			
+
 		<!-- 计时弹出框 -->
 		<uni-popup ref="timeTrackInputDialog" type="dialog" :is-mask-click="false">
-			<uni-popup-dialog
-				mode="input" 
-				:before-close="true" 
-				title="计时记录" 
-				confirmText="保存" 
-				@confirm="timeTrackFormConfirm"
-				@close="timeTrackFormClose">
+			<uni-popup-dialog mode="input" :before-close="true" title="计时记录" confirmText="保存"
+				@confirm="timeTrackFormConfirm" @close="timeTrackFormClose">
 				<view style="width: 100%;">
-					<uni-forms ref="timeTrackForm" :modelValue="timeTrackFormData" :rules="timeTrackFormRules" label-position="top" :label-width="150">
+					<uni-forms ref="timeTrackForm" :modelValue="timeTrackFormData" :rules="timeTrackFormRules"
+						label-position="top" :label-width="150">
 						<uni-forms-item name="timeTrack">
 							<picker mode="time" :value="timeTrackFormData.timeTrack" @change="timeTrackChange">
-								<view class="pick-box">{{timeTrackFormData.timeTrack}}</view>
+								<view class="pick-box">{{ timeTrackFormData.timeTrack }}</view>
 							</picker>
 						</uni-forms-item>
 					</uni-forms>
@@ -180,751 +195,741 @@
 </template>
 
 <script setup>
-	import { onMounted, ref } from 'vue';
-	import { onLoad, onPullDownRefresh, onShow } from "@dcloudio/uni-app";
-	import { rewardApi, punchInApi, userApi, scratchApi } from '@/service/apis.js';
-	import router from '@/common/constants/router.js';
-	import { scratchSourceRange, scratchCategoryRange, SCRATCH_ACTION_TYPE_INVEST, SCRATCH_ACTION_TYPE_WIN } from '@/common/constants/scratch';
-	import { useUserInfoStore } from '@/stores/userInfo.js';
-	
-	// 组件
-	/**
-	 * 刮刮乐弹出框
-	 */
-	const scratchInputDialog = ref(null);
-	
-	/**
-	 * 刮刮乐表单
-	 */
-	const scratchForm = ref(null);
-	
-	/**
-	 * 领取奖励弹出框
-	 */
-	const claimRewardInputDialog = ref(null);
-	
-	/**
-	 * 领取奖励表单
-	 */
-	const claimRewardForm = ref(null);
-	
-	/**
-	 * 计时弹出框
-	 */
-	const timeTrackInputDialog = ref(null);
-	
-	/**
-	 * 计时表单
-	 */
-	const timeTrackForm = ref(null);
-	
-	
-	// 属性
-	/**
-	 * 用户信息
-	 */
-	const userInfoStore = useUserInfoStore();
-
-	/**
-	 * 用户信息
-	 */
-	const userInfo = ref({
-		totalRewardNum: 0,
-		unclaimedRewardNum: 0,
-		claimedRewardNum: 0,
-		lotteryInvestAmount: 0.00,
-		lotteryWinAmount: 0.00
-	});
-	
-	/**
-	 * 打卡任务
-	 */
-	const punchIns = ref([]);
-	
-	/**
-	 * 刮刮乐表单数
-	 */
-	const scratchFormData = ref({});
-	
-	/**
-	 * 刮刮乐表单校验规则
-	 */
-	const scratchFormRules = ref({
-		"source": {
-			rules: [{
-				required: true,
-				errorMessage: "请选择来源"
-			}]
-		},
-		"category": {
-			rules: [{
-				required: true,
-				errorMessage: "请选择种类"
-			}]
-		},
-		"amount": {
-			rules: [{
-				required: true,
-				errorMessage: "请输入金额"
-			}, {
-				format: 'number',
-				errorMessage: "请输入有效数字"
-			}, {
-				minimum: 0.01,
-				errorMessage: "最小{minimum}元"
-			}]
-		}
-	
-	});
-	
-	/**
-	 * 领取奖励表单数据
-	 */
-	const claimRewardFormData = ref({
-		claimRewardNum: 1
-	});
-	
-	/**
-	 * 领取奖励表单规则
-	 */
-	const claimRewardFormRules = ref({
-		claimRewardNum: {
-			rules: [{
-				required: true,
-				errorMessage: "请输入领取的奖励数"
-			}, {
-				format: 'number',
-				errorMessage: "请输入有效数字"
-			}, {
-				minimum: 1,
-				errorMessage: "最少领取{minimum}个"
-			}]
-		}
-	});
-	
-	/**
-	 * 计时表单数据
-	 */
-	const timeTrackFormData = ref({
-		timeTrack: '00:00'
-	});
-	
-	/**
-	 * 计时表单规则
-	 */
-	const timeTrackFormRules = ref({
-		timeTrack: {
-			rules: [{
-				required: true,
-				errorMessage: "请输入时间"
-			}]
-		}
-	});
-	
-	
-	// 方法
-	/**
-	 * 获取用户信息
-	 */
-	const getUserInfo = async () => {
-		let res = await userApi.queryUserInfo();
-		userInfo.value = res;
-	}
+import { onMounted, ref } from 'vue';
+import { onLoad, onPullDownRefresh, onShow } from "@dcloudio/uni-app";
+import { rewardApi, punchInApi, userApi, scratchApi } from '@/service/apis.js';
+import router from '@/common/constants/router.js';
+import { scratchSourceRange, scratchCategoryRange, SCRATCH_ACTION_TYPE_INVEST, SCRATCH_ACTION_TYPE_WIN } from '@/common/constants/scratch';
+import { useUserInfoStore } from '@/stores/userInfo.js';
+
+// 组件
+/**
+ * 刮刮乐弹出框
+ */
+const scratchInputDialog = ref(null);
 
-	/**
-	 * 获取打卡
-	 */
-	const getPunchIns = async () => {
-		let res = await punchInApi.queryPunchIns();
-		punchIns.value = res;
+/**
+ * 刮刮乐表单
+ */
+const scratchForm = ref(null);
+
+/**
+ * 领取奖励弹出框
+ */
+const claimRewardInputDialog = ref(null);
+
+/**
+ * 领取奖励表单
+ */
+const claimRewardForm = ref(null);
+
+/**
+ * 计时弹出框
+ */
+const timeTrackInputDialog = ref(null);
+
+/**
+ * 计时表单
+ */
+const timeTrackForm = ref(null);
+
+
+// 属性
+/**
+ * 用户信息
+ */
+const userInfoStore = useUserInfoStore();
+
+/**
+ * 用户信息
+ */
+const userInfo = ref({
+	totalRewardNum: 0,
+	unclaimedRewardNum: 0,
+	claimedRewardNum: 0,
+	lotteryInvestAmount: 0.00,
+	lotteryWinAmount: 0.00
+});
+
+/**
+ * 打卡任务
+ */
+const punchIns = ref([]);
+
+/**
+ * 刮刮乐表单数
+ */
+const scratchFormData = ref({});
+
+/**
+ * 刮刮乐表单校验规则
+ */
+const scratchFormRules = ref({
+	"source": {
+		rules: [{
+			required: true,
+			errorMessage: "请选择来源"
+		}]
+	},
+	"category": {
+		rules: [{
+			required: true,
+			errorMessage: "请选择种类"
+		}]
+	},
+	"amount": {
+		rules: [{
+			required: true,
+			errorMessage: "请输入金额"
+		}, {
+			format: 'number',
+			errorMessage: "请输入有效数字"
+		}, {
+			minimum: 0.01,
+			errorMessage: "最小{minimum}元"
+		}]
 	}
-	
-	/**
-	 * 增加刮刮乐记录
-	 */
-	const addScratchRecord = async (e) => {
-		// 重置上一轮的表单数据
-		scratchFormData.value = {
-			actionType: e
-		};
-		scratchInputDialog.value.open();
+
+});
+
+/**
+ * 领取奖励表单数据
+ */
+const claimRewardFormData = ref({
+	claimRewardNum: 1
+});
+
+/**
+ * 领取奖励表单规则
+ */
+const claimRewardFormRules = ref({
+	claimRewardNum: {
+		rules: [{
+			required: true,
+			errorMessage: "请输入领取的奖励数"
+		}, {
+			format: 'number',
+			errorMessage: "请输入有效数字"
+		}, {
+			minimum: 1,
+			errorMessage: "最少领取{minimum}个"
+		}]
 	}
-	
-	/**
-	 * 刮刮乐表单提交
-	 */
-	const scratchFormConfirm = async () => {
-		scratchForm.value.validate(['actionType']).then(data => {
-			return scratchApi.addScratchRecord(data);
-		}).then(e => {
-			scratchInputDialog.value.close();
-			getUserInfo();
-		});
+});
+
+/**
+ * 计时表单数据
+ */
+const timeTrackFormData = ref({
+	timeTrack: '00:00'
+});
+
+/**
+ * 计时表单规则
+ */
+const timeTrackFormRules = ref({
+	timeTrack: {
+		rules: [{
+			required: true,
+			errorMessage: "请输入时间"
+		}]
 	}
-	
-	/**
-	 * 刮刮乐表单取消
-	 */
-	const scratchFormClose = async () => {
+});
+
+
+// 方法
+/**
+ * 获取用户信息
+ */
+const getUserInfo = async () => {
+	let res = await userApi.queryUserInfo();
+	userInfo.value = res;
+}
+
+/**
+ * 获取打卡
+ */
+const getPunchIns = async () => {
+	let res = await punchInApi.queryPunchIns();
+	punchIns.value = res;
+}
+
+/**
+ * 增加刮刮乐记录
+ */
+const addScratchRecord = async (e) => {
+	// 重置上一轮的表单数据
+	scratchFormData.value = {
+		actionType: e
+	};
+	scratchInputDialog.value.open();
+}
+
+/**
+ * 刮刮乐表单提交
+ */
+const scratchFormConfirm = async () => {
+	scratchForm.value.validate(['actionType']).then(data => {
+		return scratchApi.addScratchRecord(data);
+	}).then(e => {
 		scratchInputDialog.value.close();
-	}
-	
-	/**
-	 * 领取奖励(部分)
-	 * @param {String} claimType 部分领取或全部领取(part-部分/all-全部)
-	 */
-	const claimReward = (claimType) => {
-		if (userInfo.value.unclaimedRewardNum == 0) {
-			uni.showToast({
-				title: "没有可领取的奖励",
-				icon: "none"
-			});
-			return;
-		}
-		// 重置上一轮的表单数据
-		claimRewardFormData.value = {
-			claimRewardNum: claimType == 'part' ? 1 : userInfo.value.unclaimedRewardNum
-		};
-		claimRewardInputDialog.value.open();
-	}
-	
-	
-	/**
-	 * 领取奖励表单提交
-	 */
-	const claimRewardFormConfirm = async () => {
-		claimRewardForm.value.validate().then(data => {
-			return rewardApi.claimReward(data);
-		}).then(e => {
-			claimRewardInputDialog.value.close();
-			getUserInfo();
+		getUserInfo();
+	});
+}
+
+/**
+ * 刮刮乐表单取消
+ */
+const scratchFormClose = async () => {
+	scratchInputDialog.value.close();
+}
+
+/**
+ * 领取奖励(部分)
+ * @param {String} claimType 部分领取或全部领取(part-部分/all-全部)
+ */
+const claimReward = (claimType) => {
+	if (userInfo.value.unclaimedRewardNum == 0) {
+		uni.showToast({
+			title: "没有可领取的奖励",
+			icon: "none"
 		});
+		return;
 	}
-	
-	/**
-	 * 领取奖励表单取消
-	 */
-	const claimRewardFormClose = async () => {
+	// 重置上一轮的表单数据
+	claimRewardFormData.value = {
+		claimRewardNum: claimType == 'part' ? 1 : userInfo.value.unclaimedRewardNum
+	};
+	claimRewardInputDialog.value.open();
+}
+
+
+/**
+ * 领取奖励表单提交
+ */
+const claimRewardFormConfirm = async () => {
+	claimRewardForm.value.validate().then(data => {
+		return rewardApi.claimReward(data);
+	}).then(e => {
 		claimRewardInputDialog.value.close();
-	}
+		getUserInfo();
+	});
+}
 
-	/**
-	 * 确认领取奖励
-	 */
-	const claimRewardConfirm = async (val) => {
-		await rewardApi.claimReward({
-			"claimRewardNum": val
-		});
-		// getReward();
-		claimRewardDialog.value.close();
-	}
-	
-	/**
-	 * 计时时间选择监听
-	 */
-	const timeTrackChange = (e) => {
-		timeTrackFormData.value.timeTrack = e.detail.value;
-	}
-	
-	/**
-	 * 打卡(计时)
-	 */
-	const doPunchInForTimeTrack = (id, timeTrack) => {
-		// 重置上一轮的表单数据
-		timeTrackFormData.value = {
-			id,
-			timeTrack: timeTrack ? timeTrack.slice(0, 5) : '00:00'
+/**
+ * 领取奖励表单取消
+ */
+const claimRewardFormClose = async () => {
+	claimRewardInputDialog.value.close();
+}
+
+/**
+ * 确认领取奖励
+ */
+const claimRewardConfirm = async (val) => {
+	await rewardApi.claimReward({
+		"claimRewardNum": val
+	});
+	// getReward();
+	claimRewardDialog.value.close();
+}
+
+/**
+ * 计时时间选择监听
+ */
+const timeTrackChange = (e) => {
+	timeTrackFormData.value.timeTrack = e.detail.value;
+}
+
+/**
+ * 打卡(计时)
+ */
+const doPunchInForTimeTrack = (id, timeTrack) => {
+	// 重置上一轮的表单数据
+	timeTrackFormData.value = {
+		id,
+		timeTrack: timeTrack ? timeTrack.slice(0, 5) : '00:00'
+	};
+	timeTrackInputDialog.value.open();
+}
+
+/**
+ * 计时表单提交
+ */
+const timeTrackFormConfirm = async () => {
+	timeTrackForm.value.validate(['id']).then(data => {
+		return punchInApi.doPunchIn(data);
+	}).then(e => {
+		timeTrackInputDialog.value.close();
+		getPunchIns();
+	});
+}
+
+/**
+ * 刮刮乐表单取消
+ */
+const timeTrackFormClose = async () => {
+	timeTrackInputDialog.value.close();
+}
+
+
+/**
+ * 打卡
+ */
+const doPunchIn = async (id) => {
+	await punchInApi.doPunchIn({
+		id
+	});
+	getPunchIns();
+}
+
+/**
+ * 跳转用户用心
+ */
+const goUserInfoPage = () => {
+	uni.navigateTo({
+		url: router.USER_INFO_URL
+	});
+}
+
+/**
+ * 跳转打卡编辑页面
+ */
+const goPunchInEditPage = () => {
+	uni.navigateTo({
+		url: router.PUNCHIN_EDIT_URL
+	});
+};
+
+/**
+ * 跳转打卡详情页面
+ */
+const goPunchInDetailPage = (id) => {
+	uni.navigateTo({
+		url: router.PUNCHIN_DETAIL_URL + "?id=" + id
+	});
+};
+
+/**
+ * 加载数据
+ */
+const loadData = async () => {
+	// 如果还没登录就结束获取数据
+	if (!userInfoStore.isLogin) {
+		userInfo.value = {
+			totalRewardNum: 0,
+			unclaimedRewardNum: 0,
+			claimedRewardNum: 0,
+			lotteryInvestAmount: 0.00,
+			lotteryWinAmount: 0.00
 		};
-		timeTrackInputDialog.value.open();
+		punchIns.value = [];
+		return;
 	}
-	
-	/**
-	 * 计时表单提交
-	 */
-	const timeTrackFormConfirm = async () => {
-		timeTrackForm.value.validate(['id']).then(data => {
-			return punchInApi.doPunchIn(data);
-		}).then(e => {
-			timeTrackInputDialog.value.close();
-			getPunchIns();
+
+	// 已登录
+	// isLogin.value = true;
+	try {
+		uni.showLoading({
+			title: '加载中',
+			mask: true
 		});
+		// 获取用户信息
+		getUserInfo();
+		// 获取打卡
+		getPunchIns();
+	} finally {
+		uni.hideLoading();
 	}
-	
-	/**
-	 * 刮刮乐表单取消
-	 */
-	const timeTrackFormClose = async () => {
-		timeTrackInputDialog.value.close();
-	}
+};
 
+onShow(() => {
+	loadData();
+});
 
-	/**
-	 * 打卡
-	 */
-	const doPunchIn = async (id) => {
-		await punchInApi.doPunchIn({
-			id
-		});
-		getPunchIns();
+onPullDownRefresh(() => {
+	loadData();
+	uni.stopPullDownRefresh();
+});
+</script>
+
+<style lang="scss" scoped>
+.user-info {
+	display: flex;
+	align-items: center;
+	position: relative;
+
+	.user-icon {
+		display: inline-flex !important;
+
+		width: 72rpx;
+		height: 72rpx;
+		background: #FFFFFF;
+		border-radius: 50%;
+
+		justify-content: center;
+		align-items: center;
 	}
 
-	/**
-	 * 跳转用户用心
-	 */
-	const goUserInfoPage = () => {
-		uni.navigateTo({
-			url: router.USER_INFO_URL
-		});
+	.nickname {
+		margin-left: 16rpx;
+		font-size: 24rpx;
+		font-weight: 400;
+		letter-spacing: 0rpx;
+		line-height: 34.75rpx;
+		color: #000000;
 	}
 
-	/**
-	 * 跳转打卡编辑页面
-	 */
-	const goPunchInEditPage = () => {
-		uni.navigateTo({
-			url: router.PUNCHIN_EDIT_URL
-		});
-	};
-	
-	/**
-	 * 跳转打卡详情页面
-	 */
-	const goPunchInDetailPage = (id) => {
-		uni.navigateTo({
-			url: router.PUNCHIN_DETAIL_URL + "?id=" + id
-		});
-	};
-	
-	/**
-	 * 加载数据
-	 */
-	const loadData = async () => {
-		// 如果还没登录就结束获取数据
-		if (!userInfoStore.isLogin) {
-			userInfo.value = {
-				totalRewardNum: 0,
-				unclaimedRewardNum: 0,
-				claimedRewardNum: 0,
-				lotteryInvestAmount: 0.00,
-				lotteryWinAmount: 0.00
-			};
-			punchIns.value = [];
-			return;
-		}
-		
-		// 已登录
-		// isLogin.value = true;
-		try {
-			uni.showLoading({
-				title: '加载中',
-				mask: true
-			});
-			// 获取用户信息
-			getUserInfo();
-			// 获取打卡
-			getPunchIns();
-		} finally {
-			uni.hideLoading();
-		}
-	};
+	.user-btn {
+		position: absolute;
+		right: 0px;
 
-	onShow(() => {
-		loadData();
-	});
+		width: 122rpx;
+		height: 40rpx;
+		opacity: 1;
+		border-radius: 24rpx;
+		background: #FFFFFF;
+		border: 1px solid #406CE7;
 
-	onPullDownRefresh(() => {
-		loadData();
-		uni.stopPullDownRefresh();
-	});
-</script>
+		/** 文本1 */
+		font-size: 18rpx;
+		font-weight: 400;
+		letter-spacing: 0rpx;
+		line-height: 26.06rpx;
+		color: #406CE7;
 
-<style lang="scss" scoped>
-	.user-info {
 		display: flex;
 		align-items: center;
-		position: relative;
-		
-		.user-icon {
-			display: inline-flex !important;
-			
-			width: 72rpx;
-			height: 72rpx;
-			background: #FFFFFF;
-			border-radius: 50%;
-			
-			justify-content: center;
-			align-items: center;
+		justify-content: center;
+	}
+}
+
+.settle-container {
+	margin-top: 16rpx;
+	display: flex;
+
+	padding: 16rpx 24rpx;
+	height: 266rpx;
+
+	opacity: 1;
+	background: #406CE7;
+	border-radius: 21.35rpx;
+	border: 0.5px solid #E4E4E4;
+	box-shadow: 0px 1px 6px #D8D8D8;
+
+	position: relative;
+
+	.left-box {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+
+		border-right: 1px solid #FFFFFF;
+		padding-right: 24rpx;
+		font-size: 22rpx;
+		font-weight: 400;
+		letter-spacing: 0rpx;
+		line-height: 31.86rpx;
+		color: #FFFFFF;
+
+		.line-box {
+			padding-bottom: 16rpx;
+			border-bottom: 1px solid #FFFFFF;
+			position: relative;
 		}
-		
-		.nickname {
-			margin-left: 16rpx;
-			font-size: 24rpx;
-			font-weight: 400;
-			letter-spacing: 0rpx;
-			line-height: 34.75rpx;
-			color: #000000;
+
+		.under-line-box {
+			padding-top: 16rpx;
+			position: relative;
 		}
-		
-		.user-btn {
+
+		.number-box {
 			position: absolute;
 			right: 0px;
-			
-			width: 122rpx;
-			height: 40rpx;
-			opacity: 1;
-			border-radius: 24rpx;
-			background: #FFFFFF;
-			border: 1px solid #406CE7;
-			
-			/** 文本1 */
-			font-size: 18rpx;
-			font-weight: 400;
-			letter-spacing: 0rpx;
-			line-height: 26.06rpx;
-			color: #406CE7;
-			
+			text-align: right;
+		}
+
+		.split-box {
+			flex: 1;
 			display: flex;
-			align-items: center;
 			justify-content: center;
+			align-content: center;
+			flex-direction: column;
 		}
 	}
 
-	.settle-container {
-		margin-top: 16rpx;
+	.right-box {
+		flex: 2;
 		display: flex;
-		
-		padding: 16rpx 24rpx;
-		height: 266rpx;
-		
-		opacity: 1;
-		background: #406CE7;
-		border-radius: 21.35rpx;
-		border: 0.5px solid #E4E4E4;
-		box-shadow: 0px 1px 6px  #D8D8D8;
-		
-		position: relative;
-		
-		.left-box {
-			flex: 1;
-			display: flex;
-			flex-direction: column;
-			 
-			border-right: 1px solid #FFFFFF;
-			padding-right: 24rpx;
-			font-size: 22rpx;
+		flex-direction: column;
+		align-items: center;
+
+		.reward-title {
+			font-size: 26rpx;
 			font-weight: 400;
 			letter-spacing: 0rpx;
-			line-height: 31.86rpx;
+			line-height: 37.65rpx;
 			color: #FFFFFF;
-			
-			.line-box {
-				padding-bottom: 16rpx;
-				border-bottom: 1px solid #FFFFFF;
-				position: relative;
-			}
-			
-			.under-line-box {
-				padding-top: 16rpx;
-				position: relative;
-			}
-			
-			.number-box {
-				position: absolute;
-				right: 0px;
-				text-align: right;
-			}
-			
-			.split-box {
-				flex: 1;
-				display: flex;
-				justify-content: center;
-				align-content: center;
-				flex-direction: column;
-			}
 		}
-		
-		.right-box {
-			flex: 2;
+
+		.reward-num {
+			flex-grow: 1;
+			font-size: 110rpx;
+			font-weight: 700;
+			letter-spacing: 0rpx;
+			color: #FFFFFF;
+
 			display: flex;
-			flex-direction: column;
 			align-items: center;
-			
-			.reward-title {
-				font-size: 26rpx;
-				font-weight: 400;
-				letter-spacing: 0rpx;
-				line-height: 37.65rpx;
-				color: #FFFFFF;
-			}
-			
-			.reward-num {
-				flex-grow: 1;
-				font-size: 120rpx;
+			justify-content: center;
+		}
+
+		.reward-btn-group {
+			width: 100%;
+			height: 36rpx;
+
+			display: flex;
+			align-items: center;
+			justify-content: center;
+
+			.reward-btn {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				width: 108rpx;
+				height: 36rpx;
+				opacity: 1;
+				background: #FFFFFF;
+				font-size: 20rpx;
 				font-weight: 700;
 				letter-spacing: 0rpx;
-				color: #FFFFFF;
+				line-height: 28.96rpx;
+				color: #406CE7;
 			}
-			
-			.reward-btn-group {
-				width: 100%;
-				height: 36rpx;
-				
+
+			.reward-btn-left {
+				border-radius: 24rpx 0rpx 0rpx 24rpx;
+			}
+
+			.reward-btn-right {
+				border-radius: 0rpx 24rpx 24rpx 0rpx;
+			}
+		}
+	}
+
+	.refresh-btn {
+		position: absolute;
+		top: 16rpx;
+		right: 24rpx;
+		border-radius: 50%;
+
+		width: 36rpx;
+		height: 36rpx;
+		opacity: 1;
+		background: #F7F7F7;
+
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+}
+
+.task-container {
+	margin-top: 16rpx;
+
+	.task-header {
+		position: relative;
+		height: 80rpx;
+		display: flex;
+		justify-content: center;
+		/* 水平居中 */
+		align-items: center;
+		/* 垂直居中 */
+
+		.task-title {
+			position: absolute;
+			left: 0rpx;
+			font-size: 30rpx;
+			font-weight: 400;
+			line-height: 43.44rpx;
+			color: rgba(0, 0, 0, 1);
+		}
+
+		.task-add-btn {
+			display: inline-flex;
+			justify-content: center;
+			align-items: center;
+			position: absolute;
+			right: 0rpx;
+			width: 60rpx;
+			height: 60rpx;
+			border-radius: 10rpx;
+			border: 3px solid rgba(64, 108, 231, 1);
+		}
+	}
+
+	.task-item {
+		margin-top: 16rpx;
+		width: 100%;
+		// height: 239rpx;
+		border-radius: 24rpx;
+		background: #FFFFFF;
+		border: 0.5px solid #E4E4E4;
+		box-shadow: 0px 1px 6px #D8D8D8;
+
+		display: flex;
+
+		.main-box {
+			flex-grow: 1;
+			padding: 16rpx 16rpx 16rpx 24rpx;
+
+			.item-header {
+				// position: relative;
 				display: flex;
 				align-items: center;
-				justify-content: center;
-				
-				.reward-btn-left {
-					display: flex;
-					justify-content: center;
-					align-items: center;
-						
-					width: 108rpx;
-					height: 36rpx;
+
+				.item-title {
+					font-size: 30rpx;
+					font-weight: 400;
+					letter-spacing: 0rpx;
+					line-height: 43.44rpx;
+					color: #000000;
+				}
+
+				.item-reward {
+					margin-left: 8rpx;
+					font-size: 24rpx;
+					font-weight: 400;
+					letter-spacing: 0rpx;
+					line-height: 34.75rpx;
+					color: #000000;
+				}
+
+				.item-tag:first-child {
+					margin-left: 24rpx;
+				}
+
+				.item-tag {
+					margin-left: 16rpx;
+					width: 94rpx;
+					height: 38rpx;
 					opacity: 1;
-					border-radius: 24rpx 0rpx 0rpx 24rpx;
+					border-radius: 24rpx;
 					background: #FFFFFF;
-					
-					font-size: 20rpx;
-					font-weight: 700;
+					border: 1px solid #406CE7;
+
+					display: inline-flex;
+					justify-content: center;
+					align-items: center;
+
+					font-size: 18rpx;
+					font-weight: 400;
 					letter-spacing: 0rpx;
-					line-height: 28.96rpx;
+					// line-height: 26.06rpx;
 					color: #406CE7;
+
 				}
-				
-				.reward-btn-right {
-					margin-left: 5rpx;
-					display: flex;
+
+				.item-btn {
+					display: inline-flex;
+					position: absolute;
+					right: 0rpx;
+					width: 123rpx;
+					height: 42rpx;
+					border-radius: 30rpx;
+					border: 1rpx solid #2A82E4;
 					justify-content: center;
 					align-items: center;
-					
-					width: 108rpx;
-					height: 36rpx;
-					opacity: 1;
-					border-radius: 0rpx 24rpx 24rpx 0rpx;
-					background: #FFFFFF;
-					
+
 					font-size: 20rpx;
-					font-weight: 700;
-					letter-spacing: 0rpx;
-					line-height: 28.96rpx;
-					color: #406CE7;
+					font-weight: 400;
+					line-height: 28.96px;
+					color: rgba(64, 108, 231, 1);
 				}
 			}
-		}
-	
-		.refresh-btn {
-			position: absolute;
-			top: 16rpx;
-			right: 24rpx;
-			border-radius: 50%;
-			
-			width: 36rpx;
-			height: 36rpx;
-			opacity: 1;
-			background: #F7F7F7;
-			
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
-	}
-	
-	.task-container {
-		margin-top: 16rpx;
-	
-		.task-header {
-			position: relative;
-			height: 80rpx;
-			display: flex;
-			justify-content: center;
-			/* 水平居中 */
-			align-items: center;
-			/* 垂直居中 */
-	
-			.task-title {
-				position: absolute;
-				left: 0rpx;
-				font-size: 30rpx;
+
+			.item-desc {
+				margin-top: 16rpx;
+				font-size: 24rpx;
 				font-weight: 400;
-				line-height: 43.44rpx;
-				color: rgba(0, 0, 0, 1);
-			}
-	
-			.task-add-btn {
-				display: inline-flex;
-				justify-content: center;
-				align-items: center;
-				position: absolute;
-				right: 0rpx;
-				width: 60rpx;
-				height: 60rpx;
-				border-radius: 10rpx;
-				border: 3px solid rgba(64, 108, 231, 1);
+				letter-spacing: 0rpx;
+				line-height: 34.75rpx;
+				color: #000000;
 			}
-		}
-	
-		.task-item {
-			margin-top: 16rpx;
-			width: 100%;
-			// height: 239rpx;
-			border-radius: 24rpx;
-			background: #FFFFFF;
-			border: 0.5px solid #E4E4E4;
-			box-shadow: 0px 1px 6px  #D8D8D8;
-	
-			display: flex;
-			
-			.main-box {
-				flex-grow: 1;
-				padding: 16rpx 16rpx 16rpx 24rpx;
-				
-				.item-header {
-					// position: relative;
+
+			.item-detail-list {
+				margin-top: 16rpx;
+				display: grid;
+				grid-template-columns: repeat(7, 1fr);
+
+				.item-detail {
 					display: flex;
+					flex-direction: column;
+					justify-content: center;
 					align-items: center;
-					
-					.item-title {
-						font-size: 30rpx;
-						font-weight: 400;
-						letter-spacing: 0rpx;
-						line-height: 43.44rpx;
-						color: #000000;
-					}
-					
-					.item-reward {
-						margin-left: 8rpx;
-						font-size: 24rpx;
-						font-weight: 400;
-						letter-spacing: 0rpx;
-						line-height: 34.75rpx;
-						color: #000000;
-					}
-					
-					.item-tag:first-child {
-						margin-left: 24rpx;
-					}
-										
-					.item-tag {
-						margin-left: 16rpx;
-						width: 94rpx;
-						height: 38rpx;
-						opacity: 1;
-						border-radius: 24rpx;
-						background: #FFFFFF;
-						border: 1px solid #406CE7;
-						
-						display: inline-flex;
-						justify-content: center;
-						align-items: center;
-						
-						font-size: 18rpx;
+
+					.detail-text {
+						font-size: 20rpx;
 						font-weight: 400;
 						letter-spacing: 0rpx;
-						// line-height: 26.06rpx;
-						color: #406CE7;
-						
+						line-height: 28.96rpx;
+						color: rgba(0, 0, 0, 1);
 					}
-					
-					.item-btn {
-						display: inline-flex;
-						position: absolute;
-						right: 0rpx;
-						width: 123rpx;
+
+					.detail-box {
+						// display: block;
+						width: 42rpx;
 						height: 42rpx;
-						border-radius: 30rpx;
-						border: 1rpx solid #2A82E4;
-						justify-content: center;
-						align-items: center;
-					
-						font-size: 20rpx;
-						font-weight: 400;
-						line-height: 28.96px;
-						color: rgba(64, 108, 231, 1);
-					}
-				}
-				
-				.item-desc {
-					margin-top: 16rpx;
-					font-size: 24rpx;
-					font-weight: 400;
-					letter-spacing: 0rpx;
-					line-height: 34.75rpx;
-					color: #000000;
-				}
-				
-				.item-detail-list {
-					margin-top: 16rpx;
-					display: grid;
-					grid-template-columns: repeat(7, 1fr);
-					
-					.item-detail {
-						display: flex;
-						flex-direction: column;
-						justify-content: center;
-						align-items: center;
-					
-						.detail-text {
-							font-size: 20rpx;
-							font-weight: 400;
-							letter-spacing: 0rpx;
-							line-height: 28.96rpx;
-							color: rgba(0, 0, 0, 1);
-						}
-					
-						.detail-box {
-							// display: block;
-							width: 42rpx;
-							height: 42rpx;
-							margin-top: 5rpx;
-							border: 5rpx solid #000000;
-						}
+						margin-top: 5rpx;
+						border: 5rpx solid #000000;
 					}
 				}
 			}
-			
-			.func-box {
-				flex-shrink: 0;
-				width: 160rpx;
-				border-radius: 0rpx 24rpx 24rpx 0rpx;
-				
-				
-				font-size: 36rpx;
-				font-weight: 400;
-				letter-spacing: 0rpx;
-				line-height: 52.13rpx;
-				color: #FFFFFF;
-				
-				display: flex;
-				justify-content: center;
-				align-items: center;
-				flex-direction: column;
-			}
-			
-			.func-box-finish {
-				background: #F2607A;
-			}
-			
-			.func-box-unfinish {
-				background: #406CE7;
-			}
+		}
+
+		.func-box {
+			flex-shrink: 0;
+			width: 160rpx;
+			border-radius: 0rpx 24rpx 24rpx 0rpx;
+
+
+			font-size: 36rpx;
+			font-weight: 400;
+			letter-spacing: 0rpx;
+			line-height: 52.13rpx;
+			color: #FFFFFF;
+
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+		}
+
+		.func-box-finish {
+			background: #F2607A;
+		}
+
+		.func-box-unfinish {
+			background: #406CE7;
 		}
 	}
-	
-	.pick-box {
-		display: flex;
-		box-sizing: border-box;
-		flex-direction: row;
-		align-items: center;
-		border: 1px solid #dcdfe6;
-		border-radius: 4px;
-		
-		width: auto;
-		position: relative;
-		overflow: hidden;
-		flex: 1;
-		line-height: 1;
-		font-size: 14px;
-		height: 35px;
-		padding-left: 10px;
-	}
+}
+
+.pick-box {
+	display: flex;
+	box-sizing: border-box;
+	flex-direction: row;
+	align-items: center;
+	border: 1px solid #dcdfe6;
+	border-radius: 4px;
+
+	width: auto;
+	position: relative;
+	overflow: hidden;
+	flex: 1;
+	line-height: 1;
+	font-size: 14px;
+	height: 35px;
+	padding-left: 10px;
+}
 </style>

+ 149 - 151
src/pages/login/login.vue

@@ -6,176 +6,174 @@
 					<uni-icons type="person" size="60"></uni-icons>
 				</view>
 				<view class="login-nickname">
-					<uni-forms ref="loginForm" :modelValue="loginFormData" :rules="loginFormRules">
+					<uni-forms ref="loginForm" :modelValue="loginFormData" :rules="loginFormRules"
+						err-show-type="modal">
 						<uni-forms-item name="nickname">
-							<uni-easyinput type="text" 
-								v-model="loginFormData.nickname" 
-								placeholder="请输入昵称" 
-								:inputBorder="false" 
-								:styles="nicknameInputStyle"/>
+							<uni-easyinput type="text" v-model="loginFormData.nickname" placeholder="请输入昵称"
+								:clearable="false" :inputBorder="false" :styles="nicknameInputStyle" />
 						</uni-forms-item>
 					</uni-forms>
 				</view>
-				
+
 				<view class="login-btn" @click="login">登录</view>
-				
+
 			</view>
 		</template>
 	</main-layout>
 </template>
 
 <script setup>
-	import { ref } from 'vue';
-	import { loginApi } from '@/service/apis.js';
-	import router from '@/common/constants/router.js';
-	import { useUserInfoStore } from '@/stores/userInfo.js';
-	
-	// 组件
-	/**
-	 * 登录表单
-	 */
-	const loginForm = ref(null);
-	
-	// 属性
-	/**
-	 * 用户信息
-	 */
-	const userInfoStore = useUserInfoStore();
-	
-	/**
-	 * 登录表单数据
-	 */
-	const loginFormData = ref({
-		nickname: "蜗牛"
-	});
-	
-	/**
-	 * 登录表单校验规则
-	 */
-	const loginFormRules = ref({
-		nickname: {
-			rules: [{
-				required: true,
-				errorMessage: '昵称不能为空'
-			}, {
-				maxLength: 30,
-				errorMessage: '昵称不能超过{maxLength}个字符'
-			}]
-		}
-	});
-	
-	/**
-	 * 昵称输入框样式
-	 */
-	const nicknameInputStyle = {
-		width: 100+'%',
-		height: 100+'%',
-		fontSize: 36+'rpx',
-		fontWeight: 700,
-		letterSpacing: 0+'rpx',
-		lineHeight: 52.13+'rpx',
-		color: '#000000',
-		borderRadius: 24+'rpx',
-		textAlign: 'center'
-	};
-	
-	// 方法
-	const login = async () => {
-		try {
-			let formData = await loginForm.value.validate();
-			uni.showLoading({
-				title: '登录中...'
-			});
-			// 获取供应商
-			let providerResult = await uni.getProvider({ service: 'oauth' });
-			// 获取登录code
-			let loginResult = await uni.login({ provider: providerResult.provider[0] });
-			// 登录
-			let token = await loginApi.login({
-				"code": loginResult.code,
-				"nickname": formData.nickname
-			});
-			
-			// 保存用户信息(token)
-			userInfoStore.$patch({
-				token,
-				nickname: formData.nickname
-			});
-			
-			uni.showToast({
-				title: '登录成功',
-				icon: 'success',
-				duration: 1000
+import { ref } from 'vue';
+import { loginApi } from '@/service/apis.js';
+import router from '@/common/constants/router.js';
+import { useUserInfoStore } from '@/stores/userInfo.js';
+
+// 组件
+/**
+ * 登录表单
+ */
+const loginForm = ref(null);
+
+// 属性
+/**
+ * 用户信息
+ */
+const userInfoStore = useUserInfoStore();
+
+/**
+ * 登录表单数据
+ */
+const loginFormData = ref({
+	nickname: "蜗牛"
+});
+
+/**
+ * 登录表单校验规则
+ */
+const loginFormRules = ref({
+	nickname: {
+		rules: [{
+			required: true,
+			errorMessage: '昵称不能为空'
+		}, {
+			maxLength: 30,
+			errorMessage: '昵称不能超过{maxLength}个字符'
+		}]
+	}
+});
+
+/**
+ * 昵称输入框样式
+ */
+const nicknameInputStyle = {
+	width: 100 + '%',
+	height: 100 + '%',
+	fontSize: 36 + 'rpx',
+	fontWeight: 700,
+	letterSpacing: 0 + 'rpx',
+	lineHeight: 52.13 + 'rpx',
+	color: '#000000',
+	borderRadius: 24 + 'rpx',
+	textAlign: 'center'
+};
+
+// 方法
+const login = async () => {
+	try {
+		let formData = await loginForm.value.validate();
+		uni.showLoading({
+			title: '登录中...'
+		});
+		// 获取供应商
+		let providerResult = await uni.getProvider({ service: 'oauth' });
+		// 获取登录code
+		let loginResult = await uni.login({ provider: providerResult.provider[0] });
+		// 登录
+		let token = await loginApi.login({
+			"code": loginResult.code,
+			"nickname": formData.nickname
+		});
+
+		// 保存用户信息(token)
+		userInfoStore.$patch({
+			token,
+			nickname: formData.nickname
+		});
+
+		uni.showToast({
+			title: '登录成功',
+			icon: 'success',
+			duration: 1000
+		});
+
+		// 登录结束返回主页
+		setTimeout(() => {
+			uni.navigateTo({
+				url: router.INDEX_URL
 			});
-			
-			// 登录结束返回主页
-			setTimeout(() => {
-				uni.navigateTo({
-					url: router.INDEX_URL
-				});
-			}, 1000);
-		} finally {
-			uni.hideLoading();
-		}
+		}, 1000);
+	} finally {
+		uni.hideLoading();
 	}
+}
 </script>
 
 <style lang="scss" scoped>
-	.login-container {
+.login-container {
+	margin-top: 150rpx;
+
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+
+	.login-avator {
+		width: 200rpx;
+		height: 200rpx;
+		background: #FFFFFF;
+		border-radius: 50%;
+
+		// 阴影
+		border: 0.5px solid #E4E4E4;
+		box-shadow: 0px 1px 6px #D8D8D8;
+
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.login-nickname {
+		margin-top: 50rpx;
+
+		width: 599rpx;
+		height: 100rpx;
+		border-radius: 8px;
+		background: #FFFFFF;
+
+		// 阴影
+		border: 0.5px solid #E4E4E4;
+		box-shadow: 0px 1px 6px #D8D8D8;
+	}
+
+	.login-btn {
 		margin-top: 150rpx;
-		
-		width: 100%;
-		height: 100%;
+
+		width: 599rpx;
+		height: 100rpx;
+		border-radius: 24rpx;
+		background: #406CE7;
+
+		font-size: 36rpx;
+		font-weight: 400;
+		letter-spacing: 0rpx;
+		line-height: 52.13rpx;
+		color: #FFFFFF;
+
 		display: flex;
 		justify-content: center;
 		align-items: center;
-		flex-direction: column;
-		
-		.login-avator {
-			width: 200rpx;
-			height: 200rpx;
-			background: #FFFFFF;
-			border-radius: 50%;
-			
-			// 阴影
-			border: 0.5px solid #E4E4E4;
-			box-shadow: 0px 1px 6px  #D8D8D8;
-			
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
-		
-		.login-nickname {
-			margin-top: 50rpx;
-			
-			width: 599rpx;
-			height: 100rpx;
-			border-radius: 8px;
-			background: #FFFFFF;
-			
-			// 阴影
-			border: 0.5px solid #E4E4E4;
-			box-shadow: 0px 1px 6px  #D8D8D8;
-		}
-		
-		.login-btn {
-			margin-top: 150rpx;
-			
-			width: 599rpx;
-			height: 100rpx;
-			border-radius: 24rpx;
-			background: #406CE7;
-		
-			font-size: 36rpx;
-			font-weight: 400;
-			letter-spacing: 0rpx;
-			line-height: 52.13rpx;
-			color: #FFFFFF;
-			
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
 	}
+}
 </style>

+ 26 - 6
src/utils/request.js

@@ -1,4 +1,5 @@
 import { useUserInfoStore } from '@/stores/userInfo.js';
+import router from '@/common/constants/router.js';
 
 const userInfoStore = useUserInfoStore();
 
@@ -32,25 +33,44 @@ export default function request(config = {}) {
 			header,
 			withCredentials: true,
 			success: res => {
+				// 登录状态判断
+				if (res.statusCode === 401) {
+					// 清除token
+					userInfoStore.token = null;
+					uni.showModal({
+						title: "登录提示",
+						content: "登录凭据已失效,请重新登录",
+						showCancel: false,
+						success: function (res) {
+							if (res.confirm) {
+								uni.navigateTo({
+									url: router.LOGIN_URL
+								});
+							}
+						}
+					});
+					reject(res.data);
+					return;
+				}
 				if (res.data.code === '0') {
-					resolve(res.data.data)
+					resolve(res.data.data);
 				} else if (res.data.code === '999') {
 					uni.showModal({
 						title: "错误提示",
 						content: res.data.msg,
 						showCancel: false
-					})
-					reject(res.data)
+					});
+					reject(res.data);
 				} else {
 					uni.showToast({
 						title: res.data.msg,
 						icon: "none"
-					})
-					reject(res.data)
+					});
+					reject(res.data);
 				}
 			},
 			fail: err => {
-				reject(err)
+				reject(err);
 			},
 			complete: () => {
 				if (loading) {