index.js 15 KB

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