Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
taobao-mini-template
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
2
Issues
2
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
qinhaitao
taobao-mini-template
Commits
4a775d5e
Commit
4a775d5e
authored
Sep 01, 2021
by
mqf_0707
Browse files
Options
Browse Files
Download
Plain Diff
组件合并
parents
7ef34a85
3c965caf
Changes
52
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
52 changed files
with
4337 additions
and
2669 deletions
+4337
-2669
api.js
c_client/src/api.js
+4
-1
BrowserLoading.jsx
...rc/components/_tb_comps/BrowserLoading/BrowserLoading.jsx
+21
-0
BrowserLoading.module.less
...nents/_tb_comps/BrowserLoading/BrowserLoading.module.less
+29
-0
Browseroading.md
.../src/components/_tb_comps/BrowserLoading/Browseroading.md
+46
-0
GoodsList.jsx
c_client/src/components/_tb_comps/GoodsList/GoodsList.jsx
+1
-1
LoadingBar.jsx
c_client/src/components/_tb_comps/LoadingBar/LoadingBar.jsx
+51
-0
LoadingBar.module.less
...rc/components/_tb_comps/LoadingBar/LoadingBar.module.less
+33
-0
README.md
c_client/src/components/_tb_comps/Rank/README.md
+50
-0
RankList.jsx
c_client/src/components/_tb_comps/Rank/RankList/RankList.jsx
+38
-0
RankList.module.less
...c/components/_tb_comps/Rank/RankList/RankList.module.less
+0
-0
RankTitle.jsx
...ent/src/components/_tb_comps/Rank/RankTitle/RankTitle.jsx
+25
-0
RankTitle.module.less
...components/_tb_comps/Rank/RankTitle/RankTitle.module.less
+40
-0
index.jsx
c_client/src/components/_tb_comps/Rank/demo/index.jsx
+12
-0
index.js
c_client/src/components/_tb_comps/Rank/index.js
+2
-0
RankList.jsx
c_client/src/components/_tb_comps/RankList/RankList.jsx
+0
-33
RankTitle.jsx
c_client/src/components/_tb_comps/RankTitle/RankTitle.jsx
+0
-27
RankTitle.module.less
.../src/components/_tb_comps/RankTitle/RankTitle.module.less
+0
-19
RotateWheel.jsx
...ient/src/components/_tb_comps/RotateWheel/RotateWheel.jsx
+227
-0
RotateWheel.module.less
.../components/_tb_comps/RotateWheel/RotateWheel.module.less
+56
-0
rotatewheel.drawio
...t/src/components/_tb_comps/RotateWheel/rotatewheel.drawio
+49
-0
rotatewheel.md
c_client/src/components/_tb_comps/RotateWheel/rotatewheel.md
+55
-0
ScrollXView.jsx
...ient/src/components/_tb_comps/ScrollXView/ScrollXView.jsx
+53
-8
ScrollXView.md
c_client/src/components/_tb_comps/ScrollXView/ScrollXView.md
+54
-0
ScrollXView.module.less
.../components/_tb_comps/ScrollXView/ScrollXView.module.less
+34
-13
SwiperView.jsx
c_client/src/components/_tb_comps/SwiperView/SwiperView.jsx
+119
-0
SwiperView.less
c_client/src/components/_tb_comps/SwiperView/SwiperView.less
+147
-0
SwiperView.md
c_client/src/components/_tb_comps/SwiperView/SwiperView.md
+49
-0
index.jsx
.../components/_tb_comps/_Progress/ProgressContext/index.jsx
+22
-0
index.jsx
...src/components/_tb_comps/_Progress/ProgressNode/index.jsx
+117
-0
index.module.less
...onents/_tb_comps/_Progress/ProgressNode/index.module.less
+41
-0
README.md
c_client/src/components/_tb_comps/_Progress/README.md
+64
-0
index.jsx
c_client/src/components/_tb_comps/_Progress/demo/index.jsx
+79
-0
index.module.less
...src/components/_tb_comps/_Progress/demo/index.module.less
+21
-0
index.jsx
c_client/src/components/_tb_comps/_Progress/index.jsx
+97
-0
index.module.less
...ient/src/components/_tb_comps/_Progress/index.module.less
+22
-0
browse.config.js
c_client/src/config/browse.config.js
+14
-2
task.config.js
c_client/src/config/task.config.js
+1
-1
const.js
c_client/src/const.js
+10
-0
useAudio.js
c_client/src/hooks/useAudio.js
+53
-0
useAudio.md
c_client/src/hooks/useAudio.md
+89
-0
mock.js
c_client/src/mock.js
+222
-1
index.jsx
c_client/src/pages/index/index.jsx
+75
-3
index.module.less
c_client/src/pages/index/index.module.less
+1
-0
game.jsx
c_client/src/pages/packageGame/game/game.jsx
+0
-1
browseGoods.jsx
c_client/src/pages/packageGood/browseGoods/browseGoods.jsx
+26
-15
myPrize.jsx
c_client/src/pages/packagePrize/myPrize/myPrize.jsx
+3
-0
preComp.jsx
c_client/src/pages/preComp/preComp.jsx
+23
-0
preComp.module.less
c_client/src/pages/preComp/preComp.module.less
+0
-0
userInfo.js
c_client/src/store/userInfo.js
+14
-0
audio.js
c_client/src/utils/audio.js
+128
-0
util.js
c_client/src/utils/util.js
+16
-1
yarn.lock
c_client/yarn.lock
+2004
-2543
No files found.
c_client/src/api.js
View file @
4a775d5e
...
...
@@ -50,7 +50,10 @@ const apiList = {
method
:
'GET'
,
isShowLoading
:
false
,
toastError
:
false
}
},
getRotatePrizeListInfo
:
'getRotatePrizeListInfo'
,
//获取奖品列表接口,暂未实现
drawRotatePrize
:
'drawRotatePrize'
,
//大转盘抽奖接口,暂未实现
}
// 生成API
...
...
c_client/src/components/_tb_comps/BrowserLoading/BrowserLoading.jsx
0 → 100644
View file @
4a775d5e
import
React
,
{
useState
,
useEffect
}
from
"react"
;
import
{
View
,
Image
,
Text
}
from
"@tarojs/components"
;
import
LoadingBar
,{
LOAD_TYPE
}
from
"../LoadingBar/LoadingBar"
;
import
styles
from
'./BrowserLoading.module.less'
import
{
BROWSE_COUNTDOWN_OBJ
}
from
'@/config/browse.config'
const
BrowserLoading
=
(
props
)
=>
{
const
{
loadFlag
,
count
}
=
props
;
return
(
<
View
className=
{
styles
[
"browse_loading"
]
}
>
{
loadFlag
==
BROWSE_COUNTDOWN_OBJ
.
NUMBER
&&
(
<>
<
View
className=
{
styles
[
"count_img"
]
}
>
<
View
className=
{
styles
[
"count_time"
]
}
>
{
count
}
s
</
View
>
</
View
>
</>
)
}
{
loadFlag
==
BROWSE_COUNTDOWN_OBJ
.
PICTURE
&&
<
LoadingBar
type=
{
LOAD_TYPE
.
TASK
}
/>
}
</
View
>
);
};
export
default
BrowserLoading
;
c_client/src/components/_tb_comps/BrowserLoading/BrowserLoading.module.less
0 → 100644
View file @
4a775d5e
.browse_loading {
width: 200px;
height: 200px;
position: fixed;
right: 20px;
top: 400px;
border: 1px solid cyan;
box-sizing: border-box;
}
.count_img {
width: 100%;
height: 100%;
border: 1px solid rgb(47, 131, 99);
box-sizing: border-box;
background-image: url("//yun.dui88.com/7f705da9-5f16-4cf1-a239-3903c5c23995.png");
.image-property(contain, center center);
}
.count_time {
width: 100px;
height: 60px;
line-height: 60px;
margin: 40px auto 0;
border: 1px solid cyan;
box-sizing: border-box;
font-size: 40px;
font-weight: 600;
color: #000;
text-align: center;
}
c_client/src/components/_tb_comps/BrowserLoading/Browseroading.md
0 → 100644
View file @
4a775d5e
##### 是否展示浏览页中的倒计时
+
入参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| loadFlag | String | 倒计时类型"NUMBER","PICTURE" | 默认空 '' | NUMBER:数字倒计时 PICTURE:loading倒计时(默认15s,可在css中修改) |
| count | Number | 倒计时时间 | 15s | 默认倒计时15s(可改配置) |
+
使用
```
jsx
import
BrowserLoading
from
'../BrowserLoading/BrowserLoading'
export
const
Index
=
()
=>
{
return
(
<
BrowserLoading
loadFlag=
{
task
.
loadFlag
}
count=
{
count
}
/>
)
}
```
-------
###### loadingBar组件
+
入参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| bg | String | 背景loading | 'https://yun.duiba.com.cn/spark/assets/5a725b9e4ebf436a0a92c6317a5a4e47d87c8c1f.png' | / |
| bgTop | String | 上层loading | 'https://yun.duiba.com.cn/spark/assets/ccc405e28a5140d3aff9dff27b97fa5fb6bd7ff5.png' | / |
| type | String | "TASK","NORMAL" | 'NORMAL' | "TASK":自动loading倒计时 "NORMAL":静态的loading进度显示 |
| total | Number | loading总值 | / | type为"NORMAL"传入 |
| current | Number | 当前值 | 0 | type为"NORMAL"传入 |
+
使用
```
jsx
import
LoadingBar
,{
LOAD_TYPE
}
from
"../LoadingBar/LoadingBar"
;
export
const
Index
=
()
=>
{
return
(
<
LoadingBar
type=
{
LOAD_TYPE
.
NORMAL
}
total=
{
100
}
current=
{
10
}
/>
<
LoadingBar
type=
{
LOAD_TYPE
.
TASK
}
/>
)
}
```
\ No newline at end of file
c_client/src/components/_tb_comps/GoodsList/GoodsList.jsx
View file @
4a775d5e
import
React
,
{
useState
}
from
'react'
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
import
{
View
,
Image
,
ScrollView
}
from
'@tarojs/components'
import
classnames
from
'classnames'
import
tbccTs
from
'tbcc-sdk-ts'
...
...
c_client/src/components/_tb_comps/LoadingBar/LoadingBar.jsx
0 → 100644
View file @
4a775d5e
import
React
,{
useState
,
useEffect
}
from
'react'
import
{
View
,
Image
,
Text
}
from
'@tarojs/components'
import
styles
from
'./LoadingBar.module.less'
export
const
LOAD_TYPE
=
{
'TASK'
:
"TASK"
,
'NORMAL'
:
"NORMAL"
}
const
LoadingBar
=
(
props
)
=>
{
const
{
bg
=
'https://yun.duiba.com.cn/spark/assets/5a725b9e4ebf436a0a92c6317a5a4e47d87c8c1f.png'
,
bgTop
=
'https://yun.duiba.com.cn/spark/assets/ccc405e28a5140d3aff9dff27b97fa5fb6bd7ff5.png'
,
type
=
''
,
total
=
0
,
current
=
0
}
=
props
;
const
[
percent
,
setPercent
]
=
useState
(
0
);
useEffect
(()
=>
{
showCurrentLoading
();
},[])
/**
* @description 显示当前进度(进度条上没有其他内容)
*/
const
showCurrentLoading
=
()
=>
{
if
(
type
==
LOAD_TYPE
.
NORMAL
){
let
cur
=
current
>=
total
?
toal
:
current
;
setPercent
((
cur
/
total
*
100
).
toFixed
(
1
))
}
}
return
(
<
View
className=
{
styles
[
'load_container'
]
}
>
<
View
className=
{
styles
[
'load_content'
]
}
>
<
View
className=
{
styles
[
'load_bg'
]
}
style=
{
{
backgroundImage
:
`url(${bg})`
}
}
></
View
>
<
View
className=
{
`${styles['load_top']} ${type == LOAD_TYPE.TASK && 'loadAni'}`
}
style=
{
{
backgroundImage
:
`url(${bgTop})`
,
clipPath
:
`${type==LOAD_TYPE.NORMAL && `
inset
(
0
%
0
%
0
%
$
{
percent
}
%
)
`}`
}
}
></
View
>
</
View
>
</
View
>
)
}
export
default
LoadingBar
\ No newline at end of file
c_client/src/components/_tb_comps/LoadingBar/LoadingBar.module.less
0 → 100644
View file @
4a775d5e
.load_container{
.load_content{
width: 200px;
height: 80px;
margin: 0 auto;
overflow: hidden;
}
.load_bg,
.load_top{
width: 200px;
height: 60px;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
}
.loadAni{
animation: move 15s linear forwards;
}
}
@keyframes move {
0%{
clip-path: inset(0% 0% 0% 0%);
}
99%{
opacity: 1;
}
100%{
clip-path: inset(0% 100% 0% 0%);
opacity: 0;
}
}
\ No newline at end of file
c_client/src/components/_tb_comps/Rank/README.md
0 → 100644
View file @
4a775d5e
# 排行榜组件
---
## 何时使用
-
当某个页面需要展示累计邀请、分等级奖励进度条、累计签到等。
## 目录结构
`RankTitle`
排行榜头部
`RankList`
排行榜列表
## RankTitle API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --------- | ------------ | ----------- | ------------------------------------------------------- | ---- |
| titleList | 表头 | ArrayString | - | |
| myRank | 个人排名信息 | Object | { rank: '11', userNick: '用户名', rankValue: '534443' } | |
## RankList API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ----------- | ----------- | -------- | ---- |
| rankList | 排名信息 | ArrayObject | 见示例一 | |
| rankIcon | 前三名 Icon | Object | 见示例二 | |
## 示例一
```
[{
rank: 1,
userNick: '用户昵称',
hotValue: 98882892
}]
```
## 示例二
```
{
1: '//yun.duiba.com.cn/taobaomini/pike_call/icon_06.png',
2: '//yun.duiba.com.cn/taobaomini/pike_call/icon_07.png',
3: '//yun.duiba.com.cn/taobaomini/pike_call/icon_08.png'
}
```
c_client/src/components/_tb_comps/Rank/RankList/RankList.jsx
0 → 100644
View file @
4a775d5e
import
React
,{
memo
}
from
'react'
import
{
View
,
Image
,
ScrollView
}
from
'@tarojs/components'
import
{
RANK_LIST
}
from
'@/mock'
import
styles
from
'./RankList.module.less'
const
RANK_ICON
=
{
1
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_06.png'
,
2
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_07.png'
,
3
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_08.png'
}
const
RankList
=
memo
((
props
)
=>
{
const
{
rankList
=
RANK_LIST
,
rankIcon
=
RANK_ICON
}
=
props
return
(
<
ScrollView
scrollY
className=
{
styles
[
'scroll-container'
]
}
>
{
rankList
.
map
((
itm
,
i
)
=>
{
return
(
<
View
className=
{
`${styles['scroll-item']} ${
styles['scroll-item' + (i + 1)]
}`
}
>
<
View
className=
{
styles
[
'scroll-item__rank'
]
}
>
{
i
<=
2
&&
(
<
Image
className=
{
styles
[
'rank-icon'
]
}
src=
{
rankIcon
[
i
+
1
]
}
/>
)
}
<
View
className=
{
styles
[
'rank-num'
]
}
>
{
itm
.
rank
}
</
View
>
</
View
>
<
View
className=
{
styles
[
'scroll-item__user'
]
}
>
{
itm
.
userNick
}
</
View
>
<
View
className=
{
styles
[
'scroll-item__score'
]
}
>
{
itm
.
rankValue
}
</
View
>
</
View
>
)
})
}
</
ScrollView
>
)
})
export
default
RankList
c_client/src/components/_tb_comps/RankList/RankList.module.less
→
c_client/src/components/_tb_comps/Rank
/Rank
List/RankList.module.less
View file @
4a775d5e
File moved
c_client/src/components/_tb_comps/Rank/RankTitle/RankTitle.jsx
0 → 100644
View file @
4a775d5e
import
React
,
{
memo
}
from
'react'
import
{
View
}
from
'@tarojs/components'
import
styles
from
'./RankTitle.module.less'
const
RankTitle
=
memo
((
props
)
=>
{
const
{
titleList
=
[
'排名'
,
'用户名'
,
'人气值'
],
myRank
=
{
rank
:
'11'
,
userNick
:
'用户名'
,
rankValue
:
'534443'
}
}
=
props
return
(
<
View
className=
{
styles
[
'rank-box'
]
}
>
<
View
className=
{
styles
[
'rank-box__title'
]
}
>
{
titleList
.
map
(
val
=>
{
return
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
val
}
</
View
>
})
}
</
View
>
<
View
className=
{
styles
[
'rank-box__info'
]
}
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
rank
}
</
View
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
userNick
}
</
View
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
rankValue
}
</
View
>
</
View
>
</
View
>
)
})
export
default
RankTitle
c_client/src/components/_tb_comps/Rank/RankTitle/RankTitle.module.less
0 → 100644
View file @
4a775d5e
.rank-box {
.wh(100%,168px);
}
.rank-box__title {
.wh(100%,102px);
.flex-row-space();
.image('//yun.duiba.com.cn/taobaomini/pike_call/rank_title_bg.png');
}
.rank-box__info {
.wh(100%,66px);
.flex-row-space();
background: linear-gradient(-90deg, #FFDE8B 0%, #FFEAB5 100%);
}
.box-itm {
height: 66px;
width: 33%;
.flex-row-center();
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.box-itm:first-child {
font-size: 30px;
font-family: YouSheBiaoTiHei;
font-weight: 600;
color: #2D2B28;
}
.box-itm:nth-child(2) {
width: 34%;
font-size: 26px;
font-family: SourceHanSansCN;
font-weight: 400;
color: #666666;
}
.box-itm:last-child {
font-size: 28px;
font-family: WorkSans;
font-weight: 600;
color: #2D2B28;
}
\ No newline at end of file
c_client/src/components/_tb_comps/Rank/demo/index.jsx
0 → 100644
View file @
4a775d5e
import
{
RankList
,
RankTitle
}
from
'..'
const
Demo
=
()
=>
{
return
(
<>
<
RankTitle
/>
<
RankList
/>
</>
)
}
export
default
Demo
c_client/src/components/_tb_comps/Rank/index.js
0 → 100644
View file @
4a775d5e
export
{
default
as
RankList
}
from
'./RankList/RankList'
export
{
default
as
RankTitle
}
from
'./RankTitle/RankTitle'
c_client/src/components/_tb_comps/RankList/RankList.jsx
deleted
100644 → 0
View file @
7ef34a85
import
React
,
{
useState
}
from
'react'
import
{
View
,
Image
,
ScrollView
}
from
'@tarojs/components'
import
classnames
from
'classnames'
import
{
RANK_LIST
}
from
'@/mock'
import
styles
from
'./RankList.module.less'
const
RANK_ICON
=
{
1
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_06.png'
,
2
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_07.png'
,
3
:
'//yun.duiba.com.cn/taobaomini/pike_call/icon_08.png'
}
function
RankList
(
props
)
{
const
{
rankList
=
RANK_LIST
,
minNum
=
2
}
=
props
return
(
<
ScrollView
scrollY
className=
{
styles
[
'scroll-container'
]
}
>
{
rankList
.
map
((
itm
,
i
)
=>
{
return
(
<
View
className=
{
`${styles['scroll-item']} ${styles['scroll-item'+(i+1)]}`
}
>
<
View
className=
{
styles
[
'scroll-item__rank'
]
}
>
{
i
<=
minNum
&&
<
Image
className=
{
styles
[
'rank-icon'
]
}
src=
{
RANK_ICON
[
i
+
1
]
}
/>
}
<
View
className=
{
styles
[
'rank-num'
]
}
>
{
itm
.
rank
}
</
View
>
</
View
>
<
View
className=
{
styles
[
'scroll-item__user'
]
}
>
{
itm
.
userNick
}
</
View
>
<
View
className=
{
styles
[
'scroll-item__score'
]
}
>
{
itm
.
rankValue
}
</
View
>
</
View
>
)
})
}
</
ScrollView
>
)
}
export
default
RankList
\ No newline at end of file
c_client/src/components/_tb_comps/RankTitle/RankTitle.jsx
deleted
100644 → 0
View file @
7ef34a85
import
React
,
{
useState
}
from
'react'
import
{
View
,
Image
,
ScrollView
}
from
'@tarojs/components'
import
classnames
from
'classnames'
import
styles
from
'./RankTitle.module.less'
function
RankTitle
(
props
)
{
const
{
titleList
=
[
'排名'
,
'用户名'
,
'人气值'
],
myRank
=
{
rank
:
'11'
,
userNick
:
'用户名'
,
hotValue
:
'534443'
}
}
=
props
return
(
<
View
className=
{
styles
[
'rank-box'
]
}
>
<
View
className=
{
styles
[
'rank-box__title'
]
}
>
{
titleList
.
map
(
val
=>
{
return
(
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
val
}
</
View
>
)
})
}
</
View
>
<
View
className=
{
styles
[
'rank-box__info'
]
}
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
rank
}
</
View
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
userNick
}
</
View
>
<
View
className=
{
styles
[
'box-itm'
]
}
>
{
myRank
.
hotValue
}
</
View
>
</
View
>
</
View
>
)
}
export
default
RankTitle
\ No newline at end of file
c_client/src/components/_tb_comps/RankTitle/RankTitle.module.less
deleted
100644 → 0
View file @
7ef34a85
.rank-box {
.wh(100%,100px);
}
.rank-box__title,.rank-box__info {
.wh(100%,40px);
.flex-row-space();
}
.box-itm {
height: 100%;
width: 33%;
.flex-row-center();
}
.box-itm:nth-child(2) {
width: 34%;
}
.rank-box__info {
background-color: #000;
color: #ffffff;
}
\ No newline at end of file
c_client/src/components/_tb_comps/RotateWheel/RotateWheel.jsx
0 → 100644
View file @
4a775d5e
import
React
,{
useState
,
useEffect
}
from
'react'
import
{
View
,
Image
,
Text
}
from
'@tarojs/components'
import
styles
from
'./RotateWheel.module.less'
import
{
useThrottle
}
from
'@/hooks/useThrottle'
import
API
from
'@/api'
import
{
prizeList
}
from
'@/mock'
import
Taro
,{
showToast
,
redirectTo
,
navigateTo
}
from
'@tarojs/taro'
const
oneTurn
=
360
;
const
RotateWheel
=
(
props
)
=>
{
const
{
bg
=
'https://yun.duiba.com.cn/spark/assets/8b6e920ffd09fab8f9ac2de09f9154879f4d0607.png'
,
ratio
=
0.65
,
radius
=
300
,
circles
=
4
,
divideNum
=
8
,
duration
=
5000
,
timeFunction
=
'ease-out'
,
nodeInfo
=
{
width
:
100
,
height
:
100
},
imgInfo
=
{
width
:
80
,
height
:
80
},
showWay
=
"negative"
,
isShowPrizeName
=
true
,
prizeNameWidthRatio
=
1.2
,
callback
=
()
=>
{}
}
=
props
;
/* 奖品列表 */
const
[
prizelist
,
setPrizelist
]
=
useState
(
prizeList
)
/* 平分角度 */
const
[
angle
,
setAngle
]
=
useState
(
oneTurn
/
divideNum
)
/* my.createAniamation */
const
[
myAnimation
,
setMyAnimation
]
=
useState
()
/* 展示奖品列表 */
const
[
show
,
setShow
]
=
useState
(
false
)
/* 转动一圈时的角度值 */
const
[
rotateInOneTurn
,
setRotateInOneTurn
]
=
useState
(
0
)
/* 动画参数 */
const
[
ani
,
setAni
]
=
useState
({
startFlag
:
false
,
option
:{
duration
:
duration
,
timeFunction
:
timeFunction
,
rotate
:
0
}})
useEffect
(()
=>
{
computePosition
()
},[
prizeList
])
/**
* @description 获取奖品列表
*/
// const getPrizeListInfo = async () => {
// const {success,data,code,message} = await API.getRotatePrizeListInfo().catch((res)=>{
// showToast({title:res?.message ? res?.message : '网络异常,请稍后再试'})
// })
// if(success && data){
// const {list} = data;
// // setPrizelist(list)
// computePosition(list)
// }
// }
/**
* @description 计算奖品位置,旋转角度
*/
const
computePosition
=
()
=>
{
if
(
!
prizeList
.
length
)
return
;
let
centerX
,
centerY
,
color
,
rotate
;
/* 获取每块奖品的中心位置 */
prizelist
.
forEach
((
ele
,
i
)
=>
{
if
(
i
%
2
==
0
)
{
color
=
'#527aff'
;
}
else
{
color
=
'#f13082'
}
// 当前奖品左上角位置
if
(
showWay
===
'negative'
){
centerX
=
radius
-
ratio
*
radius
*
(
Math
.
sin
((
angle
/
2
+
angle
*
(
i
))
/
180
*
Math
.
PI
));
centerY
=
radius
-
ratio
*
radius
*
(
Math
.
cos
((
angle
/
2
+
angle
*
(
i
))
/
180
*
Math
.
PI
));
rotate
=
-
(
angle
/
2
+
angle
*
i
);
}
else
{
centerX
=
radius
-
ratio
*
radius
*
(
Math
.
sin
((
angle
/
2
+
angle
*
(
-
i
))
/
180
*
Math
.
PI
));
centerY
=
radius
-
ratio
*
radius
*
(
Math
.
cos
((
angle
/
2
+
angle
*
(
-
i
))
/
180
*
Math
.
PI
));
// 旋转角度
rotate
=
-
(
angle
/
2
+
angle
*
(
-
i
));
}
ele
.
rotate
=
rotate
ele
.
color
=
color
// 奖品位置
let
disleft
=
centerX
-
nodeInfo
.
width
/
2
;
let
distop
=
centerY
-
nodeInfo
.
height
/
2
;
ele
.
centerX
=
disleft
ele
.
centerY
=
distop
ele
.
num
=
i
;
// 测试:设置奖品Id
ele
.
prizeId
=
100
+
i
;
})
console
.
log
(
'prizelist'
,
prizelist
);
setPrizelist
(
prizelist
)
setShow
(
true
)
}
/**
* @description 抽奖
*/
const
drawPrize
=
useThrottle
(
async
()
=>
{
// const {success,data,message,code} = await API.drawRotatePrize().catch((res)=>{
// showToast({title:res?.message ? res?.message : '网络异常,请稍后再试'})
// });
// if(success && data){
// const {prizeId,id} = data;
// }
// test
let
prizeId
=
Math
.
floor
(
Math
.
random
()
*
prizelist
.
length
)
+
100
;
startRotation
(
prizeId
)
setTimeout
(()
=>
{
// 弹出弹窗
callback
&&
callback
()
//prizeInfo
},
duration
+
1000
);
},
duration
)
/**
* @description 根据奖品id开始旋转
* @param {*} prizeId 抽中的奖品id
*/
const
startRotation
=
(
prizeId
)
=>
{
console
.
log
(
'start'
);
let
rotateAngle
;
let
num
;
let
oneturnAngle
;
prizelist
.
forEach
((
ele
)
=>
{
if
(
ele
.
prizeId
===
prizeId
){
num
=
ele
.
num
;
}
})
// 旋转角度 ( 旋转圈数 + 对应位置(0,7) ) * 平分角度 + 平分角度 / 2
if
(
showWay
===
'negative'
){
rotateAngle
=
oneTurn
*
circles
+
num
*
angle
+
angle
/
2
;
oneturnAngle
=
num
*
angle
+
angle
/
2
;
}
else
{
rotateAngle
=
oneTurn
*
circles
+
(
prizelist
.
length
-
num
)
*
angle
+
angle
/
2
;
oneturnAngle
=
(
prizelist
.
length
-
num
)
*
angle
+
angle
/
2
}
console
.
log
(
'rotateAngle'
,
rotateAngle
,
num
,
prizeId
);
/* 执行动画 */
setAni
({
startFlag
:
true
,
option
:{
...
ani
.
option
,
rotate
:
ani
.
option
.
rotate
-
rotateInOneTurn
+
rotateAngle
}
})
setRotateInOneTurn
(
oneturnAngle
)
}
// my.createAnimation 旋转动画rot:旋转角度,timegap:旋转时间
// const animateRotation = (rot, timegap) => {
// var animation = my.createAnimation({
// transformOrigin: "center center",
// duration: 5000,
// timeFunction: "ease-out",
// delay: 0
// })
// console.log('animation',animation);
// animation.rotate(rot).step();
// setMyAnimation(animation.export())
// setTimeout(() => {
// setMyAnimation()
// }, 5000);
// }
return
(
<>
<
View
className=
{
`${styles['rotate_container']}`
}
style=
{
{
backgroundImage
:
`url(${bg})`
,
transform
:
ani
.
startFlag
?
`rotate(${ani.option.rotate}deg)`
:
''
,
transition
:
ani
.
startFlag
?
`all ${ani.option.timeFunction} ${ani.option.duration}ms`
:
''
}
}
// animation={myAnimation}
>
{
show
&&
prizelist
.
length
&&
prizelist
.
map
((
ele
,
i
)
=>
{
return
(
<
View
className=
{
styles
[
'item'
]
}
style=
{
{
// backgroundColor:`$
{
ele
?.
color
}
`,
width:`
$
{
nodeInfo
.
width
/
100
}
rem
`,
height:`
$
{
nodeInfo
.
height
/
100
}
rem
`,
transform:`
rotate
(
$
{
ele
?.
rotate
}
deg
)
`,
top:`
$
{
ele
.
centerY
/
100
}
rem
`,
left:`
$
{
ele
.
centerX
/
100
}
rem
`,
position:'absolute'
}
}
key=
{
'item'
+
i
}
>
{
isShowPrizeName
&&
<
View
className=
{
styles
[
'prize_name'
]
}
style=
{
{
width
:
`${prizeNameWidthRatio * 100}%`
,
height
:
`${30/100}rem`
,
}
}
>
{
ele
.
name
}
</
View
>
}
<
View
className=
{
styles
[
'prize_img'
]
}
style=
{
{
backgroundImage
:
`url(${ele.image})`
,
width
:
`${imgInfo.width/100}rem`
,
height
:
`${imgInfo.height/100}rem`
}
}
></
View
>
</
View
>
)
})
}
</
View
>
<
View
className=
{
styles
[
'circle'
]
}
onTap=
{
drawPrize
}
>
draw
</
View
>
</>
)
}
export
default
RotateWheel
\ No newline at end of file
c_client/src/components/_tb_comps/RotateWheel/RotateWheel.module.less
0 → 100644
View file @
4a775d5e
.rotate_container{
width: 100%;
height: 100%;
// border: 1px solid cyan;
// box-sizing: border-box;
position: relative;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.image-property(cover, center center);
.item{
position: absolute;
display: flex;
justify-content: space-evenly;
align-items: center;
transform-origin: center;
flex-direction: column;
// border: 1px solid cyan;
// box-sizing: border-box;
.prize_name{
// margin: 0 auto;
// border: 1px solid cyan;
// box-sizing: border-box;
// display: flex;
// justify-content: center;
// align-items: center;
text-align: center;
white-space: nowrap;
font-size: 18px;
text-overflow: ellipsis;
overflow: hidden;
}
.prize_img{
.image-property(cover, center center);
margin: 0 auto;
}
}
}
.circle{
// border-radius: 50%;
width: 100px;
height: 100px;
background-color: rgb(78, 159, 165);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
clip-path: polygon(50% 0%,0% 100%,100% 100%);
}
c_client/src/components/_tb_comps/RotateWheel/rotatewheel.drawio
0 → 100644
View file @
4a775d5e
<mxfile host="65bd71144e">
<diagram id="aWOBYljMTH3HiLopJFIH" name="第 1 页">
<mxGraphModel dx="899" dy="594" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="3" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;shadow=1;fillColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="200" y="160" width="300" height="300" as="geometry"/>
</mxCell>
<mxCell id="6" value="" style="endArrow=none;dashed=1;html=1;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="310" as="sourcePoint"/>
<mxPoint x="500" y="310" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="8" value="" style="endArrow=none;dashed=1;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fillColor=#FF9999;" edge="1" parent="1" source="3" target="3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="430" y="330" as="sourcePoint"/>
<mxPoint x="480" y="280" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="9" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="379" y="210" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="10" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="379" y="340" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="11" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="250" y="210" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="12" value="" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;fillColor=#FFCCCC;rotation=45;" vertex="1" parent="1">
<mxGeometry x="250" y="340" width="70" height="70" as="geometry"/>
</mxCell>
<mxCell id="13" value="1.找到每个奖品的中心位置<br>2.每个奖品旋转相应角度<br>3.给相应的奖品区域设置样式" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;shadow=0;" vertex="1" parent="1">
<mxGeometry x="490" y="180" width="250" height="50" as="geometry"/>
</mxCell>
<mxCell id="16" value="旋转逻辑" style="rounded=0;whiteSpace=wrap;html=1;shadow=0;strokeColor=#000000;fillColor=#FFCCCC;" vertex="1" parent="1">
<mxGeometry x="80" y="510" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="17" value="给每个奖品设置一个索引值,抽中的奖品id与奖品列表对应,则根据索引值旋转对应的角度。" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;shadow=0;" vertex="1" parent="1">
<mxGeometry x="80" y="590" width="200" height="110" as="geometry"/>
</mxCell>
<mxCell id="18" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;shadow=0;strokeColor=#000000;fillColor=#FFCCCC;" vertex="1" parent="1">
<mxGeometry x="310" y="270" width="80" height="80" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
\ No newline at end of file
c_client/src/components/_tb_comps/RotateWheel/rotatewheel.md
0 → 100644
View file @
4a775d5e
**记事本打开**
##### 大转盘配置项入参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| bg | String | 转盘背景 | / | / |
| radius | Number | 转盘半径大小 | 300 | px |
| ratio | Number | 距离中心点的比例系数 | 0.65 | 小于1 |
| divideNum | Number | 转盘划分为几等分 | 8 | 最少2等分|
| circles | Number | 转盘基本转动圈数 | 4 | / |
| duration | Number | 转盘持续时间 | 4000 | 毫秒 |
| timeFunction | String | 缓动动画方式 | 'ease-out' | 'ease-in-out', cubic-bezier(xx,xx,xx,xx) |
| nodeInfo | Object | 单个奖品区域大小 | {width:100,height:100} | 宽高100px |
| imgInfo | Object | 奖品图片大小 | {width:80,height:80} | 宽高80px |
| showWay | String | 奖品排列方式 | 'negative' |negative逆时针排列 positive顺时针排列|
| isShowPrizeName | Boolean | 是否展示奖品名称 | true | true展示 false不展示 |
| prizeNameWidthRatio | Number | 奖品名称容器宽度与nodeInfo宽度的比值 | 1.2 | 超过容器宽度则...省略 |
##### 出参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| callback | Function | 回调函数 | / |抽中奖品后的回调方法,后续的弹窗处理|
+
使用
```
jsx
import
RotateWheel
from
'@/components/_tb_comps/RotateWheel/RotateWheel'
const
rotateConfig
=
{
//不传走默认配置
bg
:
'https://yun.duiba.com.cn/spark/assets/8b6e920ffd09fab8f9ac2de09f9154879f4d0607.png'
,
ratio
:
0.65
,
radius
:
300
,
circles
:
4
,
divideNum
:
8
,
duration
:
5000
,
timeFunction
:
'ease-out'
,
nodeInfo
:{
width
:
100
,
height
:
100
},
imgInfo
:{
width
:
80
,
height
:
80
},
showWay
:
'negative'
,
//positive/negative
isShowPrizeName
:
true
}
export
const
Index
=
()
=>
{
return
(
<
RotateWheel
{
...
rotateConfig
}
callback=
{
()
=>
{}
}
/>
)
}
```
\ No newline at end of file
c_client/src/components/_tb_comps/ScrollXView/ScrollXView.jsx
View file @
4a775d5e
...
...
@@ -4,24 +4,69 @@ import Taro, { useShareAppMessage, useDidShow } from '@tarojs/taro'
import
classnames
from
'classnames'
import
styles
from
'./ScrollXView.module.less'
function
ScrollXView
(
props
)
{
const
{
prizeList
=
[],
marginRight
=
26
,
width
=
300
,
height
=
300
}
=
props
const
{
prizeList
=
[],
containerWidth
=
300
,
containerHeight
=
300
,
imgWidth
=
240
,
imgHeight
=
240
,
isShowPrizeName
=
true
,
prizeInCenterNum
=
2
,
marginRight
=
26
,
backgroundColor
=
'#E7E7EF'
}
=
props
const
showPrize
=
classnames
(
styles
[
'show-pize-box'
],{
[
`
${
styles
[
'show-pize-box__two'
]}
`
]:
prizeList
.
length
===
1
[
`
${
styles
[
'show-pize-box__two'
]}
`
]:
prizeList
.
length
<=
prizeInCenterNum
,
[
`
${
styles
[
'show-pize-box__more'
]}
`
]:
prizeList
.
length
>
prizeInCenterNum
,
})
return
(
<>
<
ScrollView
scrollX
className=
{
styles
[
'scroll-x-box'
]
}
>
{
<
View
className=
{
showPrize
}
style=
{
prizeList
.
length
>
1
?{
width
:
(
prizeList
.
length
*
width
+
(
prizeList
.
length
)
*
marginRight
+
100
)
/
100
+
'rem'
}:
{
width
:
'100%'
}
}
>
{
<
View
className=
{
showPrize
}
>
{
prizeList
.
map
(
itm
=>
{
prizeList
.
map
(
(
itm
,
i
)
=>
{
return
(
<
View
style=
{
{
width
:
width
/
100
+
'rem'
,
height
:
height
/
100
+
'rem'
}
}
className=
{
styles
[
'show-pirze__item'
]
}
>
<
View
className=
{
styles
[
'pirze__item-img'
]
}
>
<
Image
src=
{
itm
.
image
}
className=
{
styles
[
'pirze__item-img-icon'
]
}
/>
<
View
key=
{
'prize'
+
i
}
className=
{
styles
[
'show-pirze__item'
]
}
style=
{
{
width
:
`${containerWidth/100}rem`
,
height
:
`${containerHeight/100}rem`
,
backgroundColor
:
backgroundColor
,
marginRight
:
`${((prizeList.length > prizeInCenterNum) &&(prizeList.length - 1) !== i) ? `
$
{
marginRight
/
100
}
rem
` : ''}`
}
}
>
<
View
className=
{
styles
[
'pirze__item-img'
]
}
style=
{
{
width
:
`${imgWidth/100}rem`
,
height
:
`${imgHeight/100}rem`
}
}
>
<
Image
src=
{
itm
.
image
}
className=
{
styles
[
'pirze__item-img-icon'
]
}
style=
{
{
width
:
`${imgWidth/100}rem`
,
height
:
`${imgHeight/100}rem`
}
}
/>
</
View
>
<
View
className=
{
styles
[
'pirze__item-name'
]
}
>
{
itm
.
name
}
</
View
>
{
isShowPrizeName
&&
<
View
className=
{
styles
[
'pirze__item-name'
]
}
style=
{
{
height
:
`${60/100}rem`
,
// lineHeight:`$
{
60
/
100
}
rem
`,
fontSize:`
$
{
24
/
100
}
rem
`
}
}
>
{
itm
.
name
}
</
View
>
}
</
View
>
)
})
...
...
c_client/src/components/_tb_comps/ScrollXView/ScrollXView.md
0 → 100644
View file @
4a775d5e
##### ScrollXView滑动配置项
+
入参
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| prizeList | Array | 滑动数据 |
[
...
]
| / |
| containerWidth | Number | 单个奖品容器的宽度 | 300 | / |
| containerHeight | Number | 单个奖品容器的高度 | 300 | / |
| imgWidth | Number | 奖品图片宽度 | 200 | / |
| imgHeight | Number | 奖品图片高度 | 200 | / |
| isShowPrizeName | Boolean | 是否展示奖品名称 | true | true:展示 false:不展示 |
| prizeInCenterNum | Number | 奖品少于n个时居中展示 | n=2 | 多于n个,可滑动查看 |
| marginRight | Number | 奖品容器之间间距 | 26 | px |
| backgroundColor | Number | 奖品容器背景颜色 | #E7E7EF | / |
+
prizeList数组格式
```
json
[
{
"image"
:
""
,
"name"
:
"xxx"
,
//
...
},
//
...
]
```
+
使用
```
jsx
import
ScrollXView
from
'@/components/_tb_comps/ScrollXView/ScrollXView'
// 组件不一定在该目录下,举例说明一下
const
SCROLLXVIEW_CONFIG
=
{
//不传走默认配置
prizeList
:
[],
containerWidth
:
300
,
containerHeight
:
300
,
imgWidth
:
200
,
imgHeight
:
200
,
isShowPrizeName
:
true
,
prizeInCenterNum
:
2
,
marginRight
:
26
,
backgroundColor
:
'#E7E7EF'
}
export
const
Index
=
()
=>
{
return
(
<
View
className=
"scroll"
>
<
ScrollXView
{
...
SCROLLXVIEW_CONFIG
}
prizeList=
{
prizeList
}
/>
</
View
>
)
}
```
\ No newline at end of file
c_client/src/components/_tb_comps/ScrollXView/ScrollXView.module.less
View file @
4a775d5e
...
...
@@ -10,37 +10,58 @@
align-items: center;
}
.show-pize-box__two {
width: 100%;
display: flex;
justify-content:
center
;
justify-content:
space-around
;
align-items: center;
}
.show-pirze__item {
background: #E7E7EF;
//
background: #E7E7EF;
border-radius: 25px;
margin-left: 26px;
}
.show-pirze__item:last-child {
margin-right: 26px;
// margin-left: 26px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.show-pirze__item:first-child {
margin-left: 10px;
// .show-pirze__item:last-child {
// margin-right: 26px;
// }
// .show-pirze__item:first-child {
// margin-left: 10px;
// }
.show-pize-box__more{
// padding: 10px;
}
.pirze__item-img {
width: 224px;
height: 224px;
//
width: 224px;
//
height: 224px;
background: #FFFFFF;
border-radius: 25px;
margin: 16px auto 20px;
}
.pirze__item-img-icon {
width: 224px;
height: 224px;
//
width: 224px;
//
height: 224px;
border-radius: 25px;
.image-property(cover, center center);
}
.pirze__item-name {
font-size: 25px
;
width: 90%
;
font-family: FZLTHProGlobal;
font-weight: 400;
color: #1C1C1C;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
// 单行
// white-space: nowrap;
// 多行
// display: -webkit-box;
// -webkit-box-orient:vertical;
// -webkit-line-clamp: 2;
}
\ No newline at end of file
c_client/src/components/_tb_comps/SwiperView/SwiperView.jsx
0 → 100644
View file @
4a775d5e
import
React
,
{
useState
,
useEffect
,
useRef
}
from
"react"
;
import
{
View
,
Image
,
Text
,
Swiper
,
SwiperItem
}
from
"@tarojs/components"
;
import
'./SwiperView.less'
import
Taro
,{
showToast
,
redirectTo
,
navigateTo
}
from
'@tarojs/taro'
export
const
EASING_WAYS
=
{
'DEFAULT'
:
'default'
,
'LINEAR'
:
'linear'
,
'EASEIN'
:
'easeInCubic'
,
'EASEOUT'
:
'easeOutCubic'
,
'EASEINOUT'
:
'easeInOutCubic'
}
const
SwiperView
=
(
props
)
=>
{
/**
* @description swiperList
* {image,content,hasBtn}
*/
const
{
swiperList
=
[],
isSpecial
=
true
,
easingFunction
=
`
${
EASING_WAYS
.
LINEAR
}
`
,
circular
=
true
,
autoplay
=
false
,
vertical
=
false
,
duration
=
1000
,
interval
=
1500
,
disableTouch
=
false
}
=
props
;
const
[
currentIndex
,
setCurrentIndex
]
=
useState
(
0
);
/**
* @description onchange事件
* @param {*} e
*/
const
swiperChange
=
e
=>
{
console
.
log
(
"e"
,
e
);
setCurrentIndex
(
e
.
detail
.
current
);
};
/**
* @description 入场/出场动画
* @param {*} index 数组索引值
* @returns 返回类名
*/
const
useCustomAni
=
(
index
)
=>
{
return
`
${
currentIndex
>
0
&&
currentIndex
==
index
&&
'move_in'
}
${
currentIndex
-
1
==
index
&&
'move_out'
}
`
}
/**
* @description 获取当前卡片详情之类
*/
const
getCurrentDetail
=
(
item
)
=>
{
showToast
({
title
:
'111'
})
}
return
(
<
View
className=
"scroll_container"
>
<
Swiper
className=
"swiper_group"
current=
{
currentIndex
}
easingFunction=
{
easingFunction
}
onChange=
{
swiperChange
}
circular=
{
circular
}
vertical=
{
vertical
}
autoplay=
{
autoplay
}
duration=
{
duration
}
interval=
{
interval
}
disableTouch=
{
disableTouch
}
>
{
swiperList
.
length
&&
swiperList
.
map
((
item
,
i
)
=>
(
<
SwiperItem
>
<
View
className=
{
`scroll_item ${i === currentIndex && isSpecial ? "current_item" : ""} ${useCustomAni(i)}`
}
>
{
/* {i === currentIndex && (
<Image
className="checkPic"
src="https://yun.dui88.com/tebuXinYuan/checkGoods.png"
></Image>
)} */
}
<
View
className=
"item_img_content"
>
{
/* 单个swiper主要内容 */
}
<
Image
className=
"img"
style=
{
{
width
:
`${400/100}rem`
,
height
:
`${240/100}rem`
}
}
src=
{
item
.
image
}
></
Image
>
{
item
?.
content
&&
<
View
className=
'text_content'
style=
{
{
width
:
'100%'
,
height
:
`${160/100}rem`
}
}
>
<
View
className=
'text'
>
{
item
.
content
}
</
View
>
</
View
>
}
{
item
?.
hasBtn
&&
<
View
className=
'item_btn'
>
<
View
className=
'right_btn'
onTap=
{
()
=>
getCurrentDetail
(
item
)
}
>
按钮
{
i
}
</
View
>
</
View
>
}
</
View
>
</
View
>
</
SwiperItem
>
))
}
</
Swiper
>
</
View
>
);
};
export
default
SwiperView
;
c_client/src/components/_tb_comps/SwiperView/SwiperView.less
0 → 100644
View file @
4a775d5e
.scroll_container{
width: 450px;
margin: 300px auto 0;
overflow: hidden;
.swiper_group {
margin: 0 auto;
width: 450px;
overflow: visible;
position: relative;
swiper-item {
width: 450px;
display: flex;
justify-content: center;
align-items: center;
}
.scroll_item {
width: 400px;
margin: 0 auto;
position: relative;
border-radius: 20px;
.image-property(cover, top center);
.checkPic {
width: 60px;
height: 60px;
border-radius: 50%;
position: absolute;
right: 40px;
top: 40px;
}
.item_img_content {
width: 100%;
// padding: 20px;
.img {
margin: 20px auto 0;
border-radius: 20px;
background-repeat: no-repeat;
background-position: top center;
}
.text_content{
margin: 0 auto;
box-sizing: border-box;
padding: 16px;
display: flex;
justify-content: center;
align-items: center;
.text{
color: #232323;
text-align: center;
font-size: 24px;
padding: 16px;
}
}
.item_btn{
width: 100%;
.right_btn{
// background-image: url('https://yun.duiba.com.cn/spark/assets/33bc06a1be4bf250345e24900bc5719992328d4e.png');
// .image-property(cover, center center);
width: 200px;
height: 65px;
margin: 0 auto;
border-radius: 40px;
border: 2px solid rgb(79, 172, 118) ;
text-align: center;
line-height: 65px;
font-size: 26px;
// animation: scales 2s infinite;
}
}
}
&.current_item {
.item_img_content {
.img{}
.text_content{
.text{}
}
.item_btn{
.right_btn{}
}
}
}
// &.move_in{
// animation: movein 0.8s linear forwards;
// }
// &.move_out{
// animation: moveout 0.8s linear ;
// }
}
}
}
@keyframes movein {
from {
transform: perspective(1000px) translate3d(0,0,0) rotate3d(0, 1, 0, 25deg) scale(0.85);
transform-style: preserve-3d;
transform-origin: 45% center;
}
50%{
transform: perspective(1000px) translate3d(0,20px,0) rotate3d(0, 1, 0, 25deg) scale(0.85);
transform-style: preserve-3d;
transform-origin: 45% center;
}
to {
transform: perspective(1100px) translate3d(0,0,0) rotate3d(0, 1, 0, 0deg) scale(1);
transform-origin: 45% center;
transform-style: preserve-3d;
}
}
@keyframes moveout{
from {
transform: perspective(1000px) rotate3d(0, 1, 0, 0deg) scale(1);
transform-style: preserve-3d;
transform-origin: 45% center;
}
50%{
transform: perspective(1000px) rotate3d(0, 1, 0, 25deg) scale(1);
transform-style: preserve-3d;
transform-origin: 45% center;
}
to {
transform: perspective(1200px) rotate3d(0, 1, 0, 25deg) scale(0.85);
transform-origin: 45% center;
transform-style: preserve-3d;
}
}
@keyframes scales {
from{
transform: scale(1,1);
transform-origin: center;
}
50%{
transform: scale(1.1,1.1);
transform-origin: center;
}
to{
transform: scale(1,1);
transform-origin: center;
}
}
\ No newline at end of file
c_client/src/components/_tb_comps/SwiperView/SwiperView.md
0 → 100644
View file @
4a775d5e
##### swiperView 滑动
| 配置项 | 类型 | 描述 | 默认值 | 备注 |
| :-------- | :-----: | :--------: | :-----: | :---:|
| swiperList | Array | 滑动数组 |
[
...
]
| / |
| disableTouch | Boolean | 是否可手动滑动 | false | true 可滑动 false 不可滑动 |
| autoplay | Boolean | 是否自动切换 | false |/|
| circular | Boolean | 是否采用衔接滑动| false |/|
| vertical | Boolean | 是否垂直切换| false |/|
| duration | Number | 滑动动画时长| 1000 |/|
| interval | Number | 自动切换时间间隔| 1500 |/|
| easingFunction|String | 缓动动画类型| linear |'default','linear' 'easeInCubic' 'easeOutCubic' 'easeInOutCubic'|
#### swiperList数据
```
json
[
{
"image"
:
""
,
//图片链接
,
图片宽高需要在less中修改
"content"
:
""
,
//图片描述
"hasBtn"
:
""
,
//注入数据(是否有按钮)
//
或者手动修改组件中的字段名称
...
},
//
...
]
```
+
使用
```
jsx
import
SwiperView
from
'@/components/_tb_comps/SwiperView/SwiperView'
const
swiperConfig
=
{
//不传走默认配置
swiperList
:[],
isSpecial
:
true
,
easingFunction
:
`linear`
,
circular
:
true
,
autoplay
:
false
,
vertical
:
false
,
duration
:
1000
,
interval
:
1500
,
disableTouch
:
false
}
export
const
Index
=
()
=>
{
return
(
<
SwiperView
{
...
swiperConfig
}
swiperList=
{
swiperList
}
/>
)
}
```
\ No newline at end of file
c_client/src/components/_tb_comps/_Progress/ProgressContext/index.jsx
0 → 100644
View file @
4a775d5e
/**
* 全局配置
*/
import
React
from
'react'
export
const
BtnTexts
=
{
UNREACH
:
''
,
REACH_UNRECEIVED
:
''
,
REACH_RECEIVED
:
''
}
export
const
ProgressGlobalConfig
=
{
type
:
1
,
maxLevel
:
15
,
width
:
500
,
BtnTexts
}
export
const
ProgressContext
=
React
.
createContext
()
c_client/src/components/_tb_comps/_Progress/ProgressNode/index.jsx
0 → 100644
View file @
4a775d5e
import
{
View
,
Image
}
from
'@tarojs/components'
import
{
memo
,
useContext
,
useMemo
}
from
'react'
import
classnames
from
'classnames'
import
{
ProgressContext
}
from
'../ProgressContext'
// css
import
styles
from
'./index.module.less'
const
ProgressNode
=
memo
(
props
=>
{
const
{
descInfo
,
iconInfo
,
isReceived
=
false
,
isReach
,
levelValue
,
levelPos
,
id
}
=
props
const
{
BtnTexts
,
maxLevel
,
nodeClassName
,
iconImgClassName
,
iconTxtClassName
,
iconClassName
,
descClassName
,
btnClassName
,
activeBtnClassName
,
disableBtnClassName
,
onReceviceClick
}
=
useMemo
(()
=>
useContext
(
ProgressContext
),
ProgressContext
)
// 节点按钮点击
const
btnClick
=
()
=>
{
return
isReach
&&
!
isReceived
?
onReceviceClick
(
id
)
:
null
}
// 判断方法
const
checkFunc
=
fn
=>
{
return
typeof
fn
===
'function'
}
// 判断对象是否为空
const
checkObject
=
obj
=>
{
return
obj
instanceof
Object
&&
JSON
.
stringify
(
obj
)
!==
'{}'
}
const
getNodeStyle
=
classnames
(
styles
[
'defualt-progress-node'
],
{
[
nodeClassName
]:
nodeClassName
})
const
getDescStyle
=
classnames
(
styles
[
'defualt-progress-node-desc'
],
{
[
descInfo
?.
className
]:
descInfo
?.
className
,
[
descClassName
]:
descClassName
})
const
getIconStyle
=
classnames
(
styles
[
'defualt-progress-node-icon'
],
{
[
iconInfo
?.
className
]:
iconInfo
?.
className
,
[
iconClassName
]:
iconClassName
})
const
getIconImgStyle
=
classnames
(
styles
[
'defualt-progress-node-icon-iconImg'
],
{
[
iconImgClassName
]:
iconImgClassName
}
)
const
getIconTxtStyle
=
classnames
(
styles
[
'defualt-progress-node-icon-txt'
],
{
[
iconTxtClassName
]:
iconTxtClassName
})
const
getBtnStyle
=
classnames
(
styles
[
'defualt-progress-node-btn-txt'
],
{
[
btnClassName
]:
!
isReach
&&
btnClassName
,
[
activeBtnClassName
]:
isReach
&&
!
isReceived
&&
activeBtnClassName
,
[
disableBtnClassName
]:
isReach
&&
isReceived
&&
disableBtnClassName
})
return
(
<
View
className=
{
getNodeStyle
}
style=
{
{
left
:
levelPos
?
levelPos
:
(
levelValue
/
maxLevel
)
*
100
+
'%'
}
}
>
{
/* 描述 */
}
{
checkObject
(
descInfo
)
&&
(
<
View
className=
{
getDescStyle
}
>
{
descInfo
.
descTxt
}
</
View
>
)
}
{
/* icon */
}
{
checkObject
(
iconInfo
)
&&
(
<
View
className=
{
getIconStyle
}
>
{
iconInfo
?.
iconUrl
&&
(
<
Image
className=
{
getIconImgStyle
}
src=
{
iconInfo
.
iconUrl
}
/>
)
}
{
iconInfo
?.
iconTxt
&&
(
<
View
className=
{
getIconTxtStyle
}
>
{
iconInfo
.
iconTxt
}
</
View
>
)
}
</
View
>
)
}
{
/* 节点按钮 */
}
{
checkFunc
(
onReceviceClick
)
&&
(
<
View
className=
{
getBtnStyle
}
onTap=
{
btnClick
}
>
{
isReach
?
isReceived
?
BtnTexts
.
REACH_RECEIVED
:
BtnTexts
.
REACH_UNRECEIVED
:
BtnTexts
.
UNREACH
}
</
View
>
)
}
</
View
>
)
})
export
default
ProgressNode
c_client/src/components/_tb_comps/_Progress/ProgressNode/index.module.less
0 → 100644
View file @
4a775d5e
.defualt-progress-node {
display: flex;
flex-direction: column;
position: absolute;
z-index: 10;
font-size: 20px;
transform: translate(-100%, -100%);
white-space: nowrap;
}
// 描述
.defualt-progress-node-desc {
position: absolute;
right: -110px;
top: -54px;
z-index: 11;
}
// Icon
.defualt-progress-node-icon {
.wh(32px, 32px);
}
// Icon贴图
.defualt-progress-node-icon-iconImg {
.wh(155px, 151px);
position: absolute;
top: -54px;
}
// Icon文本
.defualt-progress-node-icon-txt {
font-size: 22px;
}
// 按钮
.defualt-progress-node-btn-txt {
position: absolute;
top: 80px;
left: 6px;
}
c_client/src/components/_tb_comps/_Progress/README.md
0 → 100644
View file @
4a775d5e
# 进度条组件
---
## 何时使用
-
当某个页面需要展示累计邀请、分等级奖励进度条、累计签到等。
## 目录结构
`ProgressContext`
进度条全局默认配置
`ProgressNode`
进度条节点
## API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| levelList | 节点数据 | ArrayObject | 见下面示例一 | |
| currentValue | 当前进度值 | Numbver | 0 | |
| className | 进度条节点组样式 | Object | - | |
| maxLevel | 最大值 | Number | 15 | |
| width | 进度条长度 | Number | 500 | |
| BtnTexts | 进度按钮状态文本 | Object | {UNREACH: '待解锁',REACH_UNRECEIVED: '已解锁',REACH_RECEIVED: '已领取'} | |
| onReceviceClick | 点击进度按钮回调 | Function | (id)=>{} | |
| nodeClassName | 节点样式 | Object | - | |
| iconImgClassName | icon图片样式 | Object | - | |
| iconTxtClassName | icon文本样式 | Object | - | |
| descClassName | 描述样式 | Object | - | |
| btnClassName | 进度按钮样式 | Object | - | |
| activeBtnClassName | 进度按钮可点样式 | Object | - | |
| disableBtnClassName | 进度按钮不可用样式 | Object | - | |
## 示例一
```
[
{
id: 0, //节点id
levelValue: 0, //节点值
isReceived: true, //是否已领取
iconInfo: {
iconUrl: '//yun.dui88.com/tebuXinYuan/main-circle-tip.png',
iconTxt: ''
},
descInfo: {
descTxt: '等级1'
}
},
{
id: 1,
levelValue: 5,
isReceived: false,
iconInfo: {
iconUrl: '//yun.dui88.com/tebuXinYuan/main-circle-tip.png',
iconTxt: ''
},
descInfo: {
descTxt: '等级2'
}
}
]
```
c_client/src/components/_tb_comps/_Progress/demo/index.jsx
0 → 100644
View file @
4a775d5e
import
React
,
{
useState
}
from
'react'
import
{
View
}
from
'@tarojs/components'
import
Progress
from
'../index'
import
styles
from
'./index.module.less'
const
initLevelList
=
[
{
id
:
0
,
levelValue
:
0
,
isReceived
:
true
,
iconInfo
:
{
iconUrl
:
'//yun.dui88.com/tebuXinYuan/main-circle-tip.png'
,
iconTxt
:
''
},
descInfo
:
{
descTxt
:
'等级1'
}
},
{
id
:
1
,
levelValue
:
5
,
isReceived
:
false
,
iconInfo
:
{
iconUrl
:
'//yun.dui88.com/tebuXinYuan/main-circle-tip.png'
,
iconTxt
:
''
},
descInfo
:
{
descTxt
:
'等级2'
}
},
{
id
:
2
,
levelValue
:
10
,
isReceived
:
false
,
iconInfo
:
{
iconUrl
:
'//yun.dui88.com/tebuXinYuan/main-circle-tip.png'
,
iconTxt
:
''
},
descInfo
:
{
descTxt
:
'等级3'
}
},
{
id
:
3
,
levelValue
:
15
,
isReceived
:
false
,
iconInfo
:
{
iconUrl
:
'//yun.dui88.com/tebuXinYuan/main-circle-tip.png'
,
iconTxt
:
''
},
descInfo
:
{
descTxt
:
'等级4'
}
}
]
const
Demo
=
props
=>
{
const
[
levelList
,
setLevelList
]
=
useState
(
initLevelList
)
const
[
currentValue
,
setCurrentValue
]
=
useState
(
10
)
const
onReceviceClick
=
id
=>
{
console
.
log
(
'点击:'
,
id
)
}
return
(
<
View
className=
{
styles
[
'progress'
]
}
>
<
Progress
levelList=
{
levelList
}
currentValue=
{
currentValue
}
btnClassName=
{
styles
[
'btnClassName'
]
}
activeBtnClassName=
{
styles
[
'activeBtn'
]
}
disableBtnClassName=
{
styles
[
'disableBtn'
]
}
onReceviceClick=
{
onReceviceClick
}
/>
</
View
>
)
}
export
default
Demo
c_client/src/components/_tb_comps/_Progress/demo/index.module.less
0 → 100644
View file @
4a775d5e
.progress {
margin-top: 100px;
display: flex;
justify-content: center;
}
.disableBtn {
.wh(108px, 42px);
.image('//yun.dui88.com/tebuXinYuan/main-received-btn.png');
}
.activeBtn {
.wh(108px, 42px);
.image('//yun.dui88.com/tebuXinYuan/main-waitReceive-btn.png');
}
.btnClassName {
.wh(108px, 42px);
.image('//yun.dui88.com/tebuXinYuan/main-waitUnlock-btn.png');
}
c_client/src/components/_tb_comps/_Progress/index.jsx
0 → 100644
View file @
4a775d5e
import
{
View
}
from
'@tarojs/components'
import
{
memo
,
useMemo
,
useCallback
}
from
'react'
import
classnames
from
'classnames'
import
ProgressNode
from
'./ProgressNode'
import
styles
from
'./index.module.less'
import
{
ProgressContext
,
ProgressGlobalConfig
}
from
'./ProgressContext'
const
Progress
=
memo
(
props
=>
{
const
{
levelList
=
[],
currentValue
=
0
,
className
,
maxLevel
=
ProgressGlobalConfig
.
maxLevel
,
width
=
ProgressGlobalConfig
.
width
}
=
props
const
LevelList
=
useMemo
(()
=>
{
return
levelList
},
levelList
)
// 合并全局配置
const
mergeConfigToDefault
=
useCallback
(
config
=>
{
return
{
...
ProgressGlobalConfig
,
...
config
}
},
[])
/**
* 过滤props
* @param {*} props 过滤对象
* @param {*} filterPropArr 需要过滤掉的属性名称
* @returns
*/
const
filterProps
=
(
props
,
filterPropArr
)
=>
{
if
(
typeof
props
!==
'object'
||
!
Array
.
isArray
(
filterPropArr
))
{
throw
new
Error
(
'参数格式不正确'
)
}
let
obj
=
{}
Object
.
keys
(
props
)
.
filter
(
key
=>
!
filterPropArr
.
includes
(
key
))
.
map
(
key
=>
{
obj
[
key
]
=
props
[
key
]
})
return
obj
}
const
getProgressStyle
=
classnames
(
styles
[
'defualt-progress'
],
{
[
className
]:
className
})
const
getProItm
=
classnames
(
styles
[
'progress-box-com'
],
{
[
`
${
styles
[
'progress-box-com-02'
]}
`
]:
currentValue
===
maxLevel
})
return
(
// 全局配置注入
<
ProgressContext
.
Provider
value=
{
mergeConfigToDefault
(
filterProps
(
props
,
[
'levelList'
,
'currentValue'
])
)
}
>
{
/* 进度条-all */
}
<
View
className=
{
styles
[
'progress-box'
]
}
style=
{
{
width
:
width
/
100
+
'rem'
}
}
>
{
/* 进度条-current */
}
<
View
className=
{
getProItm
}
style=
{
{
width
:
currentValue
>=
maxLevel
?
'100%'
:
(
currentValue
/
maxLevel
)
*
100
+
'%'
}
}
/>
{
/* 进度条节点 */
}
<
View
className=
{
getProgressStyle
}
>
{
LevelList
.
map
((
item
,
index
)
=>
{
return
(
<
ProgressNode
key=
{
index
}
{
...
item
}
isReach=
{
item
.
levelValue
<=
currentValue
}
/>
)
})
}
</
View
>
</
View
>
</
ProgressContext
.
Provider
>
)
})
export
default
Progress
c_client/src/components/_tb_comps/_Progress/index.module.less
0 → 100644
View file @
4a775d5e
.progress-box {
width: 692px;
height: 20px;
background: #371b15;
// border: 1px solid #371B15;
// box-shadow: 0px 0px 3px 0px #4D3328;
border-radius: 4px;
position: relative;
}
.defualt-progress {
}
.progress-box-com {
height: 20px;
background: linear-gradient(270deg, #ffde8b 0%, #ffce38 100%);
border-radius: 4px;
position: absolute;
top: 0;
left: 0;
transition: all 0.5s cubic-bezier(0, 0.64, 0.36, 1);
}
c_client/src/config/browse.config.js
View file @
4a775d5e
export
default
{
export
const
BROWSE_CONFIG
=
{
taskType
:
'browseGoods'
,
type
:
'01'
,
bg
:
'//yun.dui88.com/taobaomini/clientCTest/goods_bg@2x.png'
,
...
...
@@ -10,5 +10,17 @@ export default {
image
:
{
img
:
'//yun.duiba.com.cn/taobaomini/clientCTest/goods_img@2x.png'
},
color
:
'#181818'
color
:
'#181818'
,
countDown
:
''
}
/*
浏览页倒计时标识
DEFAULT: 默认为空,不展示
PICTURE: loading进度条显示倒计时
NUMBER: 数字倒计时(15s)
*/
export
const
BROWSE_COUNTDOWN_OBJ
=
{
PICTURE
:
'PICTURE'
,
NUMBER
:
"NUMBER"
,
DEFAULT
:
""
}
\ No newline at end of file
c_client/src/config/task.config.js
View file @
4a775d5e
...
...
@@ -50,7 +50,7 @@ export const TASK_CONFIG = {
},
jumpType
:
1
,
// 1 跳转浏览15s 才算完成 2 跳转即算完成
browseTime
:
15
,
// 浏览时间
browseType
:
3
,
// 1 浏览15s 才算完成 2 点击就算完成任务 3 浏览指定商品详情页 15s
browseType
:
1
,
// 1 浏览15s 才算完成 2 点击就算完成任务 3 浏览指定商品详情页 15s
showTaskType
:
1
,
// 1 弹窗 2 列表
orderType
:
1
,
// 1 集合页下单 2 跳转店铺
}
\ No newline at end of file
c_client/src/const.js
View file @
4a775d5e
...
...
@@ -24,4 +24,14 @@ export const HELP_MODAL_TYPE = {
export
const
HELP_MODAL_SHOW
=
{
SHOW
:
1
,
// 已弹
NOT_SHOW
:
2
,
// 未弹
}
/* 背景音乐 应用:牧场消消乐有效,其他应用需要重新上传文件 */
export
const
BGMUSIC_URL
=
{
MUSIC
:
'cloud://FBE3C154661ACEEBA164E8B70B4D71E2/yoga bgm.mp3'
}
/* 点击音效 */
export
const
CLOUD_OBJ
=
{
'1'
:
'cloud://0BD38A1B739CCF6A552396F3FE2D5A09/开始-音效.mp3'
,
'2'
:
'cloud://93FBC274B6B43CE37B0A70DF8C1AFA52/答题-音效.mp3'
,
'3'
:
'cloud://B8F0BA22BBA74F8FEA261E1CC9D55355/欢呼声.mp3'
}
\ No newline at end of file
c_client/src/hooks/useAudio.js
0 → 100644
View file @
4a775d5e
/**
* @description 音乐
*/
import
React
,
{
useState
,
useEffect
}
from
"react"
;
import
{
playBgMusic1
}
from
"@/utils/audio"
;
const
app
=
getApp
();
/**
* @description 一个页面不能同时create两个音频文件
* @param {*} url cloud文件链接
* @param {*} isBgMusic 是否自动调用(背景音乐自动调用),非背景音乐(点击音效)手动调用
* @returns
*/
export
const
useAudio
=
(
url
,
isBgMusic
=
false
)
=>
{
const
[
musicUrl
,
setMusicUrl
]
=
useState
();
// 若需要控制所有的音效状态,app上自定义一个变量
const
[
openStatus
,
setOpenStatus
]
=
useState
(
true
);
useEffect
(()
=>
{
getMusicInfo
();
},
[]);
useEffect
(()
=>
{
if
(
isBgMusic
){
console
.
log
(
'enter use audio function with bg music'
);
playAudio
();
}
},[
musicUrl
,
openStatus
])
/**
* @description 获取音频url链接
*/
const
getMusicInfo
=
async
()
=>
{
const
resultSrc
=
await
app
.
cloud
.
file
.
getTempFileURL
({
fileId
:
url
});
console
.
log
(
'resultSrc--------hook'
,
resultSrc
);
if
(
resultSrc
[
0
]){
setMusicUrl
(
resultSrc
[
0
].
url
);
}
};
/**
* @description 播放音效
* @param {boolean} selfStatus 是否单独控制音效状态
* @param {function} callbackFn 播放之后的回调
*/
const
playAudio
=
(
callbackFn
=
()
=>
{})
=>
{
console
.
log
(
'musicUrl'
,
musicUrl
,
'selfStatus'
,
openStatus
)
musicUrl
&&
playBgMusic1
(
openStatus
,
musicUrl
,
callbackFn
);
};
return
{
playAudio
,
openStatus
,
setOpenStatus
,
musicUrl
};
};
c_client/src/hooks/useAudio.md
0 → 100644
View file @
4a775d5e
##### useAudio
```
jsx
const
{
playAudio
,
openStatus
,
setOpenStatus
,
musicUrl
}
=
useAudio
(
url
,
isBgMusic
)
```
##### 入参
| 入参 | 类型 | 描述 | 默认值 | 备注 |
| :--- | :---: | :---: |:---: | :---: |
| url | String | cloud开头的链接 | 'cloud:xxxx.mp3' | 当前应用云存储上的链s接才有效 |
| isBgMusic | Boolean | 是否自动加载背景音乐/音效 | false | / |
##### 出参
| 出参 | 类型 | 描述 | 默认值 | 备注 |
| :--- | :---: | :---: |:---: | :---: |
| playAudio | Function | 播放音乐/音效 | 有回调函数callback | callback默认为空函数 |
| openStatus | Boolean | 默认开启播放 | true | / |
| setOpenStatus | Function | 改变开始/暂停状态 | / | true/false都会调用playMusic1方法|
| musicUrl | String | cloud文件得到的音频url链接 | 'https:xxxx.mp3' | 音频文件url链接|
+
使用
```
jsx
import
{
useAudio
}
from
'@/hooks/useAudio'
import
{
CLOUD_OBJ
}
from
'@/const'
export
const
Index
=
()
=>
{
const
{
playAudio
,
musicUrl
,
setOpenStatus
,
openStatus
}
=
useAudio
(
CLOUD_OBJ
[
'1'
])
const
gotoMainPage
=
()
=>
{
setOpenStatus
(
!
openStatus
)
playAudio
(()
=>
{
// ...场景:点击有音效,跳转的页面有背景音乐
navigateTo
({
url
:
`/pages/other/other`
})
});
// TODO...
}
return
(
<>
<
View
onTap=
{
gotoMainPage
}
>
点击音效button
</
View
>
</>
)
}
import
{
useAudio
}
from
'@/hooks/useAudio'
import
{
BGMUSIC_URL
}
from
'@/const'
export
const
Other
=
()
=>
{
// 自动播放背景音乐
const
{
playAudio
,
setOpenStatus
,
openStatus
}
=
useAudio
(
CLOUD_OBJ
[
'1'
],
true
)
return
(
<
View
>
other page
</
View
>
)
}
```
+
所有音效状态统一, 则需要在useAudio中设置一个全局变量(app.openStatus)
+
音效缓存,音效关闭,下次进入音效还是关闭
```
js
let
status
=
my
.
getStorageSync
({
key
:
'musicStatus'
});
console
.
log
(
'status'
,
status
);
if
(
status
.
data
==
undefined
||
status
.
data
===
null
||
status
.
data
===
''
){
app
.
openStatus
=
true
;
my
.
setStorageSync
({
key
:
'musicStatus'
,
data
:
true
})
}
else
if
(
status
?.
data
==
true
){
app
.
openStatus
=
true
;
}
else
if
(
status
?.
data
==
false
){
app
.
openStatus
=
false
;
}
const
{
openStatus
,
setOpenStatus
}
=
useAudio
(
CLOUD_OBJ
[
'2'
],
true
)
/**
* @description 切换音效状态
*/
const
handleMusic
=
()
=>
{
setOpenStatus
(
status
=>
!
status
)
/* 切换音效状态 */
app
.
openStatus
=
!
app
.
openStatus
;
let
musicStatus
=
my
.
getStorageSync
({
key
:
'musicStatus'
}).
data
;
console
.
log
(
'musicStatus-----初始值---->>>>>>>>>>'
,
musicStatus
);
my
.
setStorageSync
({
key
:
'musicStatus'
,
data
:
!
musicStatus
});
let
musics
=
my
.
getStorageSync
({
key
:
'musicStatus'
}).
data
;
console
.
log
(
'musicStatus----改变值----->>>>>>>>>>'
,
musics
);
}
```
\ No newline at end of file
c_client/src/mock.js
View file @
4a775d5e
This diff is collapsed.
Click to expand it.
c_client/src/pages/index/index.jsx
View file @
4a775d5e
...
...
@@ -16,6 +16,15 @@ import { useEffect } from 'react'
const
{
navigateTo
,
openDetail
,
showSharePanel
}
=
tbcc
.
tb
const
{
getImgShareUrl
,
checkIsMember
,
validateActivityStatus
}
=
tbcc
.
utils
import
{
useAudio
}
from
'@/hooks/useAudio'
import
{
CLOUD_OBJ
,
BGMUSIC_URL
}
from
'@/const'
import
ScrollXView
from
'@/components/_tb_comps/ScrollXView/ScrollXView'
import
SwiperView
from
'@/components/_tb_comps/SwiperView/SwiperView'
import
RotateWheel
from
'@/components/_tb_comps/RotateWheel/RotateWheel'
const
INDEX_CONFIG
=
{
bg
:
''
,
// 背景 cloud://C4015B7CEC23CF013A78247E2852524F//火箭待机小球抖动.json
ruleButton
:
''
,
// 规则按钮
...
...
@@ -24,6 +33,36 @@ const INDEX_CONFIG = {
taskButton
:
''
// 任务按钮
}
const
rotateConfig
=
{
bg
:
'https://yun.duiba.com.cn/spark/assets/8b6e920ffd09fab8f9ac2de09f9154879f4d0607.png'
,
ratio
:
0.65
,
radius
:
300
,
circles
:
4
,
divideNum
:
8
,
duration
:
5000
,
timeFunction
:
'ease-in-out'
,
nodeInfo
:{
width
:
100
,
height
:
100
},
imgInfo
:{
width
:
80
,
height
:
80
},
showWay
:
'negative'
,
//positive/negative
isShowPrizeName
:
true
,
prizeNameWidthRatio
:
1.2
}
const
SCROLLXVIEW_CONFIG
=
{
prizeList
:
[],
containerWidth
:
300
,
containerHeight
:
300
,
imgWidth
:
200
,
imgHeight
:
200
,
isShowPrizeName
:
true
,
prizeInCenterNum
:
2
,
marginRight
:
26
,
backgroundColor
:
'#E7E7EF'
}
function
Index
()
{
const
app
=
getApp
()
const
{
activityInfo
,
setActivityInfoAndStatus
}
=
useActivityInfoModel
()
...
...
@@ -41,6 +80,16 @@ function Index() {
// 助力弹窗标识
const
showHelp
=
useRef
(
false
)
/* 背景音乐 */
const
{
playAudio
,
musicUrl
,
setOpenStatus
,
openStatus
}
=
useAudio
(
CLOUD_OBJ
[
'1'
])
const
playCurrentAudio
=
()
=>
{
// setOpenStatus(!openStatus)
playAudio
(()
=>
{
onHandleIndex
(
'prize'
)
})
}
const
fetchActivityInfo
=
async
()
=>
{
const
{
success
,
data
}
=
await
API
.
getActivityBaseInfoById
()
if
(
success
)
{
...
...
@@ -56,7 +105,7 @@ function Index() {
success
&&
setUserInfo
(
data
)
}
useEffect
(()
=>
{
fetchActivityInfo
()
//
fetchActivityInfo()
// getImgShareUrl('cloud://CEFE74AE67921906B5AF842150646D35/share.png').then(url => {
// SHARE_IMG.current = url
// })
...
...
@@ -64,7 +113,7 @@ function Index() {
// 授权登录完成
useLogin
(
async
(
info
)
=>
{
handleVisibleModal
(
info
)
setUpdateFlag
(
1
)
//
setUpdateFlag(1)
})
// 查看是否有助力信息
const
getShareInfo
=
async
()
=>
{
...
...
@@ -128,7 +177,7 @@ function Index() {
updateActInfo
&&
fetchActivityInfo
()
},
'rule'
:
()
=>
setRuleModalVisible
(
true
),
'prize'
:
()
=>
navigateTo
(
'/pages/packagePrize/myPrize/myPrize'
)
,
'prize'
:
()
=>
{
navigateTo
(
'/pages/packagePrize/myPrize/myPrize'
)}
,
'game'
:
()
=>
navigateTo
(
'/pages/packageGame/game/game'
)
}
Fn
[
type
]()
...
...
@@ -142,6 +191,29 @@ function Index() {
<
View
className=
{
styles
.
games
}
style=
{
{
backgroundImage
:
`url(${INDEX_CONFIG.taskButton})`
}
}
onClick=
{
()
=>
onHandleIndex
(
'game'
)
}
>
游戏
</
View
>
<
View
className=
{
styles
.
bemember
}
onTap=
{
()
=>
setMemberVisible
(
true
)
}
>
入会
</
View
>
{
/* 奖品查看左右滑动 */
}
{
/* <ScrollXView {...SCROLLXVIEW_CONFIG} prizeList={prizeList} /> */
}
{
/* swiper左右滑动 */
}
{
/* <SwiperView swiperList={prizeList} /> */
}
{
/* 大转盘 */
}
{
/* <View className={styles['rotate']}
style={{
width:`${600/100}rem`,
height:`${600/100}rem`,
margin:`${100/100}rem auto`,
display:'flex',
justifyContent:'center',
alignItems:'center'
}} >
<RotateWheel {...rotateConfig} callback={()=>{}} />
</View> */
}
<
View
className=
'view'
onTap=
{
playCurrentAudio
}
>
play audio
</
View
>
{
tasksModalVisible
&&
<
TasksModal
...
...
c_client/src/pages/index/index.module.less
View file @
4a775d5e
...
...
@@ -8,6 +8,7 @@
left: 0;
right: 0;
bottom: 0;
background-image: linear-gradient(45deg,#fbc2eb 10%, #a6c1ee);
}
.index_button() {
.wh(150px, 46px);
...
...
c_client/src/pages/packageGame/game/game.jsx
View file @
4a775d5e
...
...
@@ -2,7 +2,6 @@ import React, { useEffect, useState, useRef } from 'react'
import
{
View
}
from
'@tarojs/components'
import
{
useDidShow
,
useRouter
,
useDidHide
,
getApp
}
from
'@tarojs/taro'
import
API
from
'@/api'
import
{
TASK_CONFIG
}
from
'@/const'
import
{
useLogin
,
useLoginFromShare
}
from
'@/hooks/useLogin'
import
{
useActivityInfoModel
,
useLoginInfoModel
}
from
'@/store'
import
{
...
...
c_client/src/pages/packageGood/browseGoods/browseGoods.jsx
View file @
4a775d5e
...
...
@@ -3,31 +3,35 @@ import { View } from '@tarojs/components'
import
ContainerFit
from
'@/components/_base/ContainerFit/ContainerFit'
import
GoodsTitle
from
'@/components/_tb_comps/TitleImg/TitleImg'
import
GoodsList
from
'@/components/_tb_comps/GoodsList/GoodsList'
import
BrowserLoading
from
'@/components/_tb_comps/BrowserLoading/BrowserLoading'
import
{
useDidShow
,
useRouter
,
useDidHide
}
from
'@tarojs/taro'
import
API
from
'@/api'
import
{
commonToast
}
from
'tbcc-sdk-ts/lib/core/tb'
import
styles
from
'./browseGoods.module.less'
import
{
TASK_CONFIG
,
BROSE_GOOD_TYPE
}
from
'@/config/task.config'
import
BROWSE_CONFIG
from
'@/config/browse.config'
import
{
BROWSE_CONFIG
}
from
'@/config/browse.config'
import
{
GOOD_LIST
}
from
'@/mock'
function
BrowseGoodsPage
()
{
const
{
params
:
{
itemIds
,
keepTime
}
}
=
useRouter
()
const
{
browseType
,
browseTime
=
15
}
=
TASK_CONFIG
const
[
startTimer
,
setStartTimer
]
=
useState
(
false
)
const
preBrowseTime
=
useRef
(
null
)
const
currentItemId
=
useRef
(
''
)
const
usePercent
=
useRef
(
0
)
const
browserTimer
=
useRef
(
null
)
const
[
goodsList
,
setGoodsList
]
=
useState
([])
const
{
browseGoodType
,
browseTime
=
15
}
=
TASK_CONFIG
const
{
params
:
{
itemIds
,
keepTime
}
}
=
useRouter
()
const
[
accumulateTime
,
setAccumulateTime
]
=
useState
(
+
keepTime
||
15
)
const
browserTimer
=
useRef
(
null
)
const
[
goodsList
,
setGoodsList
]
=
useState
(
GOOD_LIST
)
useEffect
(()
=>
{
getGoodsList
()
},
[])
// 浏览集合页15s
useEffect
(()
=>
{
if
(
browse
Good
Type
===
BROSE_GOOD_TYPE
.
PAGE
)
{
!
browserTimer
.
current
&&
goodsList
.
length
&&
browseGoodsTimes
()
if
(
browseType
===
BROSE_GOOD_TYPE
.
PAGE
)
{
(
!
browserTimer
.
current
&&
goodsList
.
length
)
&&
browseGoodsTimes
()
return
()
=>
browserTimer
.
current
&&
clearInterval
(
browserTimer
.
current
)
}
},[
goodsList
])
...
...
@@ -39,11 +43,11 @@ function BrowseGoodsPage() {
useDidShow
(()
=>
{
// 重新回到页面开启倒计时
if
(
browse
Good
Type
===
BROSE_GOOD_TYPE
.
PAGE
&&
startTimer
&&
usePercent
.
current
<
+
browseTime
)
{
if
(
browseType
===
BROSE_GOOD_TYPE
.
PAGE
&&
startTimer
&&
usePercent
.
current
<
+
browseTime
)
{
browseGoodsTimes
()
}
console
.
warn
(
'回到该页面了'
)
if
(
browse
Good
Type
===
BROSE_GOOD_TYPE
.
DETAIL
&&
preBrowseTime
.
current
&&
((
Date
.
now
()
-
preBrowseTime
.
current
)
/
1000
)
>=
browseTime
)
{
if
(
browseType
===
BROSE_GOOD_TYPE
.
DETAIL
&&
preBrowseTime
.
current
&&
((
Date
.
now
()
-
preBrowseTime
.
current
)
/
1000
)
>=
browseTime
)
{
onCompleteTask
()
currentItemId
.
current
=
''
preBrowseTime
.
current
=
null
...
...
@@ -53,7 +57,6 @@ function BrowseGoodsPage() {
preBrowseTime
.
current
=
null
}
})
useDidHide
(()
=>
{
// 页面关闭清除定时器
if
(
browserTimer
.
curren
)
{
...
...
@@ -90,18 +93,21 @@ function BrowseGoodsPage() {
currentItemId
.
current
=
itemId
}
}
handleFn
[
browse
Good
Type
]()
handleFn
[
browseType
]()
}
// 浏览页面定时器
const
browseGoodsTimes
=
()
=>
{
browserTimer
.
current
=
setInterval
(()
=>
{
usePercent
.
current
+=
1
console
.
warn
(
usePercent
.
current
)
const
keepTime_
=
browseTime
console
.
log
(
'enter the browse time '
);
usePercent
.
current
+=
1
setAccumulateTime
(
+
keepTime_
-
usePercent
.
current
)
console
.
warn
(
usePercent
.
current
,
keepTime_
)
if
(
usePercent
.
current
>=
keepTime_
)
{
onCompleteTask
()
clearInterval
(
browserTimer
.
current
)
usePercent
.
current
=
0
setAccumulateTime
(
0
)
}
},
1000
)
}
...
...
@@ -113,8 +119,13 @@ function BrowseGoodsPage() {
<
View
className=
{
styles
[
'page-content__list'
]
}
>
<
GoodsList
goodsList=
{
goodsList
}
task=
{
BROWSE_CONFIG
}
onOpenDetail=
{
(
itemId
,
collected
)
=>
onOpenDetail
(
itemId
,
collected
)
}
/>
</
View
>
{
BROWSE_CONFIG
.
countDown
&&
<
BrowserLoading
loadFlag=
{
BROWSE_CONFIG
.
countDown
}
count=
{
accumulateTime
}
/>
}
</
ContainerFit
>
)
}
export
default
BrowseGoodsPage
c_client/src/pages/packagePrize/myPrize/myPrize.jsx
View file @
4a775d5e
...
...
@@ -19,6 +19,7 @@ const enameStatus = { ..._enameStatus, ...commonStatus }
const
{
commonToast
,
navigateToOutside
,
setClipboard
}
=
tbccTs
.
tb
const
{
getMyPrizeList
}
=
API
import
{
useAudio
}
from
'@/hooks/useAudio'
function
Empty
(
blankTxt
)
{
return
<
View
className=
{
styles
[
'my-prize-item__empty'
]
}
>
{
blankTxt
}
</
View
>
...
...
@@ -32,6 +33,8 @@ function MyPrizeList() {
const
[
memberVisible
,
setMemberVisible
]
=
useState
(
false
)
const
[
deliveryModalVisible
,
setDeliveryModalVisible
]
=
useState
(
false
)
// const {openStatus,setOpenStatus} = useAudio(BGMUSIC_URL.MUSIC,true)
useEffect
(()
=>
{
fetchMyPriceList
()
},
[])
...
...
c_client/src/pages/preComp/preComp.jsx
0 → 100644
View file @
4a775d5e
import
React
,
{
useEffect
,
useState
,
useRef
}
from
'react'
import
{
View
}
from
'@tarojs/components'
import
{
useDidShow
,
useRouter
,
useDidHide
,
getApp
}
from
'@tarojs/taro'
import
API
from
'@/api'
import
{
useLogin
,
useLoginFromShare
}
from
'@/hooks/useLogin'
import
{
useActivityInfoModel
,
useLoginInfoModel
}
from
'@/store'
import
{
useAudio
}
from
'@/hooks/useAudio'
import
{
CLOUD_OBJ
,
BGMUSIC_URL
}
from
'@/const'
import
ScrollXView
from
'@/components/_tb_comps/ScrollXView/ScrollXView'
import
SwiperView
from
'@/components/_tb_comps/SwiperView/SwiperView'
import
RotateWheel
from
'@/components/_tb_comps/RotateWheel/RotateWheel'
export
default
function
PreComp
(
props
)
{
return
(
<
View
>
</
View
>
)
}
\ No newline at end of file
c_client/src/pages/preComp/preComp.module.less
0 → 100644
View file @
4a775d5e
c_client/src/store/userInfo.js
0 → 100644
View file @
4a775d5e
import
{
useState
}
from
'react'
import
{
createModel
}
from
'hox'
function
useUserInfo
()
{
const
[
activityInfo
,
setUserInfo
]
=
useState
({
success
:
false
,
gameTimes
:
0
})
return
{
activityInfo
,
setUserInfo
}
}
export
const
useUserInfoModel
=
createModel
(
useUserInfo
)
c_client/src/utils/audio.js
0 → 100644
View file @
4a775d5e
/**
* 创建音频类
*/
class
AudioModel
{
constructor
(
opts
=
{})
{
const
{
src
}
=
opts
;
if
(
!
src
)
{
console
.
error
(
"请输入音频链接"
);
return
false
;
}
try
{
const
innerAudioContext
=
my
.
createInnerAudioContext
();
Object
.
keys
(
opts
).
forEach
(
item
=>
{
innerAudioContext
[
item
]
=
opts
[
item
];
});
return
innerAudioContext
;
}
catch
(
e
)
{
console
.
error
(
"当前版本不支持音频"
);
}
}
}
/**
* 创建音频实例
* @param {object} opts 配置对象 例 { src: '音频链接', autoplay: false }
*/
export
const
createAudio
=
opts
=>
{
const
audioInstance
=
new
AudioModel
(
opts
);
return
audioInstance
;
};
/**
* 获取系统信息
* @returns {object} 小程序系统信息
*/
export
const
getSystemInfo
=
()
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
my
.
getSystemInfo
({
success
:
res
=>
{
resolve
(
res
);
},
fail
:
err
=>
{
reject
(
err
);
}
});
});
};
let
bgs
=
{};
export
const
playBgMusic1
=
async
(
isOn
,
src
,
callbackFn
=
()
=>
{},
loop
=
false
)
=>
{
//待测试
for
(
let
k
in
bgs
)
{
if
(
bgs
[
k
].
isOn
)
{
bgs
[
k
].
stop
();
}
// bgs[k].isOn = false; /// TODO 自己记一个开关,因为淘宝的玩意stop之后虽然听不到,但还是在播放,会触发loop播放和onEnded事件
}
const
key
=
src
;
console
.
log
(
"---------->>>>>>>>>>>>>ison"
,
isOn
);
if
(
isOn
)
{
if
(
!
bgs
[
key
])
{
console
.
log
(
"enter inner before the createAudio function"
,
src
,
loop
);
bgs
[
key
]
=
createAudio
({
src
:
src
,
autoplay
:
true
,
loop
:
loop
/// TODO 暂时无效?2020.08.12 目前有效,但stop后还会跑数据,导致到音频结束到时间又自动播放
});
console
.
log
(
"----------------src"
,
src
,
bgs
[
key
],
"bgs[key]"
);
bgs
[
key
].
onPlay
(()
=>
{
bgs
[
key
].
isOn
=
true
;
});
bgs
[
key
].
onStop
(()
=>
{
bgs
[
key
].
isOn
=
false
;
});
const
systemInfo
=
await
getSystemInfo
();
console
.
log
(
systemInfo
,
"systemInfo-------systemInfo"
);
/// TODO监听结束,因为loop无效 2020.08.12 loop有效,这个操作是为了解决stop之后还会跑音频数据的问题
bgs
[
key
].
onEnded
(()
=>
{
if
(
bgs
[
key
].
isOn
)
{
// 判断自己记录的开关
if
(
systemInfo
?.
platform
.
includes
(
"Android"
))
{
// 安卓
bgs
[
key
].
play
();
}
else
if
(
systemInfo
?.
platform
.
includes
(
"iOS"
)
||
systemInfo
?.
platform
.
includes
(
"iPhone OS "
)
)
{
// ios
bgs
[
key
].
isOn
=
false
;
}
delete
bgs
[
key
];
callbackFn
&&
callbackFn
();
}
});
bgs
[
key
].
play
();
// 安卓有时候autoplay好像莫得用
// console.log(src)
// bgs[key].isOn = true; /// TODO 自己记一个开关,因为淘宝的玩意stop之后虽然听不到,但还是在播放,会触发loop播放和onEnded事件
}
else
{
console
.
log
(
"---------->>>>>>>>>>>>>not enter "
);
bgs
[
key
].
play
();
// bgs[key].isOn = true; /// TODO 自己记一个开关,因为淘宝的玩意stop之后虽然听不到,但还是在播放,会触发loop播放和onEnded事件
callbackFn
&&
callbackFn
();
}
}
else
{
if
(
bgs
[
key
])
{
// bgs[key].pause(); /// pause 垃圾,不能用
console
.
log
(
"test stop function is work or not"
);
bgs
[
key
].
stop
();
// bgs[key].isOn = false; /// TODO 自己记一个开关,因为淘宝的玩意stop之后虽然听不到,但还是在播放,会触发loop播放和onEnded事件
callbackFn
&&
callbackFn
();
}
else
{
callbackFn
&&
callbackFn
();
}
}
};
c_client/src/utils/util.js
View file @
4a775d5e
...
...
@@ -166,6 +166,20 @@ export const getActivity = (sellerId) => {
});
})
}
/**
* 获取系统信息
* @returns {object} 小程序系统信息
*/
export
const
getSystemInfo
=
()
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
my
.
getSystemInfo
({
success
:
res
=>
{
resolve
(
res
);
},
fail
:
err
=>
{
reject
(
err
);
}
});
});
};
// 查询商家会员等级
export
const
getGrade
=
(
sellerId
)
=>
{
const
memberBenefitPlugin
=
requirePlugin
(
"memberBenefit"
)
...
...
@@ -184,4 +198,5 @@ export const getGrade = (sellerId) => {
}
});
})
}
\ No newline at end of file
}
c_client/yarn.lock
View file @
4a775d5e
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment