Commit adaf92e7 authored by Master Q's avatar Master Q

init registry

parents
node_modules
.tea
.DS_Store
.vscode
dist/
\ No newline at end of file
# 新增requestType 说明
## 背景
淘宝需求涉及下单、会员等需要跟淘宝进行强交互的需求时,目前在自测阶段只能通过服务端自测,但是对于
客户端开发的同学,此刻只能通过`yapi`这种静态数据mock的方式获取数据进行展示,其中的不足是无法与
整个业务衔接
## 目的
客户端通过像配置`yapi`那样配置风驰台开放的接口,就能模拟下单、会员等强交互的业务,且整个业务的数
据完成跟服务端实际做的一致,在自测阶段即可模拟淘宝测试环境将强交互的业务需求打通
## 配合
要做到能正常调用风驰台接口,必须服务端同学配合,可以理解成风驰台只是一个中介,真正处理业务逻辑是
在服务端同学的本地机器启动的服务上
## ☑️忽略 Webview 域名合法性检查(仅在本地模拟、预览和远程调试时生效)
具体可在`淘宝开发工具`-> 右上角`详情`-> 页面最底下
### 如何获取到`tornadoAPI`地址?
最简单的方法是:
- 直接问服务端,让其开启服务,并直接给到tornadoAPI地址
### 如何查看表数据?
- 访问地址:https://tornado.duibadev.com.cn/#/data 选择项目,您想要获取的数据均可以在`基础表`查看到
### 如何模拟下单、会员
- 访问地址:https://tornado.duibadev.com.cn/#/data 选择项目,拉到页面最底下,`淘宝api`接口等着你设置模拟数据
export class Tools {
static throttle = function (fn, delay=2000) {
let flag = true,
timer = null;
return function (...args) {
let context = this;
if(!flag) return;
flag = false;
clearTimeout(timer);
fn.apply(context, args);
timer = setTimeout(() => {
flag = true
}, delay)
}
}
static globalData = {
waitAward: {
id: 'c_awards_info',
prizeId: 'b_prize_config'
}
}
}
\ No newline at end of file
const app = getApp();
const { tbcc, cloudName, cloud, requestType } = app;
const { utils: { generateAPI }, request: tbccRequest, capi } = tbcc;
const request = tbccRequest({
cloud,
cloudName,
requestType
});
// api handle 列表
const apiList = {
...capi,
getTaskList: {
handle: 'getTaskList',
method: 'GET',
isShowLoading: false
},
receiveTaskRewards: {
handle: 'receiveTaskRewards',
method: 'GET',
isShowLoading: false
},
doCompleteTask: {
handle: 'completeTask',
method: 'GET',
isShowLoading: false
},
getCollectGoodsList: {
handle: 'getCollectGoodsList',
method: 'GET',
isShowLoading: false
},
addStats: {
handle: 'addStats',
method: 'GET',
isShowLoading: false
},
startGame: {
handle: 'startGame',
method: 'POST',
isShowLoading: true
},
getActivityBaseInfoById: {
handle: 'getActivityBaseInfoById',
method: 'POST',
isShowLoading: true
},
getVipInfo: {
handle: 'getVipInfo',
method: 'GET',
isShowLoading: false
},
login: {
handle: 'login',
method: 'GET',
isShowLoading: false
},
receiveObjectPrize: {
handle: 'receiveObjectPrize',
method: 'POST',
isShowLoading: true
},
complateGuide: {
handle: 'complateGuide',
method: 'POST',
isShowLoading: false
},
submitGame: {
handle: 'submitGame',
method: 'POST',
isShowLoading: false
},
drawLotteryPrize: {
handle: 'drawLotteryPrize',
method: 'POST',
isShowLoading: false
},
getMyShoesList: {
handle: 'getMyShoesList',
method: 'POST',
isShowLoading: true
}
};
// 生成API
const API = generateAPI(apiList, request);
export default API;
page {
background: #f7f7f7;
font-family: 'Helvetica Neue', Helvetica, Hiragino Sans GB, 'Microsoft Yahei', STHeiTi, Arial, sans-serif;
}
.scene-container {
width: 100vw;
min-height: 100vh;
position: absolute;
background-color: #f1ebdd;
}
.pointer-none {
pointer-events: none;
}
* {
box-sizing: border-box;
}
.d-flex {
display: flex
}
.d-flex__item {
flex: 1;
}
.d-flex--aligncenter {
align-items: center;
}
.modal-animate-fade-in {
opacity: 0;
animation: modalAnimateFadeIn .3s forwards;
}
.modal-animate-zoom-in {
transform: scale(0);
animation: modalAnimateZoomIn .3s forwards;
}
.modal-animate-fly-in {
transform: translateY(100%);
animation: modalAnimateFlyIn .3s forwards;
}
.btn-animate-pulse {
animation: btnAnimatePulse .8s infinite;
}
@keyframes modalAnimateFadeIn {
to {
opacity: 1;
}
}
@keyframes modalAnimateZoomIn {
to {
transform: scale(1);
}
}
@keyframes modalAnimateFlyIn {
to {
transform: translateY(0);
}
}
@keyframes btnAnimatePulse {
from {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
to {
transform: scale(1);
}
}
\ No newline at end of file
import cloud from '@tbmp/mp-cloud-sdk';
import tbcc from './tbcc-sdk';
cloud.init({
env: 'test' // 云函数环境 test 测试环境 online 线上环境
});
App({
requestType: 'cloud', // cloud: 云函数, yapi: yapi 接口, ams: ams接口,tornadoAPI: 风驰台接口
cloudName: 'yoga', // 主云函数项目名
tornadoAPI: 'https://tornado.duibadev.com.cn/tbServer/api?db=xxx&proxyIp=xxx', // 新增:当requestType: 'tornadoAPI'时,找服务端提供地址
cloud,
tbcc,
sellerId: "", // TODO sellerId
shareConfig: {
title: '李子柒暗香涌动',
desc: 'AR寻文物 赢联名螺蛳粉礼盒',
imageUrl: [
'https://img.alicdn.com/imgextra/i1/3965833216/O1CN01WF6jxU1ZcyRV8CIpT_!!3965833216-2-isvtu.png', // 普通分享
'https://img.alicdn.com/imgextra/i2/3965833216/O1CN01KdxFRc1ZcyRRQVCUh_!!3965833216-2-isvtu.png', // 卡1
'https://img.alicdn.com/imgextra/i3/3965833216/O1CN01JYD3ut1ZcyRYmZhJ1_!!3965833216-2-isvtu.png', // 卡2
'https://img.alicdn.com/imgextra/i2/3965833216/O1CN01a0ZxeE1ZcyRRQTFst_!!3965833216-2-isvtu.png', // 卡3
'https://img.alicdn.com/imgextra/i3/3965833216/O1CN014gxqyY1ZcyRQpo57B_!!3965833216-2-isvtu.png', // 卡4
], // 分享图片URL
path: 'pages/index/index'
},
onLaunch(options) {
this.handleQuery(options.query || {});
},
onShow(options) {
// 从后台被 scheme 重新打开
},
/**
* 处理链接参数
* @param {object} query 小程序链接上的参数
*/
handleQuery(query) {
const { activityId } = query;
this.activityId = activityId || '610a5614964f978611e42c8d';
}
});
// {
// "handler": "getGameInfo",
// "data": {"activityId":"60f0eb94086e65a863fa39cf"}
// }
\ No newline at end of file
{
"pages": [
"pages/loadingScene/loadingScene",
"pages/mainscene/mainscene",
"pages/rewardinfofill/rewardinfofill",
"pages/ruleScene/ruleScene",
"pages/myprize/myprize",
"pages/games/games"
],
"window": {
"allowsBounceVertical": "NO",
"defaultTitle": "C端模板",
"enableSkia":"true",
"navigationBarForceEnable": true
},
"plugins": {
"cemMember": {
"version":"*",
"provider":"3000000026642582"
}
}
}
.choose-size-modal {
position: fixed;
background-color: #ffffff;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
overflow: hidden;
bottom: 0;
width: 100%;
padding: 30rpx 80rpx 50rpx;
}
.choose-size-modal .my-picker {
height: 200rpx;
}
.choose-size-modal .confirm-btn {
margin-top: 40rpx;
line-height: 100rpx;
color: #ffffff;
text-align: center;
background: #111111;
border-radius: 50rpx;
}
.choose-size-modal .confirm-btn.disabled {
background-color: #757575;
pointer-events: none;
}
\ No newline at end of file
<view class="choose-size-modal">
<picker-view value="{{sizeValue}}" class="my-picker" onChange="onChangePicker">
<picker-view-column>
<view a:for="{{viewColumn}}">
{{item.size}} {{item.stock <= item.useStock ? '(无库存)' : ''}}
</view>
<!-- <view>2011</view>
<view>2012</view>
<view>2013</view>
<view>2014</view>
<view>2015</view>
<view>2016</view>
<view>2017</view>
<view>2018</view> -->
</picker-view-column>
</picker-view>
<view class="{{disabled ? 'confirm-btn disabled' : 'confirm-btn'}}" onTap="onConfirmFn">确认输入</view>
</view>
\ No newline at end of file
Component({
data: {
sizeValue: [0],
disabled: false
},
props: {
viewColumn: [],
onConfirm: () =>{},
onModalClose: () => {}
},
didMount() {
var i = this.data.sizeValue[0]
var currColumn = this.props.viewColumn[i]
this.setData({
disabled: currColumn.stock <= currColumn.useStock
})
},
methods: {
onChangePicker(e) {
var i = e.detail.value[0]
var currColumn = this.props.viewColumn[i]
this.setData({
sizeValue: e.detail.value,
disabled: currColumn.stock <= currColumn.useStock
})
},
onConfirmFn() {
var i = this.data.sizeValue[0]
this.props.onConfirm(this.props.viewColumn[i].size)
this.props.onModalClose()
}
}
})
{
"component": true
}
\ No newline at end of file
.common-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 20;
}
.common-modal__shade {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
.common-modal__container {
position: absolute;
width: 500rpx;
height: 300rpx;
background: #4eafd7;
background-size: 100% 100%;
left: 50%;
top: 50%;
margin-left: -250rpx;
margin-top: -150rpx;
padding: 30rpx;
}
.common-modal__bd {
font-size: 28rpx;
text-align: center;
color: #fff;
padding: 50rpx 0;
}
.common-modal__close {
position: absolute;
right: -20rpx;
top: -80rpx;
height: 86rpx;
width: 86rpx;
background: url('../../assets/modal_close_btn.png') center center no-repeat;
background-size: 48rpx 48rpx;
z-index: 9;
}
.common-modal__confirm-btn {
margin: 0 auto;
text-align: center;
width: 341rpx;
height: 77rpx;
line-height: 77rpx;
background: #FFF;
background-size: 100% 100%;
font-size: 30rpx;
color: #0077a9;
font-weight: bold;
}
<view class="common-modal">
<view class="common-modal__shade modal-animate-fade-in" />
<view class="common-modal__container modal-animate-zoom-in">
<view class="common-modal__close" onTap="onModalClose" />
<view class="common-modal__bd">
<text>{{data.content}}</text>
</view>
<view class="common-modal__ft" a:if="{{data.btnText}}">
<view onTap="onModalConfirm" class="common-modal__confirm-btn">{{data.btnText}}</view>
</view>
</view>
</view>
Component({
methods: {
onModalClose() {
const { onModalClose } = this.props;
onModalClose && onModalClose();
},
onModalConfirm () {
const { onModalConfirm } = this.props;
onModalConfirm && onModalConfirm();
}
}
});
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
@keyframes modalAnimation {
to {
opacity: 1;
}
}
.logistics-modal-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 20;
opacity: 0;
animation: modalAnimation .3s forwards;
}
@keyframes containerAnimation {
to {
transform: scale(1)
}
}
.logistics-modal-container__content {
width: 646rpx;
height: 244rpx;
padding: 0 46rpx;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
display: flex;
align-items: center;
transform: scale(0);
animation: containerAnimation .3s forwards;
}
.logistics-modal-container__close {
position: absolute;
right: -10rpx;
top: -70rpx;
height: 48rpx;
width: 48rpx;
background: url("//yun.duiba.com.cn/taobaomini/aupresViva/tc_close.png") no-repeat;
background-size: 100% 100%;
}
.logistics-modal-container__content-item {
border-radius: 10rpx;
display: flex;
}
.logistics-modal-container__content-left {
width: 144rpx;
height: 144rpx;
background: rgba(244, 244, 244, 1);
}
.logistics-modal-container__content-left image {
width: 100%;
height: 100%;
}
.logistics-modal-container__content-right {
height: 144rpx;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
font-size: 20rpx;
color: #959595;
flex: 1;
overflow: hidden;
white-space: nowrap;
}
.logistics-modal-container__content-name {
font-size: 28rpx;
color: rgba(51, 51, 51, 1);
}
.logistics-modal-container__content-desc {
font-size: 20rpx;
}
.logistics-modal-container__content-ids {
margin-bottom: 20rpx;
}
.logistics-modal-container__content-copy {
display: flex;
align-items: center;
height: 30rpx;
}
.logistics-modal-container__content-copy__code {
font-size: 20rpx;
}
.logistics-modal-container__content-copy__img {
width: 20rpx;
height: 20rpx;
background-size: 100% 100%;
margin-left: 20rpx;
}
\ No newline at end of file
<view class="logistics-modal-container">
<view class="logistics-modal-container__content"
style="{{prizeItem.shipStatus == 3 ?`background: url(${task.shipped}) no-repeat;background-size: 100% 100%;`
:`background: url(${task.notShipped}) no-repeat;background-size: 100% 100%;`}}">
<view class="logistics-modal-container__close" onTap="closeModal"></view>
<view class="logistics-modal-container__content-item">
<view class="logistics-modal-container__content-left">
<image mode="scaleToFill" src="{{prizeItem.image}}"/>
</view>
<view class="logistics-modal-container__content-right">
<view class="logistics-modal-container__content-name">{{prizeItem.name}}</view>
<view class="logistics-modal-container__content-copy">
<view class="logistics-modal-container__content-copy__code">奖品编码:{{prizeItem._id}}</view>
<view class="logistics-modal-container__content-copy__img" onTap="copyPrizeId"></view>
</view>
<view class="logistics-modal-container__content-desc">{{prizeItem.shipStatus== 3?'发货状态:已发货':'发货状态:未发货'}}</view>
<view class="logistics-modal-container__content-desc" a:if="{{prizeItem.shipStatus == 2}}">温馨提示:奖品将在活动结束7天内陆续发出</view>
<view class="logistics-modal-container__content-copy" a:else>
<view class="logistics-modal-container__content-copy__code">{{'物流单号:'+prizeItem.shipNum}}</view>
<view class="logistics-modal-container__content-copy__img" style="{{`background: url(${task.copyIcon}) no-repeat;background-size: 100% 100%;`}}" onTap="copyCode"></view>
</view>
</view>
</view>
</view>
</view>
\ No newline at end of file
const app = getApp();
const { tbcc } = app;
const { commonToast } = tbcc.tb;
Component({
mixins: [],
data: {},
props: {
prizeItem: {},
onCloseModal: () => { },
task: {
shipped: '',
notShipped: '',
}
},
didMount() { },
didUpdate() { },
didUnmount() { },
methods: {
closeModal() {
this.props.onCloseModal()
},
//复制运单号
copyCode() {
let { shipNum } = this.props.prizeItem
my.setClipboard({
text: shipNum + '',
success: () => {
commonToast('复制成功')
}
});
},
copyPrizeId() {
let { _id } = this.props.prizeItem
my.setClipboard({
text: _id + '',
success: () => {
commonToast('复制成功')
}
});
}
},
});
{
"component": true
}
\ No newline at end of file
.normal-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 20;
}
.normal-modal__shade {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
.normal-modal__container {
position: relative;
height: 100%;
}
\ No newline at end of file
<view class="normal-modal">
<view class="normal-modal__shade modal-animate-fade-in" />
<view data-view="container" class="normal-modal__container modal-animate-fly-in" onTap="onModalClose">
<view data-view="slot">
<slot></slot>
</view>
</view>
</view>
Component({
didMount() {
},
methods: {
onModalClose(e) {
if (e.target.targetDataset.view == 'container') {
const { onModalClose } = this.props;
onModalClose && onModalClose(e);
}
},
onModalConfirm () {
const { onModalConfirm } = this.props;
onModalConfirm && onModalConfirm();
}
}
});
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
const { tbcc } = getApp();
const { constants: tbccConstants } = tbcc;
// 分享配置
export const SHARE_CONFIG = {
title: 'FILA 女神家的猫',
desc: '玩猫咪消消乐,赢限量周边及宠粉礼金',
imageUrl: 'cloud://0F631D7C1FAAC7B696CA3C977CF3E12B//EC44276C-5097-4C0D-B828-6A35AF531E2D.png', // 分享图片URL
path: 'pages/index/index'
};
// 链接配置
export const REDIRECT_URL = {
'testpage': '/pages/testPage/testPage',
'tmall': 'https://www.tmall.com'
};
export const DRAW_STATUS = tbccConstants.DRAW_STATUS;
export const PRIZE_TYPE = tbccConstants.PRIZE_TYPE;
{
"name": "liziqi-scan",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/runtime": {
"version": "7.14.8",
"resolved": "https://registry.nlark.com/@babel/runtime/download/@babel/runtime-7.14.8.tgz?cache=0&sync_timestamp=1626806459168&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.14.8.tgz",
"integrity": "sha1-cRmlb0IQGIUmlCkLn5FICXORtEY=",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@tbmp/mp-cloud-sdk": {
"version": "1.4.2",
"resolved": "http://npm.dui88.com:80/@tbmp%2fmp-cloud-sdk/-/mp-cloud-sdk-1.4.2.tgz",
"integrity": "sha1-/49BtdDaNJ6H9+f9DDBMPgt/BbQ="
},
"crypto": {
"version": "1.0.1",
"resolved": "http://npm.dui88.com:80/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha1-KvG3ytgXXSTIobB3glV5SiGAMDc="
},
"fyge": {
"version": "2.0.31",
"resolved": "http://npm.dui88.com:80/fyge/-/fyge-2.0.31.tgz",
"integrity": "sha1-Sa/N/vkuI7U+Qr72qT87IhGvKB4="
},
"mini-ali-ui": {
"version": "1.3.8",
"resolved": "https://registry.nlark.com/mini-ali-ui/download/mini-ali-ui-1.3.8.tgz",
"integrity": "sha1-aktLvT+NmT1ZclTue4GbIapw+WE=",
"requires": {
"@babel/runtime": "^7.11.2"
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.nlark.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz",
"integrity": "sha1-iSV0Kpj/2QgUmI11Zq0wyjsmO1I="
}
}
}
{
"name": "liziqi-scan",
"version": "1.0.0",
"main": "",
"license": "MIT",
"dependencies": {
"@tbmp/mp-cloud-sdk": "*",
"crypto": "^1.0.1",
"fyge": "2.0.31",
"mini-ali-ui": "^1.3.8"
}
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
.canvas {
width:100%;
height:100%;
}
.page-game {
width:100%;
height:100vh;
flex: 1;
display: flex;
flex-direction: column;
background-position: center center;
background-size:cover;
background-image: url('//yun.dui88.com/72e58e2b-e4e3-45ca-ba2e-127352912d0b.png')
}
<view class="page-game">
<canvas id="canvas" type="2d" class="canvas" disable-scroll="true"
onTouchStart="onMouseEvent"
onTouchMove="onMouseEvent"
onTouchEnd="onMouseEvent"
onReady="onCanvasReady"
></canvas>
</view>
This diff is collapsed.
{
"disableScroll": "true"
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
.canvas {
width: 100%;
height: 100%;
}
.page-game {
width:100%;
height:100vh;
flex: 1;
display: flex;
flex-direction: column;
background-color: transparent;
position: absolute;
z-index: 2;
}
#arcamera {
position: absolute;
width: 100%;
height: 100vh;
z-index: 1;
}
.test-text {
position: fixed;
top: 0;
font-size: 35rpx;
width: 100%;
word-wrap: break-word;
word-break: normal;
color: #ff5502;
}
<ar-camera
a:if="{{true}}"
marker="{{markerImage}}"
id="arcamera"
mode="imageTracking"
onARFrame="handleARFrame"
disable-scroll="true"
></ar-camera>
<view class="page-game" disable-scroll="true">
<canvas id="canvas" type="webgl" class="canvas" disable-scroll="true"
onTouchStart="onMouseEvent"
onTouchMove="onMouseEvent"
onTouchEnd="onMouseEvent"
onReady="onCanvasReady"
></canvas>
</view>
<!--测试文字-->
<!-- <text class="test-text">{{text}}</text> -->
<member-shop-center
expend="{{expend}}"
onClose="onCloseMember"
onAuthFail="onMemberFail"
onAuthSuccess="onMemberSuccess"
/>
This diff is collapsed.
{
"disableScroll": "true",
"usingComponents": {
"member-shop-center": "plugin://cemMember/member-shop-center"
}
}
This diff is collapsed.
This diff is collapsed.
.sloga-cont {
position: absolute;
bottom: 150rpx;
left: 50%;
transform: translateX(-50%);
}
.loading-cont {
width: 173px;
height: 62px;
overflow: hidden;
background-image: url('//yun.dui88.com/7c5dd988-cb74-4bc9-9089-958bc0ccffc0.png');
animation: BX_SprAniKey1 0.36666666666667s steps(1) 0s infinite normal none;
}
@keyframes BX_SprAniKey1 {
0% { background-position: 0px 0px; }
10.00% { background-position: -173px 0px; }
20.00% { background-position: -346px 0px; }
30.00% { background-position: -519px 0px; }
40.00% { background-position: -692px 0px; }
50.00% { background-position: -865px 0px; }
60.00% { background-position: -1038px 0px; }
70.00% { background-position: -1211px 0px; }
80.00% { background-position: -1384px 0px; }
90.00% { background-position: -1557px 0px; }
100.00% { background-position: -1730px 0px; }
}
<view class="scene-container loading-scene__container">
<view class="sloga-cont">
<view class="loading-cont sprite">
</view>
</view>
</view>
\ No newline at end of file
import API from "../../api";
import { commonToast, getAuthUserInfo, navigateTo, redirectTo } from "../../tbcc-sdk/lib/tb"
import { Tools } from "../../Tools";
const app = getApp()
Page({
data: {},
onLoad() {
this.getAuth()
},
async getAuth() {
const userInfo = await getAuthUserInfo().catch(() => {
commonToast('未授权成功');
});
//未授权成功不进入活动
if (!userInfo) return;
const { nickName: userNick, avatar } = userInfo;
app.nickName = userNick; // 注意变量名不一样
app.avatar = avatar;
const {data, success} = await API.getVipInfo({
userNick: userNick
})
if (success) {
if (data.isVip) {
// 登陆
this.userLogin({
userNick,
avatar,
isVip: true
})
Tools.globalData.isVip = true
} else {
// todo 入会 data.url
}
}
},
async userLogin(params) {
const loginData = await API.login(params).catch(err => {
commonToast(err)
})
if (loginData && loginData.success) {
redirectTo('/pages/mainscene/mainscene')
}
}
})
\ No newline at end of file
.scene-container {
width: 100vw;
min-height: 100vh;
position: absolute;
}
.main-scene__container {
background-color: #f1ebdd;
}
.header-cont {
display: flex;
padding: 40rpx 40rpx;
align-items: center;
justify-content: space-between;
}
.header-cont .left-logo-cont {
width: 140rpx;
height: 49rpx;
background-image: url('//yun.dui88.com/8b939dcd-864d-4a11-8f40-d8925d762006.png');
background-size: cover;
}
.header-cont .rule-text {
font-weight: 700;
padding-bottom: 5rpx;
border-bottom: 4rpx solid #000000;
}
.title-cont {
margin-top: 50rpx;
margin-bottom: 40rpx;
}
.title-cont .title {
width: 457rpx;
height: 131rpx;
background: url('//yun.dui88.com/5e60a935-ed4c-4229-b666-983f5b8852b2.png');
background-size: cover;
margin: 0 auto;
}
.title-cont .desc {
font-size: 24rpx;
font-weight: 500;
margin-top: 30rpx;
text-align: center;
}
.sp-t {
color: #e85d2a;
}
.sloga-cont {
height: 656rpx;
background: url('//yun.dui88.com/0fc8a75f-7601-4748-8f88-4598a30bdf6f.png');
background-size: cover;
}
.main-scene__container .start-btn {
width: 600rpx;
margin: 30rpx auto 60rpx;
background: #111111;
padding: 30rpx;
text-align: center;
color: #ffffff;
font-size: 30rpx;
border-radius: 100rpx;
}
.bottom-cont {
margin-top: 150rpx;
position: relative;
}
.bottom-cont .dailingqu {
width: 250rpx;
height: 60rpx;
background-image: url('//yun.dui88.com/c10ef569-968d-4879-9fe7-12c0cc0e9fa0.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin: 0 auto;
position: absolute;
top: -90rpx;
left: 50%;
transform: translateX(-50%);
}
\ No newline at end of file
<view class="{{isShowLoading ? 'pointer-none scene-container main-scene__container' : 'scene-container main-scene__container' }}">
<view class="header-cont">
<view class="left-logo-cont">
</view>
<view class="rule-text" onTap="onJumpRuleScene">活动规则</view>
</view>
<view class="title-cont">
<view class="title"></view>
<view class="desc">连续完成 <label class="sp-t">N个</label> 瑜伽动作,即可解锁惊喜福利哦~</view>
</view>
<view class="sloga-cont">
</view>
<view class="bottom-cont">
<view class="dailingqu" a:if="{{isNeedReceive}}" onTap="onJumpRewardinfofillScene"></view>
<view class="start-btn" onTap="onJumpGameScene">开始游戏</view>
</view>
</view>
\ No newline at end of file
import { navigateTo } from "../index/utils"
import API from "../../api"
import { Tools } from "../../Tools"
import { commonToast } from "../../tbcc-sdk/lib/tb"
Page({
data: {
rule: '',
startTime: '',
endTime: '',
isCompleteGuide: false,
isNeedReceive: false,
isShowLoading: false
},
onLoad() {
this.getActivityBaseInfoById()
},
onShow() { // 页面显示
this.getActivityBaseInfoById()
},
async getActivityBaseInfoById() {
this.setData({
isShowLoading: true
})
const {data, success} = await API.getActivityBaseInfoById()
this.setData({
isShowLoading: false
})
data.isNeedReceive = (!data.endTime || Date.now() < data.endTime) && data.isNeedReceive
Tools.globalData = data
if (success) {
this.setData(
data
)
}
},
onJumpGameScene() {
if (this.data.endTime && Date.now() > this.data.endTime) {
commonToast('活动已结束')
return
}
this.setData({
isShowLoading: true
})
API.startGame({
isVip: Tools.globalData.isVip
}).then(res => {
navigateTo(`/pages/games/games?startId=${res.data.id}&completed=${this.data.isCompleteGuide}`)
}).finally(() => {
this.setData({
isShowLoading: false
})
})
},
onJumpRewardinfofillScene() {
if (this.data.endTime && Date.now() > this.data.endTime) return
navigateTo(`/pages/rewardinfofill/rewardinfofill?id=${this.data.waitAward.id}&prizeId=${this.data.waitAward.prizeId}`)
},
onJumpRuleScene() {
navigateTo('/pages/ruleScene/ruleScene')
}
})
\ No newline at end of file
{
"usingComponents": {
"am-loading": "mini-ali-ui/es/loading/index"
}
}
.my-prize-container {
width: 100vw;
height: 100vh;
opacity: 1;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
/* background: url('') no-repeat center top/cover; */
}
.my-prize-container .my-prize-label {
width: 208rpx;
height: 36rpx;
margin: 140rpx auto 40rpx;
background: url('//yun.dui88.com/duiba-components-c-myprizeprize_title.png') no-repeat;
background-size: 100% 100%;
}
.my-prize-content {
position: absolute;
left: 0;
top: 363rpx;
bottom: 0;
width: 100%;
}
.my-prize-content__scroll {
width: 100%;
height: 100%;
padding-top: 30rpx;
}
.my-prize-container .my-prize-list {
width: 100%;
height: auto;
}
.my-prize-container .my-prize-item__empty {
text-align: center;
color: #fff;
margin-top: 30rpx;
}
.my-prize-list .my-prize-item {
display: flex;
justify-content: center;
align-items: center;
padding: 0 36rpx 0 45rpx;
margin: 0 auto 28rpx;
position: relative;
box-sizing: border-box;
width: 737rpx;
height: 183rpx;
background: url('//yun.duiba.com.cn/aurora/assets/00ca4773078b0bafd1d3d16aaffeb742451c03cb.png') no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
}
.my-prize-list .my-prize-item .my-prize-item__avatar {
width: 126rpx;
height: 126rpx;
}
.my-prize-list .my-prize-item .my-prize-item__content {
flex: 1;
min-width: 0;
padding: 0 20rpx;
display: flex;
flex-direction: column;
height: 130rpx;
align-items: flex-start;
justify-content: center
}
.my-prize-list .my-prize-item .my-prize-item__subtitle {
display: flex;
justify-content: center;
align-items: center;
}
.my-prize-list .my-prize-item .my-prize-item__copy {
width: 20rpx;
height: 20rpx;
margin-left: 18rpx;
}
.my-prize-list .my-prize-item .prize-item__status {
width: 150rpx;
}
.prize-item__status>image {
width: 100%;
}
.my-prize-list .my-prize-item .my-prize-item__name {
width: 100%;
font-size: 28rpx;
color: #72493b;
letter-spacing: -1rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.my-prize-list .my-prize-item .my-prize-item__tip {
margin-top: 8rpx;
font-size: 20rpx;
line-height: 20rpx;
letter-spacing: 0;
color: #a48378;
}
.my-prize-list .my-prize-item .my-prize-item__code {
width: 290rpx;
font-family: PingFangSC-Regular;
font-size: 20rpx;
color: #a48378;
letter-spacing: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
\ No newline at end of file
<view class="my-prize-container" style="{{{'background':`url(${prizeConfig.bg}) no-repeat center top/cover`}}}">
<view class="my-prize-label" style="{{{'background':`url(${prizeConfig.title}) no-repeat`,'backgroundSize':'100% 100%'}}}"></view>
<view class="my-prize-content" style="{{ {'top': prizeConfig.contentTop }}}">
<scroll-view scroll-y="{{true}}" class="my-prize-content__scroll">
<view class="my-prize-list" a:if="{{myPrizeList && myPrizeList.length > 0}}">
<view class="my-prize-item" a:for="{{myPrizeList}}">
<image class="my-prize-item__avatar" src="{{item.image}}"/>
<view class="my-prize-item__content">
<label class="my-prize-item__name">{{item.name}}</label>
<view class="my-prize-item__subtitle" a:if="{{isShowPirzeId}}">
<label class="my-prize-item__code">奖品编码:{{item.id || item._id}}</label>
<!-- 复制按钮 -->
<image class="my-prize-item__copy" data-text="{{item.id || item._id}}" onTap="handleCopyId" src="{{prizeConfig.copyIcon}}" />
</view>
<view class="my-prize-item__tip" a:if="{{item.drawStatus === DRAW_STATUS.FAIL}}">{{item.remark}}</view>
<view class="my-prize-item__tip" a:if="{{item.drawStatus === DRAW_STATUS.RETRY || (item.drawStatus === DRAW_STATUS.WAITAWARD)}}">请于{{endTime}}前领取</view>
<view class="my-prize-item__tip" a:if="{{item.drawStatus === DRAW_STATUS.EXPIRED }}">奖品已过期失效</view>
</view>
<view class="prize-item__status" style="{{prizeConfig.btnStyle}}">
<!-- 实物奖品状态 -->
<block a:if="{{item.type === PRIZE_TYPE.OBJECT}}">
<image onTap="handleClick" data-item="{{item}}" src="{{objectStatus[item.drawStatus]}}" mode="widthFix" />
</block>
<!-- 非实物奖品状态 -->
<block a:else>
<image onTap="handleClick" data-item="{{item}}" src="{{(item.drawStatus === 3 && !item.useUrl) ? prizeConfig['receiveBtn'] : enameStatus[item.drawStatus]}}" mode="widthFix" />
</block>
</view>
</view>
</view>
<view a:if="{{myPrizeList && myPrizeList.length === 0}}" class="my-prize-item__empty">{{prizeConfig.blankTxt}}</view>
</scroll-view>
</view>
</view>
<logistics-modal
a:if="{{isLogisticModal}}"
prizeItem="{{currentPrize}}"
onCloseModal="closeLogisticModal"
task="{{logisticsImage}}" />
\ No newline at end of file
'use strict';
import API from "/api";
const app = getApp();
const { tbcc } = app;
const { commonToast, navigateToOutside, getUserAddress, setClipboard } = tbcc.tb;
const { dateFormatter, throttleHandle } = tbcc.utils;
const { PRIZE_TYPE, DRAW_STATUS } = tbcc.constants;
// 我的奖品配置项
const prizeConfig = {
bg: '//yun.duiba.com.cn/aurora/assets/82a5af3efba919bf1b8fd482865202d74db6d300.jpg', //背景图
// title: '//yun.dui88.com/duiba-components-c-myprizeprize_title.png',//标题
copyIcon: '//yun.duiba.com.cn/aurora/assets/1b98114c18d6da7bbbc1f8123e320bbbe5ac17b2.png', //复制
receiveBtn: '//yun.duiba.com.cn/aurora/assets/5b675d419d76d2f65b812bcd22acb8f91c68ea24.png', //已领取 权益类奖品未配置 uesUrl使用
commonStatus: {
6: '//yun.duiba.com.cn/aurora/assets/f0be6d2e36f6b2549fd9025085a5dde620ca8085.png', //重新领取
5: '//yun.duiba.com.cn/aurora/assets/80ac886e0e9503f35e554d57c407f2d26a582a4d.png', //已失效
4: '//yun.duiba.com.cn/aurora/assets/5b675d419d76d2f65b812bcd22acb8f91c68ea24.png', //领取失败
},
objectStatus: {
1: '//yun.duiba.com.cn/aurora/assets/5b90f2402bb0e1314f6af1a0455136ef137af836.png', //填写地址(实物奖品)
3: '//yun.duiba.com.cn/aurora/assets/5b675d419d76d2f65b812bcd22acb8f91c68ea24.png', //查看物流
},
enameStatus: {
1: '//yun.duiba.com.cn/aurora/assets/39cce2e10e588c4049901688b2e50ed0e791a315.png', //立即领取(除实物奖品外)
3: '//yun.duiba.com.cn/aurora/assets/00000e00ae933048ba88bf91281b3bf2386f3216.png', //去使用(除实物奖品外)
},
logisticsImage: {
shipped: '//yun.dui88.com/duiba-components-c-myprizeprize_shipped.png', // 已发货物理弹窗
notShipped: '//yun.dui88.com/duiba-components-c-myprizenotshipped.png', // 待发货物流弹窗
},
btnStyle: {
width: '136rpx'
},
contentTop: '185rpx',
blankTxt: '暂无奖品',
hasLogistic: true, // 是否展示物流信息
isShowPirzeId: true // 是否显示奖品编号
}
Page({
data: {
PRIZE_TYPE,
DRAW_STATUS,
myPrizeList: [], //我的奖品
endTime: null,//到期时间
prizeConfig: prizeConfig,
objectStatus: {
...prizeConfig.commonStatus,
...prizeConfig.objectStatus
},
enameStatus: {
...prizeConfig.commonStatus,
...prizeConfig.enameStatus
},
logisticsImage: {
...prizeConfig.logisticsImage,
copyIcon: prizeConfig.copyIcon
},
hasLogistic: prizeConfig.hasLogistic,
isShowPirzeId: prizeConfig.isShowPirzeId,
isLogisticModal: false,
currentPrize: {}
},
onLoad() {
this.getMyPrize();
},
onShow() {
},
// 到期时间
getEndTime(endTime) {
if (!endTime) return null
this.setData({
endTime: dateFormatter(endTime, 'yyyy/MM/dd hh:mm:ss')
})
console.log(this.data.endTime)
},
/**
* 获取奖品列表
* @param {string}
*/
async getMyPrize() {
const { activityId } = app;
const { success, data } = await API.getMyPrizeList({ activityId }).catch(res => {
commonToast(res && res.message);
}) || {};
if (success && data) {
const { list } = data
this.setData({
myPrizeList: list
})
const endTime = list && list[0] && list[0].expiredTime
this.getEndTime(endTime)
}
},
//领取奖品
handleClick: throttleHandle(async function(e) {
const { type, drawStatus, useUrl = '', id, _id } = e.target.dataset.item
const { hasLogistic } = this.data
if(drawStatus == 3) {
if(type != PRIZE_TYPE.OBJECT && useUrl) {
navigateToOutside(useUrl)
return;
}
}
if(!(drawStatus == 6 || drawStatus == 1)) {
return;
}
// 领取权益
const prizeId = id || _id
if (type === PRIZE_TYPE.ENAME) return this.handleGetEquity(prizeId)
// 领取实物
if (type === PRIZE_TYPE.OBJECT) return this.handleGetEntity(prizeId)
// 领取积分
if (type === PRIZE_TYPE.CREDITS) return this.handleGetIntergation(prizeId)
},2000),
// 优惠券
async handleGetEquity(id) {
const { activityId } = app;
const { success, data, message } = await API.receiveEnamePrize({ activityId, id }).catch(res => {
this.getMyPrize()
commonToast(res && res.message)
}) || {};
if (success && data) {
commonToast('领取成功')
this.getMyPrize()
}
},
// 领取实物前询问
async handleGetEntity(id) {
const { activityId } = app;
const userAddress = await getUserAddress().catch(err => {
commonToast(err && err.errorMessage);
});
if (!userAddress) return
const { name, telNumber, provinceName, cityName, cityCode, countyName, detailInfo, streetName } = userAddress || {};
const params = {
activityId,
name,
phone: telNumber,
addressDetail: detailInfo,
cityCode,
city: cityName,
province: provinceName,
area: countyName,
streetName,
id
}
my.confirm({
title: '提示',
content: '确认使用该收货地址:' + name + telNumber + userAddress.duibaAddress.address,
confirmButtonText: '确定',
cancelButtonText: '取消',
success: (result) => {
console.log(result)
const { confirm } = result;
if (confirm) {
this.receiveObjectPrize(params);
}
},
});
},
// 领取实物
async receiveObjectPrize(params) {
const { success, data } = await API.receiveObjectPrize(params).catch(res => {
commonToast(res && res.message)
}) || {}
if (success && data) {
commonToast('领取成功')
}
this.getMyPrize()
},
// 积分
async handleGetIntergation(id) {
// 判断是否为会员
const { isVip, url } = await this.getUserInfo() || {}
if (!isVip) {
commonToast('需加入会员才能领取成功哦', 2000,() => { navigateToOutside(url) });
return;
}
const { activityId } = app;
const { success, data } = await API.receiveEnamePrize({ activityId, id }).catch(res => {
commonToast(res && res.message)
}) || {};
if (success && data) {
commonToast('领取成功')
}
this.getMyPrize()
},
//获取用户vip信息
async getUserInfo() {
const { activityId } = app;
const { success, data } = await API.getVipInfo({ activityId }).catch(res => {
commonToast(res && res.message)
}) || {};
if (success && data) {
return data
}
},
// 复制编码
async handleCopyId(e) {
const { text } = e.target.dataset || {}
await setClipboard({ text })
commonToast('复制成功')
},
/**
* 关闭物流弹窗
*/
closeLogisticModal() {
this.setData({ isLogisticModal: false })
},
});
\ No newline at end of file
{
"usingComponents": {
"logistics-modal": "/components/logisticsModal/logisticsModal"
}
}
\ No newline at end of file
.scene-container {
width: 100vw;
min-height: 100vh;
position: absolute;
background-color: #f1ebdd;
}
.rewardinfofill-scene__container {
padding: 40rpx;
}
.header-cont {
display: flex;
align-items: center;
justify-content: space-between;
}
.header-cont .left-logo-cont {
width: 140rpx;
height: 49rpx;
background-image: url('//yun.dui88.com/8b939dcd-864d-4a11-8f40-d8925d762006.png');
background-size: cover;
}
.header-cont .rule-text {
padding-bottom: 5rpx;
border-bottom: 4rpx solid #000000;
font-size: 24rpx
}
.title-cont {
margin-top: 50rpx;
overflow: hidden;
}
.title-cont .title-text {
font-size: 60rpx;
font-weight: 700;
}
.title-cont .title-desc {
font-size: 26rpx;
color: #757575;
line-height: 34rpx;
margin-bottom: 20rpx;
margin-top: 10rpx;
}
.qg-form__wrap {
margin-top: 10rpx;
}
.qg-form__wrap .form-row {
margin-top: 20rpx;
}
.qg-form__wrap .form-row .form-label {
font-size: 30rpx;
line-height: 50rpx;
margin: 10rpx 0;
}
.qg-form__wrap .qg-input {
width: 100%;
line-height: 80rpx;
height: 80rpx;
display: inline-block;
padding: 0 30rpx;
color: #111111;
font-size: 28rpx;
box-sizing: border-box;
border-radius: 6rpx;
pointer-events: none;
}
.submit-btn {
width: 100%;
line-height: 100rpx;
color: #F1EBDD;
background-color: #111111;
border-radius: 50rpx;
text-align: center;
margin-top: 100rpx;
text-align: center;
font-weight: 700;
transition: all .2s ease;
}
.submit-btn.disabled {
background-color: #757575;
pointer-events: none;
}
.submit-btn:not(.disabled):active {
transform: scale(0.96);
}
.exchange-success-modal {
width: 589rpx;
height: 545rpx;
background-image: url('//yun.dui88.com/d84fd09f-0edc-49b7-b344-1a48cde4f918.png');
background-repeat: no-repeat;
background-size: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.exchange-success-modal .confirm-btn {
position: absolute;
width: 480rpx;
line-height: 90rpx;
background-color: #111111;
border-radius: 50rpx;
text-align: center;
left: 55rpx;
bottom: 40rpx;
font-size: 32rpx;
color: #f1ebdd;
transition: transform .3s ease;
}
.exchange-success-modal .confirm-btn:active {
/* transform: scale(.95); */
}
\ No newline at end of file
<view class="rewardinfofill-scene__container scene-container" >
<view class="header-cont">
<view class="left-logo-cont">
</view>
<view class="rule-text" onTap="onChooseAddress">选择已有的收货地址</view>
</view>
<view class="title-cont">
<view class="title-text">请填写您的信息</view>
<view class="title-desc">准确并完整的填写奖品递送信息,您需要填写中奖信息,逾期中奖资格作废。</view>
</view>
<view id="rewardForm" class="qg-form__wrap">
<view class="form-row">
<view class="form-label">
姓名
</view>
<view class="form-content" onTap="onChooseAddress">
<input placeholder="请输入8个以内中英文字符" data-name="name" class="qg-input"
value="{{rewardForm.name}}"
onInput="inputEvent"
/>
</view>
</view>
<view class="form-row">
<view class="form-label">
选择区域
</view>
<view class="form-content" onTap="onChooseAddress">
<input placeholder="省、市、区、街道" data-name="area" class="qg-input"
value="{{rewardForm.area}}"
onInput="inputEvent"
/>
</view>
</view>
<view class="form-row">
<view class="form-label">
详细地址
</view>
<view class="form-content" onTap="onChooseAddress">
<input placeholder="请输入消息地址" data-name="detailArea" class="qg-input"
value="{{rewardForm.detailArea}}"
onInput="inputEvent"
/>
</view>
</view>
<view class="form-row">
<view class="form-label">
手机号码
</view>
<view class="form-content" onTap="onChooseAddress">
<input placeholder="请填写11位手机号码" data-name="phone" class="qg-input"
value="{{rewardForm.phone}}"
onInput="inputEvent"
/>
</view>
</view>
<view class="form-row" a:if="{{isHasSize}}">
<view class="form-label">
尺码选择
</view>
<view class="form-content" onTap="onModalShow">
<input placeholder="请选择尺码" data-name="size" class="qg-input"
value="{{rewardForm.size}}"
onInput="inputEvent"
/>
</view>
</view>
<view class="{{disabled ? 'submit-btn disabled': 'submit-btn'}}" onTap="onSubmit">确认兑换并提交</view>
<normal-modal a:if="{{chooseSizeModalMd}}" onModalClose="onModalClose">
<choose-modal viewColumn="{{sizeList}}" onConfirm="onSetSize" onModalClose="onModalClose"></choose-modal>
</normal-modal>
<normal-modal a:if="{{exchangeModalMd}}">
<view class="exchange-success-modal">
<view class="confirm-btn" onTap="onNavigatorBack">
知道了
</view>
</view>
</normal-modal>
</view>
\ No newline at end of file
import API from "../../api";
import { getUserAddress } from "../../tbcc-sdk/lib/tb";
import { Tools } from "../../Tools";
const app = getApp();
function notEmpty(rule, value, callback) {
if (value == '') {
callback(rule.label + '不能为空')
}
}
Page({
data: {
rewardForm: {
name: '123123',
area: '123',
detailArea: '123',
phone: '123',
size: ''
},
chooseSizeModalMd: false,
disabled: true, //submit status
isHasSize: false,
sizeList: [
],
rules: {
name: [
{ validator: notEmpty, label: '姓名' },
],
area: [
{ validator: notEmpty, label: '选择区域' }
],
detailArea: [
{ validator: notEmpty, label: '详细地址' }
],
phone: [
{ validator: notEmpty, label: '手机号码' }
],
size: [
{ validator: notEmpty, label: '尺码选择' }
]
},
exchangeModalMd: false
},
waitAward: {}, // 带领取的id
onLoad(query) {
this.waitAward = query
this.getShoeseList()
this.validate()
},
async getShoeseList() {
const {data, success} = await API.getMyShoesList({
prizeId: this.waitAward.prizeId
})
if (success) {
this.setData({
isHasSize: data.isHasSize,
sizeList: data.shoesList
})
}
},
validate(isShowError) {
var rules = this.data.rules
var form = this.data.rewardForm
try {
for (let key in rules) {
let krs = rules[key]
krs.forEach(r => {
r.validator(r, form[key], (e) => {
e && isShowError && my.showToast({
content: e
});
if (e) {
throw new Error(e)
}
})
})
}
this.setData({
disabled: false
})
} catch (err) {
// console.error(err)
}
},
onModalClose() {
this.setData({
chooseSizeModalMd: false
})
},
onModalShow() {
this.setData({
chooseSizeModalMd: true
})
},
onSetSize(s) {
this.data.rewardForm.size = s
this.setData(this.data)
this.validate()
},
inputEvent(e) {
var name = e.target.dataset.name
var value = e.detail.value
this.updateFormName(name, value)
},
updateFormName(name, value) {
this.data.rewardForm[name] = value
this.setData(this.data)
this.validate()
},
chooseData: {
provinceName: 123,
cityName: 123,
countyName: 123,
streetName: 123
}, // 淘宝选择城市
async onChooseAddress() {
var data = await getUserAddress({
searchAddress: 'show',
locateAddress: 'show'
}).catch(err => {
console.log('error:', err)
})
if (!data.telNumber) return
const { error, provinceName, countyName, cityName, streetName, detailInfo, name, telNumber } = data;
this.chooseData = data
console.log(this.chooseData)
this.data.rewardForm.name = data.name
this.data.rewardForm.area = [provinceName, cityName, countyName, streetName].join('/')
this.data.rewardForm.detailArea = detailInfo
this.data.rewardForm.phone = telNumber
this.setData(this.data)
this.validate()
},
async onSubmit() {
const { error, provinceName, countyName, cityName, streetName, detailInfo, name, telNumber } = this.chooseData;
var params = {
province: provinceName,
city: cityName,
area: countyName,
addressDetail: this.data.rewardForm.detailArea,
id: this.waitAward.id,
name: this.data.rewardForm.name,
phone: this.data.rewardForm.phone,
streetName: streetName,
prizeId: this.waitAward.prizeId,
size: this.data.rewardForm.size
}
const {data, success} = await API.receiveObjectPrize(params)
if (success) {
this.setData({
exchangeModalMd: true
})
}
},
onNavigatorBack() {
my.navigateBack()
}
})
\ No newline at end of file
{
"usingComponents": {
"common-modal": "/components/commonModal/commonModal",
"normal-modal": "/components/normalModal/normalModal",
"choose-modal": "/components/chooseSizeModal/chooseSizeModal"
}
}
\ No newline at end of file
.title {
font-size: 40rpx;
font-weight: 700;
margin-top: 100rpx;
}
.rule-text {
margin-top: 40rpx;
font-size: 26rpx;
color: #757575;
line-height: 40rpx;
white-space: pre-wrap;
}
.rule-scene-container {
padding: 0 40rpx;
}
\ No newline at end of file
<view class="scene-container rule-scene-container">
<view class="title">
活动规则</view>
<view class="rule-text">{{ruleText}}</view>
</view>
\ No newline at end of file
import { Tools } from "../../Tools";
Page({
data: {
ruleText: ''
},
onLoad(query) {
this.setData({
ruleText: Tools.globalData.rule
})
}
})
\ No newline at end of file
import * as tb from './lib/tb';
import * as tbMock from './lib/tbMock';
import * as utils from './lib/utils';
import * as constants from './lib/constants';
import capi from './lib/capi';
import request from './lib/request';
const isH5 = 'undefined' !== typeof window;
// 如果为h5环境走mock数据
let _tb = {};
Object.entries(tb).forEach(([key, value]) => {
_tb[key] = isH5 ? tbMock[key] : value;
});
export default {
capi,
tb: _tb,
utils,
request,
constants
};
\ No newline at end of file
const capi = {
getMyPrizeList: {
method: 'GET',
handle: 'getMyPrizeList',
isShowLoading: true
},
receiveObjectPrize: { method: 'GET', handle: 'receiveObjectPrize' },
receiveEnamePrize: { method: 'GET', handle: 'receiveEnamePrize' },
getItemListByItemIds: { method: 'GET', handle: 'getItemListByItemIds' },
getCollectGoodsList: { method: 'GET', handle: 'getCollectGoodsList' },
doCollectGoodsTask: { method: 'GET', handle: 'doCompleteTask', defaultParams: { taskType: 'collectGoods'} },
doBrowseGoodsTask: { method: 'GET', handle: 'doCompleteTask', defaultParams: { taskType: 'browseGoods'} },
doJumpLinkTask: { method: 'GET', handle: 'doCompleteTask', defaultParams: { taskType: 'jumpLink'} },
doExchangeCreditsTask: { method: 'GET', handle: 'doCompleteTask', defaultParams: { taskType: 'exchangeCredits'} },
getVipInfo: { method: 'GET', handle: 'getVipInfo' }
};
export default capi;
import { getUserAddress, commonToast } from './tb';
import { getRequestParams } from './utils';
// 通用API封装方法
const capiFn = (apiList, request) => {
return {
async receiveObjectPrize(params) {
const { handle, method, ext } = getRequestParams(apiList['receiveObjectPrize']);
const userAddress = await getUserAddress().catch(err => {
commonToast(err.errorMessage);
});
if (userAddress) {
const { name, phone, address } = userAddress.duibaAddress;
commonConfirm('提示', '确认使用该收货地址:' + name + phone + address, async () => {
params = {
name,
phone,
address,
...params
}
const result = await request(handle, method, params, ext).catch(res => {
commonToast(res && res.message);
});
if (result && result.success) {
return true;
}
});
}
return false;
},
async receiveEnamePrize(params) {
const { handle, method, ext } = getRequestParams(apiList['receiveEnamePrize']);
const result = await request(handle, method, params, ext).catch(res => {
commonToast(res && res.message);
});
if (result && result.success) {
return true;
}
return false;
}
}
};
export default capiFn;
// 领取奖品状态
export const DRAW_STATUS = {
// 待领取
WAITAWARD: 1,
// 处理中
PROCESSING: 2,
// 领取成功
SUCCESS: 3,
// 领取失败
FAIL: 4,
// 已过期
EXPIRED: 5,
// 重新领取
RETRY: 6
}
// 奖品类型
export const PRIZE_TYPE = {
ENAME: 1,
CREDITS: 2,
OBJECT: 3,
THANKS: 5
};
\ No newline at end of file
import * as tb from './tb';
const { getAuthUserInfo } = tb;
var Buffer = require("buffer").Buffer
var crypto = require("crypto")
const request = ({ cloud, cloudName, requestType = 'cloud', mockUrl }) => {
if (!cloud) {
console.error('请传入cloud');
return false;
}
if (!cloudName) {
console.error('请传入云函数名称');
return false;
}
return async (handle, method = 'POST', params, ext = {}) => {
const { activityId, tornadoAPI, nickName='', tbcc } = getApp();
// 默认注入activityId
params = { activityId, ...params };
if (!params.activityId) {
console.error(`${handle}:请传入activityId`);
return false;
}
console.log(params, handle)
const _cloudName = ext.cloudName || cloudName;
const { isShowLoading } = ext;
const hideMyLoading = () => {
if (isShowLoading) {
my.hideLoading();
}
};
if (isShowLoading) {
my.showLoading();
}
const requestMock = () => {
// 若请求的是风驰台的api
if (requestType === 'tornadoAPI') {
// 处理涉及的三个参数
let matchRes = tornadoAPI.match(/db=(\w*)&proxyIp=([\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})/)
let db = matchRes[1]
let proxyIp = matchRes[2]
let data_ = {
handler: handle,
data: params
}
console.log(`data_`, data_)
let params_ = {
db,
proxyIp,
data: data_
}
console.log(`params_`, params_)
// nickName 转 md5 作为唯一的openId
if (!nickName) {
return getAuthUserInfo().catch(err => {
console.log('未授权成功', err);
}).then(res => {
return cb(res)
})
}
// return cb({nickName: '卞龙亭'})
function cb({nickName}) {
if (!db || !proxyIp) {
my.confirm({
title: '风驰台地址错误',
content: '请确认风驰台的地址是否正确,未查找到db和proxyIp',
confirmButtonText: '确定',
cancelButtonText: '取消'
});
return false
}
params_.openId = md5(nickName)
return new Promise((resolve, reject) => {
my.request({
url: tornadoAPI,
method: 'post',
data: params_,
dataType: 'json'
}).then(({ data: res }) => {
console.log(`调用风驰台返回结果`, res)
hideMyLoading();
if (res && res.success) {
resolve(res);
} else {
reject(res);
}
}).catch((e) => {
hideMyLoading();
console.log(e)
reject();
});
})
function md5(data) {
var buf = new Buffer(data);
var str = buf.toString("binary");
return crypto.createHash("md5").update(str).digest("hex").slice(0, 30);
}
}
} else {
const mockUrlPrefix = {
ams: 'https://ams.dui88.com/server/index.php?g=Web&c=Mock&o=simple&projectID=218&uri=',
yapi: 'https://docs.dui88.com/mock/140/'
};
const requestPrefix = mockUrl || mockUrlPrefix[requestType];
return new Promise((resolve, reject) => {
my.request({
url: requestPrefix + _cloudName + '.' + handle,
method,
data: params,
dataType: 'json'
}).then(({ data: res }) => {
hideMyLoading();
if (res && res.success) {
resolve(res);
} else {
resolve(res);
// reject(res);
}
}).catch(() => {
hideMyLoading();
reject();
});
})
}
};
const requestCloud = () => {
return new Promise((resolve, reject) => {
cloud.function.invoke(_cloudName, params, handle).then(res => {
console.log(handle, params, res);
hideMyLoading();
if (res && res.success) {
resolve(res);
} else {
reject(res);
}
return res;
}).catch(() => {
hideMyLoading();
reject();
});
});
};
return ['ams', 'yapi', 'tornadoAPI'].includes(requestType) ? requestMock() : requestCloud();
};
};
export default request;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
import capiFn from './capiFn';
/**
* 时间格式化
* @param date 接收可以被new Date()方法转换的内容
* @param format 字符串,需要的格式例如:'yyyy/MM/dd hh:mm:ss'
* @returns {String}
*/
export const dateFormatter = (date, format = 'yyyy/MM/dd') => {
if (!date) return '-';
date = new Date(
typeof date === 'string' && isNaN(date) ? date.replace(/-/g, '/') : date
);
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds(),
'q+': Math.floor((date.getMonth() + 3) / 3),
S: date.getMilliseconds()
};
if (/(y+)/.test(format)) {
format = format.replace(
RegExp.$1,
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
);
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(format)) {
format = format.replace(
RegExp.$1,
RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
);
}
}
return format;
};
/**
* 版本比较
* @param {string} cur 当前版本
* @param {string} compare 比较版本
*/
export const versionCompare = (cur, compare) => {
const _cur = cur.split('.');
const _compare = compare.split('.');
if (+_cur[0] < +_compare[0]) {
return false;
} else if ( +_cur[0] === +_compare[0] && +_cur[1] < +_compare[1] ) {
return false;
} else if (+_cur[0] === +_compare[0] && +_cur[1] === +_compare[1] && +_cur[2] < +_compare[2]) {
return false;
}
return true;
};
/**
* 获取request请求所需参数
* @param {object/string} value API项配置
*/
export const getRequestParams = value => {
if (typeof value === 'string') {
return {
handle: value,
method: 'POST',
ext: {}
}
} else if (typeof value === 'object') {
const { handle, method = 'POST', defaultParams = {}, ...ext } = value;
return {
handle,
method,
defaultParams,
ext: { ...ext }
}
} else {
console.error('getRequestParams: 传参有误');
}
};
/**
* 生成API
* @param {array} apiList API数据数组
* @param {function} request 请求
*/
export const generateAPI = (apiList, request) => {
const api = {};
Object.entries(apiList).forEach(([key, value]) => {
const { handle, method, ext, defaultParams } = getRequestParams(value);
api[key] = params => request(handle, method, Object.assign({}, defaultParams, params) , ext);
});
api.fn = capiFn(apiList, request);
return api;
};
/**
* 防连点
* @param {fn} fn 函数
* @param {wait} wait 时间
*/
export const throttleHandle = (fn, wait = 500) => {
let lastTime = 0
return function cb(...args) {
let nowTime = Date.now()
if(nowTime - lastTime > wait) {
fn.call(this,...args)
lastTime = nowTime
}
}
}
\ No newline at end of file
{
"cloud": {
"type": "CLOUDAPP"
},
"exclude": [
"server/**"
]
}
# taobao-mini-template
import request from "./utils/request";
const API = {
// 上传数据生成xslx文件 uploadDataCreateFile
exportAwardsList: (params) => request("exportAwardsList", "POST", params),
// 保存活动配置 saveActivityInfo
saveActivityInfo: (params) => request("saveActivityInfo", "POST", params),
// 删除活动 delActivity
delActivity: (params) => request("delActivity", "POST", params),
// 授权信息保存 sellerSave
sellerSave: (params) => request("sellerSave", "POST", params),
// 生成活动规则 generateRule
generateRule: params => request('generateRule', 'POST', params),
// 获取中奖名单 findWinnerInfoList
findWinnerInfoList: (params) => request("findWinnerInfoList", "POST", params),
// 获取活动列表云函数 getActivityList
getActivityList: (params) => request("getActivityList", "POST", params),
// 获取活动配置 getActivityDetail
getActivityDetail: (params) => request("getActivityDetail", "POST", params),
// 获取淘宝店家商品 findItemListByStatus
findItemListByStatus: (params) =>
request("findItemListByStatus", "POST", params, {
isShowLoading: true,
}),
// 通过id去查找商品 findItemListByIds
findItemListByIds: (params) =>
request("findItemListByIds", "POST", params, {
isShowLoading: true,
}),
// 通过权益ename查询商品 queryBenefitByEname
queryBenefitByEname: (params) =>
request("queryBenefitByEname", "POST", params),
// 复制创建新活动
createCopyActivity: (params) => request("createCopyActivity", "POST", params),
// 搜索条件查询中奖信息
downloadFile: (params) => request("downloadFile", "POST", params),
getAwardsList: (params) => request("getAwardsList", "POST", params),
// 导出数据需求
getStats: (params) => request("getStatList", "POST", params, { cloudFnType: 'c' })
};
export default API;
page {
background: #f7f7f7;
min-height: 100vh;
}
.adaptive-framework {
min-height: calc(100vh - 50px);
}
\ No newline at end of file
import cloud from '@tbmp/mp-cloud-sdk';
import { env } from './config';
cloud.init({
env,
});
App({
cloud,
onLaunch(options) {
console.info('App onLaunch');
},
onShow(options) {
// 从后台被 scheme 重新打开
// options.query == {number:1}
},
});
\ No newline at end of file
{
"pages": [
"pages/index/index",
"pages/cmp/index/index"
],
"window": {
"defaultTitle": "李子柒暗香涌动"
},
"plugins": {
"myPlugin": {
"version": "*",
"provider": "3000000002026202"
}
}
}
This diff is collapsed.
export const getMillSeconsByDays = (days = 1) => days * 24 * 3600 * 1000;
\ No newline at end of file
.db-dialog-content {
background-color: #fff;
position: fixed;
left: 50%;
top: 100px;
}
.db-dialog-title {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
font-weight: bold;
border-bottom: 1px solid rgba(215,219,224,1);
height: 60px;
padding: 0 24px;
}
.db-dialog-title_no {
height: 30px;
justify-content: flex-end;
}
.db-dialog-content_inner {
padding: 24px;
max-height: 400px;
overflow: scroll
}
.db-dialog-footer {
display: flex;
justify-content: flex-end;
border-top: 1px solid rgba(215,219,224,1);
}
.db-dialog-btns {
padding: 12px;
}
.db-dialog-btns Button {
margin-right: 15px;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
{
"component": true
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"component": true
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment