wzx 1 年之前
父节点
当前提交
3f4c619798

+ 47 - 0
custom/App.uvue

@@ -0,0 +1,47 @@
+<script lang="uts">
+	let firstBackTime = 0
+	export default {
+		onLaunch: function () {
+			console.log('App Launch')
+		},
+		onShow: function () {
+			console.log('App Show')
+		},
+		onHide: function () {
+			console.log('App Hide')
+		},
+		// #ifdef APP-ANDROID
+		onLastPageBackPress: function () {
+			console.log('App LastPageBackPress')
+			if (firstBackTime == 0) {
+				uni.showToast({
+					title: '再按一次退出应用',
+					position: 'bottom',
+				})
+				firstBackTime = Date.now()
+				setTimeout(() => {
+					firstBackTime = 0
+				}, 2000)
+			} else if (Date.now() - firstBackTime < 2000) {
+				firstBackTime = Date.now()
+				uni.exit()
+			}
+		},
+		// #endif
+		onExit: function () {
+			console.log('App Exit')
+		},
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+
+	.uni-row {
+		flex-direction: row;
+	}
+
+	.uni-column {
+		flex-direction: column;
+	}
+</style>

+ 4 - 0
custom/common/api.js

@@ -0,0 +1,4 @@
+export const apiServer = 'https://colormaprun.com/api/custom/';
+
+// test
+// export const apiTest = apiServer + 'test';

+ 307 - 0
custom/common/tools.js

@@ -0,0 +1,307 @@
+var tools = {
+	// 秒数转换成时分秒
+	convertSecondsToHMS(seconds) {
+		var hours = Math.floor(seconds / 3600);
+		var minutes = Math.floor((seconds % 3600) / 60);
+		var remainingSeconds = seconds % 60;
+		// return hours + ":" + minutes + ":" + remainingSeconds;
+		return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+	},
+
+	// 计算(中英文混合)字符串长度
+	calStrLen(str) {
+		var length = 0;
+		for (var i = 0; i < str.length; i++) {
+			// 将字符转换为 Unicode 编码
+			var charCode = str.charCodeAt(i);
+			if (charCode >= 0 && charCode <= 128) {
+				length++;
+			} else {
+				length += 2;
+			}
+		}
+
+		return length;
+	},
+
+	// 集合对象去重
+	unique(arr, field) {
+		var map = {};
+		var res = [];
+		for (var i = 0; i < arr.length; i++) {
+			if (!map[arr[i][field]]) {
+				map[arr[i][field]] = 1;
+				res.push(arr[i]);
+			}
+		}
+		return res;
+	},
+
+	// 正则取出html标签
+	repalceHtml(str) {
+		var dd = str.replace(/<\/?.+?>/g, "");
+		var dds = dd.replace(/ /g, ""); //dds为得到后的内容
+		return dds;
+	},
+
+	// 判断身份证号    
+	isSfz(idcard) {
+		var id =
+			/^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|31)|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}([0-9]|x|X)$/
+		if (idcard === '') {
+			uni.showToast({
+				title: '请输入身份证号',
+				icon: 'none'
+			})
+		} else if (!id.test(idcard)) {
+			uni.showToast({
+				title: '身份证号格式不正确!',
+				icon: 'none'
+			})
+			return false
+		} else {
+			return false
+		}
+	},
+
+	// 判断是否是手机号   
+	isPhone(val) {
+		var patrn = /^(((1[3456789][0-9]{1})|(15[0-9]{1}))+\d{8})$/
+		if (!patrn.test(val) || val === '') {
+			uni.showToast({
+				title: '手机号格式不正确',
+				icon: 'none'
+			})
+			return false
+		} else {
+			return true
+		}
+	},
+
+	// 判断邮箱
+	isEmail(email) {
+		if (email.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)
+			return true;
+		else
+			return false;
+	},
+
+	//获取随机数
+	getSuiji() {
+		var Range = Max - Min;
+		var Rand = Math.random();
+		return (Min + Math.round(Rand * Range));
+	},
+
+	//计算多长时间前
+	getDateDiff(dateTimeStamp) {
+		var minute = 1000 * 60;
+		var hour = minute * 60;
+		var day = hour * 24;
+		var halfamonth = day * 15;
+		var month = day * 30;
+		var year = day * 365;
+		var now = new Date().getTime();
+		var diffValue = now - dateTimeStamp;
+		if (diffValue < 0) {
+			return;
+		}
+		var yearC = diffValue / year;
+		var monthC = diffValue / month;
+		var weekC = diffValue / (7 * day);
+		var dayC = diffValue / day;
+		var hourC = diffValue / hour;
+		var minC = diffValue / minute;
+		if (yearC >= 1) {
+			result = "" + parseInt(yearC) + "年前";
+		}
+		if (monthC >= 1) {
+			result = "" + parseInt(monthC) + "月前";
+		} else if (weekC >= 1) {
+			result = "" + parseInt(weekC) + "周前";
+		} else if (dayC >= 1) {
+			result = "" + parseInt(dayC) + "天前";
+		} else if (hourC >= 1) {
+			result = "" + parseInt(hourC) + "小时前";
+		} else if (minC >= 1) {
+			result = "" + parseInt(minC) + "分钟前";
+		} else
+			result = "刚刚";
+		return result;
+	},
+
+	// 时间戳转时间
+	timestampToTime(timestamp, i) {
+		var date = new Date(timestamp); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+		// console.log(date, timestamp)
+		var Y = date.getFullYear() + '-';
+		var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+		var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+		var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+		var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
+		var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+		if (i == 1) {
+			return Y + M + D;
+		}
+		return Y + M + D + h + m + s;
+	},
+
+	// 是否是汉字
+	isHanzi(str) {
+		let reg = /\p{Unified_Ideograph}/ug;
+		return reg.test(str);
+	},
+
+	// 是否是字母数字
+	isStringAndNumber(str) {
+		let regNumber = new RegExp(/^[0-9A-Za-z]+$/);
+		return regNumber.test(str)
+	},
+
+	// var arr3 = [30,10,111,35,1899,50,45];
+	// 集合排序  元素数字
+	listSort(list) {
+		arr3.sort(function(a, b) {
+			return a - b;
+		})
+	},
+
+	// var arr5 = [{id:10},{id:5},{id:6},{id:9},{id:2},{id:3}];
+	// 元素  对象
+	listObjectSort(arr) {
+		arr.sort(function(a, b) {
+			return a.id - b.id
+		})
+		return arr;
+	},
+
+	/*
+	 * 忽略大小写判断字符串是否相同
+	 * @param str1
+	 * @param str2
+	 * @returns {Boolean}
+	 */
+	isEqualsIgnorecase: function(str1, str2) {
+		if (str1.toUpperCase() == str2.toUpperCase()) {
+			return true;
+		} else {
+			return false;
+		}
+	},
+
+	/**
+	 * 判断是否是数字
+	 * @param value
+	 * @returns {Boolean}
+	 */
+	isNum: function(value) {
+		if (value != null && value.length > 0 && isNaN(value) == false) {
+			return true;
+		} else {
+			return false;
+		}
+	},
+
+	/**
+	 * 判断是否是中文
+	 * @param str
+	 * @returns {Boolean}
+	 */
+	isChine: function(str) {
+		var reg = /^([u4E00-u9FA5]|[uFE30-uFFA0])*$/;
+		if (reg.test(str)) {
+			return false;
+		}
+		return true;
+	},
+
+	/*验证是否为图片*/
+	tmCheckImage: function(fileName) {
+		return /(gif|jpg|jpeg|png|GIF|JPG|PNG)$/ig.test(fileName);
+	},
+
+	/*验证是否为视频*/
+	tmCheckVideo: function(fileName) {
+		return /(mp4|mp3|flv|wav)$/ig.test(fileName);
+	},
+
+	/**
+	 * 去除字符串两边的空格
+	 * @param str
+	 * @returns {number|Number}
+	 * 调用方法:var str = utils.trim("abcd")
+	 */
+	trim: function(str) {
+		String.prototype.trim = function() {
+			return str.replace(/(^\s*)|(\s*$)/g, "");
+		}
+	},
+
+	// 判断密码是否符合 至少6位,包括大小写字母、数字、特殊字符
+	isPassword(val) {
+		var reg = /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)])+$)^.{8,16}$/;
+		if (val === '') {
+			uni.showToast({
+				title: '请输入密码',
+				icon: 'none'
+			})
+		} else if (!reg.test(val)) {
+			uni.showToast({
+				title: '至少6位,包括大小写字母、数字、特殊字符',
+				icon: 'none'
+			})
+			return false
+		} else {
+			return true
+		}
+	},
+
+	// 电话匿名
+	noPassByMobile(str) {
+		if (null != str && str != undefined) {
+			var pat = /(\d{3})\d*(\d{4})/;
+			return str.replace(pat, '$1****$2');
+		} else {
+			return "";
+		}
+	},
+
+	// 获取两点间的距离
+	//进行经纬度转换为距离的计算
+	Rad(d) {
+		return d * Math.PI / 180.0; //经纬度转换成三角函数中度分表形式。
+	},
+
+	/*
+	 计算距离,参数分别为第一点的纬度,经度;第二点的纬度,经度
+	 默认单位km
+	*/
+	getMapDistance(lat1, lat2, lng1, lng2) {
+		lat1 = lat1 || 0;
+		lng1 = lng1 || 0;
+		lat2 = lat2 || 0;
+		lng2 = lng2 || 0;
+
+		var rad1 = lat1 * Math.PI / 180.0;
+		var rad2 = lat2 * Math.PI / 180.0;
+		var a = rad1 - rad2;
+		var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
+		var r = 6378137;
+		var distance = r * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rad1) * Math.cos(rad2) *
+			Math.pow(Math.sin(b / 2), 2)));
+		console.log(lat1, lng1, lat2, lng2);
+		console.log(distance);
+		return Math.round(distance) / 1000;
+	},
+
+	// 预览图片
+	yulanImg(item) {
+		let arr = [item]
+		uni.previewImage({
+			urls: arr,
+		});
+	},
+
+}
+
+export default tools;

