index.jsx 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. import { useState, useEffect } from 'react';
  2. import Taro from '@tarojs/taro';
  3. import withLayout from '@/layout';
  4. import {
  5. ScrollView,
  6. Image,
  7. RichText,
  8. View,
  9. Text,
  10. Input,
  11. Picker,
  12. Button
  13. } from '@tarojs/components';
  14. import Disclaimer from '@/components/Disclaimer';
  15. import { useSelector } from 'react-redux';
  16. import {
  17. signupActivity,
  18. queryActivityDetail,
  19. } from "@/services/activity";
  20. import { getImgURL } from "@/utils/image";
  21. import { formatDate } from "@/utils/chatDate";
  22. import useParams from "@/utils/hooks/useParams";
  23. import useShare from "@/utils/hooks/useShare";
  24. import useFavor from "@/utils/hooks/useFavor";
  25. import { times } from "@/utils/tools";
  26. import useStatus from './useStatus'
  27. import CountDown from './CountDown'
  28. import "./index.scss";
  29. const activityStatusDict = {
  30. 0: {
  31. text: '立即参与',
  32. text1: '立即参团',
  33. className: 'yellow',
  34. },
  35. 1: {
  36. text: '未开始',
  37. text1: '未开始',
  38. className: 'blue',
  39. },
  40. 2: {
  41. text: '已结束',
  42. text1: '已结束',
  43. className: 'grey',
  44. },
  45. 3: {
  46. text: '已参与',
  47. text1: '已结束',
  48. className: 'yellow',
  49. },
  50. };
  51. export default withLayout((props) => {
  52. const { router, shareContent, trackData, person, page } = props;
  53. const { id } = router.params;
  54. const user = useSelector((state) => state.user);
  55. const [detail, setDetail] = useState({})
  56. const [canChoose, setCanChoose] = useState('none');
  57. const [inputName, setInputName] = useState('');
  58. const [selectorChecked, setSelectorChecked] = useState('1');
  59. const [selector, setSelector] = useState('');
  60. const buildingId = detail?.buildingId;
  61. const [btnText, btnDisabled] = useStatus(detail)
  62. const getDetail = (params) => {
  63. Taro.showLoading();
  64. queryActivityDetail(params).then((res) => {
  65. const maxperson = 10
  66. setSelector(times(maxperson).map((_, i) => `${i + 1}`));
  67. setDetail(res);
  68. Taro.hideLoading();
  69. });
  70. };
  71. // 本页面分享或者海报参数
  72. const paramsRef = useParams({
  73. id,
  74. buildingId,
  75. person,
  76. from: `${page.type}_share`,
  77. });
  78. const fullTrackData = { ...trackData, buildingId };
  79. const [isSaved, handleFavor] = useFavor(detail?.isSaved, {
  80. id,
  81. buildingId,
  82. ...trackData,
  83. });
  84. useShare(
  85. {
  86. title: shareContent.shareContentTitle || detail?.title,
  87. path: `${router.path}?${paramsRef.current}`,
  88. image: shareContent.shareContentImg || getImgURL(detail?.imgUrl),
  89. },
  90. fullTrackData
  91. );
  92. useEffect(() => {
  93. if (id) {
  94. getDetail(id);
  95. }
  96. }, [id])
  97. const handleSignup = () => {
  98. setCanChoose("block");
  99. };
  100. const comfire = () => {
  101. const { dynamicId } = detail
  102. const { userInfo: { person: { phone, tel } } } = user
  103. if (inputName === '') {
  104. Taro.showToast({
  105. title: '请输入姓名',
  106. icon: 'none'
  107. })
  108. return
  109. }
  110. const payload = {
  111. buildingId,
  112. dynamicId,
  113. name: inputName,
  114. phone: phone ? phone : tel,
  115. attendNum: selectorChecked,
  116. };
  117. signupActivity(payload).then(() => {
  118. Taro.showToast({
  119. title: "报名成功",
  120. });
  121. setCanChoose('none')
  122. setTimeout(() => {
  123. getDetail(id)
  124. }, 500)
  125. });
  126. };
  127. function hideModal () {
  128. setCanChoose('none');
  129. }
  130. const onInputText = (e) => {
  131. setInputName(e.detail.value);
  132. };
  133. const dymic = () => (
  134. <view className='Info'>
  135. <view>
  136. <view className='Title flex-h'>
  137. <view className='flex-item'>
  138. <text>{detail.halfTitle}</text>
  139. </view>
  140. <text className='Tips'>{detail.enlisted || 0}人已报名</text>
  141. </view>
  142. <text className='Time'>
  143. 报名截止时间:
  144. {formatDate(detail.enlistEnd, 'yyyy/M/d')}
  145. </text>
  146. <text className='Name'>{detail.title}</text>
  147. <view className='flex-h Address'>
  148. <text>地址:</text>
  149. <view className='flex-item'>
  150. <text>{detail.address}</text>
  151. </view>
  152. </view>
  153. <view className='flex-h Date'>
  154. <text>时间:</text>
  155. <view className='flex-item'>
  156. <text>
  157. {`${formatDate(detail.startDate, 'yyyy/M/d')} - ${formatDate(detail.endDate, 'yyyy/M/d')}`}
  158. </text>
  159. </view>
  160. </view>
  161. <view className='Btn'>
  162. <Button open-type='share'>
  163. <text>分享好友</text>
  164. </Button>
  165. </view>
  166. </view>
  167. </view>
  168. );
  169. const house = () => (
  170. <view className='BuildingInfo'>
  171. <view className='flex-h Title'>
  172. <view className='flex-item'>
  173. <text className='Name'>{detail.title}</text>
  174. <view className='Address flex-h'>
  175. <text className='iconfont icon-dingwei'></text>
  176. <view className='flex-item'>
  177. <text>{detail.address}</text>
  178. </view>
  179. <text className='Price'>价格待定</text>
  180. </view>
  181. <text className='Time'>时间:{formatDate(detail.startDate, 'yyyy/M/d')} - {formatDate(detail.endDate, 'yyyy/M/d')}</text>
  182. </view>
  183. <view className='Option'>
  184. <view>
  185. <text className='iconfont icon-fenxiang1'></text>
  186. <text>分享</text>
  187. <Button open-type='share' className='ShareBtn'>分享</Button>
  188. </view>
  189. <view>
  190. <text className='iconfont icon-pengyouquan1'></text>
  191. <text>朋友圈</text>
  192. </view>
  193. </view>
  194. </view>
  195. <CountDown endTime={detail?.enlistEnd} />
  196. <view className='Apply flex-h'>
  197. <view className='Collect' onClick={handleFavor}>
  198. <text className='iconfont icon-shoucang' style={isSaved ? { color: 'red' } : undefined}></text>
  199. <text>{isSaved ? '已收藏' : '收藏'}</text>
  200. </view>
  201. <text className='iconfont icon-baoming'></text>
  202. <view className='flex-item'>
  203. <text>{detail.enlisted || 0}人已报名</text>
  204. </view>
  205. <button className='Btn' disabled={btnDisabled} onClick={handleSignup}>{btnText}</button>
  206. </view>
  207. </view>
  208. );
  209. return (
  210. <>
  211. {detail && (
  212. <view className='Page activityDetail flex-v'>
  213. <view className='flex-item'>
  214. <view>
  215. <ScrollView scroll-y>
  216. <view className='PageContent'>
  217. <view className='Top'>
  218. <Image
  219. mode='aspectFill'
  220. src={getImgURL(detail.bannerListImg)}
  221. className='centerLabel'
  222. ></Image>
  223. </view>
  224. {detail.type == "dymic" && dymic()}
  225. {detail.type !== "dymic" && house()}
  226. <view className='ActivityIntro'>
  227. <view className='Title'>
  228. <text>活动介绍</text>
  229. </view>
  230. <RichText nodes={detail.desc} />
  231. </view>
  232. <Disclaimer />
  233. </view>
  234. </ScrollView>
  235. </view>
  236. </view>
  237. {detail.type == "dymic" && (
  238. <view className='PageBottom flex-h'>
  239. <Button className='Share' open-type='share'>
  240. <text className='iconfont icon-fenxiang'></text>
  241. <text>分享</text>
  242. </Button>
  243. <view className='Collect' onClick={handleFavor}>
  244. <text
  245. className='iconfont icon-shoucang'
  246. style={isSaved ? { color: "red" } : undefined}
  247. ></text>
  248. <text>{isSaved ? '已收藏' : '收藏'}</text>
  249. </view>
  250. <view className='flex-item'></view>
  251. <Button disabled={btnDisabled} className='Post' onClick={handleSignup}>
  252. {btnText}
  253. </Button>
  254. </view>
  255. )}
  256. </view>
  257. )}
  258. <View className='page-body' style={{ display: canChoose }}>
  259. <View className='mask' onClick={() => hideModal()}></View>
  260. <View className='page-section'>
  261. <Text className='page-section__title'>报名信息</Text>
  262. <View className='page-content'>
  263. <Input
  264. className='inputName'
  265. onInput={onInputText}
  266. type='text'
  267. placeholder='请输入姓名'
  268. />
  269. <Picker
  270. mode='selector'
  271. range={selector}
  272. onChange={(e) => setSelectorChecked(selector[e.detail.value])}
  273. >
  274. <View className='picker'>
  275. <Text>参加人数</Text>
  276. <Text className='content'>{selectorChecked}</Text>
  277. <Text>人</Text>
  278. </View>
  279. </Picker>
  280. <View onClick={comfire} className='comfire'>
  281. 确认
  282. </View>
  283. </View>
  284. </View>
  285. </View>
  286. </>
  287. );
  288. });