Browse Source

添加报表中单个图表导出图片逻辑

zhuth 5 years ago
parent
commit
a20ede90d6

+ 12 - 8
src/components/chartDesigner/sections/style/theme/theme2.less

@@ -188,15 +188,19 @@
     >.ant-modal-content {
         >.ant-modal-body {
             background: rgba(41,52,65,1);
-            >div>div>.chartview-toolbar {
+            >div {
                 background: rgba(41,52,65,1);
-                > .chart-title {
-                    color: #9fc8e6;
-                }
-                .anticon {
-                    color: #9fc8e6;
-                    &:hover {
-                        color: @icon-color-hover;
+
+                >div>.chartview-toolbar {
+                    background: rgba(41,52,65,1);
+                    > .chart-title {
+                        color: #9fc8e6;
+                    }
+                    .anticon {
+                        color: #9fc8e6;
+                        &:hover {
+                            color: @icon-color-hover;
+                        }
                     }
                 }
             }

+ 1 - 1
src/components/common/cusIcon/index.jsx

@@ -2,6 +2,6 @@ import { Icon } from 'antd'
 import scriptUrl from '../../../../static/iconfont/iconfont.js'
  
 export default Icon.createFromIconfontCN({
-    // scriptUrl: '//at.alicdn.com/t/font_755957_8duvb0svgqb.js'
+    // scriptUrl: '//at.alicdn.com/t/font_755957_2epuoswfizi.js' // 线上地址
     scriptUrl
 });

+ 2 - 2
src/components/dashboardDesigner/viewLayout.less

@@ -304,14 +304,14 @@
     }
     .ant-modal-body {
       height: 100%;
-      padding: 0 24px 24px 24px;
+      padding: 0 12px 12px 12px;
       .chartview  {
         display: flex;
         flex-direction: column;
         height: 100%;
         padding-top: 40px;
         .chartview-toolbar {
-          padding: 0;
+          padding: 0 0 0 12px;
           height: 40px;
           margin-top: -40px;
           display: flex;

+ 13 - 6
src/components/dashboardDesigner/viewLayoutItem.jsx

@@ -18,6 +18,10 @@ class ViewLayoutItem extends React.Component {
         dispatch({ type: 'dashboardDesigner/modifyItem', item });
     }
 
+    exportItemToImage = (itemEl, item) => {
+        this.props.dispatch({ type: 'dashboardDesigner/exportItemToImage', itemEl, item });
+    }
+
     render() {
         const { dispatch, main, dashboardDesigner, item, isPreview, reload, showPreviewBox, hidePreviewBox, esMobile, contentSize } = this.props;
         const { editing, title } = this.state;
@@ -27,7 +31,7 @@ class ViewLayoutItem extends React.Component {
         const iconCls = editMode ? 'visible-icon' : '';
 
         return (
-            <div className={`chartview${ isPreview ? ' chartview-preview' : (editMode ? ' chartview-edit' : '')}${esMobile?' es-mobile':''}`} style={{ height: '100%' }}>
+            <div ref={node => this.chartViewRef = node } className={`chartview${ isPreview ? ' chartview-preview' : (editMode ? ' chartview-edit' : '')}${esMobile?' es-mobile':''}`} style={{ height: '100%' }}>
                 <div className='chartview-toolbar mover'>
                     <div className='chart-title'>
                         {editing ? <Input width={200} ref={node => this['inputRef-' + code] = node} defaultValue={name}
@@ -74,18 +78,21 @@ class ViewLayoutItem extends React.Component {
                         </div>
                     </div>
                     <div className='chart-tools'>
-                        {viewType !== 'richText' && <Icon className={iconCls} type="sync" theme="outlined" onClick={() => {
+                        {viewType !== 'richText' && <Icon className={iconCls} type="sync" theme="outlined" title="刷新" onClick={() => {
                             let page = chartOption ? chartOption.page : 1;
                             let pageSize = chartOption ? chartOption.pageSize : (~~((layout.h * minLayoutHeight + (layout.h - 1) * 12 - 20 - 40 - 24 - 8 * 2)/38) + 1)
                             dispatch({ type: 'dashboardDesigner/fetchChartData', item, mandatory: true, page, pageSize });
                         }}/>}
-                        {!isPreview && viewType !== 'richText' && <Icon className={iconCls} type="fullscreen" onClick={() => showPreviewBox(item)}/>}
-                        {editMode && !isPreview && (item.creatorCode === currentUser.code || currentUser.role === 'superAdmin') && viewType !== 'richText' &&  <CusIcon className={iconCls} type='bi-edit' onClick={() => {
+                        {!isPreview && viewType !== 'richText' && <Icon className={iconCls} type="fullscreen" title="放大" onClick={() => showPreviewBox(item)}/>}
+                        {editMode && !isPreview && (item.creatorCode === currentUser.code || currentUser.role === 'superAdmin') && viewType !== 'richText' &&  <CusIcon className={iconCls} type='bi-edit' title="编辑" onClick={() => {
                             dispatch({ type: 'dashboard/remoteModify',hideMessage:true });
                             dispatch({ type: 'dashboardDesigner/reset' });
                             dispatch({ type: 'main/redirect', path: '/chart/' + chartCode });
                         }}/>}
-                        {!isPreview && editMode && <Icon className={iconCls} type='delete' onClick={() => {
+                        <CusIcon className={iconCls} type="bi-export" title="导出图片" onClick={(e) => {
+                            this.exportItemToImage(this.chartViewRef.parentNode, item);
+                        }}/>
+                        {!isPreview && editMode && <Icon className={iconCls} type='delete' title="移除" onClick={() => {
                             dispatch({ type: 'dashboardDesigner/deleteItem', item });
                             window.setTimeout(() => {
                                 var e = document.createEvent("Event");
@@ -93,7 +100,7 @@ class ViewLayoutItem extends React.Component {
                                 window.dispatchEvent(e);
                             }, 500);
                         }} />}
-                        {isPreview && <Icon className={iconCls} type="close" onClick={hidePreviewBox}/>}
+                        {isPreview && <Icon className={iconCls} type="close" title="关闭" onClick={hidePreviewBox}/>}
                     </div>
                 </div>
                 <ChartView key={`chartRef-${dashboardDesignerCode}-${code}`} minLayoutHeight={minLayoutHeight} editMode={isPreview ? false : editMode} item={{...item}} reload={reload} contentSize={contentSize} esMobile={esMobile} isPreview={isPreview}/>

+ 71 - 25
src/models/dashboardDesigner.js

@@ -785,13 +785,13 @@ export default {
             }
         },
 
-        *exportToImage(action, { select }) {
+        *exportToImage(action, { select, put }) {
             const dashboardDesigner = yield select(state => state.dashboardDesigner);
             const { name } = dashboardDesigner;
 
             let viewcontent = document.querySelector('.dashboard-viewcontent');
             let reactGridLayout = viewcontent.children[0];
-            let items = reactGridLayout.children;
+            let itemEls = reactGridLayout.children;
             let classList = reactGridLayout.children[0].classList; // 元素样式列表
             let classListBackup = []; // 样式备份
 
@@ -803,40 +803,86 @@ export default {
                 classListBackup.push(classList[i]);
             }
 
-            for(let i = 0; i< items.length;i++) {
+            for(let i = 0; i< itemEls.length;i++) {
                 classListBackup.forEach(c => {
-                    items[i].classList.remove(c);
-                    items[i].querySelector('.chart-title .tools').style.display = 'none';
+                    itemEls[i].classList.remove(c);
+                    itemEls[i].querySelector('.chart-title .tools').style.display = 'none';
+                    itemEls[i].querySelector('.chart-tools').style.display = 'none';
                 });
             }
 
-            yield html2canvas(reactGridLayout).then(canvas => {
-                for(let i = 0; i< items.length;i++) {
+            try {
+                yield put({ type: 'setField', name: 'loading', value: false });
+
+                yield html2canvas(reactGridLayout, { useCORS: true }).then(canvas => {
+                    let aLink = document.createElement('a');
+                    let blob = base64ToBlob(canvas.toDataURL()); //new Blob([content]);
+    
+                    let evt = document.createEvent("HTMLEvents");
+                    evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
+                    aLink.download = name;
+                    aLink.href = URL.createObjectURL(blob);
+    
+                    // aLink.dispatchEvent(evt);
+                    //aLink.click()
+                    aLink.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));//兼容火狐
+                })
+            }catch(e) {
+                message.error('报表图片错误: ' + e);
+            }finally {
+                for(let i = 0; i< itemEls.length;i++) {
                     classListBackup.forEach(c => {
-                        items[i].classList.add(c);
-                        items[i].querySelector('.chart-title .tools').style.display = '';
+                        itemEls[i].classList.add(c);
+                        itemEls[i].querySelector('.chart-title .tools').style.display = '';
+                        itemEls[i].querySelector('.chart-tools').style.display = '';
                     });
                 }
+                yield put({ type: 'setField', name: 'loading', value: false });
+            }
+        },
 
-                let aLink = document.createElement('a');
-                let blob = base64ToBlob(canvas.toDataURL()); //new Blob([content]);
+        *exportItemToImage(action, { select, put }) {
+            const { itemEl, item } = action;
+            const { name } = item;
+            let classListBackup = [];
 
-                let evt = document.createEvent("HTMLEvents");
-                evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
-                aLink.download = name;
-                aLink.href = URL.createObjectURL(blob);
+            let classList = itemEl.classList;
+            for(let i = 0; i < classList.length; i++) {
+                classListBackup.push(classList[i]);
+            }
 
-                // aLink.dispatchEvent(evt);
-                //aLink.click()
-                aLink.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));//兼容火狐
-            }).catch(e => {
-                for(let i = 0; i< items.length;i++) {
-                    classListBackup.forEach(c => {
-                        items[i].classList.add(c);
-                        items[i].querySelector('.chart-title .tools').style.display = '';
-                    });
-                }
+            classListBackup.forEach(c => {
+                itemEl.classList.remove(c);
             });
+            itemEl.querySelector('.chart-title .tools').style.display = 'none';
+            itemEl.querySelector('.chart-tools').style.display = 'none';
+            
+            try {
+                yield put({ type: 'setField', name: 'loading', value: false });
+
+                yield html2canvas(itemEl, { useCORS: true }).then(canvas => {
+                    let aLink = document.createElement('a');
+                    let blob = base64ToBlob(canvas.toDataURL()); //new Blob([content]);
+    
+                    let evt = document.createEvent("HTMLEvents");
+                    evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
+                    aLink.download = name;
+                    aLink.href = URL.createObjectURL(blob);
+    
+                    // aLink.dispatchEvent(evt);
+                    //aLink.click()
+                    aLink.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));//兼容火狐
+                })
+            }catch(e) {
+                message.error('导出图片错误:' + e);
+            }finally {
+                classListBackup.forEach(c => {
+                    itemEl.classList.add(c);
+                });
+                itemEl.querySelector('.chart-title .tools').style.display = '';
+                itemEl.querySelector('.chart-tools').style.display = '';
+                yield put({ type: 'setField', name: 'loading', value: false });
+            }
         }
     },
     subscriptions: {

File diff suppressed because it is too large
+ 0 - 0
static/iconfont/iconfont.js


Some files were not shown because too many files changed in this diff