diff --git a/src/apollo-table/component/base/_utils/getFormatter.tsx b/src/apollo-table/component/base/_utils/getFormatter.tsx index 2e19d4f1bceb16589d053323d8d6bb8a69c8f8cb..b2f5e45c40c4b8aa2dc2072fa537cc964ff45127 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 9e12bd94ac1032def38be0c1834f6f98c61f49a6..15e5e035645341b5cde512d28bf50e3c37639103 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 004e2391380f94021f105fbdaef61234d477e3fe..5e6f51d8196eb9efb7062538698784b0aa612c11 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 72cc11f7a2407126bbe58d9061997e24e908752d..9b68f79f6c53cfec8922ba80f381f7ba4ecb34f6 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 0055a1a0d12ddebc4983faa4652fa9c853a7b028..7a4ea9f8ef984fbf2741b3d8ae6e06c659ae067b 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 da06444e54cfaf2e7e9689cfdccf702c4ec5b242..e6724cfd8761d93fa27ffe024604ec405e4b37f1 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 0000000000000000000000000000000000000000..a2534da038f889f6a3633e38bbcc0222f3b1a0a9 --- /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 1211a37616a3662d432800a3b4a58b3a655e428d..8d9ee5cbd4e9a71da4b2703e5a1a46e60f7a65a6 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 7b82a93104654caa21e3daa5e730376914555bba..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..486c77f13f2f7ced8bf328cb9e990ca00ab0b548 --- /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 0000000000000000000000000000000000000000..750e5e6bb3d6ff21d95d92ef7b52b8b84095bb91 --- /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 0000000000000000000000000000000000000000..95c7e1d5a79f513b394a485fdb5df77544fc4f98 --- /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 0000000000000000000000000000000000000000..2da519aa0c07dbfe8ed94e06034e5178973dc4f7 --- /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 0000000000000000000000000000000000000000..ad7c6953354504e6a81372ac8f84078403833c06 --- /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' ? ( +