ViewArticle.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**
  2. * 文章详情
  3. * @邠心vbe on 2023/10/24
  4. */
  5. import React, { Component } from 'react';
  6. import { View, StyleSheet, Image, ScrollView, Linking } from 'react-native';
  7. import Swiper from 'react-native-swiper';
  8. import apiArticle from '../../api/apiArticle';
  9. import HeaderTitle from '../../components/HeaderTitle';
  10. import TextView from '../../components/TextView';
  11. import VbeSkeleton from '../../components/VbeSkeleton';
  12. import utils from '../../utils/utils';
  13. import { PagerView } from './ViewUtil';
  14. export default class ViewArticle extends Component {
  15. constructor(props) {
  16. super(props);
  17. this.state = {
  18. id: "",
  19. loading: true,
  20. messageInfo: {
  21. articleTypeName: "",
  22. articleTitle: "",
  23. articleContent: ""
  24. }
  25. };
  26. }
  27. componentDidMount() {
  28. if (this.props.route?.params?.id) {
  29. this.setState({
  30. id: this.props.route?.params?.id
  31. }, () => {
  32. this.readMessage();
  33. })
  34. }
  35. }
  36. readMessage() {
  37. apiArticle.readMessage(this.state.id).then(res => {
  38. if (res.data) {
  39. this.setState({
  40. messageInfo: res.data
  41. });
  42. this.setPageTitle();
  43. }
  44. }).catch(err => {
  45. toastShort(err);
  46. });
  47. }
  48. setPageTitle() {
  49. if (this.state.messageInfo.articleTitle) {
  50. this.props.navigation.setOptions({
  51. headerTitle: () => (<HeaderTitle title={this.state.messageInfo.articleTitle}/>)
  52. });
  53. setTimeout(() => {
  54. this.setState({
  55. loading: false
  56. });
  57. }, 300);
  58. }
  59. }
  60. accessLink(url) {
  61. Linking.openURL(utils.getImageUrl(url))
  62. }
  63. render() {
  64. if (this.state.loading) {
  65. return (
  66. <View style={styles.container}>
  67. <VbeSkeleton
  68. style={{width: $width, height: $width}}
  69. layout={[
  70. {width: $width, height: $width}
  71. ]}
  72. animationDirection={"horizontalRight"}/>
  73. <VbeSkeleton
  74. style={styles.loadingView}
  75. layout={[
  76. {width: '90%', height: 20, marginTop: 8},
  77. {width: '50%', height: 12, marginTop: 8},
  78. {width: '100%', height: 15, marginTop: 24},
  79. {width: '100%', height: 15, marginTop: 8},
  80. {width: '100%', height: 15, marginTop: 8},
  81. {width: '100%', height: 15, marginTop: 8},
  82. {width: '30%', height: 15, marginTop: 8}
  83. ]}
  84. animationDirection={"horizontalRight"}/>
  85. </View>
  86. )
  87. } else {
  88. return (
  89. <ScrollView
  90. style={styles.container}
  91. contentContainerStyle={$padding(0,0,32)}
  92. stickyHeaderIndices={[utils.isNotEmpty(this.state.messageInfo.articleImages) ? 1 : 0]}>
  93. { utils.isNotEmpty(this.state.messageInfo.articleImages) &&
  94. <Swiper
  95. style={{height: $width}}
  96. autoplay={true}
  97. autoplayTimeout={5}
  98. renderPagination={(index,total) => <PagerView index={index+1} total={total}/> }
  99. removeClippedSubviews={false}>
  100. { this.state.messageInfo.articleImages.map((item, index) => {
  101. return (
  102. <Image
  103. key={index}
  104. style={{width: $width, height: $width}}
  105. source={{uri: utils.getImageUrl(item.articleImagePath)}}/>
  106. );
  107. })}
  108. </Swiper>
  109. }
  110. <View style={styles.header}>
  111. <TextView
  112. style={styles.textTitle}>
  113. {this.state.messageInfo.articleTitle}
  114. </TextView>
  115. <View style={ui.flexc}>
  116. <MaterialCommunityIcons
  117. name="clock-time-four-outline"
  118. color={textSecondary}
  119. size={12}/>
  120. <TextView
  121. style={styles.textDate}
  122. numberOfLines={1}>
  123. {this.state.messageInfo.createTime}
  124. </TextView>
  125. </View>
  126. <View style={ui.flexc}>
  127. <MaterialCommunityIcons
  128. name="eye-check-outline"
  129. size={12}
  130. color={textPrimary}/>
  131. <TextView
  132. style={styles.textView}
  133. numberOfLines={1}>
  134. {this.state.messageInfo.articleViews}
  135. </TextView>
  136. </View>
  137. <View style={ui.flex}>
  138. <TextView
  139. style={styles.labelTypeText}
  140. numberOfLines={1}>
  141. {this.state.messageInfo.articleTypeName}
  142. </TextView>
  143. </View>
  144. </View>
  145. <TextView
  146. style={styles.textMessage}
  147. selectable={true}>
  148. {this.state.messageInfo.articleContent}
  149. </TextView>
  150. { utils.isNotEmpty(this.state.messageInfo.articleLinks) &&
  151. <>
  152. <TextView style={styles.textLinkTitle}>{$t("notification.labelLinks")}</TextView>
  153. { this.state.messageInfo.articleLinks.map((item, index) =>
  154. <View style={styles.itemLink} key={index}>
  155. <TextView style={styles.linkIndex}>{index + 1}.</TextView>
  156. <TextView
  157. style={styles.linkHyper}
  158. onPress={() => this.accessLink(item.articleLink)}>{item.articleLinkName}</TextView>
  159. </View>
  160. )}
  161. </>
  162. }
  163. <EndView/>
  164. </ScrollView>
  165. );
  166. }
  167. }
  168. }
  169. const styles = StyleSheet.create({
  170. container: {
  171. flex: 1,
  172. backgroundColor: pageBackground
  173. },
  174. loadingView: {
  175. flex: 1,
  176. padding: 16,
  177. justifyContent: 'flex-start',
  178. backgroundColor: pageBackground
  179. },
  180. textTitle: {
  181. color: textPrimary,
  182. fontSize: 14,
  183. fontWeight: 'bold',
  184. paddingBottom: 2
  185. },
  186. textDate: {
  187. flex: 1,
  188. color: textSecondary,
  189. fontSize: 12,
  190. paddingLeft: 2
  191. },
  192. textView: {
  193. color: textSecondary,
  194. fontSize: 14,
  195. padding: 4
  196. },
  197. header: {
  198. padding: 16,
  199. //...ElevationObject(1),
  200. backgroundColor: pageBackground
  201. },
  202. textMessage: {
  203. color: textPrimary,
  204. fontSize: 12,
  205. paddingLeft: 16,
  206. paddingRight: 16
  207. },
  208. labelTypeText: {
  209. fontSize: 12,
  210. fontWeight: 'bold',
  211. borderWidth: 1,
  212. borderRadius: 4,
  213. borderColor: colorPrimary,
  214. marginTop: 8,
  215. ...$padding(2, 6)
  216. },
  217. textLinkTitle: {
  218. color: textPrimary,
  219. fontSize: 14,
  220. fontWeight: 'bold',
  221. padding: 16
  222. },
  223. itemLink: {
  224. ...$padding(0, 16, 8),
  225. flexDirection: 'row'
  226. },
  227. linkIndex: {
  228. fontSize: 12,
  229. paddingRight: 2
  230. },
  231. linkHyper: {
  232. ...ui.link,
  233. fontSize: 12,
  234. textDecorationLine: 'underline'
  235. },
  236. linkActive: {
  237. color: "#FF3B30"
  238. }
  239. })