一、搜索Search
- 搜索框
<Search placeholder="請輸入關鍵字" defaultValue={kw && kw != 'null' ? kw : ''} className={styles.search} onChange={() => this.handleKwChange()} onSearch={(e) => this.handleSearch(e)} />
-
引入工具方法:去掉收尾空格
import {trimStr} from '@/utils/utils'; // utils.js export function trimStr(str){ return str.replace(/(^\s*)|(\s*$)/g,""); }
-
搜索按鈕觸發搜索方法,輸入內容改變自動搜索
handleSearch = e => { const { dispatch } = this.props; const { currentPage } = this.state; let kw = trimStr(e); this.setState({ keyword : kw }); dispatch({ type: 'newMallOrder/fetch', payload: { currentPage, e: { keyword: kw }, showCount: 10 }, }); }; handleKwChange = () => { const { dispatch } = this.props; const { currentPage } = this.state; if(event && event.target && event.target.value){ let value = event.target.value; this.handleSearch(value) }else{ dispatch({ type: 'newMallOrder/fetch', payload: { currentPage, e: { keyword: null }, showCount: 10 }, }); } }
二、選擇器Select & TreeSelect
- 表單中嵌入Select選擇器
<FormItem> {getFieldDecorator('tempTypeId',{ initialValue: 0 })( <Select placeholder="請選擇" style={{ width: '100%' }} onChange={this.handleTempType}> <Option value={0}>H5在線編輯</Option> <Option value={1}>賀卡</Option> <Option value={2}>海報</Option> <Option value={3}>壁紙</Option> <Option value={4}>全部</Option> </Select> )} </FormItem>
選擇方法:
handleTempType = value => { const { dispatch } = this.props; const { keyword } = this.state; this.setState({ tempType: tempTypeMap[value] }) dispatch({ type: 'temp/fetch', payload: { currentPage: 1, e: { keyword: keyword, subjectClass: tempTypeMap[value] }, showCount: 2 } }); dispatch({ type: 'temp/fetchType', payload: { ofClass: tempTypeMap[value] }, callback: (res) => { if(res.code == 200){ let typeList = res.data; // 獲取聯動選擇框的數據 typeList.forEach((typeItem, index) => { dispatch({ type: 'temp/fetchThirdType', payload: typeItem.id, callback: (res) => { if(res.code == 200 && res.data.length){ typeList[index].list = res.data; } } }) }) setTimeout(() => this.setState({ typeList }), 0) } } }); }
- 聯動選擇的第一個選擇框的父級數據
let ParentTypeData = [ { title: 'H5在線編輯', value: 0, key: 0, }, { title: '賀卡', value: 1, key: 1, }, { title: '海報', value: 2, key: 2, }, { title: '壁紙', value: 3, key: 3, }, { title: '全部', value: 4, key: 4, }, ];
- 處理獲取到的聯動選擇第二個選擇框的數據為TreeSelect需要的數據格式
let typeData = []; const typeTree = (typeList, typeData) => { if(typeList.length) { for(let i=0; i<typeList.length; i++){ typeData[i] = { title: typeList[i].kind, value: typeList[i].id, key: typeList[i].id } //二級分類 if(typeList[i].list){ typeData[i].children = []; typeTree(typeList[i].list, typeData[i].children) } } } } typeTree(typeList, typeData);
-
表單中嵌入TreeSelect選擇器
<FormItem label="主題類別" {...formLayout}> <TreeSelect defaultValue={tempType == null ? 4 : tempTypeMap.indexOf(tempType)} value={parentTypeId} style={{display: `${editDisable ? 'none' : 'inline-block'}`, width: '47%', marginRight: '6%'}} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={ParentTypeData} placeholder="請選擇" onChange={handleParentType} /> {form.getFieldDecorator('typeIds', { rules: [{ type:"array", required: true, message: '請選擇主題類別'}], initialValue: detail.types && detail.types.length ? detail.types.map((type) => type.id) : [] })( <TreeSelect multiple // 多選 style={{width: `${editDisable ? '100%' : '47%'}`}} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={typeData} placeholder="請選擇" disabled={editDisable} onChange={handleTypeChange} /> )} </FormItem>
三、圖片視頻音頻上傳Upload
- 彈框表單中上傳一張圖片、一個音頻
- 引入upload.js中封裝的handImageUpload文件上傳七牛雲的方法
import { handleImageUpload } from '@/utils/upload'; // 預覽文件時url前面需要加七牛雲服務器前綴 // eg: 'http://fileserver.liuliu123.cn/' import { setFileHost } from '@/utils/utils';
upload.js
var qiniu = require('qiniu-js') import axios from 'axios'; import configs from '@/utils/env' import { message } from 'antd'; //七牛雲上傳,input, onchange事件 export function handleImageUpload(file, type, resName) { // console.log(file,'handleImageUpload') let suffix = file.type.split('/')[1]; return new Promise(function(resolve, reject){ if(!file) { reject('file is undefined') } function dataURItoBlob(base64Data) { var byteString; if(base64Data.split(',')[0].indexOf('base64') >= 0) byteString = atob(base64Data.split(',')[1]); else byteString = unescape(base64Data.split(',')[1]); var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0]; var ia = new Uint8Array(byteString.length); for(var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ia], { type: mimeString }); } function randomString(len) { len = len || 32; var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; var maxPos = $chars.length; var pwd = ''; for (let i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e) { var fileBlob = dataURItoBlob(e.target.result); var key; switch(type){ case 'audio': key = 'sys/file/music/' + resName + '.' + suffix; break; case 'video': key = 'liveWallPaper/' + resName + '.' + suffix; break; case 'tutorial': //教程文件 key = 'sys/tutorial/' + new Date().getTime() + randomString(5) + '.' + suffix; break; case 'tutorialVideo': //針對IOS富文本視頻顯示問題單獨處理教程視頻 key = 'yihezo/' + new Date().getTime() +randomString(5) + '.' + suffix; break; default: key = 'user/h5/' + new Date().getTime() +randomString(5) + '.' + suffix; } var putExtra = { fname: file.name, params: {}, mimeType: ["image/png", "image/jpeg", "image/jpg", "image/gif", "image/webp", "image/apng", "image/svg", "audio/mp3", "audio/mp4", "audio/ogg", "audio/mpeg", "video/mp4", "video/ogg", "video/webm"] }; var config = { useCdnDomain: true, }; if(type == 'tutorialVideo' ){ //針對IOS富文本視頻顯示問題單獨處理教程視頻 axios.post(configs[process.env.API_ENV]['BG_SERVER']+'/file/qiniu/token/video', { key: 'yihezo/' + new Date().getTime() +randomString(5) //入參:教程視頻的key }, { headers: { AuthorizationToken: localStorage.getItem('login_token') } }).then(res =>{ let {data} = res; if(data.code == 200) { let token = data.data.token; let observable = qiniu.upload(fileBlob, key, token, putExtra, config) let subscription = observable.subscribe({next(res){ // console.log(res, 'loading') }, error(res){ message.error('上傳失敗'); }, complete(res) { resolve(res.key) }}) //subscription.unsubscribe() // 上傳取消 } else { message.error('獲取七牛雲token失敗'); } }).catch(error => { console.error(error) reject(error) }) }else{ axios.post(configs[process.env.API_ENV]['BG_SERVER']+'/file/qiniu/token', {}, { headers: { AuthorizationToken: localStorage.getItem('login_token') } }).then(res =>{ let {data} = res; if(data.code == 200) { let token = data.data.token; let observable = qiniu.upload(fileBlob, key, token, putExtra, config) let subscription = observable.subscribe({next(res){ // console.log(res, 'loading') }, error(res){ message.error('上傳失敗'); }, complete(res) { resolve(res.key) }}) //subscription.unsubscribe() // 上傳取消 } else { message.error('獲取七牛雲token失敗'); } }).catch(error => { console.error(error) reject(error) }) } } }) }
- state中定義初始值
fileThumb: null, // 存儲上傳七牛雲后返回的圖片url fileUri: null, // 存儲上傳七牛雲后返回的文件url fileVisible: false, // 控制預覽文件的彈框是否visible previewVisible: false,// 控制預覽圖片的彈框是否visible previewImage: '', //預覽要上傳的圖片和上傳后的圖片的url previewFile: '' //預覽要上傳的圖片和上傳后的圖片的url
-
彈框表單中Upload組件
// 上傳按鈕 const ImgUpButton = ( <div> <Icon type="plus" /> <div className="ant-upload-text">Upload</div> </div> ); const FileUpButton = ( <Button> <Icon type="upload" /> Upload </Button> )
<FormItem label="資源圖片" {...this.formLayout}> { getFieldDecorator('thumb', { rules: [{ required: true, message: '請上傳圖片' }], initialValue: current.thumb ? [{ // 默認必須是數組 uid: '-1', status: 'done', name: current.resName, url: `${setFileHost()+current.thumb}`, thumbUrl: `${setFileHost()+current.thumb}` }] : "" // 無值時必須是空串 })( <div> <Upload accept="image/*" // 限制上傳的文件類型 action={(file) => handleImageUpload(file, 'image').then(res => { const newFileThumb = []; newFileThumb.push(res); this.setState({ fileThumb: newFileThumb, }) })} // 上傳七牛雲后存儲url listType="picture-card" fileList={imgList} // 顯示的圖片數組 onRemove={this.handleImgRemove} onPreview={this.handleImgPreview} onChange={this.handleImgChange} > {imgList.length >= 1 ? null : ImgUpButton} </Upload> <Modal visible={previewVisible} footer={null} onCancel={this.handleImgCancel}> <img alt="資源圖片" style={{ width: '100%' }} src={previewImage} /> </Modal> </div> )} </FormItem> <FormItem label="資源文件" extra={resNameError || resName == null ? <span style={{color:'#1890FF'}}>請先輸入資源名稱</span> : ''} {...this.formLayout}> {getFieldDecorator('uri', { rules: [{ required: true, message: '請上傳文件' }], initialValue: current.uri ? [{ uid: '-1', status: 'done', name: current.uri, url: `${setFileHost()+current.uri}` }] : "" })( <div> <Upload accept="audio/mp3, audio/mp4, audio/ogg, audio/mpeg" disabled={ resNameError || resName == null ? true : false } action={(file) => handleImageUpload(file, 'audio', resName).then(res => { const newFileUri = []; newFileUri.push(res); this.setState({ fileUri: newFileUri }) })} fileList={fileList} onRemove={this.handleFileRemove} onPreview={this.handleFilePreview} onChange={this.handleFileChange} > {fileList.length >= 1 ? null : FileUpButton} </Upload> <Modal visible={fileVisible} footer={null} onCancel={this.handleFileCancel} style={{textAlign: 'center'}}> <audio src={previewFile} style={{ width: '80%' }} controls="controls" autoPlay="autoplay"> 您的瀏覽器不支持 audio 標簽。 </audio> </Modal> </div> )} </FormItem>
// 上傳圖片 使用的方法 // 刪除、預覽彈框關閉、預覽圖片url和預覽彈框打開,存儲改變的圖片url handleImgRemove = () => { this.setState({ imgList: [], fileThumb: [''], }) return true } handleImgCancel = () => this.setState({ previewVisible: false }) handleImgPreview = (file) => { this.setState({ previewImage: file.url || file.thumbUrl, previewVisible: true, }); } handleImgChange = ({ fileList }) => this.setState({ imgList: fileList }) // 上傳文件 使用的方法 // 刪除、預覽彈框關閉、預覽文件url和預覽彈框打開,存儲文件的圖片url handleFileRemove = () => { this.setState({ fileList: [], fileUri: [''], }) return true } handleFileCancel = () => this.setState({ fileVisible: false }) handleFilePreview = (file) => { file.url ? this.setState({ previewFile: file.url, fileVisible: true, }) : message.error('請先保存'); } handleFileChange = ({ fileList }) => this.setState({ fileList })
-
彈框表單中上傳多張圖片
-
引入upload.js中封裝的handImageUpload文件上傳七牛雲的方法
import { handleImageUpload } from '@/utils/upload'; import {setFileHost} from '@/utils/utils';
- state中定義初始數據
// 上傳多張輪播圖(可上傳視頻) imgList: [], fileThumbs: [], previewVisible: false, previewImage: '', // 上傳一張圖片 introImgList: [], introFileThumb: '', introPreviewVisible: false, introPreviewImage: '',
-
showModal顯示彈框的方法中: 處理獲得的圖片數組存入state
showEditModal = item => { const { dispatch } = this.props; dispatch({ type: 'project/fetchDetail', payload: { goodsId: item.id }, callback: (res) => { if(res){ this.setState({ detail: res.data, imgList: res.data.rotationChart && res.data.rotationChart.length ? this.initImgList(res.data) : "", // Upload顯示圖片本地存儲的圖片url數組 fileThumbs: res.data.rotationChart && res.data.rotationChart.length ? this.initFileThumbs(res.data) : "", // 上傳七牛雲后存儲的用於傳給后端的圖片url數組 introImgList: res.data.introPic ? [{ uid: '-1', status: 'done', name: res.data.introPic, url: `${setFileHost()+res.data.introPic}`, thumbUrl: `${setFileHost()+res.data.introPic}` }] : '', introFileThumb: res.data.introPic ? res.data.introPic : '', current: item, addSubmit: false }, () => { this.setState({ visible: true }) }); } } }) };
-
彈框表單中嵌入Upload組件
const ImgUpButton = ( // 上傳圖片的按鈕 <div> <Icon type="plus" /> <div className="ant-upload-text">Upload</div> </div> );
<FormItem label="產品圖片" {...formLayout}> { getFieldDecorator('rotationChart', { rules: [{ required: true, message: '請上傳1-7張圖片'}], // 默認顯示是圖片數組,無值也是空數組 initialValue: current && detail && detail.rotationChart && detail.rotationChart.length ? initImgList(detail) : [] })( <div> <Upload accept="image/*" // action={(file) => handleImageUpload(file, 'image').then(res => { // handleFileThumb(res, file, imgList) // })} listType="picture-card" fileList={imgList} onPreview={handleImgPreview} onRemove={handleImgRemove} // beforeUpload上傳前的處理函數: 嵌套handleImageUpload方法 (上傳一張圖片或一個文件時,如果需要上傳前判斷文件類型、文件大小也是這么做) // 1.包含handleFileThumb方法,代替action實現上傳七牛雲服務器后存儲state;2.同時將新的圖片數組imgArray存入本地imgList改變Upload組件顯示的圖片 beforeUpload={beforeUpload} // onChange={handleImgChange} > {imgList.length >= 7 ? null : ImgUpButton} </Upload> <Modal visible={previewVisible} footer={null} onCancel={handleImgCancel} style={{textAlign: 'center'}}> { previewType == 'liveWallPaper' ? <video src={previewImage} style={{ width: '50%' }} controls="controls" autoPlay="autoplay"> 您的瀏覽器不支持 video 標簽。 </video> : <img alt="產品圖片" style={{ width: '100%' }} src={previewImage} />} </Modal> </div> )} </FormItem>
-
使用到的方法
initImgList = (item) => { // 處理Upload默認顯示的數據 let defaultImgList = []; item.rotationChart.forEach((imgListItem, index) => { defaultImgList.push ({ uid: `${-1-index}`, status: 'done', name: item.name, url: imgListItem.img ? `${setFileHost()+imgListItem.img}` : '', thumbUrl: imgListItem.thumb ? `${setFileHost()+imgListItem.thumb}` : '' }) }) return defaultImgList }
initFileThumbs = (item) => { // 不更改不上傳新的圖片時默認向后端傳的圖片url數組 let defaultFileThumbs = []; item.rotationChart.forEach((fileThumb, index) => { defaultFileThumbs[index] = fileThumb; }) return defaultFileThumbs }
handleFileThumb = (res, file, imgList) => { // 更改fileThumbs數組 let { fileThumbs } = this.state; fileThumbs[imgList.length-1] = { img: res, index: imgList.length-1, type: file.type.split('/')[0], thumb: res }; this.setState({ fileThumbs }) }
// 關閉預覽彈框 handleImgCancel = () => this.setState({ previewVisible: false }) // 顯示預覽彈框 handleImgPreview = (file) => { this.setState({ previewImage: file.url || file.thumbUrl, previewVisible: true, }); } // 刪除預覽彈框 handleImgRemove = (file) => { const { fileThumbs, imgList } = this.state; let newList = [...imgList]; let newFileThumbs = [...fileThumbs]; newList.forEach((imgItem, index) => { if(imgItem.uid == file.uid){ newList.splice(index, 1) newFileThumbs.splice(index, 1) } }) this.setState({ imgList: newList, fileThumbs: newFileThumbs }, () => { return true }) }
beforeUpload = (file) => { let type = file.type.split('/')[0]; let name = file.name.split('.')[0]; // 判斷文件類型 -- 如果是視頻url直接存入imgList,存入fileThumb if(type == 'video') { let imgArray = [...this.state.imgList]; imgArray.push(file); handleImageUpload(file, 'video', name).then(res => { this.setState({ imgList: imgArray }) this.handleFileThumb(res, file, imgArray) }) }else{ // 如果是圖片,使用react-cropper插件相關設置進行裁剪處理 // 當打開同一張圖片的時候清除上一次的緩存 if (this.refs.cropper) { this.refs.cropper.reset(); } var reader = new FileReader(); const image = new Image(); //因為讀取文件需要時間,所以要在回調函數中使用讀取的結果 reader.readAsDataURL(file); //開始讀取文件 reader.onload = (e) => { image.src = reader.result; image.onload = () => { this.setState({ srcCropper: e.target.result, //cropper的圖片路徑 selectImgName: file.name, //文件名稱 selectImgSize: (file.size / 1024 / 1024), //文件大小 selectImgSuffix: file.type.split("/")[1], //文件類型 editImageModalVisible: true, //打開控制裁剪彈窗的變量,為true即彈窗 }) if (this.refs.cropper) { this.refs.cropper.replace(e.target.result); } } } return false; } }
-
不需要裁剪的使用beforeUpload判斷文件大小的上傳一張圖片
<FormItem label="人物介紹圖片" {...formLayout}> {getFieldDecorator('introPic', { initialValue: current && detail && detail.introPic ? [{ uid: '-1', status: 'done', name: detail.introPic, url: `${setFileHost()+detail.introPic}`, thumbUrl: `${setFileHost()+detail.introPic}` }] : '' })( <div> <Upload accept="image/*" // action={(file) => handleImageUpload(file, 'image').then(res => { // handleIntroFileThumb(res) // })} listType="picture-card" fileList={introImgList} onPreview={handleIntroImgPreview} onRemove={handleIntroImgRemove} beforeUpload={beforeIntroUpload} // onChange={handleIntroImgChange} > {introImgList.length >= 1 ? null : ImgUpButton} </Upload> <Modal visible={introPreviewVisible} footer={null} onCancel={handleIntroImgCancel} style={{textAlign: 'center'}}> <img alt="人物介紹圖片" style={{ width: '100%' }} src={introPreviewImage} /> </Modal> </div> )} </FormItem>
beforeIntroUpload = (file) => { const isLt3M = file.size / 1024 / 1024 < 3; if (!isLt3M) { //添加文件限制 message.error('文件大小不能超過3M'); return false; } // console.log('file', file) handleImageUpload(file, 'image').then(res => { this.setState({ // 存入introImgList introImgList: [{ uid: file.uid, status: 'done', name: file.name, url: `${setFileHost()+res}`, thumbUrl: `${setFileHost()+res}` }] }) this.handleIntroFileThumb(res) // 存入introFileThumbs }) return true }
轉載請注明出處