index.js 12 KB

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