+ 20 - 0
custom/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="UTF-8" />
+		<script>
+			var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+				CSS.supports('top: constant(a)'))
+			document.write(
+				'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+				(coverSupport ? ', viewport-fit=cover' : '') + '" />')
+		</script>
+		<title></title>
+		<!--preload-links-->
+		<!--app-context-->
+	</head>
+	<body>
+		<div id="app"><!--app-html--></div>
+		<script type="module" src="/main"></script>
+	</body>
+</html>

+ 9 - 0
custom/main.uts

@@ -0,0 +1,9 @@
+import App from './App.uvue'
+
+import { createSSRApp } from 'vue'
+export function createApp() {
+	const app = createSSRApp(App)
+	return {
+		app
+	}
+}

+ 54 - 0
custom/manifest.json

@@ -0,0 +1,54 @@
+{
+    "name" : "custom",
+    "appid" : "__UNI__F860CDD",
+    "description" : "彩虹定向APP内客户定制样式页面",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "uni-app-x" : {},
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3",
+    "app" : {
+        "distribute" : {
+            "icons" : {
+                "android" : {
+                    "hdpi" : "",
+                    "xhdpi" : "",
+                    "xxhdpi" : "",
+                    "xxxhdpi" : ""
+                }
+            }
+        }
+    },
+    "h5" : {
+        "router" : {
+            "mode" : "hash",
+            "base" : "/custom/"
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
+}

+ 54 - 0
custom/pages.json

@@ -0,0 +1,54 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "彩图奔跑APP定制页面"
+			}
+		},
+		{
+			"path": "pages/shanda/challenge/index",
+			"style": {
+				"navigationBarTitleText": "挑战结果"
+			}
+		},
+		{
+			"path": "pages/shanda/challenge/success",
+			"style": {
+				"navigationBarTitleText": "挑战成功"
+			}
+		},
+		{
+			"path": "pages/shanda/challenge/exit",
+			"style": {
+				"navigationBarTitleText": "退出比赛"
+			}
+		},
+		{
+			"path": "pages/xfl/challenge/index",
+			"style": {
+				"navigationBarTitleText": "挑战结果"
+			}
+		},
+		{
+			"path": "pages/xfl/challenge/success",
+			"style": {
+				"navigationBarTitleText": "挑战成功"
+			}
+		},
+		{
+			"path": "pages/xfl/challenge/exit",
+			"style": {
+				"navigationBarTitleText": "退出比赛"
+			}
+		}
+	],
+	"globalStyle": {
+		"navigationStyle": "custom",
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "彩图奔跑",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8"
+	},
+	"uniIdRouter": {}
+}

