diff --git a/admin-web/package.json b/admin-web/package.json index 8159e6e9b..bd7367e56 100644 --- a/admin-web/package.json +++ b/admin-web/package.json @@ -40,9 +40,11 @@ "bizcharts": "^3.4.3", "bizcharts-plugin-slider": "^2.1.1-beta.1", "classnames": "^2.2.6", + "crypto": "^1.0.1", "dva": "^2.4.1", "enquire-js": "^0.2.1", "hash.js": "^1.1.7", + "js-uuid": "0.0.6", "lodash": "^4.17.11", "lodash-decorators": "^6.0.1", "memoize-one": "^5.0.0", diff --git a/admin-web/src/components/Image/PicturesWall.js b/admin-web/src/components/Image/PicturesWall.js new file mode 100644 index 000000000..c7c93663c --- /dev/null +++ b/admin-web/src/components/Image/PicturesWall.js @@ -0,0 +1,171 @@ +import React from "react"; +import {fileGetQiniuToken} from "../../services/admin"; +import uuid from "js-uuid"; +import * as qiniu from "qiniu-js"; +import {Icon, Modal, Upload} from "antd"; + +import styles from './PicturesWall.less'; + +class PicturesWall extends React.Component { + state = { + token: undefined, // 七牛 token + + + previewVisible: false, + previewImage: '', + + fileList: [ + // { // 目前图片 + // uid: -1, + // name: 'xxx.png', + // status: 'done', + // url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', + // } + ], + }; + + handleCancel = () => this.setState({ previewVisible: false }) + + handlePreview = (file) => { + this.setState({ + previewImage: file.url || file.thumbUrl, + previewVisible: true, + }); + } + + beforeUpload = async () => { + const tokenResult = await fileGetQiniuToken(); + if (tokenResult.code !== 0) { + alert('获得七牛上传 Token 失败'); + return false; + } + this.setState({ + token: tokenResult.data, + }); + return true; + }; + + customRequest = ({action, + file, + headers, + onError, + onProgress, + onSuccess, + withCredentials,}) => { + // fs.readFile(path, function(err, data) { + // if (err) return; + // let md5Value= crypto.createHash('md5').update(data, 'utf8').digest('hex'); + // let observable = qiniu.upload(file, md5Value, this.state.token); + // observable.subscribe(function () { + // // next + // }, function () { + // // error + // }, function (response) { + // // complete + // debugger; + // onSuccess(response, file); + // }); + // }); + + // 使用 FileReader 将上传的文件转换成二进制流,满足 'application/octet-stream' 格式的要求 + const reader = new FileReader(); + reader.readAsArrayBuffer(file); + let fileData = null; + reader.onload = (e) => { + // 在文件读取结束后执行的操作 + fileData = e.target.result; + // debugger; + // let md5Value= crypto.createHash('md5').update(fileData, 'utf8').digest('hex'); + // 上传文件 + // fileUploadQiniu(fileData); + // debugger; + // 使用 axios 进行文件上传的请求 + // axios.put(action, fileData, { + // withCredentials, + // headers, + // onUploadProgress: ({ total, loaded }) => { + // // 进行上传进度输出,更加直观 + // onProgress({ percent: Math.round(loaded / total * 100).toFixed(2) }, file); + // }, + // }).then(response => { + // onSuccess(response, file); + // }) + // .catch(onError); + let key = uuid.v4(); // TODO 芋艿,可能后面要优化。MD5? + let observable = qiniu.upload(file, key, this.state.token); // TODO 芋艿,最后后面去掉 qiniu 的库依赖,直接 http 请求,这样更轻量 + observable.subscribe(function () { + // next + }, function () { + // error + // TODO 芋艿,后续补充 + debugger; + }, function (response) { + // complete + // debugger; + response.url = 'http://static.shop.iocoder.cn/' + response.key; // 需要设置,用于后续 onSuccess ,合并到 file 中,从而设置到 fileList + onSuccess(response, file); + }); + }; + return { + abort() { + console.log('upload progress is aborted.'); + }, + }; + }; + + handleChange = ({ file, fileList }) => { + if (file.response && file.response.url) { + // debugger + // file.url = + for (let i in fileList) { + if (fileList[i].uid === file.uid) { + fileList[i].url = file.response.url; + } + } + } + this.setState({ fileList }); + } + + getUrls = () => { + let urls = []; + for (let i in this.state.fileList) { + urls.push(this.state.fileList[i].url); + } + return urls; + }; + + render() { + const { previewVisible, previewImage, fileList } = this.state; + const uploadButton = ( +
+ +
Upload
+
+ ); + return ( +
+ + {fileList.length >= this.props.maxLength ? null : uploadButton} + + + example + +
+ ); + } +}; + +PicturesWall.propTypes = { + maxLength: Number, +}; + +export default PicturesWall; diff --git a/admin-web/src/components/Image/PicturesWall.less b/admin-web/src/components/Image/PicturesWall.less new file mode 100644 index 000000000..b2d2f2e4e --- /dev/null +++ b/admin-web/src/components/Image/PicturesWall.less @@ -0,0 +1,10 @@ + +.ant-upload-select-picture-card i { + font-size: 32px; + color: #999; +} + +.ant-upload-select-picture-card .ant-upload-text { + margin-top: 8px; + color: #666; +} diff --git a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js index 8e5ce6045..1417f79e0 100644 --- a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js +++ b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js @@ -1,136 +1,26 @@ /* eslint-disable */ import React, {PureComponent, Fragment, Component} from 'react'; +// import crypto from 'crypto'; +// import fs from 'fs'; import { connect } from 'dva'; import moment from 'moment'; import {Card, Form, Input, Radio, Button, Modal, Select, Upload, Icon} from 'antd'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; -import * as qiniu from 'qiniu-js' +// import * as qiniu from 'qiniu-js' +// import uuid from 'js-uuid'; import styles from './ProductSpuAddOrUpdate.less'; import ProductAttrSelectFormItem from "../../components/Product/ProductAttrSelectFormItem"; import ProductSkuAddOrUpdateTable from "../../components/Product/ProductSkuAddOrUpdateTable"; -import {fileGetQiniuToken, fileUploadQiniu} from "../../services/admin"; +import {fileGetQiniuToken} from "../../services/admin"; +import PicturesWall from "../../components/Image/PicturesWall"; const FormItem = Form.Item; const RadioGroup = Radio.Group; const Option = Select.Option; -class PicturesWall extends React.Component { - state = { - token: undefined, // 七牛 token - - - previewVisible: false, - previewImage: '', - - fileList: [{ // 目前图片 - uid: -1, - name: 'xxx.png', - status: 'done', - url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', - }], - }; - - handleCancel = () => this.setState({ previewVisible: false }) - - handlePreview = (file) => { - this.setState({ - previewImage: file.url || file.thumbUrl, - previewVisible: true, - }); - } - - beforeUpload = async () => { - const tokenResult = await fileGetQiniuToken(); - if (tokenResult.code !== 0) { - alert('获得七牛上传 Token 失败'); - return false; - } - this.setState({ - token: tokenResult.data, - }); - return true; - }; - - customRequest = ({action, - file, - headers, - onError, - onProgress, - onSuccess, - withCredentials,}) => { - // 使用 FileReader 将上传的文件转换成二进制流,满足 'application/octet-stream' 格式的要求 - const reader = new FileReader(); - reader.readAsArrayBuffer(file); - let fileData = null; - reader.onload = (e) => { - // 在文件读取结束后执行的操作 - fileData = e.target.result; - // 上传文件 - // fileUploadQiniu(fileData); - // debugger; - // 使用 axios 进行文件上传的请求 - // axios.put(action, fileData, { - // withCredentials, - // headers, - // onUploadProgress: ({ total, loaded }) => { - // // 进行上传进度输出,更加直观 - // onProgress({ percent: Math.round(loaded / total * 100).toFixed(2) }, file); - // }, - // }).then(response => { - // onSuccess(response, file); - // }) - // .catch(onError); - let observable = qiniu.upload(file, '123', this.state.token); - observable.subscribe(function () { - // next - }, function () { - // error - }, function () { - // complete - }); - }; - return { - abort() { - console.log('upload progress is aborted.'); - }, - }; - }; - - handleChange = ({ fileList }) => this.setState({ fileList }) - - render() { - const { previewVisible, previewImage, fileList } = this.state; - const uploadButton = ( -
- -
Upload
-
- ); - return ( -
- - {fileList.length >= 3 ? null : uploadButton} - - - example - -
- ); - } -}; - // roleList @connect(({ productSpuList, productAttrList, productSpuAddOrUpdate, loading }) => ({ // list: productSpuList.list.spus, @@ -175,9 +65,14 @@ class ProductSpuAddOrUpdate extends Component { } handleSubmit = e => { - debugger; e.preventDefault(); const { skus, dispatch } = this.props; + // 获得图片 + let picUrls = this.refs.picturesWall.getUrls(); + if (picUrls.length === 0) { + alert('请必须上传一张图片!'); + return; + } // 生成 skuStr 格式 let skuStr = []; // 因为提交是字符串格式 for (let i in skus) { @@ -199,6 +94,7 @@ class ProductSpuAddOrUpdate extends Component { alert('请设置商品规格!'); return; } + // debugger; this.props.form.validateFields((err, values) => { if (!err) { dispatch({ @@ -206,6 +102,7 @@ class ProductSpuAddOrUpdate extends Component { payload: { body: { ...values, + picUrls: picUrls.join(','), skuStr: JSON.stringify(skuStr) } }, @@ -362,11 +259,12 @@ class ProductSpuAddOrUpdate extends Component { initialValue: '', // TODO 修改 // TODO 芋艿,和面做成下拉框 })()} - + {/*{form.getFieldDecorator('picUrls', {*/} {/* initialValue: '', // TODO 修改 // TODO 芋艿,做成上传组件*/} {/*})()}*/} - + {form.getFieldDecorator('visible', { diff --git a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.less b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.less index bc395f2f3..ebb45c292 100644 --- a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.less +++ b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.less @@ -13,13 +13,3 @@ .tableDelete { color: red; } - -.ant-upload-select-picture-card i { - font-size: 32px; - color: #999; -} - -.ant-upload-select-picture-card .ant-upload-text { - margin-top: 8px; - color: #666; -}