index.js 11 KB

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