ViewCampaign.js 9.6 KB

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