wzx 1 vuosi sitten
vanhempi
commit
0a3eea125d
83 muutettua tiedostoa jossa 9655 lisäystä ja 0 poistoa
  1. 67 0
      shop/App.vue
  2. 43 0
      shop/common/api.js
  3. 1 0
      shop/common/define.js
  4. 485 0
      shop/common/tools.js
  5. 95 0
      shop/common/weixin.js
  6. 20 0
      shop/index.html
  7. 22 0
      shop/main.js
  8. 83 0
      shop/manifest.json
  9. 13 0
      shop/node_modules/.package-lock.json
  10. 21 0
      shop/node_modules/weixin-js-sdk/LICENSE
  11. 36 0
      shop/node_modules/weixin-js-sdk/README.md
  12. 601 0
      shop/node_modules/weixin-js-sdk/index.d.ts
  13. 891 0
      shop/node_modules/weixin-js-sdk/index.js
  14. 12 0
      shop/node_modules/weixin-js-sdk/package.json
  15. 29 0
      shop/package-lock.json
  16. 47 0
      shop/package.json
  17. 32 0
      shop/pages.json
  18. 288 0
      shop/pages/exchgRecord/exchgRecord.vue
  19. 177 0
      shop/pages/index/index.vue
  20. 166 0
      shop/pages/login/login.vue
  21. BIN
      shop/static/bg_index.png
  22. BIN
      shop/static/bg_login.png
  23. BIN
      shop/static/bg_topbar.png
  24. BIN
      shop/static/ctbp.png
  25. BIN
      shop/static/ico_fail.png
  26. BIN
      shop/static/ico_success.png
  27. BIN
      shop/static/logo.png
  28. BIN
      shop/static/run.png
  29. BIN
      shop/static/test/egg.png
  30. BIN
      shop/static/test/ticket_xfl.png
  31. BIN
      shop/static/test/toy.png
  32. 10 0
      shop/uni.promisify.adaptor.js
  33. 76 0
      shop/uni.scss
  34. 33 0
      shop/uni_modules/uni-badge/changelog.md
  35. 268 0
      shop/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  36. 85 0
      shop/uni_modules/uni-badge/package.json
  37. 10 0
      shop/uni_modules/uni-badge/readme.md
  38. 39 0
      shop/uni_modules/uni-data-select/changelog.md
  39. 562 0
      shop/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
  40. 86 0
      shop/uni_modules/uni-data-select/package.json
  41. 8 0
      shop/uni_modules/uni-data-select/readme.md
  42. 42 0
      shop/uni_modules/uni-icons/changelog.md
  43. 91 0
      shop/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
  44. 110 0
      shop/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
  45. 664 0
      shop/uni_modules/uni-icons/components/uni-icons/uniicons.css
  46. BIN
      shop/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
  47. 664 0
      shop/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
  48. 649 0
      shop/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
  49. 89 0
      shop/uni_modules/uni-icons/package.json
  50. 8 0
      shop/uni_modules/uni-icons/readme.md
  51. 46 0
      shop/uni_modules/uni-list/changelog.md
  52. 107 0
      shop/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
  53. 58 0
      shop/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
  54. 593 0
      shop/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
  55. 534 0
      shop/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
  56. 123 0
      shop/uni_modules/uni-list/components/uni-list/uni-list.vue
  57. 65 0
      shop/uni_modules/uni-list/components/uni-list/uni-refresh.vue
  58. 87 0
      shop/uni_modules/uni-list/components/uni-list/uni-refresh.wxs
  59. 88 0
      shop/uni_modules/uni-list/package.json
  60. 346 0
      shop/uni_modules/uni-list/readme.md
  61. 19 0
      shop/uni_modules/uni-load-more/changelog.md
  62. 5 0
      shop/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
  63. 8 0
      shop/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
  64. 5 0
      shop/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
  65. 5 0
      shop/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
  66. 112 0
      shop/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
  67. 86 0
      shop/uni_modules/uni-load-more/package.json
  68. 14 0
      shop/uni_modules/uni-load-more/readme.md
  69. 8 0
      shop/uni_modules/uni-scss/changelog.md
  70. 1 0
      shop/uni_modules/uni-scss/index.scss
  71. 82 0
      shop/uni_modules/uni-scss/package.json
  72. 4 0
      shop/uni_modules/uni-scss/readme.md
  73. 7 0
      shop/uni_modules/uni-scss/styles/index.scss
  74. 3 0
      shop/uni_modules/uni-scss/styles/setting/_border.scss
  75. 66 0
      shop/uni_modules/uni-scss/styles/setting/_color.scss
  76. 55 0
      shop/uni_modules/uni-scss/styles/setting/_radius.scss
  77. 56 0
      shop/uni_modules/uni-scss/styles/setting/_space.scss
  78. 167 0
      shop/uni_modules/uni-scss/styles/setting/_styles.scss
  79. 24 0
      shop/uni_modules/uni-scss/styles/setting/_text.scss
  80. 146 0
      shop/uni_modules/uni-scss/styles/setting/_variables.scss
  81. 19 0
      shop/uni_modules/uni-scss/styles/tools/functions.scss
  82. 31 0
      shop/uni_modules/uni-scss/theme.scss
  83. 62 0
      shop/uni_modules/uni-scss/variables.scss

+ 67 - 0
shop/App.vue

