index.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. import React, { Component } from 'react';
  2. import { Icon, message, Spin, Upload, Progress, Modal } from 'antd';
  3. import './index.less';
  4. import Viewer from 'viewerjs';
  5. import 'viewerjs/dist/viewer.css';
  6. import PropTypes from 'prop-types';
  7. import pdfimg from '../../../../image/pdf_logo.png';
  8. const uploadButton = (
  9. <div>
  10. <Icon type="plus" />
  11. <div className="ant-upload-text" style={{ cursor: 'pointer' }}>点击上传</div>
  12. </div>
  13. );
  14. class ImgList extends Component {
  15. constructor(props) {
  16. super(props);
  17. this.state = {
  18. seeMore: false,
  19. gallery: null,
  20. loading: true,
  21. imgLoadNum: 0,
  22. uploadLoading: false,
  23. percent: 0,
  24. newUploadArr: [],
  25. newUploadInforArr: {},
  26. isPDF: false,
  27. file: {},
  28. }
  29. this.imgLoading = this.imgLoading.bind(this);
  30. this.beforeUpload = this.beforeUpload.bind(this);
  31. this.setTimeOutObj = null;
  32. }
  33. componentDidMount() {
  34. this.setTimeOutObj = setTimeout(() => {
  35. this.setState({
  36. gallery: new Viewer(document.getElementById(this.props.domId))
  37. }, () => {
  38. this.setState({
  39. loading: false
  40. })
  41. })
  42. }, 10000)
  43. }
  44. imgLoading() {
  45. if (Object.keys(this.props.uploadConfig).length !== 0) {
  46. this.setTimeOutObj && clearTimeout(this.setTimeOutObj);
  47. } else {
  48. let num = this.state.imgLoadNum + 1;
  49. if (num >= this.props.fileList.length) {
  50. this.state.gallery && this.state.gallery.destroy();
  51. this.setState({
  52. gallery: new Viewer(document.getElementById(this.props.domId))
  53. }, () => {
  54. this.setTimeOutObj && clearTimeout(this.setTimeOutObj);
  55. this.setState({
  56. loading: false
  57. })
  58. })
  59. }
  60. this.setState({
  61. imgLoadNum: num
  62. })
  63. }
  64. }
  65. beforeUpload(file) {
  66. const isLt2M = file.size / 1024 / 1024 < 10;
  67. if (!isLt2M) {
  68. message.error('文件大小不能超过 10MB!');
  69. return isLt2M;
  70. }
  71. if (this.props.accept) {
  72. if (isLt2M) {
  73. this.state.newUploadArr.push(file)
  74. this.setState({
  75. newUploadArr: this.state.newUploadArr
  76. })
  77. }
  78. return isLt2M;
  79. } else {
  80. const isJPG = file.type.split('/');
  81. // if (isJPG[0] !== 'image' && isJPG[0] !== "application") {
  82. // message.error('只能上传图片或pdf文件!');
  83. // return false;
  84. // }
  85. if (isJPG[0] !== 'image') {
  86. message.error('只能上传图片!');
  87. return false;
  88. }
  89. if (isJPG && isLt2M) {
  90. //用于计算当次选择的图片数量
  91. this.state.newUploadArr.push(file)
  92. this.setState({
  93. newUploadArr: this.state.newUploadArr
  94. })
  95. }
  96. return isJPG && isLt2M;
  97. }
  98. }
  99. componentWillUnmount() {
  100. this.setTimeOutObj && clearTimeout(this.setTimeOutObj);
  101. }
  102. render() {
  103. const { fileList } = this.props;
  104. if (!fileList || !Array.isArray(fileList)) {
  105. return null;
  106. }
  107. return (
  108. <div className='ImgListComponent'>
  109. <div className='ImgList'>
  110. <Spin spinning={Object.keys(this.props.uploadConfig).length !== 0 ? false : (fileList.length === 0 ? false : this.state.loading)} tip="文件加载中...">
  111. <Upload
  112. {...this.props.uploadConfig}
  113. accept={this.props.accept || "image/*,application/pdf"}
  114. className={Object.keys(this.props.uploadConfig).length !== 0 ? "" : "demandDetailShow-upload"}
  115. listType={this.props.accept ? this.props.uploadConfig.listType : "picture-card"}
  116. fileList={
  117. Object.keys(this.props.uploadConfig).length !== 0 ?
  118. (
  119. fileList.map((v, i) => {
  120. v.index = i;
  121. v.url = v.url;
  122. v.thumbUrl = v.name.substr(v.name.lastIndexOf(".") + 1) == "pdf" ? pdfimg : v.url
  123. return v
  124. })
  125. ) : (
  126. this.state.seeMore ?
  127. fileList.map((v, i) => {
  128. v.index = i;
  129. v.url = v.url;
  130. v.thumbUrl = v.name.substr(v.name.lastIndexOf(".") + 1) == "pdf" ? pdfimg : v.url
  131. return v
  132. }) :
  133. fileList.map((v, i) => {
  134. v.index = i;
  135. v.url = v.url;
  136. v.thumbUrl = v.name.substr(v.name.lastIndexOf(".") + 1) == "pdf" ? pdfimg : v.url
  137. return v
  138. }).slice(0, 10)
  139. )
  140. }
  141. onPreview={(file) => {
  142. let types = file.name.substr(file.name.lastIndexOf(".") + 1)
  143. if (!!file.type && file.type.split('/')[0] == "application" || types == "pdf") {
  144. let url = file.response.data.indexOf("/upload") == -1
  145. ? globalConfig.avatarHost + "/upload" + file.response.data
  146. : file.response.data
  147. this.setState({
  148. isPDF: true,
  149. file: url,
  150. })
  151. // window.open(url)
  152. } else {
  153. if (Object.keys(this.props.uploadConfig).length !== 0) {
  154. //TODO 上传组件,查看图片临时解决方法,无法查看下一张
  155. let image = new Image();
  156. image.src = file.url || file.thumbUrl;
  157. let viewer = new Viewer(image, {
  158. hidden: function () {
  159. viewer.destroy();
  160. },
  161. });
  162. viewer.show();
  163. } else {
  164. this.state.gallery.view(file.index).show();
  165. }
  166. }
  167. }}
  168. beforeUpload={this.beforeUpload}
  169. onChange={(infor) => {
  170. if (infor.file.status) {
  171. let newUploadNum = this.state.newUploadArr.length
  172. this.state.gallery && this.state.gallery.destroy();
  173. this.props.onChange(infor);
  174. if (infor.file && infor.file.status === 'error') {
  175. message.error('上传失败,请重新上传!');
  176. }
  177. //用于控制进度条
  178. if (infor.file && infor.file.status !== 'removed' && infor.event) {
  179. let percent = 0;
  180. this.state.newUploadInforArr[infor.file.uid] = infor.event.percent;
  181. this.setState({
  182. newUploadInforArr: this.state.newUploadInforArr
  183. })
  184. for (let i of Object.values(this.state.newUploadInforArr)) {
  185. percent += i
  186. }
  187. let percentNum = percent / newUploadNum / 100;
  188. this.setState({
  189. percent: percentNum
  190. })
  191. if (percentNum <= 1) {
  192. this.setState({
  193. uploadLoading: true,
  194. })
  195. }
  196. if (percentNum >= 1) {
  197. this.setState({
  198. percent: 1,
  199. }, () => {
  200. setTimeout(() => {
  201. this.setState({
  202. uploadLoading: false,
  203. }, () => {
  204. this.setState({
  205. percent: 0,
  206. newUploadArr: [],
  207. newUploadInforArr: {}
  208. })
  209. })
  210. }, 1500)
  211. })
  212. }
  213. } else if (infor.file && infor.file.status === 'removed') {
  214. this.setState({
  215. percent: 0,
  216. newUploadArr: [],
  217. newUploadInforArr: {}
  218. })
  219. }
  220. }
  221. }}
  222. >
  223. {Object.keys(this.props.uploadConfig).length === 0 ? "" : uploadButton}
  224. </Upload>
  225. </Spin>
  226. </div>
  227. {fileList.length > 10 && Object.keys(this.props.uploadConfig).length === 0
  228. ? <div className='seeMore' onClick={() => { this.setState({ seeMore: !this.state.seeMore }) }}>
  229. {this.state.seeMore ? '收起' : '查看更多'}
  230. </div>
  231. : <div />}
  232. <ul id={this.props.domId} style={{ display: 'none', zIndex: -1, }}>
  233. {
  234. fileList.map((value, index) => (
  235. <li key={index}>
  236. <img src={value.name.substr(value.name.lastIndexOf(".") + 1) == "pdf" ? pdfimg : (value.url || value.thumbUrl)} onLoad={() => {
  237. this.imgLoading();
  238. }} />
  239. </li>
  240. ))
  241. }
  242. </ul>
  243. {this.state.uploadLoading ? <div className='mask'>
  244. <Progress
  245. className='progress'
  246. type="circle"
  247. status="active"
  248. percent={parseFloat(this.state.percent * 100).toFixed(0)}
  249. />
  250. <div className='promptText'>文件上传中...</div>
  251. </div> : <div />}
  252. {
  253. // PDF文件预览弹窗
  254. this.state.isPDF &&
  255. <Modal
  256. wrapClassName={"pdfmodal"}
  257. visible={this.state.isPDF}
  258. className="admin-desc-content"
  259. footer=""
  260. title=""
  261. width="1200px"
  262. onCancel={() => {
  263. this.setState({
  264. isPDF: false,
  265. file: "",
  266. })
  267. }}
  268. >
  269. <embed src={this.state.file} type="application/pdf" style={{ width: "100%", height: 700 }} />
  270. </Modal>
  271. }
  272. </div>
  273. )
  274. }
  275. }
  276. ImgList.propTypes = {
  277. domId: PropTypes.string, //如果一个界面有多个该组件,需要传入自定义id名称,用于图片列表显示
  278. fileList: PropTypes.array.isRequired, //图片文件列表
  279. uploadConfig: PropTypes.object, //上传图片配置参数(需要上传图片时需要,存在与否,用于区分是否为上传或者为查看)
  280. onChange: PropTypes.func, //选择图片
  281. }
  282. ImgList.defaultProps = {
  283. domId: 'images',
  284. fileList: [],
  285. uploadConfig: {},
  286. onChange: () => { }
  287. }
  288. export default ImgList;