+ 16 - 0
custom/pages/index/index.uvue

@@ -0,0 +1,16 @@
+<template>
+	<view></view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+		},
+		methods: {
+		}
+	}
+</script>

+ 62 - 0
custom/pages/shanda/challenge/exit.uvue

@@ -0,0 +1,62 @@
+<!-- 
+http://localhost:5173/custom/#/pages/shanda/challenge/index?pagetype=challenge_result&status=fail
+https://oss-mbh5.colormaprun.com/custom/#/pages/shanda/challenge/index?pagetype=challenge_result&status=fail
+ -->
+<template>
+	<view class="body">
+		<view class="content">
+			<view class="main">
+				<view class="exit_game"></view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		computed: {
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+		},
+		methods: {
+		}
+	}
+</script>
+
+<style>
+	.body {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.content {
+		width: 100vw;
+		/* width: 750rpx; */
+		/* margin: 0 auto; */
+	}
+
+	.main {
+		width: 100%;
+		flex-direction: column;
+		align-items: center;
+		justify-content: flex-start;
+	}
+
+	.exit_game {
+		width: 100%;
+		height: 100vh;
+		/* height: 1100rpx; */
+		/* margin-left: 40rpx; */
+		background-image: url("/static/shanda/challenge/exit_game.jpg");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: top;
+		background-size: cover;
+	}
+</style>

+ 42 - 0
custom/pages/shanda/challenge/index.uvue

@@ -0,0 +1,42 @@
+<template>
+	<view></view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+			// console.log(event);
+			const queryString = this.objectToQueryString(event);
+			// console.log(queryString);
+			const status = event["status"] ?? ""
+			
+			if (status == 'success') {	// 挑战成功
+				uni.reLaunch({
+					url: '/pages/shanda/challenge/success?' + queryString
+				});
+			}
+			else if (status == 'ok' || status == 'fail') {	// 挑战完成/挑战失败
+				uni.reLaunch({
+					url: '/pages/shanda/challenge/exit'
+				});
+			}
+			else {
+				this.showErr();
+			}
+		},
+		methods: {
+			showErr() {
+				uni.showToast({
+					title: '参数错误'
+				});
+			},
+			objectToQueryString(obj) {
+				return Object.keys(obj).map(k => k + '=' + obj[k]).join('&');
+			}
+		}
+	}
+</script>

