From 0039eb8d8d638d18231455e1bc550cde1d3f310f Mon Sep 17 00:00:00 2001 From: zhangwenshuai Date: Fri, 3 Apr 2020 01:05:58 +0800 Subject: [PATCH] update --- .../component/base/_utils/getFormatter.tsx | 3 +- .../component/base/_utils/setFormatter.tsx | 2 +- src/apollo-table/component/base/config.tsx | 8 +- .../component/base/detail/upload/index.tsx | 3 +- .../component/base/edit/container/index.tsx | 13 +- .../component/base/edit/editInterface.tsx | 4 + .../component/base/edit/upload/index.less | 22 ++ .../component/base/edit/upload/index.tsx | 82 ++++++- .../component/base/edit/upload/styles.less | 17 -- .../component/base/extra/upload/detail.less | 202 ++++++++++++++++++ .../component/base/extra/upload/fileType.ts | 31 +++ .../component/base/extra/upload/index.less | 5 + .../component/base/extra/upload/index.tsx | 151 +++++++++++++ .../component/base/extra/upload/preview.tsx | 48 +++++ .../component/base/extra/upload/utils.ts | 10 + 15 files changed, 571 insertions(+), 30 deletions(-) create mode 100644 src/apollo-table/component/base/edit/upload/index.less delete mode 100644 src/apollo-table/component/base/edit/upload/styles.less create mode 100644 src/apollo-table/component/base/extra/upload/detail.less create mode 100644 src/apollo-table/component/base/extra/upload/fileType.ts create mode 100644 src/apollo-table/component/base/extra/upload/index.less create mode 100644 src/apollo-table/component/base/extra/upload/index.tsx create mode 100644 src/apollo-table/component/base/extra/upload/preview.tsx create mode 100644 src/apollo-table/component/base/extra/upload/utils.ts diff --git a/src/apollo-table/component/base/_utils/getFormatter.tsx b/src/apollo-table/component/base/_utils/getFormatter.tsx index 2e19d4f..b2f5e45 100644 --- a/src/apollo-table/component/base/_utils/getFormatter.tsx +++ b/src/apollo-table/component/base/_utils/getFormatter.tsx @@ -1,5 +1,6 @@ import moment from 'moment'; import { isNumber } from '@/apollo-table/utils/utils'; +import { checkoutFileType } from '@/apollo-table/component/base/extra/upload/utils'; export const GetFormatter = { INPUT: (val) => { @@ -22,7 +23,7 @@ export const GetFormatter = { size = s1; return ''; }); - return { value: item.value, name: text, size }; + return { value: item.value, name: text, size, ...checkoutFileType(item.value) }; }); }, CHECKBOX: (val, config) => { diff --git a/src/apollo-table/component/base/_utils/setFormatter.tsx b/src/apollo-table/component/base/_utils/setFormatter.tsx index 9e12bd9..15e5e03 100644 --- a/src/apollo-table/component/base/_utils/setFormatter.tsx +++ b/src/apollo-table/component/base/_utils/setFormatter.tsx @@ -17,7 +17,7 @@ export const SetFormatter = { return [{ value: value, text: value }]; }, UPLOAD: (val) => { - if (!val) return null; + if (!val) return emptyModel; return val.map((item) => ({ value: item.value, text: item.name + '(' + item.size + ')' })); }, CHECKBOX: (value) => { diff --git a/src/apollo-table/component/base/config.tsx b/src/apollo-table/component/base/config.tsx index 004e239..5e6f51d 100644 --- a/src/apollo-table/component/base/config.tsx +++ b/src/apollo-table/component/base/config.tsx @@ -33,10 +33,10 @@ export const config: any = { }, '4': { name: '附件上传', - component: require('./edit/input').default, - setFormatter: SetFormatter['INPUT'], - getFormatter: GetFormatter['INPUT'], - detail: require('./detail/input').default, + component: require('./edit/upload').default, + setFormatter: SetFormatter['UPLOAD'], + getFormatter: GetFormatter['UPLOAD'], + detail: require('./detail/upload').default, }, '5': { name: '复选', diff --git a/src/apollo-table/component/base/detail/upload/index.tsx b/src/apollo-table/component/base/detail/upload/index.tsx index 72cc11f..9b68f79 100644 --- a/src/apollo-table/component/base/detail/upload/index.tsx +++ b/src/apollo-table/component/base/detail/upload/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; // import Upload from '../../extra/upload'; import styles from './styles.less'; import { UploadProps } from '../detailInterface'; +import {checkoutFileType} from '@/apollo-table/component/base/extra/upload/utils'; const itemWidth = 20; const itemSpace = 5; @@ -15,7 +16,7 @@ export default function Detail(props: UploadProps) { themeValue = formatValue.map((item) => { return { ...item, - // ...Upload.checkoutFileType(item.value), + ...checkoutFileType(item.value), }; }); } diff --git a/src/apollo-table/component/base/edit/container/index.tsx b/src/apollo-table/component/base/edit/container/index.tsx index 0055a1a..7a4ea9f 100644 --- a/src/apollo-table/component/base/edit/container/index.tsx +++ b/src/apollo-table/component/base/edit/container/index.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import {Modal} from 'antd'; import s from './index.less'; import { antiAssign } from '@/apollo-table/utils/utils'; @@ -17,7 +18,7 @@ export default function CellContainer

(Comp) { value: props.value, // 组件的值 option: undefined, // 选择项 }; - console.log('props.value',props.value) + console.log('props.value', props.value); } componentDidMount(): void { document.addEventListener('click', this.onBlur, false); @@ -26,13 +27,13 @@ export default function CellContainer

(Comp) { document.removeEventListener('click', this.onBlur, false); } changeValue = (value: any, option: any) => { - console.log('value',value) + console.log('value', value); this.setState({ value, option }); }; onBlur = () => { const { onEmitChange } = this.props; const { value, option } = this.state; - console.log('state.value',value) + console.log('state.value', value); if (typeof onEmitChange === 'function') { onEmitChange(value, option); } @@ -46,7 +47,11 @@ export default function CellContainer

(Comp) { const { value } = this.state; return (

- +
); } diff --git a/src/apollo-table/component/base/edit/editInterface.tsx b/src/apollo-table/component/base/edit/editInterface.tsx index da06444..e6724cf 100644 --- a/src/apollo-table/component/base/edit/editInterface.tsx +++ b/src/apollo-table/component/base/edit/editInterface.tsx @@ -6,6 +6,7 @@ import { CheckboxProps, CheckboxGroupProps } from 'antd/es/checkbox'; import { TreeSelectProps } from 'antd/es/tree-select'; import { CascaderProps } from 'antd/es/cascader'; import { RateProps } from 'antd/es/rate'; +import { UploadProps } from 'antd/es/upload'; export interface LinkData { text?: string; @@ -57,3 +58,6 @@ export interface ApolloCascaderProps extends CascaderProps, CommonProps { request: Function; } export interface ApolloRateProps extends RateProps, CommonProps {} +export interface ApolloUploadProps extends UploadProps, CommonProps { + isMultiple?: boolean; +} diff --git a/src/apollo-table/component/base/edit/upload/index.less b/src/apollo-table/component/base/edit/upload/index.less new file mode 100644 index 0000000..a2534da --- /dev/null +++ b/src/apollo-table/component/base/edit/upload/index.less @@ -0,0 +1,22 @@ +@import '~@/common'; +.container { + width: 100%; + height: 100%; + overflow: hidden; + display: flex; + align-items: center; + .add { + cursor: pointer; + font-size: @textFontGen; + } + .picContainer { + margin-left: @marginSmX; + .pic { + height: 30px; + } + } +} +.uploadContainer { + height: 500px; + overflow-y: auto; +} diff --git a/src/apollo-table/component/base/edit/upload/index.tsx b/src/apollo-table/component/base/edit/upload/index.tsx index 1211a37..8d9ee5c 100644 --- a/src/apollo-table/component/base/edit/upload/index.tsx +++ b/src/apollo-table/component/base/edit/upload/index.tsx @@ -1,3 +1,81 @@ -// import UpLoad from '../../extra/upload'; +import React, { useEffect, useRef, useState } from 'react'; +import { ApolloUploadProps } from '../editInterface'; +import { antiAssign } from '@/apollo-table/utils/utils'; +import CellContainer from '../container'; +import s from './index.less'; +import Upload from '../../extra/upload'; +import IconFont from '@/apollo-table/component/base/extra/iconFont'; +import { Modal, Tooltip } from 'antd'; -// export default UpLoad; +const ApolloUpload = (props) => { + const { isMultiple, onEmitChange } = props; + const selfProps = antiAssign(props, ['onChange', 'value']); + if (isMultiple) { + selfProps.multiple = true; + } + const [value, setValue] = useState(props.value || []); + const changeValue = (value) => { + console.log(value); + setValue(value); + }; + const [visible, setVisible] = useState(false); + const refHelper = useRef(visible); + const toggleUploadDialog = (flag) => { + refHelper.current = flag; + setVisible(flag); + }; + useEffect(() => { + document.addEventListener('click', onBlur, false); + return () => { + document.removeEventListener('click', onBlur, false); + }; + }, []); + const onBlur = () => { + if (refHelper.current) { + return; + } + if (typeof onEmitChange === 'function') { + onEmitChange(props.value); + } + }; + const onOk = () => { + if (typeof onEmitChange === 'function') { + onEmitChange(value); + } + toggleUploadDialog(false); + }; + const onCancel = () => { + if (typeof onEmitChange === 'function') { + onEmitChange(props.value); + } + toggleUploadDialog(false); + }; + const onClickContainer = (e) => { + e.stopPropagation(); //阻止事件冒泡 + e.nativeEvent.stopImmediatePropagation(); + }; + return ( +
+
+ +
+ {value && + value.map((item, i) => { + return ( +
+ + + +
+ ); + })} + +
+ +
+
+
+ ); +}; + +export default ApolloUpload; diff --git a/src/apollo-table/component/base/edit/upload/styles.less b/src/apollo-table/component/base/edit/upload/styles.less deleted file mode 100644 index 7b82a93..0000000 --- a/src/apollo-table/component/base/edit/upload/styles.less +++ /dev/null @@ -1,17 +0,0 @@ -.container { - position: relative; - top: 0; - left: 0; - - .input { - padding-right: 100px; - } - - .wordNumber { - position: absolute; - color: #E1E1E1FF; - font-size: 12px; - right: 7px; - top: 7px; - } -} diff --git a/src/apollo-table/component/base/extra/upload/detail.less b/src/apollo-table/component/base/extra/upload/detail.less new file mode 100644 index 0000000..486c77f --- /dev/null +++ b/src/apollo-table/component/base/extra/upload/detail.less @@ -0,0 +1,202 @@ +@import "~@/common"; + +.fileList { + display: flex; + flex-flow: row; + flex-wrap: wrap; +} + +.fileListCenter { + justify-content: center; +} + +.wrap { + position: relative; + cursor: pointer; +} + +.wrap:hover .fileBoxHove { + display: flex; +} + +.fileBox { + padding: 10px; + width: 100px; + display: flex; + flex-flow: column; + justify-items: center; + align-items: center; + border-radius: 4px; + overflow: hidden; +} + +.fileBoxHove { + position: absolute; + top: 0; + left: 0; + display: none; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + + .icon { + color: #fff; + padding: 5px; + } +} + +.fileName { + margin-top: 5px; + width: 80px; + font-size: 12px; + font-weight: 400; + color: rgba(90, 104, 118, 1); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; +} + +.fileStyle { + height: 56px; +} + +.dialog { + width: 900px !important; + min-height: 500px; +} + +.textUploadList { + box-sizing: border-box; + margin: 0; + padding: 0; + color: rgba(0, 0, 0, 0.65); + font-size: 14px; + font-variant: tabular-nums; + line-height: 1.5; + list-style: none; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + zoom: 1; + + .textUploadListItem { + position: relative; + height: 22px; + margin-top: 8px; + font-size: 14px; + + .textUploadListItemInfo { + height: 100%; + padding: 0 12px 0 4px; + + .textUploadListItemBox { + display: flex; + align-items: center; + + .textUploadListItemInfoName { + display: inline-block; + margin-right: 10px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: #5a6876; + + &:hover { + color: #5c99ff; + } + } + } + } + } +} + +.downIcon { + display: inline-block; + position: absolute; + right: 0; + top: 50%; + transform: translate(0, -50%); + cursor: pointer; +} + +.pictureTextUploadList { + box-sizing: border-box; + margin: 0; + padding: 0; + color: rgba(0, 0, 0, 0.65); + font-size: 14px; + font-variant: tabular-nums; + line-height: 1.5; + list-style: none; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + zoom: 1; + overflow: hidden; + width: 100%; + + .textUploadListItem { + position: relative; + display: flex; + justify-items: center; + height: 41px; + margin-top: 10px; + font-size: 14px; + width: 100%; + + .textUploadListItemInfo { + width: 100%; + height: 100%; + padding: 0 12px 0 4px; + + .textUploadListItemBox { + display: flex; + align-items: center; + height: 100%; + + .fileImgStyle { + width: 32px; + margin-right: 10px; + cursor: pointer; + } + + .textUploadListItemInfoName { + display: inline-block; + margin-right: 10px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: @textGeneralColor; + + &:hover { + color: @primaryColor; + } + } + &:hover{ + .downIcon{ + opacity: 1; + } + } + + .downIcon { + display: inline-block; + position: absolute; + right: 0; + top: 50%; + transform: translate(0, -50%); + cursor: pointer; + color: @textSupplyColor; + opacity: 0; + transition: opacity 0.2s linear; + } + } + } + } +} + + +// .textUploadListItemInfo:hover { +// background: #e6f7ff; +// } diff --git a/src/apollo-table/component/base/extra/upload/fileType.ts b/src/apollo-table/component/base/extra/upload/fileType.ts new file mode 100644 index 0000000..750e5e6 --- /dev/null +++ b/src/apollo-table/component/base/extra/upload/fileType.ts @@ -0,0 +1,31 @@ +const CDN_PATH = 'https://static.mttop.cn/admin'; +export const fileType = { + image: {}, + ppt: { + thumbUrl: `${CDN_PATH}/pptIcon.png`, + }, + pptx: { + thumbUrl: `${CDN_PATH}/pptIcon.png`, + }, + zip: { + thumbUrl: `${CDN_PATH}/zipIcon.png`, + }, + xlsx: { + thumbUrl: `${CDN_PATH}/xlsIcon.png`, + }, + xls: { + thumbUrl: `${CDN_PATH}/xlsIcon.png`, + }, + doc: { + thumbUrl: `${CDN_PATH}/docIcon.png`, + }, + docx: { + thumbUrl: `${CDN_PATH}/docIcon.png`, + }, + pdf: { + thumbUrl: `${CDN_PATH}/pdfIcon.png`, + }, + other: { + thumbUrl: `${CDN_PATH}/otherIcon.png`, + }, +}; diff --git a/src/apollo-table/component/base/extra/upload/index.less b/src/apollo-table/component/base/extra/upload/index.less new file mode 100644 index 0000000..95c7e1d --- /dev/null +++ b/src/apollo-table/component/base/extra/upload/index.less @@ -0,0 +1,5 @@ +@import '~@/common'; +.container { + .upload { + } +} diff --git a/src/apollo-table/component/base/extra/upload/index.tsx b/src/apollo-table/component/base/extra/upload/index.tsx new file mode 100644 index 0000000..2da519a --- /dev/null +++ b/src/apollo-table/component/base/extra/upload/index.tsx @@ -0,0 +1,151 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { message, Upload } from 'antd'; +import moment from 'moment'; +import { getToken } from '@/apollo-table/services/globalSearchApi'; +import IconFont from '@/apollo-table/component/base/extra/iconFont'; +import s from './index.less'; +import { antiAssign, getRandom } from '@/apollo-table/utils/utils'; +import { checkoutFileType } from './utils'; +import Preview from './preview'; + +message.config({ + maxCount: 1, +}); + +const UploadCom = (props) => { + const { onChange, CDN_HOST, getFormat, setFormat } = props; + const selfProps = antiAssign(props, ['onChange', 'CDN_HOST']); + const getFormatFileList = (fileList = []) => { + if (!fileList) { + return []; + } + if (typeof getFormat === 'function') { + return getFormat(fileList); + } + return fileList.map((item: any) => { + return { + name: item.name, + value: item.value, + size: item.size, + uid: item.value, + ...checkoutFileType(item.value), + }; + }); + }; + const setFormatFile = (file) => { + if (!file) { + return {}; + } + if (typeof setFormat === 'function') { + return setFormat(fileList); + } + const data = file.response || {}; + const url = `${domain ? 'https://' + domain : CDN_HOST}/${data.key}`; + return { + uid: file.uid, + name: file.name, + value: url, + size: file.size, + ...checkoutFileType(url), + }; + }; + const [fileList, setFileList] = useState(getFormatFileList(props.value)); + useEffect(() => { + setFileList(getFormatFileList(props.value)); + }, [props.value]); + const [token, setToken] = useState(null); + const [domain, setDomain] = useState(null); + const previewModel = useRef(); + //自定义七牛文件唯一key + const getKey = (file) => { + if (!file) return; + let suffix = file.name.match(/\.\w+$/)[0]; + let rand6 = getRandom(); + let time = moment().format('YYYYMMDDHHmmss'); + return time + rand6 + suffix; + }; + //七牛上传额外数据,token和key + const getData = (file) => { + return { + token, + key: getKey(file), + }; + }; + //获取七牛上传token + const getUploadToken = async () => { + const response = await getToken(); + if (response && response.success && response.data) { + setToken(response.data.token); + setDomain(response.data.domain); + } + }; + + const onSaveFileList = (fileList = []) => { + if (typeof onChange === 'function') { + onChange(fileList); + } + }; + + const beforeUpload = async () => { + await getUploadToken(); + return true; + }; + const changeFileList = ({ file, fileList }) => { + let newList = fileList; + if (file.status === 'done' && file.response) { + const itemObj = setFormatFile(file); + newList = fileList.map((item) => { + return item.uid === itemObj.uid ? itemObj : item; + }); + onSaveFileList(newList); + } + setFileList(newList); + }; + const previewFile = (file) => { + return new Promise((res, rej) => { + const obj = checkoutFileType(file.name); + const typeArr = file.name.match(/\.[a-zA-Z]+$/); + const type = typeArr && typeArr[0] ? typeArr[0].replace('.', '') : ''; + if (!['png', 'gif', 'bmp', 'jpg', 'jpeg'].includes(type)) { + res(obj.thumbUrl); + } + }); + }; + const onPreview = (file) => { + if (previewModel.current && previewModel.current.onPreview) { + previewModel.current.onPreview(file.value, file.name); + } + }; + const onRemove = (file) => { + const newFileList = fileList.filter((item) => item.uid !== file.uid); + onSaveFileList(newFileList); + }; + + return ( +
+ + + + +
+ ); +}; +export default UploadCom; diff --git a/src/apollo-table/component/base/extra/upload/preview.tsx b/src/apollo-table/component/base/extra/upload/preview.tsx new file mode 100644 index 0000000..ad7c695 --- /dev/null +++ b/src/apollo-table/component/base/extra/upload/preview.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import styles from './detail.less'; +import { message, Modal } from 'antd'; + +export default class uploadDetail extends React.Component { + state = { + showDialog: false, + type: 'image', + url: '', + }; + onPreview = (url, name) => { + const typeArr = (name || url).match(/\.[a-zA-Z]+$/); + let type = typeArr && typeArr[0] ? typeArr[0].replace('.', '') : ''; + type = type.toLowerCase(); + if (['png', 'gif', 'bmp', 'jpg', 'jpeg'].includes(type)) { + this.setState({ showDialog: true, type: 'image', url }); + } else if (['doc', 'docx', 'document', 'xls', 'xlsx', 'ppt', 'pptx'].includes(type)) { + this.setState({ showDialog: true, type: 'office', url }); + } else if (type === 'pdf') { + this.setState({ showDialog: true, type: 'pdf', url }); + } else { + message.warn('暂不支持预览'); + } + }; + handleCancel = () => { + this.setState({ showDialog: false }); + }; + render() { + const { showDialog, type, url } = this.state; + return ( +
+ +
+ {type === 'image' ? example : null} + {type === 'office' ? ( +