ViewCampaign.js 9.1 KB

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