index.js 11 KB

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