@@ -0,0 +1,67 @@
+<script>
+	export default {
+		onLaunch: function() {
+			// console.log('App Launch')
+		},
+		onShow: function() {
+			// console.log('App Show')
+		},
+		onHide: function() {
+			// console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+
+	.body {
+		/* width: 100vw; */
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.body-radius {
+		border-radius: 50rpx;
+		overflow: hidden;
+		/* 确保边框圆角不会溢出 */
+	}
+
+	.uni-row {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-column {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.uni-jct {
+		justify-content: start;
+	}
+
+	.uni-jcc {
+		justify-content: center;
+	}
+
+	.uni-jcsa {
+		justify-content: space-around;
+	}
+
+	.uni-jcsb {
+		justify-content: space-between;
+	}
+
+	.uni-jcse {
+		justify-content: space-evenly;
+	}
+
+	.hidden {
+		visibility: hidden;
+	}
+</style>

+ 43 - 0
shop/common/api.js

@@ -0,0 +1,43 @@
+export const apiServer = process.env.API_BASE_URL;
+// console.log("apiServer", apiServer);
+
+export const token = '';
+// export const token = '5c654da466ad325c6a1121e6d9e18f21';
+
+// 商家系统登录
+export const apiVerfSignIn = apiServer + 'VerfSignIn';
+
+// 商家系统核销
+export const apiVerfExchange = apiServer + 'VerfExchange';
+
+// 商家系统已核销记录查询
+export const apiVerfExchangedListQuery = apiServer + 'VerfExchangedListQuery';
+
+// 商家系统获取微信JsConfig
+export const apiGetWxJsSdkConfig = apiServer + 'GetWxJsSdkConfig';
+
+
+// 检测request的返回值
+export function checkResCode(res) {
+	if (res.data.code == 0) {
+		return true;
+	} else if (res.statusCode == 401) { // 未登录
+		uni.showToast({
+			title: `您尚未登录`,
+			icon: 'none',
+			duration: 3000
+		});
+		// window.location.href = `action://to_login/`;
+		uni.navigateTo({
+			url: '/pages/login/login'
+		});
+		return false;
+	} else {
+		uni.showToast({
+			title: `${res.data.message}`,
+			icon: 'none',
+			duration: 3000
+		});
+		return false;
+	}
+};

+ 1 - 0
shop/common/define.js

@@ -0,0 +1 @@
+// export const teamName = [];

+ 485 - 0
shop/common/tools.js

@@ -0,0 +1,485 @@
+var tools = {
+
+	tokenKey: "token",
+	shopInfoKey: "shopInfo",
+
+	getToken() {
+		try {
+			const value = uni.getStorageSync(this.tokenKey);
+			// console.log('[getToken]', value);
+			return value
+		} catch (e) {
+			console.log('[getToken] fail', e);
+			return "";
+		}
+	},
+
+	setToken(token) {
+		try {
+			uni.setStorageSync(this.tokenKey, token);
+		} catch (e) {
+			console.log('[setToken] fail', e);
+		}
+	},
+
+	getShopInfo() {
+		try {
+			const value = uni.getStorageSync(this.shopInfoKey);
+			// console.log('[getShopInfo]', value);
+			return value
+		} catch (e) {
+			console.log('[getShopInfo] fail', e);
+			return "";
+		}
+	},
+
+	setShopInfo(shopinfo) {
+		try {
+			uni.setStorageSync(this.shopInfoKey, shopinfo);
+		} catch (e) {
+			console.log('[setShopInfo] fail', e);
+		}
+	},
+
+	// 检测token
+	checkToken(token) {
+		const regex = /^[0-9A-Za-f]{32}$/;
+		if (regex.test(token)) {
+			return true;
+		} else { // 未登录
+			console.log('checkToken err! token: ', token);
+			uni.showToast({
+				title: `您尚未登录`,
+				icon: 'none',
+				duration: 3000
+			});
+
+			uni.navigateTo({
+				url: '/pages/login/login'
+			});
+			return false;
+		}
+	},
+
+	// 判断赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+	checkMcState(beginSecond, endSecond) {
+		let mcState = 0; // 未开始
+		if (beginSecond > 0 && endSecond > 0) {
+			const now = Date.now() / 1000;
+			const dif1 = beginSecond - now;
+			const dif2 = endSecond - now;
+			// const dif = 3600*24 - 60;
+			if (dif1 > 0) {
+				console.log("活动未开始");
+				mcState = 0; // 未开始
+			} else if (dif2 > 0) {
+				console.log("活动进行中");
+				mcState = 1; // 进行中
+			} else {
+				console.log("活动已结束");
+				mcState = 2; // 已结束
+			}
+		}
+		return mcState;
+	},
+
+	// 动态创建<style>标签,将CSS代码插入到文档中
+	loadCssCode(cssCode) {
+		this.removeCssCode();
+
+		const styleId = "css-custom";
+		var style = window.document.createElement("style");
+		style.type = "text/css";
+		style.id = styleId;
+		if (style.styleSheet) {
+			// This is required for IE8 and below.
+			style.styleSheet.cssText = cssCode;
+		} else {
+			style.appendChild(document.createTextNode(cssCode));
+		}
+		document.getElementsByTagName("head")[0].appendChild(style);
+		// console.log("head:", document.getElementsByTagName("head")[0]);
+		// console.log("head:", document.getElementById(styleId));
+		// console.log("style:", style);
+	},
+
+	// 删除之前动态创建的<style>标签
+	removeCssCode() {
+		const styleId = "css-custom";
+		var oldCss = document.getElementById(styleId);
+		// console.log("oldCss:", oldCss);
+		if (oldCss != null) {
+			document.getElementsByTagName("head")[0].removeChild(oldCss);
+			console.log("oldCss 已移除");
+		}
+	},
+
+	// uni-data-select 组件,根据选中的值获取对应的文本
+	getSelectedText(obj, value) {
+		const selectedOption = obj.find(option => option.value === value);
+		return selectedOption ? selectedOption.text : '';
+	},
+
+	objectToQueryString(obj) {
+		return Object.keys(obj).map(k => k + '=' + obj[k]).join('&');
+	},
+
+	// 秒数转换成 XX天XX小时
+	convertSecondsToDHM(seconds) {
+		var days = Math.floor(seconds / (3600 * 24));
+		var hours = Math.floor((seconds % (3600 * 24)) / 3600);
+		var minutes = Math.floor((seconds % (3600 * 24)) % 3600 / 60);
+		if (days > 0)
+			// return `${days.toString().padStart(2, '0')}天${hours.toString().padStart(2, '0')}小时`;
+			return `${days}天${hours.toString().padStart(2, '0')}小时`;
+		else
+			return `${hours.toString().padStart(2, '0')}小时${minutes.toString().padStart(2, '0')}分钟`;
+	},
+
+	// 秒数转换成时分秒
+	// style:  0 [01:02:03]  1 [1h:02'3"]
+	convertSecondsToHMS(seconds, style = 0) {
+		var hours = Math.floor(seconds / 3600);
+		var minutes = Math.floor((seconds % 3600) / 60);
+		var remainingSeconds = Math.floor(seconds % 60);
+		// return hours + ":" + minutes + ":" + remainingSeconds;
+		if (style == 0)
+			return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+		else if (style == 1) {
+			if (hours > 0)
+				return `${hours}h:${minutes}′${remainingSeconds}″`;
+			else
+				return `${minutes}′${remainingSeconds}″`;
+		}
+	},
+
+	// 计算(中英文混合)字符串长度
+	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));
+	},
+
+	// 获取指定时间内指定数量的年月列表
+	getMonthList(monthNum=6, timestamp = "") {
+		var data = null;
+		
+		if (timestamp > 0)
+			data = new Date(timestamp);
+		else
+			data = new Date();
+			
+		var year = data.getFullYear();
+		var mon = data.getMonth() + 1;
+		var arry = new Array();
+		for (var i = 0; i < monthNum; i++) {
+			if (mon <= 0) {
+				year = year - 1;
+				mon = mon + 12;
+			}
+			if (mon < 10) {
+				mon = "0" + mon;
+			}
+			arry[i] = year + "-" + mon;
+			mon = mon - 1;
+		}
+
+		return arry;
+	},
+
+	//计算多长时间前
+	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;
+		} else if (i == 2) {
+			return Y + '年' + M + '月' + D + '日';
+		} else if (i == 3) {
+			return Y + '-' + M + '-' + D + ' ' + h + ':' + m;
+		} else if (i == 4) {
+			return Y + '-' + M;
+		}
+		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;

+ 95 - 0
shop/common/weixin.js

@@ -0,0 +1,95 @@
+var weixin = {
+	
+	AppId: 'wx6de69d22565ac596',
+	
+	// 解析页面查询参数
+	parseQueryParams(url, decode=true) {
+	    var queryString = url.split('?')[1];
+	    // console.log('queryString: ' + queryString);
+	    if (queryString == undefined)
+	        return '';
+	
+	    if (decode)
+	        queryString = Base64.decode(queryString);
+	    // console.log(queryString);
+	    var params = new URLSearchParams(queryString);
+	    return params;
+	},
+	
+	// 获取微信code用于后续服务端获取用户openid
+	getWxCode() {
+		var code = '';
+		var params = this.parseQueryParams(window.location.href, false);
+		if (params != '')
+			code = params.get('code');
+		
+		if (code == null || code === '') {
+			var redirect_uri = window.location.href;
+			redirect_uri = encodeURIComponent(redirect_uri);
+			console.log('redirect_uri:' + redirect_uri);
+			window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='+ this.AppId 
+				+ '&redirect_uri=' + redirect_uri
+				+ '&response_type=code&scope=snsapi_base&state=1#wechat_redirect';
+		} else {
+			return code;
+		}
+	},
+	
+	initWeixinJSBridge(payParam, successFunc=null, successParam=null, failFunc=null, failParam=null) {
+		// 支付只能在微信内置浏览器才有效果,在其他浏览器里面是无效的,进行判断
+		if (typeof WeixinJSBridge == "undefined") {
+			console.log("请在微信客户端打开");
+			alert("请在微信客户端打开");
+			if (document.addEventListener) {
+				document.addEventListener('WeixinJSBridgeReady', onBridgeReady(payParam, successFunc, successParam, failFunc, failParam), false);
+			} else if (document.attachEvent) {
+				document.attachEvent('WeixinJSBridgeReady', onBridgeReady(payParam, successFunc, successParam, failFunc, failParam));
+				document.attachEvent('onWeixinJSBridgeReady', onBridgeReady(payParam, successFunc, successParam, failFunc, failParam));
+			}
+		} else {
+			onBridgeReady(payParam, successFunc, successParam, failFunc, failParam);
+		}
+	},
+	
+	// JSAPI调起支付
+	onBridgeReady(payParam, successFunc=null, successParam=null, failFunc=null, failParam=null) {
+		WeixinJSBridge.invoke(
+			"getBrandWCPayRequest",
+			{
+				appId: payParam.AppId,          //公众号ID,由商户传入
+				timeStamp: payParam.TimeStamp,  //时间戳,自1970年以来的秒数
+				nonceStr: payParam.NonceStr,    //随机串
+				package: payParam.Package,
+				signType: payParam.SignType,    //微信签名方式
+				paySign: payParam.PaySign       //微信签名
+			},
+			function (res) {
+				if (res.err_msg == "get_brand_wcpay_request:ok") {
+					// 使用以上方式判断前端返回,微信团队郑重提示:
+					//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
+					if (successFunc != null && successFunc != '') {
+						if (successParam != null && successParam != '') {
+							successFunc(successParam);
+						} else {
+							successFunc();
+						}
+					} else {
+						alert("支付成功");
+					}
+				} else {
+					if (failFunc != null && failFunc != '') {
+						if (failParam != null && failParam != '') {
+							failFunc(failParam);
+						} else {
+							failFunc();
+						}
+					} else {
+						alert("支付取消");
+					}
+				}
+			}
+		);
+	}
+};
+
+export default weixin;

+ 20 - 0
shop/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.js"></script>
+  </body>
+</html>

+ 22 - 0
shop/main.js

@@ -0,0 +1,22 @@
+import App from './App'
+
+// #ifndef VUE3
+import Vue from 'vue'
+import './uni.promisify.adaptor'
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+  ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif

+ 83 - 0
shop/manifest.json

@@ -0,0 +1,83 @@
+{
+    "name" : "shop",
+    "appid" : "__UNI__5D9E804",
+    "description" : "彩图奔跑 - 商家小程序",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "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",
+    "h5" : {
+        "router" : {
+            "mode" : "hash",
+            "base" : "/shop/"
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
+}

+ 13 - 0
shop/node_modules/.package-lock.json

@@ -0,0 +1,13 @@
+{
+  "name": "shop",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "node_modules/weixin-js-sdk": {
+      "version": "1.6.5",
+      "resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz",
+      "integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ=="
+    }
+  }
+}

+ 21 - 0
shop/node_modules/weixin-js-sdk/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Yanxi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 36 - 0
shop/node_modules/weixin-js-sdk/README.md

@@ -0,0 +1,36 @@
+微信官方 js-sdk
+----
+
+说明: 仅将官方 js-sdk 发布到 npm,支持 CommonJS,便于 browserify, webpack 等直接使用,支持 TypeScript。
+
+
+官方 JS 源码: https://res.wx.qq.com/open/js/jweixin-1.6.0.js
+
+官方使用说明: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
+
+安装:
+```shell
+npm install weixin-js-sdk
+```
+
+使用:
+```javascript
+// commonjs
+var wx = require('weixin-js-sdk');
+
+// es module
+import wx from 'weixin-js-sdk'
+```
+
+### Old versions
+
+* [1.0.0](https://github.com/yanxi123-com/weixin-js-sdk/tree/1.0.0)
+* [1.2.0](https://github.com/yanxi123-com/weixin-js-sdk/tree/1.2.0)
+
+### 个人主页
+
+* [https://yanxi123.com/](https://yanxi123.com/)
+
+### 感谢
+
+TypeScript 定义文件来自 [wx-jssdk-ts](https://github.com/zhaoky/wx-jssdk-ts/blob/master/index.d.ts)

+ 601 - 0
shop/node_modules/weixin-js-sdk/index.d.ts

@@ -0,0 +1,601 @@
+// Type definitions for weixin jssdk 1.6.0
+// Project: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+declare namespace wx {
+  type ImageSizeType = "original" | "compressed";
+  type ImageSourceType = "album" | "camera";
+  type VideoSourceType = "album" | "camera";
+  type ApiMethod =
+    | "onMenuShareTimeline"
+    | "onMenuShareAppMessage"
+    | "onMenuShareQQ"
+    | "onMenuShareWeibo"
+    | "onMenuShareQZone"
+    | "updateAppMessageShareData"
+    | "updateTimelineShareData"
+    | "startRecord"
+    | "stopRecord"
+    | "onVoiceRecordEnd"
+    | "playVoice"
+    | "pauseVoice"
+    | "stopVoice"
+    | "onVoicePlayEnd"
+    | "uploadVoice"
+    | "downloadVoice"
+    | "chooseImage"
+    | "previewImage"
+    | "uploadImage"
+    | "downloadImage"
+    | "translateVoice"
+    | "getNetworkType"
+    | "openLocation"
+    | "getLocation"
+    | "hideOptionMenu"
+    | "showOptionMenu"
+    | "hideMenuItems"
+    | "showMenuItems"
+    | "hideAllNonBaseMenuItem"
+    | "showAllNonBaseMenuItem"
+    | "closeWindow"
+    | "scanQRCode"
+    | "chooseWXPay"
+    | "openProductSpecificView"
+    | "addCard"
+    | "chooseCard"
+    | "openCard";
+  // 所有JS接口列表
+  type jsApiList = ApiMethod[];
+
+  // 开放标签列表
+  // https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html
+  type openTag = "wx-open-launch-weapp" | "wx-open-launch-app" | "wx-open-subscribe" | "wx-open-audio"
+  type openTagList = openTag[];
+
+  // 所有菜单项列表
+  // 基本类
+  type menuBase =
+    | "menuItem:exposeArticle" // 举报
+    | "menuItem:setFont" // 调整字体
+    | "menuItem:dayMode" // 日间模式
+    | "menuItem:nightMode" // 夜间模式
+    | "menuItem:refresh" // 刷新
+    | "menuItem:profile" // 查看公众号(已添加)
+    | "menuItem:addContact"; // 查看公众号(未添加)
+  // 传播类
+  type menuShare =
+    | "menuItem:share:appMessage" // 发送给朋友
+    | "menuItem:share:timeline" // 分享到朋友圈
+    | "menuItem:share:qq" // 分享到QQ
+    | "menuItem:share:weiboApp" // 分享到Weibo
+    | "menuItem:favorite" // 收藏
+    | "menuItem:share:facebook" // 分享到FB
+    | "menuItem:share:QZone"; // 分享到 QQ 空间
+
+  // 保护类
+  type menuProtected =
+    | "menuItem:editTag" // 编辑标签
+    | "menuItem:delete" // 删除
+    | "menuItem:copyUrl" // 复制链接
+    | "menuItem:originPage" // 原网页
+    | "menuItem:readMode" // 阅读模式
+    | "menuItem:openWithQQBrowser" // 在QQ浏览器中打开
+    | "menuItem:openWithSafari" // 在Safari中打开
+    | "menuItem:share:email" // 邮件
+    | "menuItem:share:brand"; // 一些特殊公众号
+
+  type menuList = Array<menuBase | menuProtected | menuShare>;
+
+  function config(conf: {
+    debug?: boolean; // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
+    appId: string; // 必填,公众号的唯一标识
+    timestamp: number; // 必填,生成签名的时间戳
+    nonceStr: string; // 必填,生成签名的随机串
+    signature: string; // 必填,签名,见附录1
+    jsApiList?: jsApiList; // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
+    openTagList?: openTagList;
+  }): void;
+
+  interface Resouce {
+    localId: string;
+  }
+  interface BaseParams {
+    success?(...args: any[]): void;
+    /** 接口调用失败的回调函数 */
+    fail?(...args: any[]): void;
+    /** 接口取消调用的回调函数 */
+    cancel?(...args: any[]): void;
+    /** 接口调用结束的回调函数(调用成功、失败都会执行) */
+    complete?(...args: any[]): void;
+  }
+  function ready(fn: () => void): void;
+  function error(fn: (err: { errMsg: string }) => void): void;
+
+  interface IcheckJsApi extends BaseParams {
+    jsApiList: jsApiList; // 需要检测的JS接口列表,所有JS接口列表见附录2,
+    // 以键值对的形式返回,可用的api值true,不可用为false
+    // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
+    success(res: {
+      checkResult: { [api: string]: boolean };
+      errMsg: string;
+    }): void;
+  }
+  /**
+   * 判断当前客户端版本是否支持指定JS接口
+   * 备注:checkJsApi接口是客户端6.0.2新引入的一个预留接口,第一期开放的接口均可不使用checkJsApi来检测。
+   */
+  function checkJsApi(params: IcheckJsApi): void;
+
+  interface IonMenuShareTimeline extends BaseParams {
+    title: string; // 分享标题
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+    // 用户取消分享后执行的回调函数
+    cancel(): void;
+  }
+  /*=============================基础接口================================*/
+  /**
+   * 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
+   */
+  function onMenuShareTimeline(params: IonMenuShareTimeline): void;
+
+  interface IonMenuShareAppMessage extends BaseParams {
+    title: string; // 分享标题
+    desc: string; // 分享描述
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    type?: "music" | "video或link" | "link"; // 分享类型,music、video或link,不填默认为link
+    dataUrl?: string; // 如果type是music或video,则要提供数据链接,默认为空
+    // 用户确认分享后执行的回调函数
+    success(): void;
+    // 用户取消分享后执行的回调函数
+    cancel(): void;
+  }
+  /**
+   * 获取“分享给朋友”按钮点击状态及自定义分享内容接口
+   */
+  function onMenuShareAppMessage(params: IonMenuShareAppMessage): void;
+
+  interface IonMenuShareQQ extends BaseParams {
+    title: string; // 分享标题
+    desc: string; // 分享描述
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+    // 用户取消分享后执行的回调函数
+    cancel(): void;
+  }
+  /**
+   * 获取“分享到QQ”按钮点击状态及自定义分享内容接口
+   */
+  function onMenuShareQQ(params: IonMenuShareQQ): void;
+
+  interface IonMenuShareWeibo extends BaseParams {
+    title: string; // 分享标题
+    desc: string; // 分享描述
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+    // 用户取消分享后执行的回调函数
+    cancel(): void;
+  }
+  /**
+   * 获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口
+   */
+  function onMenuShareWeibo(params: IonMenuShareWeibo): void;
+
+  interface IonMenuShareQZone extends BaseParams {
+    title: string; // 分享标题
+    desc: string; // 分享描述
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+    // 用户取消分享后执行的回调函数
+    cancel(): void;
+  }
+  /**
+   * 获取“分享到QQ空间”按钮点击状态及自定义分享内容接口
+   */
+  function onMenuShareQZone(params: IonMenuShareQZone): void;
+
+  interface IupdateAppMessageShareData extends BaseParams {
+    title: string; // 分享标题
+    desc: string; // 分享描述
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+  }
+  /**
+   * 获取“分享给朋友”及“分享到QQ”按钮点击状态及自定义分享内容接口(新)
+   */
+  function updateAppMessageShareData(params: IupdateAppMessageShareData): void;
+
+  interface IupdateTimelineShareData extends BaseParams {
+    title: string; // 分享标题
+    link: string; // 分享链接
+    imgUrl: string; // 分享图标
+    // 用户确认分享后执行的回调函数
+    success(): void;
+  }
+  /**
+   * 获取“分享到朋友圈”及“分享到QQ空间”按钮点击状态及自定义分享内容接口
+   */
+  function updateTimelineShareData(params: IupdateTimelineShareData): void;
+  /*=============================基础接口================================*/
+
+  /*=============================图像接口================================*/
+  interface IchooseImage extends BaseParams {
+    /** 最多可以选择的图片张数,默认9 */
+    count?: number;
+    /** original 原图,compressed 压缩图,默认二者都有 */
+    sizeType?: ImageSizeType[];
+    /** album 从相册选图,camera 使用相机,默认二者都有 */
+    sourceType?: ImageSourceType[];
+    /** 成功则返回图片的本地文件路径列表 tempFilePaths */
+    success(res: {
+      sourceType: string; // weixin album camera
+      localIds: string[];
+      errMsg: string;
+    }): void;
+    cancel(): void;
+  }
+  /**
+   * 从本地相册选择图片或使用相机拍照。
+   */
+  function chooseImage(params: IchooseImage): void;
+
+  interface IpreviewImage extends BaseParams {
+    current: string; // 当前显示图片的http链接
+    urls: string[]; // 需要预览的图片http链接列表
+  }
+  /**
+   * 预览图片接口
+   */
+  function previewImage(params: IpreviewImage): void;
+
+  interface IuploadResource extends BaseParams {
+    localId: string; // 需要上传的图片的本地ID,由chooseImage接口获得
+    isShowProgressTips: number; // 默认为1,显示进度提示
+    // 返回图片的服务器端ID
+    success(res: { serverId: string }): void;
+  }
+  /**
+   * 上传图片接口
+   */
+  function uploadImage(params: IuploadResource): void;
+
+  interface IdownloadResource extends BaseParams {
+    serverId: string; // 需要下载的图片的服务器端ID,由uploadImage接口获得
+    isShowProgressTips: number; // 默认为1,显示进度提示
+    // 返回图片下载后的本地ID
+    success(res: Resouce): void;
+  }
+  /**
+   * 下载图片接口
+   */
+  function downloadImage(params: IdownloadResource): void;
+
+  interface IgetLocalImgData extends BaseParams {
+    localId: string; // 图片的localID
+    // localData是图片的base64数据,可以用img标签显示
+    success(res: { localData: string }): void;
+  }
+
+  /**
+   * 获取本地图片接口
+   */
+  function getLocalImgData(params: IgetLocalImgData): void;
+  /*=============================图像接口================================*/
+  /*=============================音频接口================================*/
+  /**
+   * 开始录音接口
+   */
+  function startRecord(): void;
+
+  interface IstopRecord extends BaseParams {
+    success(res: Resouce): void;
+  }
+  /**
+   * 停止录音接口
+   */
+  function stopRecord(params: IstopRecord): void;
+
+  interface IonVoiceRecordEnd extends BaseParams {
+    // 录音时间超过一分钟没有停止的时候会执行 complete 回调
+    complete(res: Resouce): void;
+  }
+  /**
+   * 监听录音自动停止接口
+   */
+  function onVoiceRecordEnd(params: IonVoiceRecordEnd): void;
+
+  interface IplaypausestopVoice extends BaseParams {
+    localId: string; // 需要播放的音频的本地ID,由stopRecord接口获得
+  }
+  /**
+   * 播放语音接口
+   */
+  function playVoice(params: IplaypausestopVoice): void;
+
+  /**
+   * 暂停播放接口
+   */
+  function pauseVoice(params: IplaypausestopVoice): void;
+  /**
+   * 停止播放接口
+   */
+  function stopVoice(params: IplaypausestopVoice): void;
+
+  interface IonVoicePlayEnd extends BaseParams {
+    success(res: Resouce): void;
+  }
+  /**
+   * 监听语音播放完毕接口
+   */
+  function onVoicePlayEnd(params: IonVoicePlayEnd): void;
+  /**
+   * 上传语音接口
+   * 备注:上传语音有效期3天,可用微信多媒体接口下载语音到自己的服务器
+   * ,此处获得的 serverId 即 media_id,参考文档
+   * ../12 / 58bfcfabbd501c7cd77c19bd9cfa8354.html
+   * 目前多媒体文件下载接口的频率限制为10000次/ 天,
+   * 如需要调高频率,请邮件weixin - open@qq.com,
+   * 邮件主题为【申请多媒体接口调用量】,请对你的项目进行简单描述,
+   * 附上产品体验链接,并对用户量和使用量进行说明。
+   */
+  function uploadVoice(params: IuploadResource): void;
+  /**
+   * 下载语音接口
+   */
+  function downloadVoice(params: IdownloadResource): void;
+  /*=============================音频接口================================*/
+  /*=============================智能接口================================*/
+
+  interface ItranslateVoice extends BaseParams {
+    localId: string; // 需要识别的音频的本地Id,由录音相关接口获得
+    isShowProgressTips: number; // 默认为1,显示进度提示
+    success(res: { translateResult: string }): void;
+  }
+  /**
+   * 识别音频并返回识别结果接口
+   */
+  function translateVoice(params: ItranslateVoice): void;
+
+  /*=============================智能接口================================*/
+
+  /*=============================设备信息================================*/
+  type networkType = "2g" | "3g" | "4g" | "wifi";
+  interface IgetNetworkType extends BaseParams {
+    success(res: { networkType: networkType }): void;
+  }
+  /**
+   * 获取网络状态接口
+   */
+  function getNetworkType(params: IgetNetworkType): void;
+  /*=============================设备信息================================*/
+
+  /*=============================地理位置================================*/
+  interface IopenLocation extends BaseParams {
+    latitude: number; // 纬度,浮点数,范围为90 ~ -90
+    longitude: number; // 经度,浮点数,范围为180 ~ -180。
+    name: string; // 位置名
+    address: string; // 地址详情说明
+    scale: number; // 地图缩放级别,整形值,范围从1~28。默认为最大
+    infoUrl: string; // 在查看位置界面底部显示的超链接,可点击跳转
+  }
+  /**
+   * 使用微信内置地图查看位置接口
+   */
+  function openLocation(params: IopenLocation): void;
+
+  interface IgetLocation extends BaseParams {
+    type: "wgs84" | "gcj02"; // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
+    success(res: {
+      latitude: number; // 纬度,浮点数,范围为90 ~ -90
+      longitude: number; // 经度,浮点数,范围为180 ~ -180。
+      speed: number; // 速度,以米/每秒计
+      accuracy: number; // 位置精度
+    }): void;
+  }
+  /**
+   * 获取地理位置接口
+   */
+  function getLocation(params: IgetLocation): void;
+  /*=============================地理位置================================*/
+  /*=============================摇一摇周边================================*/
+  interface IstartSearchBeacons extends BaseParams {
+    ticket: string; // 摇周边的业务ticket, 系统自动添加在摇出来的页面链接后面
+    // 开启查找完成后的回调函数
+    complete(argv: any): void;
+  }
+  /**
+   * 开启查找周边ibeacon设备接口
+   * 备注:如需接入摇一摇周边功能,请参考:申请开通摇一摇周边
+   */
+  function startSearchBeacons(params: IstartSearchBeacons): void;
+
+  interface IstopSearchBeacons extends BaseParams {
+    // 关闭查找完成后的回调函数
+    complete(res: any): void;
+  }
+
+  /**
+   * 关闭查找周边ibeacon设备接口
+   */
+  function stopSearchBeacons(params: IstopSearchBeacons): void;
+
+  interface IonSearchBeacons extends BaseParams {
+    // 回调函数,可以数组形式取得该商家注册的在周边的相关设备列表
+    complete(argv: any): void;
+  }
+  /**
+   * 监听周边ibeacon设备接口
+   */
+  function onSearchBeacons(params: IonSearchBeacons): void;
+  /*=============================摇一摇周边================================*/
+  /*=============================界面操作================================*/
+
+  /**
+   * 隐藏右上角菜单接口
+   */
+  function hideOptionMenu(): void;
+
+  /**
+   * 显示右上角菜单接口
+   */
+  function showOptionMenu(): void;
+
+  /**
+   * 关闭当前网页窗口接口
+   */
+  function closeWindow(): void;
+
+  interface IhideMenuItems extends BaseParams {
+    menuList: Array<menuProtected | menuShare>; // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
+  }
+  /**
+   * 批量隐藏功能按钮接口
+   */
+  function hideMenuItems(params: IhideMenuItems): void;
+
+  interface IshowMenuItems extends BaseParams {
+    menuList: menuList; // 要显示的菜单项,所有menu项见附录3
+  }
+  /**
+   * 批量显示功能按钮接口
+   */
+  function showMenuItems(params: IshowMenuItems): void;
+
+  /**
+   * 隐藏所有非基础按钮接口
+   * “基本类”按钮详见附录3
+   */
+  function hideAllNonBaseMenuItem(): void;
+
+  /**
+   * 显示所有功能按钮接口
+   */
+  function showAllNonBaseMenuItem(): void;
+  /*=============================界面操作================================*/
+  /*=============================微信扫一扫================================*/
+
+  type scanType = "qrCode" | "barCode";
+
+  interface IscanQRCode extends BaseParams {
+    needResult: 0 | 1; // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+    scanType: scanType[]; // 可以指定扫二维码还是一维码,默认二者都有
+    // 当needResult 为 1 时,扫码返回的结果
+    success(res: { resultStr: string }): void;
+  }
+  /**
+   * 调起微信扫一扫接口
+   */
+  function scanQRCode(params: IscanQRCode): void;
+  /*=============================微信扫一扫================================*/
+  /*=============================微信小店================================*/
+
+  interface IopenProductSpecificView extends BaseParams {
+    productId: string; // 商品id
+    viewType: "0" | "1" | "2"; // 0.默认值,普通商品详情页1.扫一扫商品详情页2.小店商品详情页
+  }
+  /**
+   * 跳转微信商品页接口
+   */
+  function openProductSpecificView(params: IopenProductSpecificView): void;
+  /*=============================微信卡券================================*/
+
+  interface IchooseCard extends BaseParams {
+    shopId: string; // 门店Id
+    cardType: string; // 卡券类型
+    cardId: string; // 卡券Id
+    timestamp: number; // 卡券签名时间戳
+    nonceStr: string; // 卡券签名随机串
+    signType: string; // 签名方式,默认'SHA1'
+    cardSign: string; // 卡券签名
+    success(res: { cardList: string[] }): void;
+  }
+  /**
+   * 拉取适用卡券列表并获取用户选择信息
+   */
+  function chooseCard(params: IchooseCard): void;
+
+  interface IaddCard extends BaseParams {
+    cardList: Array<{
+      cardId: string;
+      cardExt: string;
+    }>; // 需要添加的卡券列表
+    success(res: { cardList: string[] }): void;
+  }
+  /**
+   * 批量添加卡券接口
+   */
+  function addCard(): void;
+
+  interface IopenCard extends BaseParams {
+    cardList: Array<{
+      cardId: string;
+      code: string;
+    }>; // 需要打开的卡券列表
+  }
+  /**
+   * 查看微信卡包中的卡券接口
+   */
+  function openCard(params: IopenCard): void;
+
+  interface IconsumeAndShareCard extends BaseParams {
+    cardId: string;
+    code: string;
+  }
+  /**
+   * 核销后再次赠送卡券接口
+   */
+  function consumeAndShareCard(params: IconsumeAndShareCard): void;
+  /*=============================微信卡券================================*/
+  /*=============================微信支付================================*/
+
+  interface IchooseWXPay extends BaseParams {
+    timestamp: number; // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+    nonceStr: string; // 支付签名随机串,不长于 32 位
+    package: string; // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
+    signType: string; // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+    paySign: string; // 支付签名
+    // 支付成功后的回调函数
+    success(res: any): void;
+  }
+  /**
+   * 发起一个微信支付请求
+   */
+  function chooseWXPay(params: IchooseWXPay): void;
+  /*=============================微信支付================================*/
+  /*=============================微信小程序==============================*/
+  interface miniProgramMethodsParams extends BaseParams {
+    url: string;
+  }
+  interface miniProgramMethods {
+    navigateTo(params: miniProgramMethodsParams): void;
+    navigateBack(params: miniProgramMethodsParams): void;
+    switchTab(params: miniProgramMethodsParams): void;
+    reLaunch(params: miniProgramMethodsParams): void;
+    redirectTo(params: miniProgramMethodsParams): void;
+    postMessage(params: { data: any }): void;
+    getEnv(fn: (res: any) => void): void;
+  }
+  const miniProgram: miniProgramMethods;
+  /*=============================微信小程序==============================*/
+}
+declare function wx(): void;
+/*=============================微信内全局变量==============================*/
+declare global {
+  interface Window {
+    WeixinJSBridge: any;
+    __wxjs_environment: any;
+  }
+  const WeixinJSBridge: any;
+}
+export default wx;

+ 891 - 0
shop/node_modules/weixin-js-sdk/index.js

@@ -0,0 +1,891 @@
+!(function (e, n) {
+  module.exports = n(e);
+})(typeof window === "object" && window, function (r, e) {
+  if (!r) {
+    console.warn("can't use weixin-js-sdk in server side");
+    return;
+  }
+  var a, c, n, i, t, o, s, d, l, u, p, f, m, g, h, S, y, I, v, _, w, T;
+  if (!r.jWeixin)
+    return (
+      (a = {
+        config: "preVerifyJSAPI",
+        onMenuShareTimeline: "menu:share:timeline",
+        onMenuShareAppMessage: "menu:share:appmessage",
+        onMenuShareQQ: "menu:share:qq",
+        onMenuShareWeibo: "menu:share:weiboApp",
+        onMenuShareQZone: "menu:share:QZone",
+        previewImage: "imagePreview",
+        getLocation: "geoLocation",
+        openProductSpecificView: "openProductViewWithPid",
+        addCard: "batchAddCard",
+        openCard: "batchViewCard",
+        chooseWXPay: "getBrandWCPayRequest",
+        openEnterpriseRedPacket: "getRecevieBizHongBaoRequest",
+        startSearchBeacons: "startMonitoringBeacons",
+        stopSearchBeacons: "stopMonitoringBeacons",
+        onSearchBeacons: "onBeaconsInRange",
+        consumeAndShareCard: "consumedShareCard",
+        openAddress: "editAddress",
+      }),
+      (c = (function () {
+        var e,
+          n = {};
+        for (e in a) n[a[e]] = e;
+        return n;
+      })()),
+      (n = r.document),
+      (i = n.title),
+      (t = navigator.userAgent.toLowerCase()),
+      (f = navigator.platform.toLowerCase()),
+      (o = !(!f.match("mac") && !f.match("win"))),
+      (s = -1 != t.indexOf("wxdebugger")),
+      (d = -1 != t.indexOf("micromessenger")),
+      (l = -1 != t.indexOf("android")),
+      (u = -1 != t.indexOf("iphone") || -1 != t.indexOf("ipad")),
+      (p = (f =
+        t.match(/micromessenger\/(\d+\.\d+\.\d+)/) ||
+        t.match(/micromessenger\/(\d+\.\d+)/))
+        ? f[1]
+        : ""),
+      (m = {
+        initStartTime: L(),
+        initEndTime: 0,
+        preVerifyStartTime: 0,
+        preVerifyEndTime: 0,
+      }),
+      (g = {
+        version: 1,
+        appId: "",
+        initTime: 0,
+        preVerifyTime: 0,
+        networkType: "",
+        isPreVerifyOk: 1,
+        systemType: u ? 1 : l ? 2 : -1,
+        clientVersion: p,
+        url: encodeURIComponent(location.href),
+      }),
+      (h = {}),
+      (S = { _completes: [] }),
+      (y = { state: 0, data: {} }),
+      O(function () {
+        m.initEndTime = L();
+      }),
+      (I = !1),
+      (v = []),
+      (_ = {
+        config: function (e) {
+          C("config", (h = e));
+          var o = !1 !== h.check;
+          O(function () {
+            if (o)
+              k(
+                a.config,
+                {
+                  verifyJsApiList: A(h.jsApiList),
+                  verifyOpenTagList: A(h.openTagList),
+                },
+                ((S._complete = function (e) {
+                  (m.preVerifyEndTime = L()), (y.state = 1), (y.data = e);
+                }),
+                (S.success = function (e) {
+                  g.isPreVerifyOk = 0;
+                }),
+                (S.fail = function (e) {
+                  S._fail ? S._fail(e) : (y.state = -1);
+                }),
+                (t = S._completes).push(function () {
+                  B();
+                }),
+                (S.complete = function (e) {
+                  for (var n = 0, i = t.length; n < i; ++n) t[n]();
+                  S._completes = [];
+                }),
+                S)
+              ),
+                (m.preVerifyStartTime = L());
+            else {
+              y.state = 1;
+              for (var e = S._completes, n = 0, i = e.length; n < i; ++n)
+                e[n]();
+              S._completes = [];
+            }
+            var t;
+          }),
+            _.invoke ||
+              ((_.invoke = function (e, n, i) {
+                r.WeixinJSBridge && WeixinJSBridge.invoke(e, P(n), i);
+              }),
+              (_.on = function (e, n) {
+                r.WeixinJSBridge && WeixinJSBridge.on(e, n);
+              }));
+        },
+        ready: function (e) {
+          (0 != y.state || (S._completes.push(e), !d && h.debug)) && e();
+        },
+        error: function (e) {
+          p < "6.0.2" || (-1 == y.state ? e(y.data) : (S._fail = e));
+        },
+        checkJsApi: function (e) {
+          k(
+            "checkJsApi",
+            { jsApiList: A(e.jsApiList) },
+            ((e._complete = function (e) {
+              l && (i = e.checkResult) && (e.checkResult = JSON.parse(i));
+              var n,
+                i = e,
+                t = i.checkResult;
+              for (n in t) {
+                var o = c[n];
+                o && ((t[o] = t[n]), delete t[n]);
+              }
+            }),
+            e)
+          );
+        },
+        onMenuShareTimeline: function (e) {
+          M(
+            a.onMenuShareTimeline,
+            {
+              complete: function () {
+                k(
+                  "shareTimeline",
+                  {
+                    title: e.title || i,
+                    desc: e.title || i,
+                    img_url: e.imgUrl || "",
+                    link: e.link || location.href,
+                    type: e.type || "link",
+                    data_url: e.dataUrl || "",
+                  },
+                  e
+                );
+              },
+            },
+            e
+          );
+        },
+        onMenuShareAppMessage: function (n) {
+          M(
+            a.onMenuShareAppMessage,
+            {
+              complete: function (e) {
+                "favorite" === e.scene
+                  ? k("sendAppMessage", {
+                      title: n.title || i,
+                      desc: n.desc || "",
+                      link: n.link || location.href,
+                      img_url: n.imgUrl || "",
+                      type: n.type || "link",
+                      data_url: n.dataUrl || "",
+                    })
+                  : k(
+                      "sendAppMessage",
+                      {
+                        title: n.title || i,
+                        desc: n.desc || "",
+                        link: n.link || location.href,
+                        img_url: n.imgUrl || "",
+                        type: n.type || "link",
+                        data_url: n.dataUrl || "",
+                      },
+                      n
+                    );
+              },
+            },
+            n
+          );
+        },
+        onMenuShareQQ: function (e) {
+          M(
+            a.onMenuShareQQ,
+            {
+              complete: function () {
+                k(
+                  "shareQQ",
+                  {
+                    title: e.title || i,
+                    desc: e.desc || "",
+                    img_url: e.imgUrl || "",
+                    link: e.link || location.href,
+                  },
+                  e
+                );
+              },
+            },
+            e
+          );
+        },
+        onMenuShareWeibo: function (e) {
+          M(
+            a.onMenuShareWeibo,
+            {
+              complete: function () {
+                k(
+                  "shareWeiboApp",
+                  {
+                    title: e.title || i,
+                    desc: e.desc || "",
+                    img_url: e.imgUrl || "",
+                    link: e.link || location.href,
+                  },
+                  e
+                );
+              },
+            },
+            e
+          );
+        },
+        onMenuShareQZone: function (e) {
+          M(
+            a.onMenuShareQZone,
+            {
+              complete: function () {
+                k(
+                  "shareQZone",
+                  {
+                    title: e.title || i,
+                    desc: e.desc || "",
+                    img_url: e.imgUrl || "",
+                    link: e.link || location.href,
+                  },
+                  e
+                );
+              },
+            },
+            e
+          );
+        },
+        updateTimelineShareData: function (e) {
+          k(
+            "updateTimelineShareData",
+            { title: e.title, link: e.link, imgUrl: e.imgUrl },
+            e
+          );
+        },
+        updateAppMessageShareData: function (e) {
+          k(
+            "updateAppMessageShareData",
+            { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl },
+            e
+          );
+        },
+        startRecord: function (e) {
+          k("startRecord", {}, e);
+        },
+        stopRecord: function (e) {
+          k("stopRecord", {}, e);
+        },
+        onVoiceRecordEnd: function (e) {
+          M("onVoiceRecordEnd", e);
+        },
+        playVoice: function (e) {
+          k("playVoice", { localId: e.localId }, e);
+        },
+        pauseVoice: function (e) {
+          k("pauseVoice", { localId: e.localId }, e);
+        },
+        stopVoice: function (e) {
+          k("stopVoice", { localId: e.localId }, e);
+        },
+        onVoicePlayEnd: function (e) {
+          M("onVoicePlayEnd", e);
+        },
+        uploadVoice: function (e) {
+          k(
+            "uploadVoice",
+            {
+              localId: e.localId,
+              isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1,
+            },
+            e
+          );
+        },
+        downloadVoice: function (e) {
+          k(
+            "downloadVoice",
+            {
+              serverId: e.serverId,
+              isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1,
+            },
+            e
+          );
+        },
+        translateVoice: function (e) {
+          k(
+            "translateVoice",
+            {
+              localId: e.localId,
+              isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1,
+            },
+            e
+          );
+        },
+        chooseImage: function (e) {
+          k(
+            "chooseImage",
+            {
+              scene: "1|2",
+              count: e.count || 9,
+              sizeType: e.sizeType || ["original", "compressed"],
+              sourceType: e.sourceType || ["album", "camera"],
+            },
+            ((e._complete = function (e) {
+              if (l) {
+                var n = e.localIds;
+                try {
+                  n && (e.localIds = JSON.parse(n));
+                } catch (e) {}
+              }
+            }),
+            e)
+          );
+        },
+        getLocation: function (e) {
+          (e = e || {}),
+            k(
+              a.getLocation,
+              { type: e.type || "wgs84" },
+              ((e._complete = function (e) {
+                delete e.type;
+              }),
+              e)
+            );
+        },
+        previewImage: function (e) {
+          k(a.previewImage, { current: e.current, urls: e.urls }, e);
+        },
+        uploadImage: function (e) {
+          k(
+            "uploadImage",
+            {
+              localId: e.localId,
+              isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1,
+            },
+            e
+          );
+        },
+        downloadImage: function (e) {
+          k(
+            "downloadImage",
+            {
+              serverId: e.serverId,
+              isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1,
+            },
+            e
+          );
+        },
+        getLocalImgData: function (e) {
+          !1 === I
+            ? ((I = !0),
+              k(
+                "getLocalImgData",
+                { localId: e.localId },
+                ((e._complete = function (e) {
+                  var n;
+                  (I = !1),
+                    0 < v.length && ((n = v.shift()), wx.getLocalImgData(n));
+                }),
+                e)
+              ))
+            : v.push(e);
+        },
+        getNetworkType: function (e) {
+          k(
+            "getNetworkType",
+            {},
+            ((e._complete = function (e) {
+              var n = e,
+                e = n.errMsg,
+                i = ((n.errMsg = "getNetworkType:ok"), n.subtype);
+              if ((delete n.subtype, i)) n.networkType = i;
+              else {
+                var i = e.indexOf(":"),
+                  t = e.substring(i + 1);
+                switch (t) {
+                  case "wifi":
+                  case "edge":
+                  case "wwan":
+                    n.networkType = t;
+                    break;
+                  default:
+                    n.errMsg = "getNetworkType:fail";
+                }
+              }
+            }),
+            e)
+          );
+        },
+        openLocation: function (e) {
+          k(
+            "openLocation",
+            {
+              latitude: e.latitude,
+              longitude: e.longitude,
+              name: e.name || "",
+              address: e.address || "",
+              scale: e.scale || 28,
+              infoUrl: e.infoUrl || "",
+            },
+            e
+          );
+        },
+        hideOptionMenu: function (e) {
+          k("hideOptionMenu", {}, e);
+        },
+        showOptionMenu: function (e) {
+          k("showOptionMenu", {}, e);
+        },
+        closeWindow: function (e) {
+          k("closeWindow", {}, (e = e || {}));
+        },
+        hideMenuItems: function (e) {
+          k("hideMenuItems", { menuList: e.menuList }, e);
+        },
+        showMenuItems: function (e) {
+          k("showMenuItems", { menuList: e.menuList }, e);
+        },
+        hideAllNonBaseMenuItem: function (e) {
+          k("hideAllNonBaseMenuItem", {}, e);
+        },
+        showAllNonBaseMenuItem: function (e) {
+          k("showAllNonBaseMenuItem", {}, e);
+        },
+        scanQRCode: function (e) {
+          k(
+            "scanQRCode",
+            {
+              needResult: (e = e || {}).needResult || 0,
+              scanType: e.scanType || ["qrCode", "barCode"],
+            },
+            ((e._complete = function (e) {
+              var n;
+              u &&
+                (n = e.resultStr) &&
+                ((n = JSON.parse(n)),
+                (e.resultStr = n && n.scan_code && n.scan_code.scan_result));
+            }),
+            e)
+          );
+        },
+        openAddress: function (e) {
+          k(
+            a.openAddress,
+            {},
+            ((e._complete = function (e) {
+              ((e = e).postalCode = e.addressPostalCode),
+                delete e.addressPostalCode,
+                (e.provinceName = e.proviceFirstStageName),
+                delete e.proviceFirstStageName,
+                (e.cityName = e.addressCitySecondStageName),
+                delete e.addressCitySecondStageName,
+                (e.countryName = e.addressCountiesThirdStageName),
+                delete e.addressCountiesThirdStageName,
+                (e.detailInfo = e.addressDetailInfo),
+                delete e.addressDetailInfo;
+            }),
+            e)
+          );
+        },
+        openProductSpecificView: function (e) {
+          k(
+            a.openProductSpecificView,
+            {
+              pid: e.productId,
+              view_type: e.viewType || 0,
+              ext_info: e.extInfo,
+            },
+            e
+          );
+        },
+        addCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, card_ext: r.cardExt };
+            i.push(r);
+          }
+          k(
+            a.addCard,
+            { card_list: i },
+            ((e._complete = function (e) {
+              if ((n = e.card_list)) {
+                for (var n, i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
+                  var o = n[i];
+                  (o.cardId = o.card_id),
+                    (o.cardExt = o.card_ext),
+                    (o.isSuccess = !!o.is_succ),
+                    delete o.card_id,
+                    delete o.card_ext,
+                    delete o.is_succ;
+                }
+                (e.cardList = n), delete e.card_list;
+              }
+            }),
+            e)
+          );
+        },
+        chooseCard: function (e) {
+          k(
+            "chooseCard",
+            {
+              app_id: h.appId,
+              location_id: e.shopId || "",
+              sign_type: e.signType || "SHA1",
+              card_id: e.cardId || "",
+              card_type: e.cardType || "",
+              card_sign: e.cardSign,
+              time_stamp: e.timestamp + "",
+              nonce_str: e.nonceStr,
+            },
+            ((e._complete = function (e) {
+              (e.cardList = e.choose_card_info), delete e.choose_card_info;
+            }),
+            e)
+          );
+        },
+        openCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, code: r.code };
+            i.push(r);
+          }
+          k(a.openCard, { card_list: i }, e);
+        },
+        consumeAndShareCard: function (e) {
+          k(
+            a.consumeAndShareCard,
+            { consumedCardId: e.cardId, consumedCode: e.code },
+            e
+          );
+        },
+        chooseWXPay: function (e) {
+          k(a.chooseWXPay, x(e), e), B({ jsApiName: "chooseWXPay" });
+        },
+        openEnterpriseRedPacket: function (e) {
+          k(a.openEnterpriseRedPacket, x(e), e);
+        },
+        startSearchBeacons: function (e) {
+          k(a.startSearchBeacons, { ticket: e.ticket }, e);
+        },
+        stopSearchBeacons: function (e) {
+          k(a.stopSearchBeacons, {}, e);
+        },
+        onSearchBeacons: function (e) {
+          M(a.onSearchBeacons, e);
+        },
+        openEnterpriseChat: function (e) {
+          k(
+            "openEnterpriseChat",
+            { useridlist: e.userIds, chatname: e.groupName },
+            e
+          );
+        },
+        launchMiniProgram: function (e) {
+          k(
+            "launchMiniProgram",
+            {
+              targetAppId: e.targetAppId,
+              path: (function (e) {
+                var n;
+                if ("string" == typeof e && 0 < e.length)
+                  return (
+                    (n = e.split("?")[0]),
+                    (n += ".html"),
+                    void 0 !== (e = e.split("?")[1]) ? n + "?" + e : n
+                  );
+              })(e.path),
+              envVersion: e.envVersion,
+            },
+            e
+          );
+        },
+        openBusinessView: function (e) {
+          k(
+            "openBusinessView",
+            {
+              businessType: e.businessType,
+              queryString: e.queryString || "",
+              envVersion: e.envVersion,
+            },
+            ((e._complete = function (n) {
+              if (l) {
+                var e = n.extraData;
+                if (e)
+                  try {
+                    n.extraData = JSON.parse(e);
+                  } catch (e) {
+                    n.extraData = {};
+                  }
+              }
+            }),
+            e)
+          );
+        },
+        miniProgram: {
+          navigateBack: function (e) {
+            (e = e || {}),
+              O(function () {
+                k(
+                  "invokeMiniProgramAPI",
+                  { name: "navigateBack", arg: { delta: e.delta || 1 } },
+                  e
+                );
+              });
+          },
+          navigateTo: function (e) {
+            O(function () {
+              k(
+                "invokeMiniProgramAPI",
+                { name: "navigateTo", arg: { url: e.url } },
+                e
+              );
+            });
+          },
+          redirectTo: function (e) {
+            O(function () {
+              k(
+                "invokeMiniProgramAPI",
+                { name: "redirectTo", arg: { url: e.url } },
+                e
+              );
+            });
+          },
+          switchTab: function (e) {
+            O(function () {
+              k(
+                "invokeMiniProgramAPI",
+                { name: "switchTab", arg: { url: e.url } },
+                e
+              );
+            });
+          },
+          reLaunch: function (e) {
+            O(function () {
+              k(
+                "invokeMiniProgramAPI",
+                { name: "reLaunch", arg: { url: e.url } },
+                e
+              );
+            });
+          },
+          postMessage: function (e) {
+            O(function () {
+              k(
+                "invokeMiniProgramAPI",
+                { name: "postMessage", arg: e.data || {} },
+                e
+              );
+            });
+          },
+          getEnv: function (e) {
+            O(function () {
+              e({ miniprogram: "miniprogram" === r.__wxjs_environment });
+            });
+          },
+        },
+      }),
+      (w = 1),
+      (T = {}),
+      n.addEventListener(
+        "error",
+        function (e) {
+          var n, i, t;
+          l ||
+            ((t = (n = e.target).tagName),
+            (i = n.src),
+            "IMG" != t && "VIDEO" != t && "AUDIO" != t && "SOURCE" != t) ||
+            (-1 != i.indexOf("wxlocalresource://") &&
+              (e.preventDefault(),
+              e.stopPropagation(),
+              (t = n["wx-id"]) || ((t = w++), (n["wx-id"] = t)),
+              T[t] ||
+                ((T[t] = !0),
+                wx.ready(function () {
+                  wx.getLocalImgData({
+                    localId: i,
+                    success: function (e) {
+                      n.src = e.localData;
+                    },
+                  });
+                }))));
+        },
+        !0
+      ),
+      n.addEventListener(
+        "load",
+        function (e) {
+          var n;
+          l ||
+            ((n = (e = e.target).tagName),
+            e.src,
+            "IMG" != n && "VIDEO" != n && "AUDIO" != n && "SOURCE" != n) ||
+            ((n = e["wx-id"]) && (T[n] = !1));
+        },
+        !0
+      ),
+      e && (r.wx = r.jWeixin = _),
+      _
+    );
+  else return r.jWeixin;
+  function k(n, e, i) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.invoke(n, P(e), function (e) {
+          V(n, e, i);
+        })
+      : C(n, i);
+  }
+  function M(n, i, t) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.on(n, function (e) {
+          t && t.trigger && t.trigger(e), V(n, e, i);
+        })
+      : C(n, t || i);
+  }
+  function P(e) {
+    return (
+      ((e = e || {}).appId = h.appId),
+      (e.verifyAppId = h.appId),
+      (e.verifySignType = "sha1"),
+      (e.verifyTimestamp = h.timestamp + ""),
+      (e.verifyNonceStr = h.nonceStr),
+      (e.verifySignature = h.signature),
+      e
+    );
+  }
+  function x(e) {
+    return {
+      timeStamp: e.timestamp + "",
+      nonceStr: e.nonceStr,
+      package: e.package,
+      paySign: e.paySign,
+      signType: e.signType || "SHA1",
+    };
+  }
+  function V(e, n, i) {
+    ("openEnterpriseChat" != e && "openBusinessView" !== e) ||
+      (n.errCode = n.err_code),
+      delete n.err_code,
+      delete n.err_desc,
+      delete n.err_detail;
+    var t = n.errMsg,
+      e =
+        (t ||
+          ((t = n.err_msg),
+          delete n.err_msg,
+          (t = (function (e, n) {
+            var i = c[e];
+            i && (e = i);
+            i = "ok";
+            {
+              var t;
+              n &&
+                ((t = n.indexOf(":")),
+                ("access denied" !=
+                  (i = (i = (i =
+                    -1 !=
+                    (i =
+                      -1 !=
+                      (i =
+                        "failed" ==
+                        (i = "confirm" == (i = n.substring(t + 1)) ? "ok" : i)
+                          ? "fail"
+                          : i).indexOf("failed_")
+                        ? i.substring(7)
+                        : i).indexOf("fail_")
+                      ? i.substring(5)
+                      : i).replace(/_/g, " ")).toLowerCase()) &&
+                  "no permission to execute" != i) ||
+                  (i = "permission denied"),
+                "" ==
+                  (i =
+                    "config" == e && "function not exist" == i ? "ok" : i)) &&
+                (i = "fail");
+            }
+            return (n = e + ":" + i);
+          })(e, t)),
+          (n.errMsg = t)),
+        (i = i || {})._complete && (i._complete(n), delete i._complete),
+        (t = n.errMsg || ""),
+        h.debug && !i.isInnerInvoke && alert(JSON.stringify(n)),
+        t.indexOf(":"));
+    switch (t.substring(e + 1)) {
+      case "ok":
+        i.success && i.success(n);
+        break;
+      case "cancel":
+        i.cancel && i.cancel(n);
+        break;
+      default:
+        i.fail && i.fail(n);
+    }
+    i.complete && i.complete(n);
+  }
+  function A(e) {
+    if (e) {
+      for (var n = 0, i = e.length; n < i; ++n) {
+        var t = e[n],
+          t = a[t];
+        t && (e[n] = t);
+      }
+      return e;
+    }
+  }
+  function C(e, n) {
+    var i;
+    !h.debug ||
+      (n && n.isInnerInvoke) ||
+      ((i = c[e]) && (e = i),
+      n && n._complete && delete n._complete,
+      console.log('"' + e + '",', n || ""));
+  }
+  function B(n) {
+    var i;
+    o ||
+      s ||
+      h.debug ||
+      p < "6.0.2" ||
+      g.systemType < 0 ||
+      ((i = new Image()),
+      (g.appId = h.appId),
+      (g.initTime = m.initEndTime - m.initStartTime),
+      (g.preVerifyTime = m.preVerifyEndTime - m.preVerifyStartTime),
+      _.getNetworkType({
+        isInnerInvoke: !0,
+        success: function (e) {
+          g.networkType = e.networkType;
+          e =
+            "https://open.weixin.qq.com/sdk/report?v=" +
+            g.version +
+            "&o=" +
+            g.isPreVerifyOk +
+            "&s=" +
+            g.systemType +
+            "&c=" +
+            g.clientVersion +
+            "&a=" +
+            g.appId +
+            "&n=" +
+            g.networkType +
+            "&i=" +
+            g.initTime +
+            "&p=" +
+            g.preVerifyTime +
+            "&u=" +
+            g.url +
+            "&jsapi_name=" +
+            (n ? n.jsApiName : "");
+          i.src = e;
+        },
+      }));
+  }
+  function L() {
+    return new Date().getTime();
+  }
+  function O(e) {
+    d &&
+      (r.WeixinJSBridge
+        ? e()
+        : n.addEventListener &&
+          n.addEventListener("WeixinJSBridgeReady", e, !1));
+  }
+});

