ViewCampaign.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /**
  2. * 活动详情
  3. * @邠心vbe on 2023/08/17
  4. */
  5. import React, { Component } from 'react';
  6. import { View, StyleSheet, Image, ScrollView, Linking, Animated, Easing } from 'react-native';
  7. import Swiper from 'react-native-swiper';
  8. import apiArticle from '../../api/apiArticle';
  9. import TextView from '../../components/TextView';
  10. import VbeSkeleton from '../../components/VbeSkeleton';
  11. import utils from '../../utils/utils';
  12. import { PagerView } from './ViewUtil';
  13. import MyStatusBar from '../../components/MyStatusBar';
  14. import Toolbar, { BackButton } from '../../components/Toolbar';
  15. export default class ViewCampaign extends Component {
  16. constructor(props) {
  17. super(props);
  18. this.state = {
  19. id: "",
  20. loading: true,
  21. showTitleBar: false,
  22. messageInfo: {
  23. articleTypeName: "",
  24. articleTitle: "",
  25. articleContent: ""
  26. },
  27. opacity: new Animated.Value(0)
  28. };
  29. }
  30. componentDidMount() {
  31. if (this.props.route?.params?.id) {
  32. this.setState({
  33. id: this.props.route?.params?.id
  34. }, () => {
  35. this.readMessage();
  36. })
  37. }
  38. MyStatusBar.setStatusBarTheme(MyStatusBar.LIGHT_STYLE);
  39. this.props.navigation.addListener('beforeRemove', (e) => {
  40. MyStatusBar.setStatusBarTheme(MyStatusBar.DEFAULT_STYLE);
  41. });
  42. }
  43. readMessage() {
  44. apiArticle.readMessage(this.state.id).then(res => {
  45. if (res.data) {
  46. this.setState({
  47. messageInfo: res.data
  48. });
  49. this.setPageTitle();
  50. }
  51. }).catch(err => {
  52. toastShort(err);
  53. });
  54. }
  55. setPageTitle() {
  56. if (this.state.messageInfo.articleTitle) {
  57. /*this.props.navigation.setOptions({
  58. headerTitle: () => (<HeaderTitle title={this.state.messageInfo.articleTitle}/>)
  59. })*/
  60. setTimeout(() => {
  61. this.setState({
  62. loading: false
  63. });
  64. }, 300);
  65. }
  66. }
  67. accessLink(url) {
  68. Linking.openURL(utils.getImageUrl(url))
  69. }
  70. getColorByType(type) {
  71. switch (type) {
  72. case "Ended":
  73. return {
  74. backgroundColor: "#E11919"
  75. }
  76. case "Upcoming":
  77. return {
  78. backgroundColor: "#FFAA2C"
  79. }
  80. }
  81. }
  82. onScrollView(e) {
  83. if (e.nativeEvent.contentOffset) {
  84. const isR = e.nativeEvent.contentOffset.y >= $vw(95);
  85. if (isR != this.state.showTitleBar) {
  86. this.setState({
  87. showTitleBar: isR
  88. });
  89. if (isR) {
  90. this.startTitleAnimate();
  91. } else {
  92. this.hideTitleAnimate();
  93. }
  94. MyStatusBar.setStatusBarTheme(isR ? MyStatusBar.DEFAULT_STYLE : MyStatusBar.LIGHT_STYLE);
  95. }
  96. }
  97. }
  98. startTitleAnimate() {
  99. Animated.timing(this.state.opacity, {
  100. toValue: 1,
  101. duration: 250,
  102. easing: Easing.linear,
  103. useNativeDriver: true
  104. }).start(() => {
  105. });
  106. }
  107. hideTitleAnimate() {
  108. Animated.timing(this.state.opacity, {
  109. toValue: 0,
  110. duration: 250,
  111. easing: Easing.linear,
  112. useNativeDriver: true
  113. }).start(() => {
  114. });
  115. }
  116. render() {
  117. if (this.state.loading) {
  118. return (
  119. <View style={styles.container}>
  120. <VbeSkeleton
  121. style={{width: $width, height: $width}}
  122. layout={[
  123. {width: $width, height: $width}
  124. ]}
  125. animationDirection={"horizontalRight"}/>
  126. <VbeSkeleton
  127. style={styles.loadingView}
  128. layout={[
  129. {width: '90%', height: 20, marginTop: 8},
  130. {width: '50%', height: 12, marginTop: 8},
  131. {width: '100%', height: 15, marginTop: 24},
  132. {width: '100%', height: 15, marginTop: 8},
  133. {width: '100%', height: 15, marginTop: 8},
  134. {width: '100%', height: 15, marginTop: 8},
  135. {width: '30%', height: 15, marginTop: 8},
  136. {width: '100%', height: 15, marginTop: 24},
  137. {width: '100%', height: 15, marginTop: 8},
  138. {width: '100%', height: 15, marginTop: 8},
  139. {width: '100%', height: 15, marginTop: 8},
  140. {width: '30%', height: 15, marginTop: 8}
  141. ]}
  142. animationDirection={"horizontalRight"}/>
  143. </View>
  144. )
  145. }
  146. return (
  147. <>
  148. <ScrollView
  149. style={styles.container}
  150. onScroll={e => this.onScrollView(e)}
  151. scrollEventThrottle={16}
  152. contentContainerStyle={$padding(0,0,32)}>
  153. { utils.isNotEmpty(this.state.messageInfo.articleImages) &&
  154. <Swiper
  155. style={{height: $width}}
  156. autoplay={true}
  157. autoplayTimeout={5}
  158. renderPagination={(index,total) => <PagerView index={index+1} total={total}/> }
  159. removeClippedSubviews={false}>
  160. { this.state.messageInfo.articleImages.map((item, index) => {
  161. return (
  162. <Image
  163. key={index}
  164. style={{width: $width, height: $width}}
  165. source={{uri: utils.getImageUrl(item.articleImagePath)}}/>
  166. );
  167. })}
  168. </Swiper>
  169. }
  170. <View style={styles.header}>
  171. <View>
  172. <TextView
  173. style={[styles.labelTypeText, this.getColorByType(this.state.messageInfo.campaignMark)]}
  174. numberOfLines={1}>
  175. {this.state.messageInfo.campaignMark}
  176. </TextView>
  177. <TextView
  178. style={styles.textTitle}
  179. numberOfLines={2}
  180. ellipsizeMode="tail">
  181. <TextView
  182. style={styles.hideText}
  183. numberOfLines={1}>
  184. {this.state.messageInfo.campaignMark}
  185. </TextView>
  186. {this.state.messageInfo.articleTitle}
  187. </TextView>
  188. </View>
  189. <View style={ui.flexc}>
  190. <MaterialCommunityIcons
  191. name="clock-time-four-outline"
  192. color={textSecondary}
  193. size={12}/>
  194. <TextView
  195. style={styles.textDate}
  196. numberOfLines={1}>
  197. {this.state.messageInfo.createTime}
  198. </TextView>
  199. <MaterialCommunityIcons
  200. name="eye-check-outline"
  201. size={12}
  202. color={textPrimary}/>
  203. <TextView
  204. style={styles.textView}
  205. numberOfLines={1}>
  206. {this.state.messageInfo.articleViews}
  207. </TextView>
  208. </View>
  209. </View>
  210. <TextView style={styles.textLinkTitle}>{$t("notification.labelSummary")}</TextView>
  211. <TextView
  212. style={styles.textSummary}>
  213. {$t("notification.startTime")}
  214. {this.state.messageInfo.startTime}
  215. </TextView>
  216. <TextView
  217. style={styles.textSummary}>
  218. {$t("notification.endTime")}
  219. {this.state.messageInfo.endTime}
  220. </TextView>
  221. <TextView style={styles.textLinkTitle}>{$t("notification.labelDetails")}</TextView>
  222. <TextView
  223. style={styles.textMessage}
  224. selectable={true}>
  225. {this.state.messageInfo.articleContent}
  226. </TextView>
  227. { utils.isNotEmpty(this.state.messageInfo.articleLinks) &&
  228. <>
  229. <TextView style={styles.textLinkTitle}>{$t("notification.labelLinks")}</TextView>
  230. { this.state.messageInfo.articleLinks.map((item, index) =>
  231. <View style={styles.itemLink} key={index}>
  232. <TextView style={styles.linkIndex}>{index + 1}.</TextView>
  233. <TextView
  234. style={styles.linkHyper}
  235. onPress={() => this.accessLink(item.articleLink)}>{item.articleLinkName}</TextView>
  236. </View>
  237. )}
  238. </>
  239. }
  240. <EndView/>
  241. </ScrollView>
  242. { !this.state.showTitleBar &&
  243. <View style={[styles.toolbar, {top: statusHeight + 4}]}>
  244. <BackButton style={styles.backIcon} color={"#F0F0F0"}/>
  245. </View>
  246. }
  247. <Animated.View style={[styles.toolbar, {opacity: this.state.opacity}]}>
  248. <Toolbar title={this.state.messageInfo.articleTitle}/>
  249. </Animated.View>
  250. </>
  251. );
  252. }
  253. }
  254. const styles = StyleSheet.create({
  255. container: {
  256. flex: 1,
  257. backgroundColor: pageBackground
  258. },
  259. toolbar: {
  260. top: 0,
  261. left: 0,
  262. right: 0,
  263. zIndex: 2,
  264. position: 'absolute'
  265. },
  266. backIcon: {
  267. width: 48,
  268. height: 48,
  269. zIndex: 2,
  270. marginLeft: 4,
  271. alignItems: 'center',
  272. justifyContent: 'center'
  273. },
  274. loadingView: {
  275. flex: 1,
  276. padding: 16,
  277. justifyContent: 'flex-start',
  278. backgroundColor: pageBackground
  279. },
  280. textTitle: {
  281. color: textPrimary,
  282. fontSize: 18,
  283. fontWeight: 'bold',
  284. paddingBottom: 2
  285. },
  286. textDate: {
  287. flex: 1,
  288. color: textSecondary,
  289. fontSize: 10,
  290. paddingLeft: 2
  291. },
  292. textView: {
  293. color: textSecondary,
  294. fontSize: 10,
  295. paddingLeft: 4
  296. },
  297. header: {
  298. padding: 16,
  299. backgroundColor: pageBackground
  300. },
  301. textSummary: {
  302. color: textPrimary,
  303. fontSize: 14,
  304. ...$padding(0, 16, 8)
  305. },
  306. textMessage: {
  307. color: textPrimary,
  308. fontSize: 14,
  309. ...$padding(0, 16, 16)
  310. },
  311. labelTypeText: {
  312. color: textLight,
  313. height: 16,
  314. fontSize: 10,
  315. borderRadius: 4,
  316. marginTop: 3,
  317. ...$padding(0, 6),
  318. position: 'absolute',
  319. backgroundColor: "#1ABD00"
  320. },
  321. hideText: {
  322. height: 16,
  323. opacity: 0,
  324. fontSize: 10,
  325. ...$padding(2, 8),
  326. },
  327. textLinkTitle: {
  328. color: textPrimary,
  329. fontSize: 16,
  330. fontWeight: 'bold',
  331. padding: 16
  332. },
  333. itemLink: {
  334. ...$padding(0, 16, 8),
  335. flexDirection: 'row'
  336. },
  337. linkIndex: {
  338. fontSize: 14,
  339. paddingRight: 2
  340. },
  341. linkHyper: {
  342. ...ui.link,
  343. fontSize: 14,
  344. textDecorationLine: 'underline'
  345. },
  346. linkActive: {
  347. color: "#FF3B30"
  348. }
  349. })