+ 213 - 0
custom/pages/shanda/challenge/success.uvue

@@ -0,0 +1,213 @@
+<!-- 
+http://localhost:5173/custom/#/pages/shanda/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+https://oss-mbh5.colormaprun.com/custom/#/pages/shanda/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+ -->
+<template>
+	<view class="body">
+		<view class="content">
+			<view class="top">
+				<image class="logo" mode="aspectFit" src="/static/shanda/logo.webp"></image>
+				<text class="gameName">山大定向3日赛</text>
+			</view>
+			<view class="main">
+				<view class="main-content">
+					<view class="rank">
+						<view class="statistic">
+							<text class="statistic-title">总用时:</text>
+							<view class="statistic-right">
+								<text class="statistic-value">{{durationMin}}</text><text
+									class="statistic-unit">min</text>
+							</view>
+						</view>
+						<view class="statistic">
+							<text class="statistic-title">总里程:</text>
+							<view class="statistic-right">
+								<text class="statistic-value">{{distanceKm}}</text><text
+									class="statistic-unit">Km</text>
+							</view>
+						</view>
+						<view class="statistic">
+							<text class="statistic-title">脑力值:</text>
+							<view class="statistic-right">
+								<text class="statistic-value">{{accuracy}}</text><text class="statistic-unit">%</text>
+							</view>
+						</view>
+					</view>
+					<text class="name">{{nameSub}}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+
+	export default {
+		data() {
+			return {
+				status: "",		// success: 挑战成功, ok: 挑战完成(没在规定时间完成,但打了所有点), fail: 挑战结束
+				name: "",		// 用户名
+				duration: 0,	// 总用时,秒
+				distance: 0,	// 总里程,米
+				cal: 0,			// 卡路里,卡 int
+				accuracy: 0,	// 脑力值百分比
+				syscount: 0		// 点数
+			}
+		},
+		computed: {
+			nameSub() {
+				const maxlen = 8;
+				const nameLen = tools.calStrLen(this.name);
+				console.log('nameLen', nameLen);
+				if (nameLen <= 6) {
+					return '选手: ' + this.name;
+				}
+				// else if (nameLen >= maxlen) {
+				// 	return this.name.substring(0,maxlen-1) + '...';
+				// }
+				else {
+					return this.name;
+				}
+			},
+			durationMin() {
+				return Math.round(this.duration * 10 / 60) / 10;
+			},
+			distanceKm() {
+				return Math.round(this.distance * 10 / 1000) / 10;
+			}
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+			console.log('[challenge result] onLoad');
+			this.status = event["status"] ?? "";
+			this.name = event["name"] ?? "";
+			this.duration = event["duration"] ?? 0;
+			this.distance = event["distance"] ?? 0;
+			this.cal = event["cal"] ?? 0;
+			this.accuracy = event["accuracy"] ?? 0;
+			this.syscount = event["syscount"] ?? 0;
+		},
+		methods: {
+		}
+	}
+</script>
+
+<style>
+	.body {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		/* background-color: black; */
+		background-image: url("/static/shanda/challenge/success_bg.webp");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: top;
+		background-size: cover;
+	}
+
+	.content {
+		width: 750rpx;
+		min-height: 100vh;
+		/* margin: 0 auto; */
+	}
+
+	.top {
+		width: 100%;
+		/* height: 600rpx; */
+		padding-top: 160rpx;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.logo {
+		width: 210rpx;
+		height: 210rpx;
+	}
+	
+	.gameName {
+		padding-top: 50rpx;
+		padding-bottom: 50rpx;
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		font-size: 66rpx;
+		color: #ffffff;
+	}
+
+	.main {
+		width: 100%;
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.main-content {
+		/* margin-top: 25rpx; */
+		margin-bottom: 60rpx;
+		height: 700rpx;
+		background-image: url("/static/shanda/challenge/rank_bg.webp");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: top;
+		background-size: contain;
+	}
+
+	.rank {
+		width: 400rpx;
+		/* height: 500rpx; */
+		margin-left: 180rpx;
+		margin-top: 150rpx;
+	}
+
+	.name {
+		width: 330rpx;
+		/* 确保文本在一行内显示 */
+		white-space: nowrap;
+		/* 超出容器部分的文本隐藏起来 */
+		overflow: hidden;
+		/* 使用省略号表示被截断的文本 */
+		/* text-overflow: ellipsis; */
+		text-align: center;
+		margin-left: 250rpx;
+		margin-top: 40rpx;
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		font-size: 36rpx;
+		color: #000000;
+	}
+
+	.statistic {
+		height: 110rpx;
+		margin-bottom: 16rpx;
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+	}
+
+	.statistic-right {
+		flex-direction: row;
+		align-items: baseline;
+	}
+
+	.statistic-title {
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		font-size: 46rpx;
+		color: #ffffff;
+	}
+
+	.statistic-value {
+		font-family: Source Han Sans CN;
+		font-size: 56rpx;
+		color: #ffffff;
+		font-weight: bold;
+	}
+
+	.statistic-unit {
+		font-family: Source Han Sans CN;
+		font-size: 40rpx;
+		color: #ffffff;
+		padding-left: 10rpx;
+	}
+
+</style>

+ 62 - 0
custom/pages/xfl/challenge/exit.uvue

@@ -0,0 +1,62 @@
+<!-- 
+http://localhost:5173/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&status=fail
+https://oss-mbh5.colormaprun.com/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&status=fail
+ -->
+<template>
+	<view class="body">
+		<view class="content">
+			<view class="main">
+				<view class="exit_game"></view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		computed: {
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+		},
+		methods: {
+		}
+	}
+</script>
+
+<style>
+	.body {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.content {
+		width: 100vw;
+		/* width: 750rpx; */
+		/* margin: 0 auto; */
+	}
+
+	.main {
+		width: 100%;
+		flex-direction: column;
+		align-items: center;
+		justify-content: flex-start;
+	}
+
+	.exit_game {
+		width: 100%;
+		height: 100vh;
+		/* height: 1100rpx; */
+		/* margin-left: 40rpx; */
+		background-image: url("/static/xfl/challenge/exit_game.jpg");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: bottom;
+		background-size: cover;
+	}
+</style>

+ 46 - 0
custom/pages/xfl/challenge/index.uvue

@@ -0,0 +1,46 @@
+<!-- 
+http://localhost:5173/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+https://oss-mbh5.colormaprun.com/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+ -->
+<template>
+	<view></view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+			// console.log(event);
+			const queryString = this.objectToQueryString(event);
+			// console.log(queryString);
+			const status = event["status"] ?? ""
+			
+			if (status == 'success') {	// 挑战成功
+				uni.reLaunch({
+					url: '/pages/xfl/challenge/success?' + queryString
+				});
+			}
+			else if (status == 'ok' || status == 'fail') {	// 挑战完成/挑战失败
+				uni.reLaunch({
+					url: '/pages/xfl/challenge/exit'
+				});
+			}
+			else {
+				this.showErr();
+			}
+		},
+		methods: {
+			showErr() {
+				uni.showToast({
+					title: '参数错误'
+				});
+			},
+			objectToQueryString(obj) {
+				return Object.keys(obj).map(k => k + '=' + obj[k]).join('&');
+			}
+		}
+	}
+</script>