+ 12 - 0
shop/node_modules/weixin-js-sdk/package.json

@@ -0,0 +1,12 @@
+{
+  "name": "weixin-js-sdk",
+  "version": "1.6.5",
+  "license": "MIT",
+  "main": "index.js",
+  "description": "微信官方 js-sdk npm 安装版,支持 typescript",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/yanxi123-com/weixin-js-sdk"
+  },
+  "homepage": "https://yanxi123.com/"
+}

+ 29 - 0
shop/package-lock.json

@@ -0,0 +1,29 @@
+{
+  "name": "shop",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "shop",
+      "version": "1.0.0",
+      "license": "ISC",
+      "dependencies": {
+        "jweixin-module": "^1.6.0",
+        "weixin-js-sdk": "^1.6.5"
+      }
+    },
+    "node_modules/weixin-js-sdk": {
+      "version": "1.6.5",
+      "resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz",
+      "integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ=="
+    }
+  },
+  "dependencies": {
+    "weixin-js-sdk": {
+      "version": "1.6.5",
+      "resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz",
+      "integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ=="
+    }
+  }
+}

+ 47 - 0
shop/package.json

@@ -0,0 +1,47 @@
+{
+  "name": "shop",
+  "version": "1.0.0",
+  "description": "彩图奔跑 - 商家小程序",
+  "main": "main.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "uni-app": {
+    "scripts": {
+      "dev-h5": {
+        "title": "开发版 - h5",
+        "env": {
+          "UNI_PLATFORM": "h5",
+          "API_BASE_URL": "https://t-mapi.colormaprun.com/api/shop/"
+        }
+      },
+      "prod-h5": {
+        "title": "正式版 - h5",
+        "env": {
+          "UNI_PLATFORM": "h5",
+          "API_BASE_URL": "https://colormaprun.com/api/shop/"
+        }
+      },
+      "dev-mp-weixin": {
+        "title": "开发版 - 微信小程序",
+        "env": {
+          "UNI_PLATFORM": "mp-weixin",
+          "API_BASE_URL": "https://t-mapi.colormaprun.com/api/shop/"
+        }
+      },
+      "prod-mp-weixin": {
+        "title": "正式版 - 微信小程序",
+        "env": {
+          "UNI_PLATFORM": "mp-weixin",
+          "API_BASE_URL": "https://colormaprun.com/api/shop/"
+        }
+      }
+    }
+  },
+  "dependencies": {
+    "weixin-js-sdk": "^1.6.5"
+  }
+}