+ 211 - 0
custom/pages/xfl/challenge/success.uvue

@@ -0,0 +1,211 @@
+<!-- 
+http://localhost:5173/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+https://oss-mbh5.colormaprun.com/custom/#/pages/xfl/challenge/index?pagetype=challenge_result&distance=1320&status=success&name=天生我材必有用&cal=13500100&duration=3600&accuracy=50&syscount=25
+ -->
+<template>
+	<view class="body">
+		<view class="main">
+			<view class="main-content">
+				<view class="rank">
+					<view class="statistic">
+						<view class="statistic-left">
+							<image class="statistic-ico" mode="aspectFit" src="../../../static/xfl/challenge/ico1.png">
+							</image>
+							<text class="statistic-title">总用时:</text>
+						</view>
+						<view class="statistic-right">
+							<text class="statistic-value">{{durationMin}}</text><text class="statistic-unit">min</text>
+						</view>
+					</view>
+					<view class="statistic">
+						<view class="statistic-left">
+							<image class="statistic-ico" mode="aspectFit" src="../../../static/xfl/challenge/ico2.png">
+							</image>
+							<text class="statistic-title">总里程:</text>
+						</view>
+						<view class="statistic-right">
+							<text class="statistic-value">{{distanceKm}}</text><text class="statistic-unit">Km</text>
+						</view>
+					</view>
+					<view class="statistic">
+						<view class="statistic-left">
+							<image class="statistic-ico" mode="aspectFit" src="../../../static/xfl/challenge/ico3.png">
+							</image>
+							<text class="statistic-title">脑力值:</text>
+						</view>
+						<view class="statistic-right">
+							<text class="statistic-value">{{accuracy}}</text><text class="statistic-unit">分</text>
+						</view>
+					</view>
+				</view>
+				<view class="line"></view>
+				<text class="name">选手: {{nameSub}}</text>
+			</view>
+			<text class="memo">请至活动查看排名详情</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+
+	export default {
+		data() {
+			return {
+				status: "",		// success: 挑战成功, ok: 挑战完成(没在规定时间完成,但打了所有点), fail: 挑战结束
+				name: "",		// 用户名
+				duration: 0,	// 总用时,秒
+				distance: 0,	// 总里程,米
+				cal: 0,			// 卡路里,卡 int
+				accuracy: 0,	// 脑力值百分比
+				syscount: 0		// 点数
+			}
+		},
+		computed: {
+			nameSub() {
+				return this.name;
+				/* const maxlen = 8;
+				const nameLen = tools.calStrLen(this.name);
+				console.log('nameLen', nameLen);
+				if (nameLen <= 6) {
+					return '选手: ' + this.name;
+				}
+				else {
+					return this.name;
+				} */
+			},
+			durationMin() {
+				return Math.round(this.duration * 10 / 60) / 10;
+			},
+			distanceKm() {
+				return Math.round(this.distance * 10 / 1000) / 10;
+			}
+		},
+		onLoad(event) { // 类型非必填,可自动推导
+			console.log('[challenge result] onLoad');
+			this.status = event["status"] ?? "";
+			this.name = event["name"] ?? "";
+			this.duration = event["duration"] ?? 0;
+			this.distance = event["distance"] ?? 0;
+			this.cal = event["cal"] ?? 0;
+			this.accuracy = event["accuracy"] ?? 0;
+			this.syscount = event["syscount"] ?? 0;
+		},
+		methods: {
+		}
+	}
+</script>
+
+<style>
+	.body {
+		display: flex;
+		width: 100vw;
+		height: 100vh;
+		flex-direction: column;
+		align-items: center;
+		justify-content: flex-end;
+		/* background-color: black; */
+		background-image: url("/static/xfl/challenge/success_bg.jpg");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: bottom;
+		background-size: cover;
+		/* background-size: 100% 100%; */
+	}
+
+	.main {
+		margin-bottom: 430rpx;
+		align-items: center;
+	}
+
+	.main-content {
+		width: 80vw;
+		height: 375rpx;
+		background-color: #ffffff;
+		border-radius: 25rpx;
+		align-items: center;
+	}
+
+	.rank {
+		width: 500rpx;
+		/* height: 500rpx; */
+		margin-top: 20rpx;
+	}
+
+	.statistic {
+		height: 86rpx;
+		/* margin-bottom: 16rpx; */
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+	}
+
+	.statistic-left {
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.statistic-right {
+		flex-direction: row;
+		align-items: baseline;
+	}
+
+	.statistic-ico {
+		width: 50rpx;
+		height: 50rpx;
+		margin-right: 10rpx;
+	}
+
+	.statistic-title {
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		font-size: 36rpx;
+		color: #333333;
+	}
+
+	.statistic-value {
+		font-family: Source Han Sans CN;
+		font-size: 50rpx;
+		color: #333333;
+		font-weight: bold;
+	}
+
+	.statistic-unit {
+		font-family: Source Han Sans CN;
+		font-size: 20rpx;
+		color: #333333;
+		padding-left: 10rpx;
+	}
+
+	.line {
+		width: 500rpx;
+		height: 3rpx;
+		margin-top: 12rpx;
+		background-color: #e6e6e6;
+	}
+
+	.name {
+		width: 500rpx;
+		/* 确保文本在一行内显示 */
+		white-space: nowrap;
+		/* 超出容器部分的文本隐藏起来 */
+		overflow: hidden;
+		/* 使用省略号表示被截断的文本 */
+		text-overflow: ellipsis;
+		text-align: center;
+		margin-top: 18rpx;
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		font-size: 28rpx;
+		color: #9e9e9e;
+	}
+
+	.memo {
+		margin-top: 30rpx;
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		color: #ffffff;
+		font-size: 36rpx;
+		text-align: center;
+	}
+</style>

二进制
custom/static/logo.png


二进制
custom/static/shanda/challenge/exit_game.jpg


二进制
custom/static/shanda/challenge/exit_game_bk.webp


二进制
custom/static/shanda/challenge/rank_bg.webp


二进制
custom/static/shanda/challenge/success_bg.webp


二进制
custom/static/shanda/logo.webp


二进制
custom/static/xfl/challenge/exit_game.jpg


二进制
custom/static/xfl/challenge/ico1.png


二进制
custom/static/xfl/challenge/ico2.png


二进制
custom/static/xfl/challenge/ico3.png


二进制
custom/static/xfl/challenge/ico4.png


二进制
custom/static/xfl/challenge/success_bg.jpg


+ 76 - 0
custom/uni.scss

@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16px;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;