+ 32 - 0
shop/pages.json

@@ -0,0 +1,32 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "彩图奔跑 - 商家小程序"
+			}
+		},
+		{
+			"path" : "pages/login/login",
+			"style" : 
+			{
+				"navigationBarTitleText" : "登录"
+			}
+		},
+		{
+			"path" : "pages/exchgRecord/exchgRecord",
+			"style" : 
+			{
+				"navigationBarTitleText" : "兑换记录"
+			}
+		}
+	],
+	"globalStyle": {
+		"navigationStyle": "custom",
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "彩图奔跑 - 商家小程序",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8"
+	},
+	"uniIdRouter": {}
+}

+ 288 - 0
shop/pages/exchgRecord/exchgRecord.vue

@@ -0,0 +1,288 @@
+<template>
+	<view class="body uni-jct">
+		<!-- <view class="topnav uni-row uni-jcsb">
+			<text class="topnav-left" @click="btnBack"><</text>
+			<text class="topnav-center">兑换记录</text>
+			<text class="topnav-right" @click="btnClose">×</text>
+		</view> -->
+		<view class="topbar uni-row uni-jcsb">
+			<view class="topbar-left">
+				<text class="btnBack" @click="btnBack">&lt;</text>
+				<text class="">{{shopInfo.shopName}}</text>
+			</view>
+			<!-- <text class="topbar-left" @click="btnBack"><</text>
+			<text class="topbar-left">{{shopInfo.shopName}}</text> -->
+			<text class="topbar-right"></text>
+		</view>
+		<view class="selectbar uni-row uni-jcsb">
+			<uni-data-select v-model="selectedDate" :clear="false" :localdata="selectList" @change="dateChange"></uni-data-select>
+			<text class="selectbar-date">共 {{rsCount}} 条</text>
+		</view>
+		<view class="main uni-column">
+			<view class="list" v-if="rsCount > 0">
+				<view class="list-item uni-row" v-for="(item,index) in exchangedList" :key="index">
+					<image mode="aspectFit" class="list-item-ico" :src="item.iconUrl"></image>
+					<text class="list-item-aiName">{{item.aiName}}</text>
+					<view class="list-item-right uni-column">
+						<text class="list-item-phone">{{item.phone}}</text>
+						<text class="list-item-exTime">兑换时间</text>
+						<text class="list-item-exTime">{{fmtTime(item.exTime)}}</text>
+					</view>
+				</view>
+			</view>
+			<view class="norecord" v-else>暂无记录</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import { apiVerfExchangedListQuery, checkResCode } from '../../common/api.js';
+
+	export default {
+		data() {
+			return {
+				token: "",
+				shopInfo: {
+					shopName: ""
+				},
+				exchangedList: [],
+				/* exchangedList: [{
+						aiName: '三个鸡蛋',
+						exTime: '1719735225',
+						phone: '188****9600',
+						iconUrl: '/static/test/egg.png',
+					},
+					{
+						aiName: '课时券',
+						exTime: '1719735225',
+						phone: '188****9500',
+						iconUrl: '/static/test/ticket_xfl.png',
+					},
+					{
+						aiName: 'Mickey玩具 发撒士大夫撒旦飞大厦asdfdsasdf21234563245',
+						exTime: '1719735225',
+						phone: '188****9000',
+						iconUrl: '/static/test/toy.png',
+					},
+				], */
+				rsCount: 0,
+				selectedDate: "",
+				selectList: []
+			}
+		},
+		onLoad() {
+			this.token = tools.getToken();
+			// tools.checkToken(this.token);
+			this.shopInfo = tools.getShopInfo();
+			// console.log("shopInfo:", this.shopInfo);
+			
+			this.initDateSelect();
+			this.verfExchangedListQuery();
+		},
+		methods: {
+			initDateSelect() {
+				const monthlist = tools.getMonthList(6);
+				for (var i = 0; i < monthlist.length; i++) {
+					let option = {};
+					option.value = monthlist[i];
+					option.text = monthlist[i];
+					this.selectList.push(option);
+				}
+				this.selectedDate = monthlist[0];
+			},
+			dateChange(e) {
+				console.log("e:", e);
+				if (e != "") {
+					this.verfExchangedListQuery();
+				}
+			},
+			fmtTime(timestamp) {
+				if (timestamp > 0)
+					return tools.timestampToTime(timestamp*1000, 3);
+			},
+			// 商家系统已核销记录查询
+			verfExchangedListQuery() {
+				uni.request({
+					url: apiVerfExchangedListQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						yearMonth: this.selectedDate
+					},
+					success: (res) => {
+						console.log("verfExchangedListQuery", res);
+						
+						if (checkResCode(res)) {
+							this.exchangedList = res.data.data;
+							this.rsCount = this.exchangedList.length;
+						}
+					},
+					fail: (err) => {
+						console.log("verfExchangedListQuery err", err)
+					},
+				});
+			},
+			btnBack() {
+				uni.navigateTo({
+					url: "/pages/index/index"
+				})
+			},
+			btnClose() {
+				uni.exitMiniProgram({
+					success: function() {
+						console.log('退出小程序成功');
+					},
+					fail: function(err) {
+						console.log('退出小程序失败', err);
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	body {
+		background: #fcf4f2;
+	}
+
+	.topnav {
+		width: 92vw;
+		height: 50px;
+		align-items: flex-end;
+		margin-bottom: 6px;
+	}
+
+	.topnav-left {
+		font-size: 30px;
+		line-height: 25px;
+	}
+
+	.topnav-center {
+		font-weight: 500;
+		color: #000000;
+		font-size: 16px;
+		text-align: center;
+	}
+
+	.topnav-right {
+		font-size: 30px;
+		/* line-height: 40px; */
+		line-height: 25px;
+	}
+
+	.topbar {
+		width: 100vw;
+		height: 70px;
+		background: url("/static/bg_topbar.png") no-repeat;
+		background-size: 100% 100%;
+	}
+
+	.topbar-left {
+		margin-left: 15px;
+		font-weight: 500;
+		color: #ffffff;
+		font-size: 20px;
+		text-align: center;
+	}
+
+	.topbar-right {
+		margin-right: 20px;
+		font-weight: 500;
+		color: #ffffff;
+		font-size: 16px;
+		text-align: right;
+	}
+	
+	.btnBack {
+		font-size: 26px;
+		margin-right: 15px;
+	}
+
+	.selectbar {
+		width: 90vw;
+		margin-top: 10px;
+	}
+
+	/deep/ .uni-select {
+		width: 100px;
+		height: 30px;
+	}
+
+	.selectbar-date {
+		font-weight: 500;
+		color: #000000;
+		font-size: 13px;
+	}
+
+	.main {
+		width: 90%;
+		/* height: 60vh; */
+		justify-content: space-evenly;
+		/* flex-grow: 1; */
+	}
+
+	.list {
+		width: 100%;
+		overflow: scroll;
+	}
+
+	.list-item {
+		width: 100%;
+		height: 70px;
+		margin: 8px 0px;
+		background: #fff;
+		border-radius: 5px;
+	}
+
+	.list-item-ico {
+		flex-shrink: 0;
+		width: 50px;
+		height: 50px;
+		margin: 0 10px;
+	}
+
+	.list-item-aiName {
+		flex-grow: 1;
+		font-weight: 500;
+		color: #000000;
+		font-size: 16px;
+		/* 超出容器部分的文本隐藏起来 */
+		overflow: hidden;
+		/* 使用省略号表示被截断的文本 */
+		text-overflow: ellipsis;
+	}
+
+	.list-item-right {
+		width: 105px;
+		flex-shrink: 0;
+		align-items: flex-end;
+		margin-right: 10px;
+	}
+
+	.list-item-phone {
+		font-weight: 500;
+		color: #333333;
+		font-size: 16px;
+		text-align: right;
+	}
+
+	.list-item-exTime {
+		font-weight: 500;
+		color: #c6c6c6;
+		font-size: 12px;
+		text-align: right;
+		text-wrap: nowrap;
+	}
+	
+	.norecord {
+		color:#818181;
+		font-size:12px;
+		line-height: 60vh;
+	}
+	
+</style>

+ 177 - 0
shop/pages/index/index.vue

@@ -0,0 +1,177 @@
+<template>
+	<view class="body body-bg">
+		<view class="main uni-column">
+			<text class="shopname">{{shopInfo.shopName}}</text>
+			<text class="button" @click="btnScanQR">扫码兑换</text>
+			<text class="button" @click="btnExchgRecord">兑换记录</text>
+			<!-- <text class="">{{qrCode}}</text> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import {
+		apiVerfExchange,
+		apiGetWxJsSdkConfig,
+		checkResCode
+	} from '../../common/api.js';
+
+	import wx from 'weixin-js-sdk';
+
+	export default {
+		data() {
+			return {
+				token: "",
+				wxcode: "",
+				wxconfig: {},
+				shopInfo: {
+					shopName: ""
+				},
+				qrCode: ""
+			}
+		},
+		onLoad() {
+			this.token = tools.getToken();
+			// console.log("token:", this.token);
+			tools.checkToken(this.token);
+
+			this.shopInfo = tools.getShopInfo();
+			// console.log("shopInfo:", this.shopInfo);
+
+			this.getWxJsSdkConfig();
+		},
+		methods: {
+			// 获取微信JsConfig
+			getWxJsSdkConfig() {
+				let that = this;
+				var url = location.href.split('#')[0]; //获取当前网页的url
+				// console.log("url ", url);
+				uni.request({
+					url: apiGetWxJsSdkConfig,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+					},
+					method: "POST",
+					data: {
+						url: url
+					},
+					success: (res) => {
+						// console.log("getWxJsSdkConfig", res);
+						that.wxconfig = res.data.data;
+
+						wx.config({
+							debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
+							appId: that.wxconfig.appId, // 必填,公众号的唯一标识
+							timestamp: that.wxconfig.timestamp, // 必填,生成签名的时间戳
+							nonceStr: that.wxconfig.nonceStr, // 必填,生成签名的随机串
+							signature: that.wxconfig.signature, // 必填,签名
+							jsApiList: ['checkJsApi', 'scanQRCode'] // 必填,需要使用的JS接口列表
+						});
+					},
+					fail: (err) => {
+						console.log("getWxJsSdkConfig err", err);
+					},
+				});
+			},
+			btnScanQR() {
+				try {
+					let that = this;
+					wx.ready(function() {
+						wx.scanQRCode({
+							needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+							scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
+							success: function(res) {
+								console.log("scanQRCode result: ", res);
+								that.qrCode = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
+								that.verfExchange();
+							}
+						});
+					});
+
+					wx.error(function(res) {
+						// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
+						console.log("wx.error:", res);
+					});
+				} catch (e) {
+					console.log("btnScanQR err:", e.message);
+				}
+			},
+			// 商家系统核销
+			verfExchange() {
+				uni.request({
+					url: apiVerfExchange,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						qrCode: this.qrCode
+					},
+					success: (res) => {						
+						console.log("verfExchange", res);
+						if (checkResCode(res)) {
+							uni.showToast({
+								icon: "success",
+								title: "核销成功",
+								duration: 2000
+							});
+						}
+					},
+					fail: (err) => {
+						console.log("verfExchange err", err);
+						uni.showToast({
+							icon: "error",
+							title: "核销失败",
+							duration: 3000
+						});
+					},
+				});
+			},
+			btnExchgRecord() {
+				uni.navigateTo({
+					url: "/pages/exchgRecord/exchgRecord"
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.body-bg {
+		width: 100vw;
+		height: 100vh;
+		background: url("/static/bg_index.png") no-repeat;
+		background-size: 100% 100%;
+	}
+
+	.main {
+		width: 90%;
+		height: 60%;
+		justify-content: space-evenly;
+	}
+
+	.shopname {
+		font-weight: 500;
+		color: #000000;
+		font-size: 30px;
+		text-align: center;
+	}
+
+	.button {
+		width: 230px;
+		height: 80px;
+		background: linear-gradient(180deg, #ffffff 0%, #ebebeb 71.96%, #ffffff 100%);
+		border: 1px solid;
+		border-color: #d8d8d8;
+		border-radius: 42px;
+		box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
+
+		text-align: center;
+		line-height: 80px;
+		font-weight: 500;
+		color: #000000;
+		font-size: 29px;
+	}
+</style>

+ 166 - 0
shop/pages/login/login.vue

@@ -0,0 +1,166 @@
+<template>
+	<view class="body body-bg">
+		<view class="main uni-column">
+			<view class="topLogo"></view>
+			<text class="title">商家小程序</text>
+			<view class="box uni-column">
+				<input class="input" placeholder-class="input-placeholder" type="text" maxlength="20"
+					placeholder="请输入用户名" v-model="username" />
+				<input class="input" placeholder-class="input-placeholder" password type="text" maxlength="20"
+					placeholder="请输入密码" v-model="password" />
+				<button class="button" @click="login">登 录</button>
+			</view>
+			<view class="bottomLogo"></view>
+		</view>
+		<text class="bottomText">彩图奔跑定向APP</text>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import { apiVerfSignIn } from '../../common/api.js';
+
+	export default {
+		data() {
+			return {
+				username: "",
+				password: "",
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			// 商家系统登录
+			login() {
+				uni.request({
+					url: apiVerfSignIn,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+					},
+					method: "POST",
+					data: {
+						username: this.username,
+						password: this.password
+					},
+					success: (res) => {
+						console.log("login", res)
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const token = data.token;
+							const shopinfo = {
+								shopName: data.shopName
+							}
+							
+							tools.setToken(token);
+							tools.setShopInfo(shopinfo);
+							
+							uni.showToast({
+								title: `登录成功`,
+								icon: 'none',
+								duration: 3000
+							});
+							
+							uni.navigateTo({
+								url: "/pages/index/index"
+							});
+						}
+						else {
+							uni.showToast({
+								title: `登录失败,请重新登录`,
+								icon: 'none',
+								duration: 3000
+							});
+						}
+					},
+					fail: (err) => {
+						console.log("login err", err)
+					},
+				});
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.body-bg {
+		width: 100vw;
+		height: 100vh;
+		background: url("/static/bg_login.png") no-repeat;
+		background-size: contain;
+		/* background-size: 100% 100%; */
+		justify-content: space-between;
+	}
+
+	.main {
+		width: 90%;
+		height: 570px;
+		margin-top: 15%;
+		justify-content: space-evenly;
+	}
+
+	.topLogo {
+		width: 90px;
+		height: 110px;
+		background: url("/static/run.png") no-repeat;
+		background-size: contain;
+	}
+
+	.title {
+		font-weight: 500;
+		color: #ffffff;
+		font-size: 30px;
+		text-align: center;
+	}
+
+	.box {
+		/* width: 317px; */
+		width: 92%;
+		height: 237px;
+		padding-top: 10px;
+		padding-bottom: 10px;
+		justify-content: space-evenly;
+		background-color: white;
+		border-radius: 13px;
+		box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.16);
+	}
+
+	.input {
+		width: 72%;
+		height: 46px;
+		padding: 0 5%;
+		border: 1px solid;
+		border-color: #c6c6c6;
+		border-radius: 3px;
+	}
+
+	.input-placeholder {
+		font-weight: 300;
+		color: #bfbfbf;
+		font-size: 16px;
+	}
+
+	.button {
+		width: 82%;
+		background: #ffb40b;
+		border-radius: 6px;
+		font-weight: 500;
+		color: #333333;
+		word-spacing: 15px;
+	}
+
+	.bottomLogo {
+		width: 232px;
+		height: 36px;
+		background: url("/static/ctbp.png") no-repeat;
+		background-size: contain;
+	}
+
+	.bottomText {
+		margin-bottom: 30px;
+		font-weight: 500;
+		color: #000000;
+		font-size: 12px;
+		text-align: center;
+	}
+</style>

BIN
shop/static/bg_index.png


BIN
shop/static/bg_login.png


BIN
shop/static/bg_topbar.png


BIN
shop/static/ctbp.png


BIN
shop/static/ico_fail.png


BIN
shop/static/ico_success.png


BIN
shop/static/logo.png


BIN
shop/static/run.png


BIN
shop/static/test/egg.png


BIN
shop/static/test/ticket_xfl.png


BIN
shop/static/test/toy.png


+ 10 - 0
shop/uni.promisify.adaptor.js

@@ -0,0 +1,10 @@
+uni.addInterceptor({
+  returnValue (res) {
+    if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
+      return res;
+    }
+    return new Promise((resolve, reject) => {
+      res.then((res) => res[0] ? reject(res[0]) : resolve(res[1]));
+    });
+  },
+});

+ 76 - 0
shop/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;

+ 33 - 0
shop/uni_modules/uni-badge/changelog.md

@@ -0,0 +1,33 @@
+## 1.2.2(2023-01-28)
+- 修复 运行/打包 控制台警告问题
+## 1.2.1(2022-09-05)
+- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7(2021-11-08)
+- 优化 升级ui
+- 修改 size 属性默认值调整为 small
+- 修改 type 属性,默认值调整为 error,info 替换 default
+## 1.1.6(2021-09-22)
+- 修复 在字节小程序上样式不生效的 bug
+## 1.1.5(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4(2021-07-29)
+- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
+## 1.1.3(2021-06-24)
+- 优化 示例项目
+## 1.1.1(2021-05-12)
+- 新增 组件示例地址
+## 1.1.0(2021-05-12)
+- 新增 uni-badge 的 absolute 属性,支持定位
+- 新增 uni-badge 的 offset 属性,支持定位偏移
+- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
+- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
+- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
+## 1.0.7(2021-05-07)
+- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
+- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
+- 新增 uni-badge 属性 custom-style, 支持自定义样式
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范

+ 268 - 0
shop/uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					minWidth: '0',
+					height: '10px',
+					padding: '0',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		font-feature-settings: "tnum";
+		min-width: 20px;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		padding: 0 4px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>

+ 85 - 0
shop/uni_modules/uni-badge/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.2",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 10 - 0
shop/uni_modules/uni-badge/readme.md

@@ -0,0 +1,10 @@
+## Badge 数字角标
+> **组件名:uni-badge**
+> 代码块: `uBadge`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+

+ 39 - 0
shop/uni_modules/uni-data-select/changelog.md

@@ -0,0 +1,39 @@
+## 1.0.8(2024-03-28)
+- 修复 在vue2下:style动态绑定导致编译失败的bug
+## 1.0.7(2024-01-20)
+- 修复 长文本回显超过容器的bug,超过容器部分显示省略号
+## 1.0.6(2023-04-12)
+- 修复 微信小程序点击时会改变背景颜色的 bug
+## 1.0.5(2023-02-03)
+- 修复 禁用时会显示清空按钮
+## 1.0.4(2023-02-02)
+- 优化 查询条件短期内多次变更只查询最后一次变更后的结果
+- 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue
+## 1.0.3(2023-01-16)
+- 修复 不关联服务空间报错的问题
+## 1.0.2(2023-01-14)
+- 新增  属性 `format` 可用于格式化显示选项内容
+## 1.0.1(2022-12-06)
+- 修复  当where变化时,数据不会自动更新的问题
+## 0.1.9(2022-09-05)
+- 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框
+## 0.1.8(2022-08-29)
+- 修复 点击的位置不准确
+## 0.1.7(2022-08-12)
+- 新增 支持 disabled 属性
+## 0.1.6(2022-07-06)
+- 修复 pc端宽度异常的bug
+## 0.1.5
+- 修复 pc端宽度异常的bug
+## 0.1.4(2022-07-05)
+- 优化 显示样式
+## 0.1.3(2022-06-02)
+- 修复 localdata 赋值不生效的 bug
+- 新增 支持  uni.scss 修改颜色
+- 新增 支持选项禁用(数据选项设置 disabled: true 即禁用)
+## 0.1.2(2022-05-08)
+- 修复 当 value 为 0 时选择不生效的 bug
+## 0.1.1(2022-05-07)
+- 新增 记住上次的选项(仅 collection 存在时有效)
+## 0.1.0(2022-04-22)
+- 初始化

+ 562 - 0
shop/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue

@@ -0,0 +1,562 @@
+<template>
+	<view class="uni-stat__select">
+		<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
+		<view class="uni-stat-box" :class="{'uni-stat__actived': current}">
+			<view class="uni-select" :class="{'uni-select--disabled':disabled}">
+				<view class="uni-select__input-box" @click="toggleSelector">
+					<view v-if="current" class="uni-select__input-text">{{textShow}}</view>
+					<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
+					<view v-if="current && clear && !disabled" @click.stop="clearVal">
+						<uni-icons type="clear" color="#c0c4cc" size="24" />
+					</view>
+					<view v-else>
+						<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+					</view>
+				</view>
+				<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
+				<view class="uni-select__selector" :style="getOffsetByPlacement" v-if="showSelector">
+					<view :class="placement=='bottom'?'uni-popper__arrow_bottom':'uni-popper__arrow_top'"></view>
+					<scroll-view scroll-y="true" class="uni-select__selector-scroll">
+						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
+							<text>{{emptyTips}}</text>
+						</view>
+						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index"
+							@click="change(item)">
+							<text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
+						</view>
+					</scroll-view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * DataChecklist 数据选择器
+	 * @description 通过数据渲染的下拉框组件
+	 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
+	 * @property {String} value 默认值
+	 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
+	 * @property {Boolean} clear 是否可以清空已选项
+	 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
+	 * @property {String} label 左侧标题
+	 * @property {String} placeholder 输入框的提示文字
+	 * @property {Boolean} disabled 是否禁用
+	 * @property {String} placement 弹出位置
+	 * 	@value top   		顶部弹出
+	 * 	@value bottom		底部弹出(default)
+	 * @event {Function} change  选中发生变化触发
+	 */
+
+	export default {
+		name: "uni-data-select",
+		mixins: [uniCloud.mixinDatacom || {}],
+		props: {
+			localdata: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Number],
+				default: ''
+			},
+			label: {
+				type: String,
+				default: ''
+			},
+			placeholder: {
+				type: String,
+				default: '请选择'
+			},
+			emptyTips: {
+				type: String,
+				default: '无选项'
+			},
+			clear: {
+				type: Boolean,
+				default: true
+			},
+			defItem: {
+				type: Number,
+				default: 0
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			// 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
+			format: {
+				type: String,
+				default: ''
+			},
+			placement: {
+				type: String,
+				default: 'bottom'
+			}
+		},
+		data() {
+			return {
+				showSelector: false,
+				current: '',
+				mixinDatacomResData: [],
+				apps: [],
+				channels: [],
+				cacheKey: "uni-data-select-lastSelectedValue",
+			};
+		},
+		created() {
+			this.debounceGet = this.debounce(() => {
+				this.query();
+			}, 300);
+			if (this.collection && !this.localdata.length) {
+				this.debounceGet();
+			}
+		},
+		computed: {
+			typePlaceholder() {
+				const text = {
+					'opendb-stat-app-versions': '版本',
+					'opendb-app-channels': '渠道',
+					'opendb-app-list': '应用'
+				}
+				const common = this.placeholder
+				const placeholder = text[this.collection]
+				return placeholder ?
+					common + placeholder :
+					common
+			},
+			valueCom() {
+				// #ifdef VUE3
+				return this.modelValue;
+				// #endif
+				// #ifndef VUE3
+				return this.value;
+				// #endif
+			},
+			textShow() {
+				// 长文本显示
+				let text = this.current;
+				if (text.length > 10) {
+					return text.slice(0, 25) + '...';
+				}
+				return text;
+			},
+			getOffsetByPlacement() {
+				switch (this.placement) {
+					case 'top':
+						return "bottom:calc(100% + 12px);";
+					case 'bottom':
+						return "top:calc(100% + 12px);";
+				}
+			}
+		},
+
+		watch: {
+			localdata: {
+				immediate: true,
+				handler(val, old) {
+					if (Array.isArray(val) && old !== val) {
+						this.mixinDatacomResData = val
+					}
+				}
+			},
+			valueCom(val, old) {
+				this.initDefVal()
+			},
+			mixinDatacomResData: {
+				immediate: true,
+				handler(val) {
+					if (val.length) {
+						this.initDefVal()
+					}
+				}
+			},
+
+		},
+		methods: {
+			debounce(fn, time = 100) {
+				let timer = null
+				return function(...args) {
+					if (timer) clearTimeout(timer)
+					timer = setTimeout(() => {
+						fn.apply(this, args)
+					}, time)
+				}
+			},
+			// 执行数据库查询
+			query() {
+				this.mixinDatacomEasyGet();
+			},
+			// 监听查询条件变更事件
+			onMixinDatacomPropsChange() {
+				if (this.collection) {
+					this.debounceGet();
+				}
+			},
+			initDefVal() {
+				let defValue = ''
+				if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
+					defValue = this.valueCom
+				} else {
+					let strogeValue
+					if (this.collection) {
+						strogeValue = this.getCache()
+					}
+					if (strogeValue || strogeValue === 0) {
+						defValue = strogeValue
+					} else {
+						let defItem = ''
+						if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
+							defItem = this.mixinDatacomResData[this.defItem - 1].value
+						}
+						defValue = defItem
+					}
+					if (defValue || defValue === 0) {
+						this.emit(defValue)
+					}
+				}
+				const def = this.mixinDatacomResData.find(item => item.value === defValue)
+				this.current = def ? this.formatItemName(def) : ''
+			},
+
+			/**
+			 * @param {[String, Number]} value
+			 * 判断用户给的 value 是否同时为禁用状态
+			 */
+			isDisabled(value) {
+				let isDisabled = false;
+
+				this.mixinDatacomResData.forEach(item => {
+					if (item.value === value) {
+						isDisabled = item.disable
+					}
+				})
+
+				return isDisabled;
+			},
+
+			clearVal() {
+				this.emit('')
+				if (this.collection) {
+					this.removeCache()
+				}
+			},
+			change(item) {
+				if (!item.disable) {
+					this.showSelector = false
+					this.current = this.formatItemName(item)
+					this.emit(item.value)
+				}
+			},
+			emit(val) {
+				this.$emit('input', val)
+				this.$emit('update:modelValue', val)
+				this.$emit('change', val)
+				if (this.collection) {
+					this.setCache(val);
+				}
+			},
+			toggleSelector() {
+				if (this.disabled) {
+					return
+				}
+
+				this.showSelector = !this.showSelector
+			},
+			formatItemName(item) {
+				let {
+					text,
+					value,
+					channel_code
+				} = item
+				channel_code = channel_code ? `(${channel_code})` : ''
+
+				if (this.format) {
+					// 格式化输出
+					let str = "";
+					str = this.format;
+					for (let key in item) {
+						str = str.replace(new RegExp(`{${key}}`, "g"), item[key]);
+					}
+					return str;
+				} else {
+					return this.collection.indexOf('app-list') > 0 ?
+						`${text}(${value})` :
+						(
+							text ?
+							text :
+							`未命名${channel_code}`
+						)
+				}
+			},
+			// 获取当前加载的数据
+			getLoadData() {
+				return this.mixinDatacomResData;
+			},
+			// 获取当前缓存key
+			getCurrentCacheKey() {
+				return this.collection;
+			},
+			// 获取缓存
+			getCache(name = this.getCurrentCacheKey()) {
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				return cacheData[name];
+			},
+			// 设置缓存
+			setCache(value, name = this.getCurrentCacheKey()) {
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				cacheData[name] = value;
+				uni.setStorageSync(this.cacheKey, cacheData);
+			},
+			// 删除缓存
+			removeCache(name = this.getCurrentCacheKey()) {
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				delete cacheData[name];
+				uni.setStorageSync(this.cacheKey, cacheData);
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-base-color: #6a6a6a !default;
+	$uni-main-color: #333 !default;
+	$uni-secondary-color: #909399 !default;
+	$uni-border-3: #e5e5e5;
+
+	/* #ifndef APP-NVUE */
+	@media screen and (max-width: 500px) {
+		.hide-on-phone {
+			display: none;
+		}
+	}
+
+	/* #endif */
+	.uni-stat__select {
+		display: flex;
+		align-items: center;
+		// padding: 15px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+		width: 100%;
+		flex: 1;
+		box-sizing: border-box;
+	}
+
+	.uni-stat-box {
+		width: 100%;
+		flex: 1;
+	}
+
+	.uni-stat__actived {
+		width: 100%;
+		flex: 1;
+		// outline: 1px solid #2979ff;
+	}
+
+	.uni-label-text {
+		font-size: 14px;
+		font-weight: bold;
+		color: $uni-base-color;
+		margin: auto 0;
+		margin-right: 5px;
+	}
+
+	.uni-select {
+		font-size: 14px;
+		border: 1px solid $uni-border-3;
+		box-sizing: border-box;
+		border-radius: 4px;
+		padding: 0 5px;
+		padding-left: 10px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		user-select: none;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		border-bottom: solid 1px $uni-border-3;
+		width: 100%;
+		flex: 1;
+		height: 35px;
+
+		&--disabled {
+			background-color: #f5f7fa;
+			cursor: not-allowed;
+		}
+	}
+
+	.uni-select__label {
+		font-size: 16px;
+		// line-height: 22px;
+		height: 35px;
+		padding-right: 10px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__input-box {
+		height: 35px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-select__input {
+		flex: 1;
+		font-size: 14px;
+		height: 22px;
+		line-height: 22px;
+	}
+
+	.uni-select__input-plac {
+		font-size: 14px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__selector {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+		position: absolute;
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		border: 1px solid #EBEEF5;
+		border-radius: 6px;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		z-index: 3;
+		padding: 4px 0;
+	}
+
+	.uni-select__selector-scroll {
+		/* #ifndef APP-NVUE */
+		max-height: 200px;
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	/* #ifdef H5 */
+	@media (min-width: 768px) {
+		.uni-select__selector-scroll {
+			max-height: 600px;
+		}
+	}
+
+	/* #endif */
+
+	.uni-select__selector-empty,
+	.uni-select__selector-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		line-height: 35px;
+		font-size: 14px;
+		text-align: center;
+		/* border-bottom: solid 1px $uni-border-3; */
+		padding: 0px 10px;
+	}
+
+	.uni-select__selector-item:hover {
+		background-color: #f9f9f9;
+	}
+
+	.uni-select__selector-empty:last-child,
+	.uni-select__selector-item:last-child {
+		/* #ifndef APP-NVUE */
+		border-bottom: none;
+		/* #endif */
+	}
+
+	.uni-select__selector__disabled {
+		opacity: 0.4;
+		cursor: default;
+	}
+
+	/* picker 弹出层通用的指示小三角 */
+	.uni-popper__arrow_bottom,
+	.uni-popper__arrow_bottom::after,
+	.uni-popper__arrow_top,
+	.uni-popper__arrow_top::after,
+	{
+	position: absolute;
+	display: block;
+	width: 0;
+	height: 0;
+	border-color: transparent;
+	border-style: solid;
+	border-width: 6px;
+	}
+
+	.uni-popper__arrow_bottom {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow_bottom::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+
+	.uni-popper__arrow_top {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		bottom: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-bottom-width: 0;
+		border-top-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow_top::after {
+		content: " ";
+		bottom: 1px;
+		margin-left: -6px;
+		border-bottom-width: 0;
+		border-top-color: #fff;
+	}
+
+
+	.uni-select__input-text {
+		// width: 280px;
+		width: 100%;
+		color: $uni-main-color;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		overflow: hidden;
+	}
+
+	.uni-select__input-placeholder {
+		color: $uni-base-color;
+		font-size: 12px;
+	}
+
+	.uni-select--mask {
+		position: fixed;
+		top: 0;
+		bottom: 0;
+		right: 0;
+		left: 0;
+		z-index: 2;
+	}
+</style>

+ 86 - 0
shop/uni_modules/uni-data-select/package.json

@@ -0,0 +1,86 @@
+{
+  "id": "uni-data-select",
+  "displayName": "uni-data-select 下拉框选择器",
+  "version": "1.0.8",
+  "description": "通过数据驱动的下拉框选择器",
+  "keywords": [
+    "uni-ui",
+    "select",
+    "uni-data-select",
+    "下拉框",
+    "下拉选"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.1"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-load-more"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+        "QQ": "u",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 8 - 0
shop/uni_modules/uni-data-select/readme.md

@@ -0,0 +1,8 @@
+## DataSelect 下拉框选择器
+> **组件名:uni-data-select**
+> 代码块: `uDataSelect`
+
+当选项过多时,使用下拉菜单展示并选择内容
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 

+ 42 - 0
shop/uni_modules/uni-icons/changelog.md

@@ -0,0 +1,42 @@
+## 2.0.10(2024-06-07)
+- 优化 uni-app x 中,size 属性的类型
+## 2.0.9(2024-01-12)
+fix: 修复图标大小默认值错误的问题
+## 2.0.8(2023-12-14)
+- 修复 项目未使用 ts 情况下,打包报错的bug
+## 2.0.7(2023-12-14)
+- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug
+## 2.0.6(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.5(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.4(2023-12-06)
+- 优化 uni-app x 下示例项目图标排序
+## 2.0.3(2023-12-06)
+- 修复 nvue下引入组件报错的bug
+## 2.0.2(2023-12-05)
+-优化 size 属性支持单位
+## 2.0.1(2023-12-05)
+- 新增 uni-app x 支持定义图标
+## 1.3.5(2022-01-24)
+- 优化 size 属性可以传入不带单位的字符串数值
+## 1.3.4(2022-01-24)
+- 优化 size 支持其他单位
+## 1.3.3(2022-01-17)
+- 修复 nvue 有些图标不显示的bug,兼容老版本图标
+## 1.3.2(2021-12-01)
+- 优化 示例可复制图标名称
+## 1.3.1(2021-11-23)
+- 优化 兼容旧组件 type 值
+## 1.3.0(2021-11-19)
+- 新增 更多图标
+- 优化 自定义图标使用方式
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
+## 1.1.7(2021-11-08)
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.5(2021-05-12)
+- 新增 组件示例地址
+## 1.1.4(2021-02-05)
+- 调整为uni_modules目录规范

+ 91 - 0
shop/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue

@@ -0,0 +1,91 @@
+<template>
+  <text class="uni-icons" :style="styleObj">
+    <slot>{{unicode}}</slot>
+  </text>
+</template>
+
+<script>
+  import { fontData, IconsDataItem } from './uniicons_file'
+
+  /**
+   * Icons 图标
+   * @description 用于展示 icon 图标
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+   * @property {Number,String} size 图标大小
+   * @property {String} type 图标图案,参考示例
+   * @property {String} color 图标颜色
+   * @property {String} customPrefix 自定义图标
+   * @event {Function} click 点击 Icon 触发事件
+   */
+  export default {
+    name: "uni-icons",
+    props: {
+      type: {
+        type: String,
+        default: ''
+      },
+      color: {
+        type: String,
+        default: '#333333'
+      },
+      size: {
+        type: [Number, String],
+        default: 16
+      },
+      fontFamily: {
+        type: String,
+        default: ''
+      }
+    },
+    data() {
+      return {};
+    },
+    computed: {
+      unicode() : string {
+        let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
+        if (codes !== null) {
+          return codes.unicode
+        }
+        return ''
+      },
+      iconSize() : string {
+        const size = this.size
+        if (typeof size == 'string') {
+          const reg = /^[0-9]*$/g
+          return reg.test(size as string) ? '' + size + 'px' : '' + size;
+          // return '' + this.size
+        }
+        return this.getFontSize(size as number)
+      },
+      styleObj() : UTSJSONObject {
+        if (this.fontFamily !== '') {
+          return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
+        }
+        return { color: this.color, fontSize: this.iconSize }
+      }
+    },
+    created() { },
+    methods: {
+      /**
+       * 字体大小
+       */
+      getFontSize(size : number) : string {
+        return size + 'px';
+      },
+    },
+  }
+</script>
+
+<style scoped>
+  @font-face {
+    font-family: UniIconsFontFamily;
+    src: url('./uniicons.ttf');
+  }
+
+  .uni-icons {
+    font-family: UniIconsFontFamily;
+    font-size: 18px;
+    font-style: normal;
+    color: #333;
+  }
+</style>

+ 110 - 0
shop/uni_modules/uni-icons/components/uni-icons/uni-icons.vue

@@ -0,0 +1,110 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
+	<!-- #endif -->
+	<!-- #ifndef APP-NVUE -->
+	<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
+		<slot></slot>
+	</text>
+	<!-- #endif -->
+</template>
+
+<script>
+	import { fontData } from './uniicons_file_vue.js';
+
+	const getVal = (val) => {
+		const reg = /^[0-9]*$/g
+		return (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;
+	}
+
+	// #ifdef APP-NVUE
+	var domModule = weex.requireModule('dom');
+	import iconUrl from './uniicons.ttf'
+	domModule.addRule('fontFace', {
+		'fontFamily': "uniicons",
+		'src': "url('" + iconUrl + "')"
+	});
+	// #endif
+
+	/**
+	 * Icons 图标
+	 * @description 用于展示 icons 图标
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+	 * @property {Number} size 图标大小
+	 * @property {String} type 图标图案,参考示例
+	 * @property {String} color 图标颜色
+	 * @property {String} customPrefix 自定义图标
+	 * @event {Function} click 点击 Icon 触发事件
+	 */
+	export default {
+		name: 'UniIcons',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			color: {
+				type: String,
+				default: '#333333'
+			},
+			size: {
+				type: [Number, String],
+				default: 16
+			},
+			customPrefix: {
+				type: String,
+				default: ''
+			},
+			fontFamily: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				icons: fontData
+			}
+		},
+		computed: {
+			unicode() {
+				let code = this.icons.find(v => v.font_class === this.type)
+				if (code) {
+					return code.unicode
+				}
+				return ''
+			},
+			iconSize() {
+				return getVal(this.size)
+			},
+			styleObj() {
+				if (this.fontFamily !== '') {
+					return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
+				}
+				return `color: ${this.color}; font-size: ${this.iconSize};`
+			}
+		},
+		methods: {
+			_onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	/* #ifndef APP-NVUE */
+	@import './uniicons.css';
+
+	@font-face {
+		font-family: uniicons;
+		src: url('./uniicons.ttf');
+	}
+
+	/* #endif */
+	.uni-icons {
+		font-family: uniicons;
+		text-decoration: none;
+		text-align: center;
+	}
+</style>

+ 664 - 0
shop/uni_modules/uni-icons/components/uni-icons/uniicons.css

@@ -0,0 +1,664 @@
+
+.uniui-cart-filled:before {
+  content: "\e6d0";
+}
+
+.uniui-gift-filled:before {
+  content: "\e6c4";
+}
+
+.uniui-color:before {
+  content: "\e6cf";
+}
+
+.uniui-wallet:before {
+  content: "\e6b1";
+}
+
+.uniui-settings-filled:before {
+  content: "\e6ce";
+}
+
+.uniui-auth-filled:before {
+  content: "\e6cc";
+}
+
+.uniui-shop-filled:before {
+  content: "\e6cd";
+}
+
+.uniui-staff-filled:before {
+  content: "\e6cb";
+}
+
+.uniui-vip-filled:before {
+  content: "\e6c6";
+}
+
+.uniui-plus-filled:before {
+  content: "\e6c7";
+}
+
+.uniui-folder-add-filled:before {
+  content: "\e6c8";
+}
+
+.uniui-color-filled:before {
+  content: "\e6c9";
+}
+
+.uniui-tune-filled:before {
+  content: "\e6ca";
+}
+
+.uniui-calendar-filled:before {
+  content: "\e6c0";
+}
+
+.uniui-notification-filled:before {
+  content: "\e6c1";
+}
+
+.uniui-wallet-filled:before {
+  content: "\e6c2";
+}
+
+.uniui-medal-filled:before {
+  content: "\e6c3";
+}
+
+.uniui-fire-filled:before {
+  content: "\e6c5";
+}
+
+.uniui-refreshempty:before {
+  content: "\e6bf";
+}
+
+.uniui-location-filled:before {
+  content: "\e6af";
+}
+
+.uniui-person-filled:before {
+  content: "\e69d";
+}
+
+.uniui-personadd-filled:before {
+  content: "\e698";
+}
+
+.uniui-arrowthinleft:before {
+  content: "\e6d2";
+}
+
+.uniui-arrowthinup:before {
+  content: "\e6d3";
+}
+
+.uniui-arrowthindown:before {
+  content: "\e6d4";
+}
+
+.uniui-back:before {
+  content: "\e6b9";
+}
+
+.uniui-forward:before {
+  content: "\e6ba";
+}
+
+.uniui-arrow-right:before {
+  content: "\e6bb";
+}
+
+.uniui-arrow-left:before {
+  content: "\e6bc";
+}
+
+.uniui-arrow-up:before {
+  content: "\e6bd";
+}
+
+.uniui-arrow-down:before {
+  content: "\e6be";
+}
+
+.uniui-arrowthinright:before {
+  content: "\e6d1";
+}
+
+.uniui-down:before {
+  content: "\e6b8";
+}
+
+.uniui-bottom:before {
+  content: "\e6b8";
+}
+
+.uniui-arrowright:before {
+  content: "\e6d5";
+}
+
+.uniui-right:before {
+  content: "\e6b5";
+}
+
+.uniui-up:before {
+  content: "\e6b6";
+}
+
+.uniui-top:before {
+  content: "\e6b6";
+}
+
+.uniui-left:before {
+  content: "\e6b7";
+}
+
+.uniui-arrowup:before {
+  content: "\e6d6";
+}
+
+.uniui-eye:before {
+  content: "\e651";
+}
+
+.uniui-eye-filled:before {
+  content: "\e66a";
+}
+
+.uniui-eye-slash:before {
+  content: "\e6b3";
+}
+
+.uniui-eye-slash-filled:before {
+  content: "\e6b4";
+}
+
+.uniui-info-filled:before {
+  content: "\e649";
+}
+
+.uniui-reload:before {
+  content: "\e6b2";
+}
+
+.uniui-micoff-filled:before {
+  content: "\e6b0";
+}
+
+.uniui-map-pin-ellipse:before {
+  content: "\e6ac";
+}
+
+.uniui-map-pin:before {
+  content: "\e6ad";
+}
+
+.uniui-location:before {
+  content: "\e6ae";
+}
+
+.uniui-starhalf:before {
+  content: "\e683";
+}
+
+.uniui-star:before {
+  content: "\e688";
+}
+
+.uniui-star-filled:before {
+  content: "\e68f";
+}
+
+.uniui-calendar:before {
+  content: "\e6a0";
+}
+
+.uniui-fire:before {
+  content: "\e6a1";
+}
+
+.uniui-medal:before {
+  content: "\e6a2";
+}
+
+.uniui-font:before {
+  content: "\e6a3";
+}
+
+.uniui-gift:before {
+  content: "\e6a4";
+}
+
+.uniui-link:before {
+  content: "\e6a5";
+}
+
+.uniui-notification:before {
+  content: "\e6a6";
+}
+
+.uniui-staff:before {
+  content: "\e6a7";
+}
+
+.uniui-vip:before {
+  content: "\e6a8";
+}
+
+.uniui-folder-add:before {
+  content: "\e6a9";
+}
+
+.uniui-tune:before {
+  content: "\e6aa";
+}
+
+.uniui-auth:before {
+  content: "\e6ab";
+}
+
+.uniui-person:before {
+  content: "\e699";
+}
+
+.uniui-email-filled:before {
+  content: "\e69a";
+}
+
+.uniui-phone-filled:before {
+  content: "\e69b";
+}
+
+.uniui-phone:before {
+  content: "\e69c";
+}
+
+.uniui-email:before {
+  content: "\e69e";
+}
+
+.uniui-personadd:before {
+  content: "\e69f";
+}
+
+.uniui-chatboxes-filled:before {
+  content: "\e692";
+}
+
+.uniui-contact:before {
+  content: "\e693";
+}
+
+.uniui-chatbubble-filled:before {
+  content: "\e694";
+}
+
+.uniui-contact-filled:before {
+  content: "\e695";
+}
+
+.uniui-chatboxes:before {
+  content: "\e696";
+}
+
+.uniui-chatbubble:before {
+  content: "\e697";
+}
+
+.uniui-upload-filled:before {
+  content: "\e68e";
+}
+
+.uniui-upload:before {
+  content: "\e690";
+}
+
+.uniui-weixin:before {
+  content: "\e691";
+}
+
+.uniui-compose:before {
+  content: "\e67f";
+}
+
+.uniui-qq:before {
+  content: "\e680";
+}
+
+.uniui-download-filled:before {
+  content: "\e681";
+}
+
+.uniui-pyq:before {
+  content: "\e682";
+}
+
+.uniui-sound:before {
+  content: "\e684";
+}
+
+.uniui-trash-filled:before {
+  content: "\e685";
+}
+
+.uniui-sound-filled:before {
+  content: "\e686";
+}
+
+.uniui-trash:before {
+  content: "\e687";
+}
+
+.uniui-videocam-filled:before {
+  content: "\e689";
+}
+
+.uniui-spinner-cycle:before {
+  content: "\e68a";
+}
+
+.uniui-weibo:before {
+  content: "\e68b";
+}
+
+.uniui-videocam:before {
+  content: "\e68c";
+}
+
+.uniui-download:before {
+  content: "\e68d";
+}
+
+.uniui-help:before {
+  content: "\e679";
+}
+
+.uniui-navigate-filled:before {
+  content: "\e67a";
+}
+
+.uniui-plusempty:before {
+  content: "\e67b";
+}
+
+.uniui-smallcircle:before {
+  content: "\e67c";
+}
+
+.uniui-minus-filled:before {
+  content: "\e67d";
+}
+
+.uniui-micoff:before {
+  content: "\e67e";
+}
+
+.uniui-closeempty:before {
+  content: "\e66c";
+}
+
+.uniui-clear:before {
+  content: "\e66d";
+}
+
+.uniui-navigate:before {
+  content: "\e66e";
+}
+
+.uniui-minus:before {
+  content: "\e66f";
+}
+
+.uniui-image:before {
+  content: "\e670";
+}
+
+.uniui-mic:before {
+  content: "\e671";
+}
+
+.uniui-paperplane:before {
+  content: "\e672";
+}
+
+.uniui-close:before {
+  content: "\e673";
+}
+
+.uniui-help-filled:before {
+  content: "\e674";
+}
+
+.uniui-paperplane-filled:before {
+  content: "\e675";
+}
+
+.uniui-plus:before {
+  content: "\e676";
+}
+
+.uniui-mic-filled:before {
+  content: "\e677";
+}
+
+.uniui-image-filled:before {
+  content: "\e678";
+}
+
+.uniui-locked-filled:before {
+  content: "\e668";
+}
+
+.uniui-info:before {
+  content: "\e669";
+}
+
+.uniui-locked:before {
+  content: "\e66b";
+}
+
+.uniui-camera-filled:before {
+  content: "\e658";
+}
+
+.uniui-chat-filled:before {
+  content: "\e659";
+}
+
+.uniui-camera:before {
+  content: "\e65a";
+}
+
+.uniui-circle:before {
+  content: "\e65b";
+}
+
+.uniui-checkmarkempty:before {
+  content: "\e65c";
+}
+
+.uniui-chat:before {
+  content: "\e65d";
+}
+
+.uniui-circle-filled:before {
+  content: "\e65e";
+}
+
+.uniui-flag:before {
+  content: "\e65f";
+}
+
+.uniui-flag-filled:before {
+  content: "\e660";
+}
+
+.uniui-gear-filled:before {
+  content: "\e661";
+}
+
+.uniui-home:before {
+  content: "\e662";
+}
+
+.uniui-home-filled:before {
+  content: "\e663";
+}
+
+.uniui-gear:before {
+  content: "\e664";
+}
+
+.uniui-smallcircle-filled:before {
+  content: "\e665";
+}
+
+.uniui-map-filled:before {
+  content: "\e666";
+}
+
+.uniui-map:before {
+  content: "\e667";
+}
+
+.uniui-refresh-filled:before {
+  content: "\e656";
+}
+
+.uniui-refresh:before {
+  content: "\e657";
+}
+
+.uniui-cloud-upload:before {
+  content: "\e645";
+}
+
+.uniui-cloud-download-filled:before {
+  content: "\e646";
+}
+
+.uniui-cloud-download:before {
+  content: "\e647";
+}
+
+.uniui-cloud-upload-filled:before {
+  content: "\e648";
+}
+
+.uniui-redo:before {
+  content: "\e64a";
+}
+
+.uniui-images-filled:before {
+  content: "\e64b";
+}
+
+.uniui-undo-filled:before {
+  content: "\e64c";
+}
+
+.uniui-more:before {
+  content: "\e64d";
+}
+
+.uniui-more-filled:before {
+  content: "\e64e";
+}
+
+.uniui-undo:before {
+  content: "\e64f";
+}
+
+.uniui-images:before {
+  content: "\e650";
+}
+
+.uniui-paperclip:before {
+  content: "\e652";
+}
+
+.uniui-settings:before {
+  content: "\e653";
+}
+
+.uniui-search:before {
+  content: "\e654";
+}
+
+.uniui-redo-filled:before {
+  content: "\e655";
+}
+
+.uniui-list:before {
+  content: "\e644";
+}
+
+.uniui-mail-open-filled:before {
+  content: "\e63a";
+}
+
+.uniui-hand-down-filled:before {
+  content: "\e63c";
+}
+
+.uniui-hand-down:before {
+  content: "\e63d";
+}
+
+.uniui-hand-up-filled:before {
+  content: "\e63e";
+}
+
+.uniui-hand-up:before {
+  content: "\e63f";
+}
+
+.uniui-heart-filled:before {
+  content: "\e641";
+}
+
+.uniui-mail-open:before {
+  content: "\e643";
+}
+
+.uniui-heart:before {
+  content: "\e639";
+}
+
+.uniui-loop:before {
+  content: "\e633";
+}
+
+.uniui-pulldown:before {
+  content: "\e632";
+}
+
+.uniui-scan:before {
+  content: "\e62a";
+}
+
+.uniui-bars:before {
+  content: "\e627";
+}
+
+.uniui-checkbox:before {
+  content: "\e62b";
+}
+
+.uniui-checkbox-filled:before {
+  content: "\e62c";
+}
+
+.uniui-shop:before {
+  content: "\e62f";
+}
+
+.uniui-headphones:before {
+  content: "\e630";
+}
+
+.uniui-cart:before {
+  content: "\e631";
+}

BIN
shop/uni_modules/uni-icons/components/uni-icons/uniicons.ttf


+ 664 - 0
shop/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts

@@ -0,0 +1,664 @@
+
+export type IconsData = {
+	id : string
+	name : string
+	font_family : string
+	css_prefix_text : string
+	description : string
+	glyphs : Array<IconsDataItem>
+}
+
+export type IconsDataItem = {
+	font_class : string
+	unicode : string
+}
+
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+] as IconsDataItem[]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

+ 649 - 0
shop/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js

@@ -0,0 +1,649 @@
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

+ 89 - 0
shop/uni_modules/uni-icons/package.json

@@ -0,0 +1,89 @@
+{
+  "id": "uni-icons",
+  "displayName": "uni-icons 图标",
+  "version": "2.0.10",
+  "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "icon",
+    "图标"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.2.14"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y",
+          "app-uvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y",
+					"钉钉": "y",
+					"快手": "y",
+					"飞书": "y",
+					"京东": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 8 - 0
shop/uni_modules/uni-icons/readme.md

@@ -0,0 +1,8 @@
+## Icons 图标
+> **组件名:uni-icons**
+> 代码块: `uIcons`
+
+用于展示 icons 图标 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 

+ 46 - 0
shop/uni_modules/uni-list/changelog.md

@@ -0,0 +1,46 @@
+## 1.2.14(2023-04-14)
+- 优化 uni-list-chat 具名插槽`header` 非app端套一层元素,方便使用时通过外层元素定位实现样式修改
+## 1.2.13(2023-03-03)
+- uni-list-chat 新增 支持具名插槽`header`
+## 1.2.12(2023-02-01)
+- 新增 列表图标新增 customPrefix 属性 ,用法 [详见](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props)
+## 1.2.11(2023-01-31)
+- 修复 无反馈效果呈现的bug
+## 1.2.9(2022-11-22)
+- 修复 uni-list-chat 在vue3下跳转报错的bug
+## 1.2.8(2022-11-21)
+- 修复 uni-list-chat avatar属性 值为本地路径时错误的问题
+## 1.2.7(2022-11-21)
+- 修复 uni-list-chat avatar属性 在腾讯云版uniCloud下错误的问题
+## 1.2.6(2022-11-18)
+- 修复 uni-list-chat note属性 支持:“草稿”字样功能 文本少1位的问题
+## 1.2.5(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug
+## 1.2.4(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug
+## 1.2.3(2022-11-14)
+- uni-list-chat 新增 avatar 支持 fileId
+## 1.2.2(2022-11-11)
+- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
+- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
+- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor
+## 1.2.1(2022-03-30)
+- 删除无用文件
+## 1.2.0(2021-11-23)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
+## 1.1.3(2021-08-30)
+- 修复 在vue3中to属性在发行应用的时候报错的bug
+## 1.1.2(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.1.1(2021-07-21)
+- 修复 与其他组件嵌套使用时,点击失效的Bug
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.17(2021-05-12)
+- 新增 组件示例地址
+## 1.0.16(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.15(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 uni-list-chat 角标显示不正常的问题

+ 107 - 0
shop/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue

@@ -0,0 +1,107 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view class="uni-list-ad">
+			<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
+			<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
+			 unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+	export default {
+		name: 'UniListAd',
+		props: {
+			title: {
+				type: String,
+				default: '',
+
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				border: false,
+				borderShow: true,
+			}
+		},
+
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true
+					this.isFirstChild = true
+				}
+				this.border = this.list.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			aderror(e) {
+				console.log("aderror: " + JSON.stringify(e.detail));
+			},
+			closeAd(e) {
+				this.borderShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-list-ad {
+		position: relative;
+		border: 1px red solid;
+	}
+
+	.uni-list--border {
+		position: relative;
+		padding-bottom: 1px;
+		/* #ifdef APP-PLUS */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		margin-left: $uni-spacing-row-lg;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: $uni-border-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+</style>

+ 58 - 0
shop/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss

@@ -0,0 +1,58 @@
+/**
+ * 这里是 uni-list 组件内置的常用样式变量
+ * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码
+ *
+ */
+
+// 背景色
+$background-color : #fff;
+// 分割线颜色
+$divide-line-color : #e5e5e5;
+
+// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像
+// nvue 页面不支持修改头像大小
+$avatar-width : 45px ;
+
+// 头像边框
+$avatar-border-radius: 5px;
+$avatar-border-color: #eee;
+$avatar-border-width: 1px;
+
+// 标题文字样式
+$title-size : 16px;
+$title-color : #3b4144;
+$title-weight : normal;
+
+// 描述文字样式
+$note-size : 12px;
+$note-color : #999;
+$note-weight : normal;
+
+// 右侧额外内容默认样式
+$right-text-size : 12px;
+$right-text-color : #999;
+$right-text-weight : normal;
+
+// 角标样式
+// nvue 页面不支持修改圆点位置以及大小
+// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
+$badge-left: 0px;
+$badge-top: 0px;
+
+// 显示圆点时,圆点大小
+$dot-width: 10px;
+$dot-height: 10px;
+
+// 显示角标时,角标大小和字体大小
+$badge-size : 18px;
+$badge-font : 12px;
+// 显示角标时,角标前景色
+$badge-color : #fff;
+// 显示角标时,角标背景色
+$badge-background-color : #ff5a5f;
+// 显示角标时,角标左右间距
+$badge-space : 6px;
+
+// 状态样式
+// 选中颜色
+$hover : #f5f5f5;

+ 593 - 0
shop/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue

@@ -0,0 +1,593 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick">
+			<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
+			<view class="uni-list-chat__container">
+				<view class="uni-list-chat__header-warp">
+					<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
+						<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
+					</view>
+					<!-- 头像组 -->
+					<view v-else class="uni-list-chat__header">
+						<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
+						 :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
+							<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
+							 mode="aspectFill"></image>
+						</view>
+					</view>
+				</view>
+				<!-- #ifndef APP -->
+				<view class="slot-header">
+				<!-- #endif -->
+					<slot name="header"></slot>
+				<!-- #ifndef APP -->
+				</view>
+				<!-- #endif -->
+				<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
+					<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+				</view>
+				<view class="uni-list-chat__content">
+					<view class="uni-list-chat__content-main">
+						<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
+						<view style="flex-direction: row;">
+							<text class="draft" v-if="isDraft">[草稿]</text>
+							<text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14):note}}</text>
+						</view>
+					</view>
+					<view class="uni-list-chat__content-extra">
+						<slot>
+							<text class="uni-list-chat__content-extra-text">{{ time }}</text>
+							<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
+								<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+							</view>
+						</slot>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	// 头像大小
+	const avatarWidth = 45;
+
+	/**
+	 * ListChat 聊天列表
+	 * @description 聊天列表,用于创建聊天类列表
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈,默认为false
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String}  	badgePositon = [left|right]		角标位置,默认为 right
+	 * @property {String} 	link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false
+	 *  @value false	 	不开启
+	 *  @value navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {String} 	time							右侧时间显示
+	 * @property {Boolean} 	avatarCircle = [true|false]		是否显示圆形头像,默认为false
+	 * @property {String} 	avatar							头像地址,avatarCircle 不填时生效
+	 * @property {Array} 	avatarList 						头像组,格式为 [{url:''}]
+	 * @event {Function} 	click 							点击 uniListChat 触发事件
+	 */
+	export default {
+		name: 'UniListChat',
+		emits:['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			badgeText: {
+				type: [String, Number],
+				default: ''
+			},
+			badgePositon: {
+				type: String,
+				default: 'right'
+			},
+			time: {
+				type: String,
+				default: ''
+			},
+			avatarCircle: {
+				type: Boolean,
+				default: false
+			},
+			avatar: {
+				type: String,
+				default: ''
+			},
+			avatarList: {
+				type: Array,
+				default () {
+					return [];
+				}
+			}
+		},
+		// inject: ['list'],
+		computed: {
+			isDraft(){
+				return this.note.slice(0,14) == '[uni-im-draft]'
+			},
+			isSingle() {
+				if (this.badgeText === 'dot') {
+					return 'uni-badge--dot';
+				} else {
+					const badgeText = this.badgeText.toString();
+					if (badgeText.length > 1) {
+						return 'uni-badge--complex';
+					} else {
+						return 'uni-badge--single';
+					}
+				}
+			},
+			computedAvatar() {
+				if (this.avatarList.length > 4) {
+					this.imageWidth = avatarWidth * 0.31;
+					return 'avatarItem--3';
+				} else if (this.avatarList.length > 1) {
+					this.imageWidth = avatarWidth * 0.47;
+					return 'avatarItem--2';
+				} else {
+					this.imageWidth = avatarWidth;
+					return 'avatarItem--1';
+				}
+			}
+		},
+		watch: {
+			avatar:{
+				handler(avatar) {
+					if(avatar.substr(0,8) == 'cloud://'){
+						uniCloud.getTempFileURL({
+							fileList: [avatar]
+						}).then(res=>{
+							// console.log(res);
+							// 兼容uniCloud私有化部署
+							let fileList = res.fileList || res.result.fileList
+							this.avatarUrl = fileList[0].tempFileURL
+						})
+					}else{
+						this.avatarUrl = avatar
+					}
+				},
+				immediate: true
+			}
+		},
+		data() {
+			return {
+				isFirstChild: false,
+				border: true,
+				// avatarList: 3,
+				imageWidth: 50,
+				avatarUrl:''
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+				this.border = this.list.border;
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				let callback = {
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+					}
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+					uni.navigateTo(callback)
+				}
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-font-size-lg:16px;
+	$uni-spacing-row-sm: 5px;
+	$uni-spacing-row-base: 10px;
+	$uni-spacing-row-lg: 15px;
+	$background-color: #fff;
+	$divide-line-color: #e5e5e5;
+	$avatar-width: 45px;
+	$avatar-border-radius: 5px;
+	$avatar-border-color: #eee;
+	$avatar-border-width: 1px;
+	$title-size: 16px;
+	$title-color: #3b4144;
+	$title-weight: normal;
+	$note-size: 12px;
+	$note-color: #999;
+	$note-weight: normal;
+	$right-text-size: 12px;
+	$right-text-color: #999;
+	$right-text-weight: normal;
+	$badge-left: 0px;
+	$badge-top: 0px;
+	$dot-width: 10px;
+	$dot-height: 10px;
+	$badge-size: 18px;
+	$badge-font: 12px;
+	$badge-color: #fff;
+	$badge-background-color: #ff5a5f;
+	$badge-space: 6px;
+	$hover: #f5f5f5;
+
+	.uni-list-chat {
+		font-size: $uni-font-size-lg;
+		position: relative;
+		flex-direction: column;
+		justify-content: space-between;
+		background-color: $background-color;
+	}
+
+	// .uni-list-chat--disabled {
+	// 	opacity: 0.3;
+	// }
+
+	.uni-list-chat--hover {
+		background-color: $hover;
+	}
+
+	.uni-list--border {
+		position: relative;
+		margin-left: $uni-spacing-row-lg;
+		/* #ifdef APP-PLUS */
+		border-top-color: $divide-line-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $divide-line-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+
+	.uni-list-chat--first {
+		border-top-width: 0px;
+	}
+
+	.uni-ellipsis {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+	}
+
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		/* #endif */
+	}
+
+	.uni-list-chat__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		padding: $uni-spacing-row-base $uni-spacing-row-lg;
+		position: relative;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-warp {
+		position: relative;
+	}
+
+	.uni-list-chat__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		align-content: center;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		flex-wrap: wrap-reverse;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+
+		border-radius: $avatar-border-radius;
+		border-color: $avatar-border-color;
+		border-width: $avatar-border-width;
+		border-style: solid;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-box {
+		/* #ifndef APP-PLUS */
+		box-sizing: border-box;
+		display: flex;
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		overflow: hidden;
+		border-radius: 2px;
+	}
+
+	.uni-list-chat__header-image {
+		margin: 1px;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list-chat__header-image {
+		display: block;
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--1 {
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--2 {
+		width: 47%;
+		height: 47%;
+	}
+
+	.avatarItem--3 {
+		width: 32%;
+		height: 32%;
+	}
+
+	/* #endif */
+	.header--circle {
+		border-radius: 50%;
+	}
+
+	.uni-list-chat__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		overflow: hidden;
+		padding: 2px 0;
+	}
+
+	.uni-list-chat__content-main {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		padding-left: $uni-spacing-row-base;
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__content-title {
+		font-size: $title-size;
+		color: $title-color;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+
+	.draft ,.uni-list-chat__content-note {
+		margin-top: 3px;
+		color: $note-color;
+		font-size: $note-size;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+	.draft{
+		color: #eb3a41;
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		/* #endif */
+		padding-right: 3px;
+	}
+
+	.uni-list-chat__content-extra {
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: flex-end;
+		margin-left: 5px;
+	}
+
+	.uni-list-chat__content-extra-text {
+		color: $right-text-color;
+		font-size: $right-text-size;
+		font-weight: $right-text-weight;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__badge-pos {
+		position: absolute;
+		/* #ifdef APP-NVUE */
+		left: 55px;
+		top: 3px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
+		top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
+		/* #endif */
+	}
+
+	.uni-list-chat__badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		border-radius: 100px;
+		background-color: $badge-background-color;
+	}
+
+	.uni-list-chat__badge-text {
+		color: $badge-color;
+		font-size: $badge-font;
+	}
+
+	.uni-badge--single {
+		/* #ifndef APP-NVUE */
+		// left: calc(#{$avatar-width} + 7px + #{$badge-left});
+		/* #endif */
+		width: $badge-size;
+		height: $badge-size;
+	}
+
+	.uni-badge--complex {
+		/* #ifdef APP-NVUE */
+		left: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: auto;
+		/* #endif */
+		height: $badge-size;
+		padding: 0 $badge-space;
+	}
+
+	.uni-badge--dot {
+		/* #ifdef APP-NVUE */
+		left: 60px;
+		top: 6px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
+		/* #endif */
+		width: $dot-width;
+		height: $dot-height;
+		padding: 0;
+	}
+
+	.uni-list-chat--right {
+		/* #ifdef APP-NVUE */
+		left: 0;
+		/* #endif */
+	}
+</style>

+ 534 - 0
shop/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue

@@ -0,0 +1,534 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell :keep-scroll-position="keepScrollPosition">
+		<!-- #endif -->
+		<view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
+			:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
+			class="uni-list-item" @click="onClick">
+			<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
+			<view class="uni-list-item__container"
+				:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
+				:style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
+				<slot name="header">
+					<view class="uni-list-item__header">
+						<view v-if="thumb" class="uni-list-item__icon">
+							<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
+						</view>
+						<view v-else-if="showExtraIcon" class="uni-list-item__icon">
+							<uni-icons :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
+						</view>
+					</view>
+				</slot>
+				<slot name="body">
+					<view class="uni-list-item__content"
+						:class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
+						<text v-if="title" class="uni-list-item__content-title"
+							:class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
+						<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
+					</view>
+				</slot>
+				<slot name="footer">
+					<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
+						:class="{ 'flex--justify': direction === 'column' }">
+						<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
+						<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
+						<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
+							@change="onSwitchChange" />
+					</view>
+				</slot>
+			</view>
+			<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * ListItem 列表子组件
+	 * @description 列表子组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {String} 	thumb 							左侧缩略图,若thumb有值,则不会显示扩展图标
+	 * @property {String}  	thumbSize = [lg|base|sm]		略缩图大小
+	 * 	@value 	 lg			大图
+	 * 	@value 	 base		一般
+	 * 	@value 	 sm			小图
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String} 	badgeType 						数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
+	 * @property {Object}   badgeStyle           数字角标样式
+	 * @property {String} 	rightText 						右侧文字内容
+	 * @property {Boolean} 	disabled = [true|false]			是否禁用
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈
+	 * @property {String} 	link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
+	 *  @value 	navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {Boolean} 	showBadge = [true|false] 		是否显示数字角标
+	 * @property {Boolean} 	showSwitch = [true|false] 		是否显示Switch
+	 * @property {Boolean} 	switchChecked = [true|false] 	Switch是否被选中
+	 * @property {Boolean} 	showExtraIcon = [true|false] 	左侧是否显示扩展图标
+	 * @property {Object} 	extraIcon 						扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
+	 * @property {String} 	direction = [row|column]		排版方向
+	 * @value row 			水平排列
+	 * @value column 		垂直排列
+	 * @event {Function} 	click 							点击 uniListItem 触发事件
+	 * @event {Function} 	switchChange 					点击切换 Switch 时触发
+	 */
+	export default {
+		name: 'UniListItem',
+		emits: ['click', 'switchChange'],
+		props: {
+			direction: {
+				type: String,
+				default: 'row'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			ellipsis: {
+				type: [Number, String],
+				default: 0
+			},
+			disabled: {
+				type: [Boolean, String],
+				default: false
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			showArrow: {
+				type: [Boolean, String],
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			showBadge: {
+				type: [Boolean, String],
+				default: false
+			},
+			showSwitch: {
+				type: [Boolean, String],
+				default: false
+			},
+			switchChecked: {
+				type: [Boolean, String],
+				default: false
+			},
+			badgeText: {
+				type: String,
+				default: ''
+			},
+			badgeType: {
+				type: String,
+				default: 'success'
+			},
+			badgeStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			rightText: {
+				type: String,
+				default: ''
+			},
+			thumb: {
+				type: String,
+				default: ''
+			},
+			thumbSize: {
+				type: String,
+				default: 'base'
+			},
+			showExtraIcon: {
+				type: [Boolean, String],
+				default: false
+			},
+			extraIcon: {
+				type: Object,
+				default () {
+					return {
+						type: '',
+						color: '#000000',
+						size: 20,
+						customPrefix: ''
+					};
+				}
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {
+						padding: '',
+						backgroundColor: '#FFFFFF'
+					}
+				}
+			},
+			keepScrollPosition: {
+				type: Boolean,
+				default: false
+			}
+		},
+		watch: {
+			'customStyle.padding': {
+				handler(padding) {
+					if(typeof padding == 'number'){
+						padding += ''
+					}
+					let paddingArr = padding.split(' ')
+					if (paddingArr.length === 1) {
+						const allPadding = paddingArr[0]
+						this.padding = {
+							"top": allPadding,
+							"right": allPadding,
+							"bottom": allPadding,
+							"left": allPadding
+						}
+					} else if (paddingArr.length === 2) {
+						const [verticalPadding, horizontalPadding] = paddingArr;
+						this.padding = {
+							"top": verticalPadding,
+							"right": horizontalPadding,
+							"bottom": verticalPadding,
+							"left": horizontalPadding
+						}
+					} else if (paddingArr.length === 4) {
+							const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
+							this.padding = {
+								"top": topPadding,
+								"right": rightPadding,
+								"bottom": bottomPadding,
+								"left": leftPadding
+							}
+					}
+				},
+				immediate: true
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				padding: {
+					top: "",
+					right: "",
+					bottom: "",
+					left: ""
+				}
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			// 判断是否存在 uni-list 组件
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			onSwitchChange(e) {
+				this.$emit('switchChange', e.detail);
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				let callback = {
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+					}
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+						uni.navigateTo(callback)
+				}
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-font-size-sm:12px;
+	$uni-font-size-base:14px;
+	$uni-font-size-lg:16px;
+	$uni-spacing-col-lg: 12px;
+	$uni-spacing-row-lg: 15px;
+	$uni-img-size-sm:20px;
+	$uni-img-size-base:26px;
+	$uni-img-size-lg:40px;
+	$uni-border-color:#e5e5e5;
+	$uni-bg-color-hover:#f1f1f1;
+	$uni-text-color-grey:#999;
+	$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+
+	.uni-list-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		font-size: $uni-font-size-lg;
+		position: relative;
+		justify-content: space-between;
+		align-items: center;
+		background-color: #fff;
+		flex-direction: row;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-list-item--disabled {
+		opacity: 0.3;
+	}
+
+	.uni-list-item--hover {
+		background-color: $uni-bg-color-hover !important;
+	}
+
+	.uni-list-item__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: $list-item-pd;
+		padding-left: $uni-spacing-row-lg;
+		flex: 1;
+		overflow: hidden;
+		// align-items: center;
+	}
+
+	.container--right {
+		padding-right: 0;
+	}
+
+	// .border--left {
+	// 	margin-left: $uni-spacing-row-lg;
+	// }
+	.uni-list--border {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+
+	/* #endif */
+	.uni-list-item__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding-right: 8px;
+		flex: 1;
+		color: #3b4144;
+		// overflow: hidden;
+		flex-direction: column;
+		justify-content: space-between;
+		overflow: hidden;
+	}
+
+	.uni-list-item__content--center {
+		justify-content: center;
+	}
+
+	.uni-list-item__content-title {
+		font-size: $uni-font-size-base;
+		color: #3b4144;
+		overflow: hidden;
+	}
+
+	.uni-list-item__content-note {
+		margin-top: 6rpx;
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+		overflow: hidden;
+	}
+
+	.uni-list-item__extra {
+		// width: 25%;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-list-item__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-list-item__icon {
+		margin-right: 18rpx;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-list-item__icon-img {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+		margin-right: 10px;
+	}
+
+	.uni-icon-wrapper {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		padding: 0 10px;
+	}
+
+	.flex--direction {
+		flex-direction: column;
+		/* #ifndef APP-NVUE */
+		align-items: initial;
+		/* #endif */
+	}
+
+	.flex--justify {
+		/* #ifndef APP-NVUE */
+		justify-content: initial;
+		/* #endif */
+	}
+
+	.uni-list--lg {
+		height: $uni-img-size-lg;
+		width: $uni-img-size-lg;
+	}
+
+	.uni-list--base {
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+	}
+
+	.uni-list--sm {
+		height: $uni-img-size-sm;
+		width: $uni-img-size-sm;
+	}
+
+	.uni-list-item__extra-text {
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+	}
+
+	.uni-ellipsis-1 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+</style>

+ 123 - 0
shop/uni_modules/uni-list/components/uni-list/uni-list.vue

@@ -0,0 +1,123 @@
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view class="uni-list uni-border-top-bottom">
+		<view v-if="border" class="uni-list--border-top"></view>
+		<slot />
+		<view v-if="border" class="uni-list--border-bottom"></view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
+		loadmoreoffset="15">
+		<slot />
+	</list>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * List 列表
+	 * @description 列表组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	border = [true|false] 		标题
+	 */
+	export default {
+		name: 'uniList',
+		'mp-weixin': {
+			options: {
+				multipleSlots: false
+			}
+		},
+		props: {
+			stackFromEnd:{
+				type: Boolean,
+				default:false
+			},
+			enableBackToTop: {
+				type: [Boolean, String],
+				default: false
+			},
+			scrollY: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			renderReverse:{
+				type: Boolean,
+				default: false
+			}
+		},
+		// provide() {
+		// 	return {
+		// 		list: this
+		// 	};
+		// },
+		created() {
+			this.firstChildAppend = false;
+		},
+		methods: {
+			loadMore(e) {
+				this.$emit('scrolltolower');
+			},
+			scroll(e) {
+				this.$emit('scroll', e);
+			}
+		}
+	};
+</script>
+<style lang="scss">
+	$uni-bg-color:#ffffff;
+	$uni-border-color:#e5e5e5;
+
+	.uni-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		background-color: $uni-bg-color;
+		position: relative;
+		flex-direction: column;
+	}
+
+	.uni-list--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		border-bottom-color: $uni-border-color;
+		border-bottom-style: solid;
+		border-bottom-width: 0.5px;
+		/* #endif */
+		z-index: -1;
+	}
+
+	/* #ifndef APP-NVUE */
+
+	.uni-list--border-top {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+		z-index: 1;
+	}
+
+	.uni-list--border-bottom {
+		position: absolute;
+		bottom: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+
+	/* #endif */
+</style>

+ 65 - 0
shop/uni_modules/uni-list/components/uni-list/uni-refresh.vue

@@ -0,0 +1,65 @@
+<template>
+    <!-- #ifdef APP-NVUE -->
+    <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
+        <slot />
+    </refresh>
+    <!-- #endif -->
+    <!-- #ifndef APP-NVUE -->
+    <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
+        <slot />
+    </view>
+    <!-- #endif -->
+</template>
+
+<script>
+    export default {
+        name: 'UniRefresh',
+        props: {
+            display: {
+                type: [String],
+                default: "hide"
+            }
+        },
+        data() {
+            return {
+                pulling: false
+            }
+        },
+        computed: {
+            isShow() {
+                if (this.display === "show" || this.pulling === true) {
+                    return true;
+                }
+                return false;
+            }
+        },
+        created() {},
+        methods: {
+            onchange(value) {
+                this.pulling = value;
+            },
+            onrefresh(e) {
+                this.$emit("refresh", e);
+            },
+            onpullingdown(e) {
+                // #ifdef APP-NVUE
+                this.$emit("pullingdown", e);
+                // #endif
+                // #ifndef APP-NVUE
+                var detail = {
+                    viewHeight: 90,
+                    pullingDistance: e.height
+                }
+                this.$emit("pullingdown", detail);
+                // #endif
+            }
+        }
+    }
+</script>
+
+<style>
+    .uni-refresh {
+        height: 0;
+        overflow: hidden;
+    }
+</style>

+ 87 - 0
shop/uni_modules/uni-list/components/uni-list/uni-refresh.wxs

@@ -0,0 +1,87 @@
+var pullDown = {
+    threshold: 95,
+    maxHeight: 200,
+    callRefresh: 'onrefresh',
+    callPullingDown: 'onpullingdown',
+    refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+    var state = instance.getState()
+    state.canPullDown = newValue;
+    // console.log(newValue);
+}
+
+function touchStart(e, instance) {
+    var state = instance.getState();
+    state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+    state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+    if (!state.canPullDown) {
+        return
+    }
+
+    // console.log("touchStart");
+
+    state.height = 0;
+    state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    state.refreshInstance.setStyle({
+        'height': 0
+    });
+    state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+    var instance = e.instance;
+    var state = instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    var oldHeight = state.height;
+    var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    var height = endY - state.touchStartY;
+    if (height > pullDown.maxHeight) {
+        return;
+    }
+
+    var refreshInstance = state.refreshInstance;
+    refreshInstance.setStyle({
+        'height': height + 'px'
+    });
+
+    height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+    state.height = height;
+    refreshInstance.callMethod(pullDown.callPullingDown, {
+        height: height
+    });
+}
+
+function touchEnd(e, ownerInstance) {
+    var state = e.instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    state.refreshInstance.callMethod("onchange", false);
+
+    var refreshInstance = state.refreshInstance;
+    if (state.height > pullDown.threshold) {
+        refreshInstance.callMethod(pullDown.callRefresh);
+        return;
+    }
+
+    refreshInstance.setStyle({
+        'height': 0
+    });
+}
+
+function propObserver(newValue, oldValue, instance) {
+    pullDown = newValue;
+}
+
+module.exports = {
+    touchmove: touchMove,
+    touchstart: touchStart,
+    touchend: touchEnd,
+    propObserver: propObserver
+}

+ 88 - 0
shop/uni_modules/uni-list/package.json

@@ -0,0 +1,88 @@
+{
+  "id": "uni-list",
+  "displayName": "uni-list 列表",
+  "version": "1.2.14",
+  "description": "List 组件 ,帮助使用者快速构建列表。",
+  "keywords": [
+    "",
+    "uni-ui",
+    "uniui",
+    "列表",
+    "",
+    "list"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [
+      "uni-badge",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 346 - 0
shop/uni_modules/uni-list/readme.md

@@ -0,0 +1,346 @@
+## List 列表
+> **组件名:uni-list**
+> 代码块: `uList`、`uListItem`
+> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad`
+
+
+List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。
+
+在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。
+
+uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。
+
+uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。
+
+内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。
+
+涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。
+
+下文均有样例给出。
+
+uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29)
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件
+> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item`
+> - 只有开启点击反馈后,会有点击选中效果
+> - 使用插槽时,可以完全自定义内容
+> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展
+> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译
+> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义
+> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli`
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+ 
+
+### 基本用法 
+
+- 设置 `title` 属性,可以显示列表标题
+- 设置 `disabled` 属性,可以禁用当前项
+
+```html
+<uni-list>
+	<uni-list-item  title="列表文字" ></uni-list-item>
+	<uni-list-item :disabled="true" title="列表禁用状态" ></uni-list-item>
+</uni-list>
+			 
+```
+
+### 多行内容显示
+
+- 设置 `note` 属性 ,可以在第二行显示描述文本信息
+
+```html
+<uni-list>
+	<uni-list-item title="列表文字" note="列表描述信息"></uni-list-item>
+	<uni-list-item :disabled="true" title="列表文字" note="列表禁用状态"></uni-list-item>
+</uni-list>
+
+```
+
+### 右侧显示角标、switch
+
+- 设置 `show-badge` 属性 ,可以显示角标内容
+- 设置 `show-switch` 属性,可以显示 switch 开关
+
+```html
+<uni-list>
+	<uni-list-item  title="列表右侧显示角标" :show-badge="true" badge-text="12" ></uni-list-item>
+	<uni-list-item title="列表右侧显示 switch"  :show-switch="true"  @switchChange="switchChange" ></uni-list-item>
+</uni-list>
+
+```
+
+### 左侧显示略缩图、图标  
+
+- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图
+- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标
+
+```html
+ <uni-list>
+ 	<uni-list-item title="列表左侧带略缩图" note="列表描述信息" thumb="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png"
+ 	 thumb-size="lg" rightText="右侧文字"></uni-list-item>
+ 	<uni-list-item :show-extra-icon="true" :extra-icon="extraIcon1" title="列表左侧带扩展图标" ></uni-list-item>
+</uni-list>
+```
+
+### 开启点击反馈和右侧箭头
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头
+- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+
+```html
+
+<uni-list>
+	<uni-list-item title="开启点击反馈" clickable  @click="onClick" ></uni-list-item>
+	<uni-list-item title="默认 navigateTo 方式跳转页面" link to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+	<uni-list-item title="reLaunch 方式跳转页面" link="reLaunch" to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+</uni-list>
+
+```
+
+
+### 聊天列表示例
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+- 设置 `to` 属性,可以跳转页面
+- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示
+- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效
+- 可以通过默认插槽自定义列表右侧内容
+
+```html
+
+<uni-list>
+	<uni-list :border="true">
+		<!-- 显示圆形头像 -->
+		<uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat>
+		<!-- 右侧带角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12" :badge-style="{backgroundColor:'#FF80AB'}"></uni-list-chat>
+		<!-- 头像显示圆点 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 头像显示角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="99"></uni-list-chat>
+		<!-- 显示多头像 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 自定义右侧内容 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot">
+			<view class="chat-custom-right">
+				<text class="chat-custom-text">刚刚</text>
+				<!-- 需要使用 uni-icons 请自行引入 -->
+				<uni-icons type="star-filled" color="#999" size="18"></uni-icons>
+			</view>
+		</uni-list-chat>
+	</uni-list>
+</uni-list>
+
+```
+
+```javascript
+
+export default {
+	components: {},
+	data() {
+		return {
+			avatarList: [{
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}]
+		}
+	}
+}
+
+```
+
+
+```css
+
+.chat-custom-right {
+	flex: 1;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: column;
+	justify-content: space-between;
+	align-items: flex-end;
+}
+
+.chat-custom-text {
+	font-size: 12px;
+	color: #999;
+}
+
+```
+
+## API
+
+### List Props
+
+属性名			|类型		|默认值		|	说明																									
+:-:				|:-:		|:-:		|	:-:	
+border			|Boolean	|true		|	是否显示边框
+
+
+### ListItem Props
+
+属性名			|类型		|默认值		|	说明																					
+:-:				|:-:		|:-:		|	:-:	
+title			|String		|-			|	标题
+note			|String		|-			|	描述
+ellipsis		|Number		|0			|	title 是否溢出隐藏,可选值,0:默认;  1:显示一行;	2:显示两行;【nvue 暂不支持】
+thumb			|String		|-			|	左侧缩略图,若thumb有值,则不会显示扩展图标
+thumbSize		|String 	|medium 	|	略缩图尺寸,可选值,lg:大图;  medium:一般;	sm:小图;
+showBadge		|Boolean	|false		|	是否显示数字角标	
+badgeText		|String		|-			|	数字角标内容
+badgeType		|String		|-			|	数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)	
+badgeStyle  |Object   |-      | 数字角标样式,使用uni-badge的custom-style参数
+rightText		|String		|-			|	右侧文字内容
+disabled		|Boolean	|false		|	是否禁用	
+showArrow 		|Boolean	|true		|	是否显示箭头图标			
+link			|String 	|navigateTo	|	新页面跳转方式,可选值见下表
+to				|String		|-			|	新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功			
+clickable		|Boolean	|false		|	是否开启点击反馈
+showSwitch	    |Boolean	|false		|	是否显示Switch																			
+switchChecked	|Boolean	|false		|	Switch是否被选中																			
+showExtraIcon   |Boolean	|false		|	左侧是否显示扩展图标																		
+extraIcon		|Object		|-			|	扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28)	
+direction		| String	|row		|	排版方向,可选值,row:水平排列;  column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制
+
+
+#### Link Options
+
+属性名				|	说明
+:-:					|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch		|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItem Events
+
+事件称名			|说明									|返回参数			
+:-:				|:-:									|:-:				
+click			|点击 uniListItem 触发事件,需开启点击反馈	|-					
+switchChange	|点击切换 Switch 时触发,需显示 switch		|e={value:checked}	
+
+
+
+### ListItem Slots
+
+名称	 	|	说明					
+:-:		|	:-:						
+header	|	左/上内容插槽,可完全自定义默认显示
+body	|	中间内容插槽,可完全自定义中间内容				
+footer	|	右/下内容插槽,可完全自定义右侧内容		
+
+
+> **通过插槽扩展**
+> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现
+> 如果	`uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。
+> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer`
+> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分
+> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分
+> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。
+
+	
+**示例**
+
+```html
+<uni-list>
+	<uni-list-item title="自定义右侧插槽" note="列表描述信息" link>
+		<template slot="header">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+	<uni-list-item>
+		<!-- 自定义 header -->
+		<view slot="header" class="slot-box"><image class="slot-image" src="/static/logo.png" mode="widthFix"></image></view>
+		<!-- 自定义 body -->
+		<text slot="body" class="slot-box slot-text">自定义插槽</text>
+		<!-- 自定义 footer-->
+		<template slot="footer">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+</uni-list>
+```
+
+
+
+
+
+### ListItemChat Props
+
+属性名			|类型		|默认值		|	说明																		
+:-:				|:-:		|:-:		|	:-:	
+title 			|String		|-			|	标题
+note 			|String		|-			|	描述
+clickable		|Boolean	|false		|	是否开启点击反馈
+badgeText		|String		|-			|	数字角标内容,设置为 `dot` 将显示圆点
+badgePositon 	|String		|right		|	角标位置
+link			|String 	|navigateTo	|	是否展示右侧箭头并开启点击反馈,可选值见下表
+clickable		|Boolean	|false		|	是否开启点击反馈
+to				|String		|-			|	跳转页面地址,如填写此属性,click 会返回页面是否跳转成功	
+time			|String 	|-			|	右侧时间显示
+avatarCircle 	|Boolean 	|false		|	是否显示圆形头像
+avatar			|String 	|-			|	头像地址,avatarCircle 不填时生效
+avatarList 		|Array	 	|-			|	头像组,格式为 [{url:''}]
+
+#### Link Options
+
+属性名		|	说明
+:-:			|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch	|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItemChat Slots
+
+名称	 	|	说明					
+:-		|	:-						
+default	|	自定义列表右侧内容(包括时间和角标显示)
+
+### ListItemChat Events
+事件称名			|	说明						|	返回参数			
+:-:				|	:-:						|	:-:	
+@click			|	点击 uniListChat 触发事件	|	{data:{}}	,如有 to 属性,会返回页面跳转信息	
+
+
+
+
+
+
+## 基于uni-list扩展的页面模板
+
+通过扩展插槽,可实现多种常见样式的列表
+
+**新闻列表类**
+
+1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546)
+2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583)
+3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584)
+4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585)
+5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586)
+6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587)
+7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588)
+
+**商品列表类**
+
+1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651)
+2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671)
+3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672)
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list)

+ 19 - 0
shop/uni_modules/uni-load-more/changelog.md

@@ -0,0 +1,19 @@
+## 1.3.3(2022-01-20)
+- 新增 showText属性 ,是否显示文本
+## 1.3.2(2022-01-19)
+- 修复 nvue 平台下不显示文本的bug
+## 1.3.1(2022-01-19)
+- 修复 微信小程序平台样式选择器报警告的问题
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+## 1.2.1(2021-08-24)
+- 新增 支持国际化
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8(2021-05-12)
+- 新增 组件示例地址
+## 1.1.7(2021-03-30)
+- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug
+## 1.1.6(2021-02-05)
+- 调整为uni_modules目录规范

+ 5 - 0
shop/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "Pull up to show more",
+	"uni-load-more.contentrefresh": "loading...",
+	"uni-load-more.contentnomore": "No more data"
+}

+ 8 - 0
shop/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js

@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 5 - 0
shop/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉显示更多",
+	"uni-load-more.contentrefresh": "正在加载...",
+	"uni-load-more.contentnomore": "没有更多数据了"
+}

+ 5 - 0
shop/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉顯示更多",
+	"uni-load-more.contentrefresh": "正在加載...",
+	"uni-load-more.contentnomore": "沒有更多數據了"
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 112 - 0
shop/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue


+ 86 - 0
shop/uni_modules/uni-load-more/package.json

@@ -0,0 +1,86 @@
+{
+  "id": "uni-load-more",
+  "displayName": "uni-load-more 加载更多",
+  "version": "1.3.3",
+  "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "加载更多",
+    "load-more"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 14 - 0
shop/uni_modules/uni-load-more/readme.md

@@ -0,0 +1,14 @@
+
+
+### LoadMore 加载更多
+> **组件名:uni-load-more**
+> 代码块: `uLoadMore`
+
+
+用于列表中,做滚动加载使用,展示 loading 的各种状态。
+
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+

+ 8 - 0
shop/uni_modules/uni-scss/changelog.md

@@ -0,0 +1,8 @@
+## 1.0.3(2022-01-21)
+- 优化 组件示例
+## 1.0.2(2021-11-22)
+- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
+## 1.0.1(2021-11-22)
+- 修复 vue3中scss语法兼容问题
+## 1.0.0(2021-11-18)
+- init

+ 1 - 0
shop/uni_modules/uni-scss/index.scss

@@ -0,0 +1 @@
+@import './styles/index.scss';

+ 82 - 0
shop/uni_modules/uni-scss/package.json

@@ -0,0 +1,82 @@
+{
+  "id": "uni-scss",
+  "displayName": "uni-scss 辅助样式",
+  "version": "1.0.3",
+  "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。",
+  "keywords": [
+    "uni-scss",
+    "uni-ui",
+    "辅助样式"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "category": [
+        "JS SDK",
+        "通用 SDK"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "n",
+          "联盟": "n"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 4 - 0
shop/uni_modules/uni-scss/readme.md

@@ -0,0 +1,4 @@
+`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 

+ 7 - 0
shop/uni_modules/uni-scss/styles/index.scss

@@ -0,0 +1,7 @@
+@import './setting/_variables.scss';
+@import './setting/_border.scss';
+@import './setting/_color.scss';
+@import './setting/_space.scss';
+@import './setting/_radius.scss';
+@import './setting/_text.scss';
+@import './setting/_styles.scss';

+ 3 - 0
shop/uni_modules/uni-scss/styles/setting/_border.scss

@@ -0,0 +1,3 @@
+.uni-border {
+	border: 1px $uni-border-1 solid;
+}

+ 66 - 0
shop/uni_modules/uni-scss/styles/setting/_color.scss

@@ -0,0 +1,66 @@
+
+// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
+// @mixin get-styles($k,$c) {
+// 	@if $k == size or $k == weight{
+// 		font-#{$k}:#{$c}
+// 	}@else{
+// 		#{$k}:#{$c}
+// 	}
+// }
+$uni-ui-color:(
+	// 主色
+	primary: $uni-primary,
+	primary-disable: $uni-primary-disable,
+	primary-light: $uni-primary-light,
+	// 辅助色
+	success: $uni-success,
+	success-disable: $uni-success-disable,
+	success-light: $uni-success-light,
+	warning: $uni-warning,
+	warning-disable: $uni-warning-disable,
+	warning-light: $uni-warning-light,
+	error: $uni-error,
+	error-disable: $uni-error-disable,
+	error-light: $uni-error-light,
+	info: $uni-info,
+	info-disable: $uni-info-disable,
+	info-light: $uni-info-light,
+	// 中性色
+	main-color: $uni-main-color,
+	base-color: $uni-base-color,
+	secondary-color: $uni-secondary-color,
+	extra-color: $uni-extra-color,
+	// 背景色
+	bg-color: $uni-bg-color,
+	// 边框颜色
+	border-1: $uni-border-1,
+	border-2: $uni-border-2,
+	border-3: $uni-border-3,
+	border-4: $uni-border-4,
+	// 黑色
+	black:$uni-black,
+	// 白色
+	white:$uni-white,
+	// 透明
+	transparent:$uni-transparent
+) !default;
+@each $key, $child in $uni-ui-color {
+	.uni-#{"" + $key} {
+		color: $child;
+	}
+	.uni-#{"" + $key}-bg {
+		background-color: $child;
+	}
+}
+.uni-shadow-sm {
+	box-shadow: $uni-shadow-sm;
+}
+.uni-shadow-base {
+	box-shadow: $uni-shadow-base;
+}
+.uni-shadow-lg {
+	box-shadow: $uni-shadow-lg;
+}
+.uni-mask {
+	background-color:$uni-mask;
+}

+ 55 - 0
shop/uni_modules/uni-scss/styles/setting/_radius.scss

@@ -0,0 +1,55 @@
+@mixin radius($r,$d:null ,$important: false){
+  $radius-value:map-get($uni-radius, $r) if($important, !important, null);
+  // Key exists within the $uni-radius variable
+  @if (map-has-key($uni-radius, $r) and  $d){
+		@if $d == t {
+				border-top-left-radius:$radius-value;
+				border-top-right-radius:$radius-value;
+		}@else if $d == r {
+				border-top-right-radius:$radius-value;
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == b {
+				border-bottom-left-radius:$radius-value;
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == l {
+				border-top-left-radius:$radius-value;
+				border-bottom-left-radius:$radius-value;
+		}@else if $d == tl {
+				border-top-left-radius:$radius-value;
+		}@else if $d == tr {
+				border-top-right-radius:$radius-value;
+		}@else if $d == br {
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == bl {
+				border-bottom-left-radius:$radius-value;
+		}
+  }@else{
+		border-radius:$radius-value;
+  }
+}
+
+@each $key, $child in $uni-radius {
+	@if($key){
+		.uni-radius-#{"" + $key} {
+				@include radius($key)
+		}
+	}@else{
+		.uni-radius {
+				@include radius($key)
+		}
+	}
+}
+
+@each $direction in t, r, b, l,tl, tr, br, bl {
+	@each $key, $child in $uni-radius {
+		@if($key){
+			.uni-radius-#{"" + $direction}-#{"" + $key} {
+				@include radius($key,$direction,false)
+			}
+		}@else{
+			.uni-radius-#{$direction} {
+				@include radius($key,$direction,false)
+			}
+		}
+	}
+}

+ 56 - 0
shop/uni_modules/uni-scss/styles/setting/_space.scss

@@ -0,0 +1,56 @@
+
+@mixin fn($space,$direction,$size,$n) {
+	@if $n {
+		#{$space}-#{$direction}: #{$size*$uni-space-root}px
+	} @else {
+		 #{$space}-#{$direction}: #{-$size*$uni-space-root}px
+	}
+}
+@mixin get-styles($direction,$i,$space,$n){
+	@if $direction == t {
+		@include fn($space, top,$i,$n);
+	} 
+	@if $direction == r {
+		@include fn($space, right,$i,$n);
+	} 
+	@if $direction == b {
+		@include fn($space, bottom,$i,$n);
+	} 
+	@if $direction == l {
+	 @include fn($space, left,$i,$n);
+	} 
+	@if $direction == x {
+		@include fn($space, left,$i,$n);
+		@include fn($space, right,$i,$n);
+	} 
+	@if $direction == y {
+		@include fn($space, top,$i,$n);
+		@include fn($space, bottom,$i,$n);
+	} 
+	@if $direction == a {
+		@if $n {
+			#{$space}:#{$i*$uni-space-root}px;
+		} @else {
+			#{$space}:#{-$i*$uni-space-root}px;
+		}
+	} 
+}
+
+@each $orientation in m,p {
+	$space: margin;
+	@if $orientation == m {
+		$space: margin;
+	} @else {
+		$space: padding;
+	}
+	@for $i from 0 through 16 {
+		@each $direction in t, r, b, l, x, y, a {
+			.uni-#{$orientation}#{$direction}-#{$i} { 
+				@include  get-styles($direction,$i,$space,true);
+			} 
+			.uni-#{$orientation}#{$direction}-n#{$i} { 
+				@include  get-styles($direction,$i,$space,false);
+			}
+		}
+	}
+}

+ 167 - 0
shop/uni_modules/uni-scss/styles/setting/_styles.scss

@@ -0,0 +1,167 @@
+/* #ifndef APP-NVUE */
+
+$-color-white:#fff;
+$-color-black:#000;
+@mixin base-style($color) {
+	color: #fff;
+	background-color: $color;
+	border-color: mix($-color-black, $color, 8%);
+	&:not([hover-class]):active {
+		background: mix($-color-black, $color, 10%);
+		border-color: mix($-color-black, $color, 20%);
+		color: $-color-white;
+		outline: none;
+	}
+}
+@mixin is-color($color) {
+	@include base-style($color);
+	&[loading] {
+		@include base-style($color);
+		&::before {
+			margin-right:5px;
+		}
+	}
+	&[disabled] {
+	  &,
+		&[loading],
+	  &:not([hover-class]):active {
+	    color: $-color-white;
+			border-color: mix(darken($color,10%), $-color-white);
+	    background-color: mix($color, $-color-white);
+	  }
+	}
+
+}
+@mixin base-plain-style($color) {
+	color:$color;
+	background-color: mix($-color-white, $color, 90%);
+	border-color: mix($-color-white, $color, 70%);
+	&:not([hover-class]):active {
+	  background: mix($-color-white, $color, 80%);
+	  color: $color;
+	  outline: none;
+		border-color: mix($-color-white, $color, 50%);
+	}
+}
+@mixin is-plain($color){
+	&[plain] {
+		@include base-plain-style($color);
+		&[loading] {
+			@include base-plain-style($color);
+			&::before {
+				margin-right:5px;
+			}
+		}
+		&[disabled] {
+		  &,
+		  &:active {
+		    color: mix($-color-white, $color, 40%);
+		    background-color: mix($-color-white, $color, 90%);
+				border-color: mix($-color-white, $color, 80%);
+		  }
+		}
+	}
+}
+
+
+.uni-btn {
+	margin: 5px;
+	color: #393939;
+	border:1px solid #ccc;
+	font-size: 16px;
+	font-weight: 200;
+	background-color: #F9F9F9;
+	// TODO 暂时处理边框隐藏一边的问题
+	overflow: visible;
+	&::after{
+		border: none;
+	}
+
+	&:not([type]),&[type=default] {
+		color: #999;
+		&[loading] {
+			background: none;
+			&::before {
+				margin-right:5px;
+			}
+		}
+
+
+
+		&[disabled]{
+			color: mix($-color-white, #999, 60%);
+		  &,
+			&[loading],
+		  &:active {
+				color: mix($-color-white, #999, 60%);
+		    background-color: mix($-color-white,$-color-black , 98%);
+				border-color: mix($-color-white,  #999, 85%);
+		  }
+		}
+
+		&[plain] {
+			color: #999;
+			background: none;
+			border-color: $uni-border-1;
+			&:not([hover-class]):active {
+				background: none;
+			  color: mix($-color-white, $-color-black, 80%);
+				border-color: mix($-color-white, $-color-black, 90%);
+			  outline: none;
+			}
+			&[disabled]{
+			  &,
+				&[loading],
+			  &:active {
+			    background: none;
+					color: mix($-color-white, #999, 60%);
+					border-color: mix($-color-white,  #999, 85%);
+			  }
+			}
+		}
+	}
+
+	&:not([hover-class]):active {
+	  color: mix($-color-white, $-color-black, 50%);
+	}
+
+	&[size=mini] {
+		font-size: 16px;
+		font-weight: 200;
+		border-radius: 8px;
+	}
+
+
+
+	&.uni-btn-small {
+		font-size: 14px;
+	}
+	&.uni-btn-mini {
+		font-size: 12px;
+	}
+
+	&.uni-btn-radius {
+		border-radius: 999px;
+	}
+	&[type=primary] {
+		@include is-color($uni-primary);
+		@include is-plain($uni-primary)
+	}
+	&[type=success] {
+		@include is-color($uni-success);
+		@include is-plain($uni-success)
+	}
+	&[type=error] {
+		@include is-color($uni-error);
+		@include is-plain($uni-error)
+	}
+	&[type=warning] {
+		@include is-color($uni-warning);
+		@include is-plain($uni-warning)
+	}
+	&[type=info] {
+		@include is-color($uni-info);
+		@include is-plain($uni-info)
+	}
+}
+/* #endif */

+ 24 - 0
shop/uni_modules/uni-scss/styles/setting/_text.scss

@@ -0,0 +1,24 @@
+@mixin get-styles($k,$c) {
+	@if $k == size or $k == weight{
+		font-#{$k}:#{$c}
+	}@else{
+		#{$k}:#{$c}
+	}
+}
+
+@each $key, $child in $uni-headings {
+	/* #ifndef APP-NVUE */
+	.uni-#{$key} {
+		@each $k, $c in $child {
+			@include get-styles($k,$c)
+		}
+	}
+	/* #endif */
+	/* #ifdef APP-NVUE */
+	.container .uni-#{$key} {
+		@each $k, $c in $child {
+			@include get-styles($k,$c)
+		}
+	}
+	/* #endif */
+}

+ 146 - 0
shop/uni_modules/uni-scss/styles/setting/_variables.scss

@@ -0,0 +1,146 @@
+// @use "sass:math";
+@import  '../tools/functions.scss';
+// 间距基础倍数
+$uni-space-root: 2 !default;
+// 边框半径默认值
+$uni-radius-root:5px !default;
+$uni-radius: () !default;
+// 边框半径断点
+$uni-radius: map-deep-merge(
+  (
+    0: 0,
+		// TODO 当前版本暂时不支持 sm 属性
+    // 'sm': math.div($uni-radius-root, 2),
+    null: $uni-radius-root,
+    'lg': $uni-radius-root * 2,
+    'xl': $uni-radius-root * 6,
+    'pill': 9999px,
+    'circle': 50%
+  ),
+  $uni-radius
+);
+// 字体家族
+$body-font-family: 'Roboto', sans-serif !default;
+// 文本
+$heading-font-family: $body-font-family !default;
+$uni-headings: () !default;
+$letterSpacing: -0.01562em;
+$uni-headings: map-deep-merge(
+  (
+    'h1': (
+      size: 32px,
+			weight: 300,
+			line-height: 50px,
+			// letter-spacing:-0.01562em
+    ),
+    'h2': (
+      size: 28px,
+      weight: 300,
+      line-height: 40px,
+      // letter-spacing: -0.00833em
+    ),
+    'h3': (
+      size: 24px,
+      weight: 400,
+      line-height: 32px,
+      // letter-spacing: normal
+    ),
+    'h4': (
+      size: 20px,
+      weight: 400,
+      line-height: 30px,
+      // letter-spacing: 0.00735em
+    ),
+    'h5': (
+      size: 16px,
+      weight: 400,
+      line-height: 24px,
+      // letter-spacing: normal
+    ),
+    'h6': (
+      size: 14px,
+      weight: 500,
+      line-height: 18px,
+      // letter-spacing: 0.0125em
+    ),
+    'subtitle': (
+      size: 12px,
+      weight: 400,
+      line-height: 20px,
+      // letter-spacing: 0.00937em
+    ),
+    'body': (
+      font-size: 14px,
+			font-weight: 400,
+			line-height: 22px,
+			// letter-spacing: 0.03125em
+    ),
+    'caption': (
+      'size': 12px,
+      'weight': 400,
+      'line-height': 20px,
+      // 'letter-spacing': 0.03333em,
+      // 'text-transform': false
+    )
+  ),
+  $uni-headings
+);
+
+
+
+// 主色
+$uni-primary: #2979ff !default;
+$uni-primary-disable:lighten($uni-primary,20%) !default;
+$uni-primary-light: lighten($uni-primary,25%) !default;
+
+// 辅助色
+// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
+$uni-success: #18bc37 !default;
+$uni-success-disable:lighten($uni-success,20%) !default;
+$uni-success-light: lighten($uni-success,25%) !default;
+
+$uni-warning: #f3a73f !default;
+$uni-warning-disable:lighten($uni-warning,20%) !default;
+$uni-warning-light: lighten($uni-warning,25%) !default;
+
+$uni-error: #e43d33 !default;
+$uni-error-disable:lighten($uni-error,20%) !default;
+$uni-error-light: lighten($uni-error,25%) !default;
+
+$uni-info: #8f939c !default;
+$uni-info-disable:lighten($uni-info,20%) !default;
+$uni-info-light: lighten($uni-info,25%) !default;
+
+// 中性色
+// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
+$uni-main-color: #3a3a3a !default; 			// 主要文字
+$uni-base-color: #6a6a6a !default;			// 常规文字
+$uni-secondary-color: #909399 !default;	// 次要文字
+$uni-extra-color: #c7c7c7 !default;			// 辅助说明
+
+// 边框颜色
+$uni-border-1: #F0F0F0 !default;
+$uni-border-2: #EDEDED !default;
+$uni-border-3: #DCDCDC !default;
+$uni-border-4: #B9B9B9 !default;
+
+// 常规色
+$uni-black: #000000 !default;
+$uni-white: #ffffff !default;
+$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
+
+// 背景色
+$uni-bg-color: #f7f7f7 !default;
+
+/* 水平间距 */
+$uni-spacing-sm: 8px !default;
+$uni-spacing-base: 15px !default;
+$uni-spacing-lg: 30px !default;
+
+// 阴影
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
+
+// 蒙版
+$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;

+ 19 - 0
shop/uni_modules/uni-scss/styles/tools/functions.scss

@@ -0,0 +1,19 @@
+// 合并 map
+@function map-deep-merge($parent-map, $child-map){
+	$result: $parent-map;
+	@each $key, $child in $child-map {
+		$parent-has-key: map-has-key($result, $key);
+		$parent-value: map-get($result, $key);
+		$parent-type: type-of($parent-value);
+		$child-type: type-of($child);
+		$parent-is-map: $parent-type == map;
+		$child-is-map: $child-type == map;
+			
+		@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
+			$result: map-merge($result, ( $key: $child ));
+		}@else {
+			$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
+		}
+	}
+	@return $result;
+};

+ 31 - 0
shop/uni_modules/uni-scss/theme.scss

@@ -0,0 +1,31 @@
+// 间距基础倍数
+$uni-space-root: 2;
+// 边框半径默认值
+$uni-radius-root:5px;
+// 主色
+$uni-primary: #2979ff;
+// 辅助色
+$uni-success: #4cd964;
+// 警告色
+$uni-warning: #f0ad4e;
+// 错误色
+$uni-error: #dd524d;
+// 描述色
+$uni-info: #909399;
+// 中性色
+$uni-main-color: #303133;
+$uni-base-color: #606266;
+$uni-secondary-color: #909399;
+$uni-extra-color: #C0C4CC;
+// 背景色
+$uni-bg-color: #f5f5f5;
+// 边框颜色
+$uni-border-1: #DCDFE6;
+$uni-border-2: #E4E7ED;
+$uni-border-3: #EBEEF5;
+$uni-border-4: #F2F6FC;
+
+// 常规色
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);

+ 62 - 0
shop/uni_modules/uni-scss/variables.scss

@@ -0,0 +1,62 @@
+@import './styles/setting/_variables.scss';
+// 间距基础倍数
+$uni-space-root: 2;
+// 边框半径默认值
+$uni-radius-root:5px;
+
+// 主色
+$uni-primary: #2979ff;
+$uni-primary-disable:mix(#fff,$uni-primary,50%);
+$uni-primary-light: mix(#fff,$uni-primary,80%);
+
+// 辅助色
+// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
+$uni-success: #18bc37;
+$uni-success-disable:mix(#fff,$uni-success,50%);
+$uni-success-light: mix(#fff,$uni-success,80%);
+
+$uni-warning: #f3a73f;
+$uni-warning-disable:mix(#fff,$uni-warning,50%);
+$uni-warning-light: mix(#fff,$uni-warning,80%);
+
+$uni-error: #e43d33;
+$uni-error-disable:mix(#fff,$uni-error,50%);
+$uni-error-light: mix(#fff,$uni-error,80%);
+
+$uni-info: #8f939c;
+$uni-info-disable:mix(#fff,$uni-info,50%);
+$uni-info-light: mix(#fff,$uni-info,80%);
+
+// 中性色
+// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
+$uni-main-color: #3a3a3a; 			// 主要文字
+$uni-base-color: #6a6a6a;			// 常规文字
+$uni-secondary-color: #909399;	// 次要文字
+$uni-extra-color: #c7c7c7;			// 辅助说明
+
+// 边框颜色
+$uni-border-1: #F0F0F0;
+$uni-border-2: #EDEDED;
+$uni-border-3: #DCDCDC;
+$uni-border-4: #B9B9B9;
+
+// 常规色
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);
+
+// 背景色
+$uni-bg-color: #f7f7f7;
+
+/* 水平间距 */
+$uni-spacing-sm: 8px;
+$uni-spacing-base: 15px;
+$uni-spacing-lg: 30px;
+
+// 阴影
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
+
+// 蒙版
+$uni-mask: rgba($color: #000000, $alpha: 0.4);

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä