Jelajahi Sumber

chart图字体自适应/切换面板后重新计算title高度

zhuth 8 tahun lalu
induk
melakukan
a877260d74

+ 0 - 10
kanban-client/app/assets/Form/index.css

@@ -5,16 +5,6 @@ body,
   font-size: 16px;
   overflow: hidden;
 }
-@media only screen and (max-width: 641px) {
-  html {
-    font-size: 14px !important;
-  }
-}
-@media only screen and (max-width: 450px) {
-  html {
-    font-size: 12px !important;
-  }
-}
 #root {
   background-color: #2f2e2c;
 }

+ 0 - 10
kanban-client/app/assets/Form/index.less

@@ -3,16 +3,6 @@ html,body,#root{
     font-size: 16px;
     overflow: hidden;
 }
-@media only screen and (max-width: 641px){
-    html {
-        font-size: 14px !important; 
-    }
-}
-@media only screen and (max-width: 450px){
-    html {
-        font-size: 12px !important; 
-    }
-}
 #root {
     background-color: #2f2e2c;
 }

+ 2 - 2
kanban-client/app/component/Layout.dev.js

@@ -4,8 +4,8 @@ import { WidthProvider } from 'react-grid-layout';
 var ReactGridLayout = WidthProvider(require('react-grid-layout'));
 import '../assets/layoutStyle.css';
 
-import Form from '../src/Form/index.js';
-import Table from './Table.jsx';
+import Form from '../src/Form/index.dev.js';
+import Table from './Table.dev.jsx';
 import Charts from '../src/Charts/ECharts.dev.js';
 
 

+ 283 - 0
kanban-client/app/component/Table.dev.jsx

@@ -0,0 +1,283 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Table from '../src/Table/index.js';
+import Animate from 'rc-animate';
+import {isEqual} from '../utils/BaseUtils.js';
+import '../assets/Table/index.less';
+import '../assets/Table/animation.less';
+import {sort} from '../utils/BaseUtils.js';
+
+class TableModel extends React.Component {
+	constructor(props) {
+		super(props);
+		this.newProps = props;
+		this.columns = this.setColumnsRender(props.columns);
+		this.state = {
+			data: []
+		};
+		this.timerKeys = []; // 定时器key数组
+		this.sorts = []; // 排序规则
+	}
+	// 初始化检索columns,获得排序规则
+	initSort() {
+		// 先重置
+		this.sorts = [];
+
+		let cols = this.columns;
+		let i = 0;
+		for (i; i < cols.length; i++) {
+			let col = cols[i];
+			if (Math.abs(col['sort']) > 0) {
+				this.sorts.push({
+					sortKey: col['dataIndex'],
+					sortLevel: Math.abs(col['sort']), // 仅用于规则排序
+					direction: col['sort'] > 0 ? 1 : -1
+				});
+			}
+		}
+		// 把排序规则排序
+		sort(this.sorts, [{ key: 'sortLevel', direction: 1 }]);
+	}
+	// 根据sort值分层排序data
+	sortData(data) {
+		let sortArray = this.sorts.map(function (s, i) {
+			return {
+				key: s.sortKey,
+				direction: s.direction
+			};
+		});
+		if (sortArray) { }
+		let sortData = sort(data || [], sortArray);
+		return sortData;
+	}
+	// 根据renderName设置每列的render
+	setColumnsRender(columns) {
+		let cols = columns;
+		// 如果需要增加序号列
+		if (this.newProps.index) {
+			cols.unshift({
+				key: 'index',
+				title: '序号',
+				render: 'index_render'
+			})
+		}
+		// 根据render方法名获得对应方法实体
+		for (let i = 0; i < cols.length; i++) {
+			let col = cols[i];
+			let renderFunction = col.render ? col.render : this.newProps.render ? this.newProps.render : function (_v, _r, _i) { return { children: _v, props: {} } };
+			col.render = renderFunction;
+		}
+		return cols;
+	}
+	// 设置排序合并以及表头和表体列对齐
+	onShow() {
+		this.adaptiveRowSize();
+		this.switchAnimate();
+	}
+
+	// 定时任务
+	timing(obj) {
+		let key = setInterval(function () {
+			obj.intervalFunction(this, this.state);
+		}.bind(this), obj.intervalTime || 3000);
+		this.timerKeys.push(key);
+	}
+
+	// 调整行
+	adaptiveRowSize() {
+		const { fontSize, pageSize } = this.newProps;
+		let node = this.refs.body;
+		let title = node.getElementsByClassName('rc-table-title')[0] || { offsetHeight: 0 };
+		let thead = node.getElementsByClassName('rc-table-thead')[0];
+		this.cHeight = node.offsetHeight - title.offsetHeight;
+		let trHeight = (this.cHeight) / (this.rowCount + 1);
+		let trFontSize = pageSize ? `${fontSize/.6 > trHeight ? trHeight * .6 : fontSize}px` : `${trHeight * .6}px`;
+		// let trFontSize = `${fontSize}px`;
+		thead.style.fontSize = trFontSize;
+		if(thead.getElementsByTagName('th').length == 0) return; 
+		thead.getElementsByTagName('th')[0].style.height = `${trHeight}px` ;
+		let count = this.state.data.length;
+		if (count == 0) { return; }
+		let trs = node.getElementsByClassName('fade-enter');
+		for (let i = 0; i < trs.length; i++) {
+			trs[i].style.fontSize = trFontSize;
+			trs[i].style.height = `${trHeight}px` ;
+		}
+	}
+
+	// 切换动画
+	switchAnimate() {
+		let node = this.refs.body;
+		let title = node.getElementsByClassName('rc-table-title')[0] || { offsetHeight: 0 };
+		let rows = node.getElementsByClassName('rc-table-row');
+		if (rows.length > 0) {
+			let cells = rows[0].cells || [];
+			let oldTrs = node.getElementsByClassName('fade-leave') || [];
+			let firstRow = rows[0];
+			let rowHeight = firstRow.offsetHeight;
+			let firstRowTop = firstRow.offsetTop + title.offsetHeight;
+			let newTds = firstRow.getElementsByTagName('td');
+			// 动画效果定位实现部分
+			for (let i = 0; i < oldTrs.length; i++) {
+				// 先设置旧tr为绝对布局
+				oldTrs[i].style.position = 'absolute';
+				// 宽度为100%
+				oldTrs[i].style.width = '100%';
+				// 新tr的位置高度
+				let newTrTop = firstRowTop + rowHeight * i;
+				// 将旧tr上移覆盖新的tr
+				oldTrs[i].style.top = `${newTrTop}px`;
+				// 获得旧tds
+				let oldTds = oldTrs[i].getElementsByTagName('td');
+				for (let j = 0; j < oldTds.length; j++) {
+					// 设置旧td=新td宽度
+					oldTds[j].style.maxWidth = `${newTds[j].offsetWidth}px`;
+					oldTds[j].style.minWidth = `${newTds[j].offsetWidth}px`;
+					oldTds[j].width = newTds[j].offsetWidth;
+					oldTds[j].height = newTds[j].offsetHeight - 2; 
+				}
+			}
+		}
+	}
+
+	/**
+	 * 根据容器高度分割data展示
+	 */
+	splitData() {
+		const { fontSize, pageSize } = this.newProps;
+		let node = this.refs.body;
+		let title = node.getElementsByClassName('rc-table-title')[0] || { offsetHeight: 0 };
+		let thead = node.getElementsByClassName('rc-table-thead')[0];
+		this.cHeight = node.offsetHeight - title.offsetHeight - thead.offsetHeight;
+		this.cWidth = node.offsetWidth;
+		this.rowCount = pageSize || Math.round(this.cHeight / (fontSize / .6));
+		this.rowHeight = this.cHeight / this.rowCount;
+		let a = this.newProps.data;
+		let result = [];
+		let j = 0;
+		for (let i = 0; i < a.length; i = i + j) {
+			let arr = [];
+			for (j = 0; j < this.rowCount && a[i + j]; j++) {
+				arr.push(a[i + j]);
+			}
+			result.push(arr);
+		}
+
+		this.dataArr = result;
+		this.dataIndex = 0;
+	}
+
+	setRefresh() {
+		this.changeData();
+		if (this.dataArr.length > 1) {
+			this.timing({
+				intervalFunction: function () {
+					this.changeData();
+				}.bind(this),
+				intervalTime: this.newProps.refreshInterval * 1000 || this.rowCount * this.columns.length * 200
+			});
+		}
+	}
+
+	changeData() {
+		this.setState({
+			data: this.dataArr[this.dataIndex] || []
+		}, () => {
+			this.onShow();
+			this.dataIndex++;
+			if (this.dataIndex >= this.dataArr.length) {
+				this.dataIndex = 0
+			}
+		});
+	}
+
+	clearInterval() {
+		for (let index in this.timerKeys) {
+			clearInterval(this.timerKeys[index]);
+			this.timerKeys.splice(index, 1);
+		}
+	}
+
+	componentWillMount() {
+	}
+	componentDidMount() {
+		this.initSort();
+		this.sortData(this.newProps.data);
+		this.splitData();
+		this.setRefresh();
+	}
+	componentWillUnmount() {
+		this.clearInterval();
+	}
+	componentWillReceiveProps(nextProps) {
+		if (isEqual(this.sortData(nextProps.data), this.newProps.data)) {
+			this.newProps = nextProps;
+			return;
+		}
+		this.clearInterval();
+		this.splitData();
+		this.setRefresh();
+	}
+
+	shouldComponentUpdate(nextProps, nextState) {
+			return true;
+	}
+	getBodyWrapper(body) {
+		return (
+			<Animate transitionName="fade" component="tbody" className={body.props.className}
+				transitionAppear={true}
+				transitionLeave={true}
+			>
+				{body.props.children}
+			</Animate>
+		);
+	}
+
+	getTitle() {
+		const { title } = this.newProps;
+		// return function (state) {
+			return title;
+		// }
+	}
+
+	render() {
+		const { fontSize } = this.newProps;
+		return (
+			<div ref='body' style={{ height: '100%', overflow: 'hidden', padding: '0px' }}>
+				<Table
+					prefixCls={this.newProps.prefixCls || 'rc-table'}
+					className={this.newProps.className}
+					useFixedHeader={this.newProps.useFixedHeader || false}
+					scroll={{ x: false, y: this.newProps.scroll } || { x: false, y: false }}
+					expandIconAsCell={this.newProps.expandIconAsCell || false}
+					expandIconColumnIndex={this.newProps.expandIconColumnIndex || 0}
+					rowKey={this.newProps.rowKey || 'key'}
+					rowClassName={this.newProps.rowClassName || function () { }}
+					rowRef={this.newProps.rowRef || function () { }}
+					defaultExpandedRowKeys={this.newProps.defaultExpandedRowKeys || []}
+					expandedRowKeys={this.newProps.expandedRowKeys || []}
+					defaultExpandAllRows={this.newProps.defaultExpandAllRows || false}
+					onExpandedRowsChange={this.newProps.onExpandedRowsChange || function () { }}
+					onExpand={this.newProps.onExpand || function () { }}
+					expandedRowClassName={this.newProps.expandedRowClassName || function () { }}
+					indentSize={this.newProps.indentSize || 15}
+					onRowClick={this.newProps.onRowClick || function () { }}
+					onRowDoubleClick={this.newProps.onRowDoubleClick || function () { }}
+					onRowMouseEnter={this.newProps.onRowMouseEnter || function () { }}
+					onRowMouseLeave={this.newProps.onRowMouseLeave || function () { }}
+					showHeader={this.newProps.showHeader || true}
+					title={this.getTitle()}
+					footer={this.newProps.footer}
+					emptyText={this.newProps.emptyText || 'No Data'}
+					columns={this.columns || []}
+					data={this.state.data || []}
+					getBodyWrapper={this.getBodyWrapper}
+					state={this.state}
+					headerRowsStyle={this.newProps.headerRowsStyle}
+					rowsStyle={this.newProps.rowsStyle}
+				/>
+			</div>
+		);
+	}
+}
+export default TableModel;

+ 406 - 0
kanban-client/app/component/converter.dev.js

@@ -0,0 +1,406 @@
+function converter(data) {
+    let { content } = data;
+    let { title, items } = content;
+    let itemsarr = items ? (items instanceof Array ? items : [items]) : [];
+
+    let me = this;
+    let newItems = itemsarr.map(function (v, i) {
+        let type = v.type;
+        if (type == 'form') {
+            return formConfig(v);
+        } else if (type == 'table') {
+            return tableConfig(v);
+        } else if (type == 'bar') {
+            return barConfig(v);
+        } else if (type == 'line') {
+            return lineConfig(v);
+        } else if (type == 'pie') {
+            return pieConfig(v);
+        } else {
+
+        }
+    });
+    return {
+        title: titleConfig(title),
+        content: {
+            items: newItems
+        }
+    }
+}
+
+function titleConfig(title) {
+    return {
+        title: replaceSpecTag(title),
+        fontSize: getFontSize()
+    }
+}
+
+function formConfig(model) {
+    let { type, config, layout } = model;
+    let { fontSize, header, fieldStyle, valueStyle, columns, data } = config;
+    data = data ? ( ( data instanceof Array ) ? data : [data] ) : [];
+    data = data.map((d) => {
+        d.field = {
+            text: d.field.text,
+            style: parseStyleStr(d.field.style)
+        };
+        d.value = {
+            text: d.value.text,
+            style: parseStyleStr(d.value.style)
+        };
+        d.render = renderFunction(d.render);
+        return d;
+    });
+    if(header) {
+        header.style = parseStyleStr(header.style || '{}');
+    }
+    let c = {
+        type: 'form',
+        config: {
+            fontSize: fontSize || getFontSize(),
+            header: header,
+            fieldStyle: parseStyleStr(fieldStyle),
+            valueStyle: parseStyleStr(valueStyle),
+            columns,
+            data
+        },
+        layout: getLayout(layout)
+    }
+    return c;
+}
+
+function tableConfig(model) {
+    let { type, config, layout } = model;
+    let { fontSize, title, cls, render, columns, data, pagesize, interval, headerrowsstyle, rowsstyle } = config;
+    let allWidth = 0;
+    columns = columns ? ( ( columns instanceof Array ) ? columns : [columns] ) : [];
+    columns.map((c, i) => allWidth += (c.width || 100));
+    data = data ? ( ( data instanceof Array ) ? data : [data] ) : [];
+    if(title) {
+        title.style = parseStyleStr(title.style || '{}');
+    }
+    return {
+        type: 'table',
+        config: {
+            fontSize: fontSize || getFontSize(),
+            pageSize: pagesize,
+            refreshInterval: interval,
+            title: title,
+            render: renderFunction(render),
+            columns: columns.map( (v, i) => {
+                v.key = i;
+                v.width ? v.width = getScreenSize().width * (layout.w/100) * (v.width/ allWidth) : '';
+                v.render = renderFunction(v.render);
+                v.headerRowStyle = parseStyleStr(v.headerrowstyle);
+                v.rowStyle = parseStyleStr(v.rowstyle);
+                return v;
+            }),
+            data: data.map( (v, i) => {
+                if(v){
+                    v.key = i;
+                }
+                return v || {};
+            } ),
+            headerRowsStyle: parseStyleStr(headerrowsstyle),
+            rowsStyle: parseStyleStr(rowsstyle),
+        },
+        layout: getLayout(layout)
+    }
+}
+
+function barConfig(model) {
+    let { type, config, layout } = model;
+    let { fontSize, title, subtitle, xtitle, xtype, xfields, ytitle, ytype, yfields, series } = config;
+    let xf = (xfields instanceof Array) ? xfields : (xfields.replace(['['], '').replace([']'], '').split(','));
+    return {
+        type: 'charts',
+        config: {
+            option: {
+                title: getChartsTitle(fontSize, layout, title, subtitle),
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {
+                        type: 'shadow'
+                    }
+                },
+                grid: {
+                    top: layout.h * getScreenSize().height / 100 < 310 ? '35%' : '28%',
+                    bottom: layout.h * getScreenSize().height / 100 < 310 ? '20%' : '16%',
+                },
+                legend: {
+                    top: layout.h * getScreenSize().height / 100 < 310 ? '20%' : '18%',
+                    right: '5%',
+                    padding: 0,
+                    orient: 'horizontal',
+                    itemGap: layout.w,
+                    data: series.map((v, i) => {
+                        return v.name
+                    })
+                },
+                xAxis: [{
+                    type: xtype,
+                    data: xf,
+                    name: xtitle,
+                    nameGap: 5,
+                    nameRotate: 270,
+                    nameLocation: 'end',
+                    axisLabel: {
+                        rotate: getScreenSize().width * layout.w / xf.length / 100 < 80 ? 45 : 0,
+                        interval: 0
+                    }
+                }],
+                yAxis: [{
+                    name: ytitle,
+                    nameRotate: .1,
+                    type: ytype == 'numeric' ? 'value' : ytype,
+                }],
+                series: getBarSeries(fontSize, layout, series)
+            }
+        },
+        layout: getLayout(layout)
+    }
+}
+
+function lineConfig(model) {
+    let { type, config, layout } = model;
+    let { fontSize, title, subtitle, xtitle, xtype, xfields, ytitle, ytype, yfields, series } = config;
+    let xf = (xfields instanceof Array) ? xfields : (xfields.replace(['['], '').replace([']'], '').split(','));
+    return {
+        type: 'charts',
+        config: {
+            option: {
+                title: getChartsTitle(fontSize, layout, title, subtitle),
+                tooltip: {
+                    trigger: 'axis'
+                },
+                grid: {
+                    top: layout.h * getScreenSize().height / 100 < 310 ? '35%' : '28%',
+                    bottom: layout.h * getScreenSize().height / 100 < 310 ? '20%' : '16%',
+                },
+                legend: {
+                    top: layout.h * getScreenSize().height / 100 < 310 ? '20%' : '18%',
+                    right: '5%',
+                    padding: 0,
+                    orient: 'horizontal',
+                    itemGap: layout.w,
+                    data: series.map((v, i) => {
+                        return v.name
+                    })
+                },
+                xAxis: [{
+                    type: xtype,
+                    data: xf,
+                    name: xtitle,
+                    nameRotate: 270,
+                    nameLocation: 'end',
+                    nameGap: 5,
+                    axisLabel: {
+                        rotate: getScreenSize().width * layout.w / xf.length / 100 < 80 ? 45 : 0,
+                        interval: 0
+                    }
+                }],
+                yAxis: [{
+                    name: ytitle,
+                    nameRotate: .1,
+                    type: ytype == 'numeric' ? 'value' : ytype
+                }],
+                series: getLineSeries(fontSize, series),
+                dataZoom: [
+                    {
+                        type: 'slider',
+                        show: false,
+                        xAxisIndex: [0],
+                        start: 0,
+                        endValue: Math.round(getScreenSize().width * layout.w / 100 / 60) >= series[0].data.length ? series[0].data.length - 1 : Math.round(getScreenSize().width * layout.w / 100 / 60),
+                    }
+                ],
+            }
+        },
+        layout: getLayout(layout)
+    }
+}
+
+function pieConfig(model) {
+    let { type, config, layout } = model;
+    let { fontSize, title, subtitle, series } = config;
+    series = series.map((v, i) => {
+        v.value = v.data;
+        return v;
+    });
+    return {
+        type: 'charts',
+        config: {
+            option: {
+                title: getChartsTitle(fontSize, layout, title, subtitle),
+                tooltip: {
+                    trigger: 'item',
+                    formatter: '{b} : {c} ({d}%)'
+                },
+                legend: getPieLegend(fontSize, layout, series),
+                series: getPieSeries(fontSize, layout, series)
+            }
+        },
+        layout: getLayout(layout)
+    }
+}
+
+function renderFunction(funcStr) {
+    let func = undefined;
+    func = (new Function("return " + funcStr))();
+    return func;
+}
+
+function getChartsTitle(fontSize, layout, title, subtitle) {
+    var title = {
+        show: true,
+        text: title,
+        subtext: layout.h * getScreenSize().height / 100 < 300 ? '' : subtitle,
+        textAlign: 'center',
+        textStyle: {
+            verticalAlign: 'top'
+        },
+        subtextStyle: {
+            verticalAlign: 'top'
+        },
+        left: '50%',
+        right: '50%',
+        itemGap: 5,
+        padding: 10
+    }
+    return title;
+}
+
+function getBarSeries(fontSize, layout, series) {
+    let s = [];
+    const model = {
+        type: 'bar',
+        label: {
+            normal: {
+                show: true,
+                position: 'top',
+                formatter: '{c}',
+            }
+        },
+        barGap: 0
+    }
+    s = series.map((v, i) => {
+        let m = Object.assign({}, model);
+        m.name = v.name;
+        m.data = v.data instanceof Array ? v.data : [v.data];
+        return m;
+    });
+    return s;
+}
+
+function getLineSeries(fontSize, series) {
+    let s = [];
+    const model = {
+        type: 'line',
+        smooth: false,
+        markLine: {
+            symbol: '',
+            label: {
+                normal: {
+                    show: false
+                }
+            },
+            data: [{
+                name: '起始位置',
+                yAxis: null,
+                xAxis: ''
+            }]
+        },
+        label: {
+            normal: {
+                show: true,
+                position: 'inside',
+                formatter: '{c}'
+            }
+        }
+    }
+    s = series.map((v, i) => {
+        let m = Object.assign({}, model);
+        m.name = v.name;
+        m.data = v.data instanceof Array ? v.data : [v.data];
+        return m;
+    });
+    return s;
+}
+
+function getPieSeries(fontSize, layout, series) {
+    let data = series instanceof Array ? series : [series];
+    const model = {
+        type: 'pie',
+        label: {
+            normal: {
+                formatter: '{b}:  {c} \n {d}%'
+            }
+        }
+    }
+    let s = Object.assign({}, model);
+    s.name = '';
+    s.data = data.map((d, i) => { d.name = d.name || 'Unkonw'; return d; });
+    return [s];
+}
+
+function getPieLegend(fontSize, layout, series) {
+    let legend = {
+        padding: 0,
+        itemGap: layout.w / 10,
+        data: series.map((v, i) => {
+            return v.name || 'Unkonw';
+        })
+    }
+    return legend;
+}
+
+function getLayout(layout) {
+    let l = {};
+    for (let k in layout) {
+        l[k] = layout[k] / 10
+    }
+    return l;
+}
+
+function parseStyleStr(str) {
+    if (!str) {
+        return {};
+    }
+    if (typeof str == 'object') {
+        return str;
+    }else {
+        return JSON.parse(str);
+    }
+}
+
+function replaceSpecTag(str) {
+    if (str) {
+        if (typeof (str) === 'string') {
+            return str.replace(/&amp;/g, '&')
+                .replace(/&lt;/g, '<')
+                .replace(/&gt;/g, '>')
+                .replace(/&apos;/g, '\'')
+                .replace(/&quot;/g, '"')
+                .replace(/&nbsp;/g, ' ');
+        } else {
+            return str;
+        }
+    } else {
+        return str;
+    }
+}
+
+function getScreenSize() {
+    let root = document.getElementById('root');
+    let height = root.offsetHeight;
+    let width = root.offsetWidth;
+    return { height, width };
+}
+
+function getFontSize() {
+    let { height, width } = getScreenSize();
+    let fontSize = width / 300 * 2 + 16 + Math.round(width / 1000) * 2;
+    return fontSize;
+}
+
+export { converter };

+ 6 - 2
kanban-client/app/component/converter.js

@@ -51,7 +51,9 @@ function formConfig(model) {
         d.render = renderFunction(d.render);
         return d;
     });
-    header.style = parseStyleStr(header.style || '{}');
+    if(header) {
+        header.style = parseStyleStr(header.style || '{}');
+    }
     let c = {
         type: 'form',
         config: {
@@ -74,7 +76,9 @@ function tableConfig(model) {
     columns = columns ? ( ( columns instanceof Array ) ? columns : [columns] ) : [];
     columns.map((c, i) => allWidth += (c.width || 100));
     data = data ? ( ( data instanceof Array ) ? data : [data] ) : [];
-    title.style = parseStyleStr(title.style || '{}');
+    if(title) {
+        title.style = parseStyleStr(title.style || '{}');
+    }
     return {
         type: 'table',
         config: {

+ 9 - 15
kanban-client/app/component/factory.dev.js

@@ -1,31 +1,30 @@
 import React from 'react';
 import Container from './Layout.dev.js';
-import Title from '../src/Title/Title.jsx';
+import Title from '../src/Title/Title.dev.jsx';
 import MessageBox from '../src/MsgBox/MessageBox.jsx';
-import { converter } from './converter.js';
+import { converter } from './converter.dev.js';
 import URL from '../constants/url.dev.json';
 
-import tempdata from '../data/cc.json';
+import tempdata from '../data/testform.json';
 
 class Factory extends React.Component {
 
     constructor(props) {
         super(props);
-        this.dev = 'local';
+        this.dev = 'local ';
         this.index = 0;
         this.state = {
             titleHeight: 0,
             error: null,
             firstRequestTime: new Date()
         };
-        window.forceUpdate = this.forceUpdate.bind(this);
     }
 
     getModelConfig(mid) {
         let me = this;
         fetch(URL.path + mid, {
             method: 'POST',
-            credentials: 'include',
+            credentials: 'include'
         }).then(function (response) {
             return (response.json())
         }).then((json) => {
@@ -35,8 +34,7 @@ class Factory extends React.Component {
             let instance = json.instance;
             if (!me.state.instance) {
                 me.setState({
-                    instance: instance,
-                    lastRequestTime: new Date()
+                    instance: instance
                 }, me.setRefresh);
             }
             return json.data[0];
@@ -47,7 +45,6 @@ class Factory extends React.Component {
             me.setState({
                 error: null,
                 model: converter(modelconfig),
-                // titleHeight: 73
             });
         }).catch(function (ex) {
             me.setState({
@@ -91,7 +88,7 @@ class Factory extends React.Component {
         if (refresh.current) {
             if (refresh.current.enable) {
                 this.refreshThis = setInterval(function () {
-                    this.getModelConfig(this.props.code[0] + '?relatedKanban=' + codes[this.index]);
+                    this.getModelConfig(this.props.code[0] + '?kanbanCode=' + codes[this.index]);
                 }.bind(this), refresh.current.interval * 1000 || 10000)
             }
         }
@@ -110,7 +107,7 @@ class Factory extends React.Component {
     }
 
     onWindowResize() {
-        this.forceUpdate();
+        this.setTitleHeight(this.getTitleHeight());
     }
 
     componentDidUpdate() {
@@ -128,7 +125,7 @@ class Factory extends React.Component {
     }
 
     componentDidMount() {
-        window.addEventListener('resize', this.onWindowResize);
+        window.addEventListener('resize', this.onWindowResize.bind(this));
         this.setState({
             titleHeight: this.getTitleHeight()
         });
@@ -148,9 +145,6 @@ class Factory extends React.Component {
     }
 
     componentWillReceiveProps(nextProps) {
-        this.setState({
-            titleHeight: this.getTitleHeight()
-        });
     }
 
     render() {

+ 1 - 1
kanban-client/app/constants/url.dev.json

@@ -1,3 +1,3 @@
 {
-    "path": "http://localhost:8080/panelInstance/parseData/"
+    "path": "http://localhost:8081/panelInstance/parseData/"
 }

+ 37 - 574
kanban-client/app/data/cc.json

@@ -1,607 +1,70 @@
 {
     "instance": {
-        "enabledKanbanCodes": ["5DE01DE4D16"],
+        "enabledKanbanCodes": ["63975A40E1D"],
         "display": "AutoSwitch",
         "switchFrequency": 10,
         "refreshFrequency": 5,
-        "parameters": [{
-            "code": "5E326742F2A",
-            "createTime": 1508485784623,
-            "inputMode": "DropDownBox",
-            "lastModified": 1508919901414,
-            "name": "线别",
-            "optionalValues": ["SMT"],
-            "panelCode": "5DE01C8DF14",
-            "type": "String",
-            "value": "SMT",
-            "version": 5
-        }, {
-            "code": "5FD06CEC511",
-            "createTime": 1508919918275,
-            "inputMode": "DropDownBox",
-            "lastModified": 1508919918275,
-            "name": "新参数",
-            "optionalValues": ["a"],
-            "panelCode": "5DE01C8DF14",
-            "type": "String",
-            "value": "a",
-            "version": 1
-        }]
+        "parameters": []
     },
     "data": [{
         "content": {
-            "title": "<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"1\" style=\"font-weight: bold; background: #2f2e2c;border-collapse: collapse;color: white; text-align: center;\">  <tr>    <td width=\"20%\" rowspan=\"2\" style=\"border:1px solid white\"><img style=\"width: auto;height: 40%; max-width: 100%; max-height: 100%;\" src=\"static/images/log.png\" alt=\"\"/></td>    <td width=\"60%\" rowspan=\"4\" colspan=\"2\" style=\"border:1px solid white\">车间执行进度看板</td>    <td width=\"10%\" rowspan=\"1\" style=\"border:1px solid white\">车间</td>  <td width=\"10%\" rowspan=\"1\" style=\"border:1px solid white;color:red\">车间</td>  </tr>  <tr>    <td width=\"10%\" rowspan=\"1\" style=\"border:1px solid white\">SMT</td><td width=\"10%\" rowspan=\"1\" style=\"border:1px solid white;color:red\">SMT</td>  </tr>  </table>",
-            "items": [{
+            "items": {
                 "layout": {
-                    "w": 40,
+                    "w": 100,
                     "x": 0,
-                    "h": 57,
-                    "y": 0
-                },
-                "type": "form",
-                "config": {
-                    "valueStyle": "{\"color\":\"blue\"}",
-                    "data": [{
-                        "field": {
-                            "text": "组长"
-                        },
-                        "value": {
-                            "style": "{\"fontStyle\":\"oblique\"}",
-                            "text": "余海文1111111111111111111111"
-                        },
-                        "render": "function(field,value){;if(1==1){return{field:{text:field,style:{\"fontStyle\":\"oblique\"}},value:{text:'1000',style:{\"color\":\"blue\",\"fontStyle\":\"oblique\"}}}}}"
-                    }, {
-                        "field": {
-                            "text": "PE"
-                        },
-                        "value": {
-                            "text": "黄伟平"
-                        }
-                    }, {
-                        "field": {
-                            "text": "机动"
-                        },
-                        "value": {
-                            "text": "何伟文"
-                        }
-                    }, {
-                        "field": {
-                            "style": "{\"color\":\"red\"}",
-                            "text": "IPQC"
-                        },
-                        "value": {
-                            "text": "张晓辉"
-                        }
-                    }, {
-                        "field": {
-                            "text": "当前产量"
-                        },
-                        "width": 100,
-                        "value": {
-                            "style": "{\"color\":\"red\"}",
-                            "text": 0
-                        },
-                        "render": "function(field,value){;if(1==1){return{field:{text:field,style:{}},value:{text:value + '100000011111111111111111111111111111000',style:{}}}}}"
-                    }, {
-                        "field": {
-                            "text": "计划产量"
-                        },
-                        "width": 100,
-                        "value": {
-                            "style": "{\"color\":\"red\"}",
-                            "text": 0
-                        }
-                    }, {
-                        "field": {
-                            "text": "计划达成率"
-                        },
-                        "width": 100,
-                        "value": {
-                            "style": "{\"color\":\"red\"}",
-                            "text": 0
-                        }
-                    }, {
-                        "field": {
-                            "text": "直通率"
-                        },
-                        "width": 100,
-                        "value": {
-                            "style": "{\"color\":\"red\"}",
-                            "text": 0
-                        }
-                    }],
-                    "columns": 1,
-                    "header": {
-                        "text": "header",
-                        "style":"{}"
-                    }
-                }
-            }, {
-                "layout": {
-                    "w": 40,
-                    "x": 0,
-                    "h": 43,
-                    "y": 57
-                },
-                "type": "table",
-                "config": {
-                    "data": [{
-                        "前五大不良": "反面"
-                    }, {
-                        "前五大不良": "漏印"
-                    }, {
-                        "前五大不良": "反向"
-                    }, {
-                        "前五大不良": "其它"
-                    }, {
-                        "前五大不良": "漏件"
-                    }],
-                    "columns": [{
-                        "dataIndex": "前五大不良",
-                        "width": 180,
-                        "sort": 0,
-                        "title": "前五大不良"
-                    }, {
-                        "dataIndex": "数量",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "数量"
-                    }, {
-                        "dataIndex": "原因",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "原因"
-                    }],
-                    "pagesize": 5,
-                    "interval": 3,
-                    "title": {}
-                }
-            }, {
-                "layout": {
-                    "w": 60,
-                    "x": 40,
                     "h": 100,
                     "y": 0
                 },
-                "type": "table",
+                "type": "pie",
                 "config": {
-                    "data": [{
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 5
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 53
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 642
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 52
-                    }, {
-                        "时段": "8~9",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 14
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 6
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 119
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 0
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 7
-                    }, {
-                        "时段": "9~10",
-                        "投入数": 89
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 2
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 92
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 252
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 144
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 62
-                    }, {
-                        "时段": "10~11",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 8
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 38
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 40
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
-                    }, {
-                        "时段": "11~12",
-                        "投入数": 0
+                    "series": [{
+                        "data": 14,
+                        "name": "平台部"
                     }, {
-                        "时段": "11~12",
-                        "投入数": 0
+                        "name": "运营中心"
                     }, {
-                        "时段": "11~12",
-                        "投入数": 0
+                        "data": 9,
+                        "name": "测试部"
                     }, {
-                        "时段": "11~12",
-                        "投入数": 0
+                        "data": 3,
+                        "name": "IPQC部"
                     }, {
-                        "时段": "上午",
-                        "投入数": 201
+                        "data": 3,
+                        "name": "人力资源部"
                     }, {
-                        "时段": "上午",
-                        "投入数": 1517
+                        "data": 4,
+                        "name": "投资部"
                     }, {
-                        "时段": "上午",
-                        "投入数": 0
+                        "data": 32,
+                        "name": "软件部"
                     }, {
-                        "时段": "上午",
-                        "投入数": 0
+                        "data": 16,
+                        "name": "采购部"
                     }, {
-                        "时段": "上午",
-                        "投入数": 1648
-                    }, {
-                        "时段": "上午",
-                        "投入数": 0
-                    }, {
-                        "时段": "上午",
-                        "投入数": 922
-                    }, {
-                        "时段": "上午",
-                        "投入数": 13
-                    }, {
-                        "时段": "上午",
-                        "投入数": 701
-                    }, {
-                        "时段": "上午",
-                        "投入数": 0
-                    }, {
-                        "时段": "上午",
-                        "投入数": 0
-                    }, {
-                        "时段": "上午",
-                        "投入数": 718
-                    }, {
-                        "时段": "上午",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 21
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 126
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 113
-                    }, {
-                        "时段": "12~13",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 19
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 2
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 12
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 34
-                    }, {
-                        "时段": "13~14",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 3
-                    }, {
-                        "时段": "14~15",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 40
-                    }, {
-                        "时段": "下午",
-                        "投入数": 2
-                    }, {
-                        "时段": "下午",
-                        "投入数": 138
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "下午",
-                        "投入数": 150
-                    }, {
-                        "时段": "下午",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 201
-                    }, {
-                        "时段": "当天",
-                        "投入数": 718
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 741
-                    }, {
-                        "时段": "当天",
-                        "投入数": 15
-                    }, {
-                        "时段": "当天",
-                        "投入数": 1060
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 1648
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }, {
-                        "时段": "当天",
-                        "投入数": 1667
-                    }, {
-                        "时段": "当天",
-                        "投入数": 0
-                    }],
-                    "columns": [{
-                        "dataIndex": "时段",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "时段"
+                        "data": 21,
+                        "name": "国内销售部"
                     }, {
-                        "dataIndex": "计划数",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "计划数"
+                        "data": 13,
+                        "name": "项目部"
                     }, {
-                        "dataIndex": "投入数",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "投入数",
-                        "render": "function(value,record,index){;if(value>200){return{children:value,props:{style:{\"color\":\"#99CC00\"}}}}else{return{children:value,props:{style:{}}}}}"
+                        "data": 9,
+                        "name": "硬件部"
                     }, {
-                        "dataIndex": "送检数",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "送检数"
+                        "data": 6,
+                        "name": "PMC部"
                     }, {
-                        "dataIndex": "包装数",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "包装数"
+                        "data": 4,
+                        "name": "行政部"
                     }, {
-                        "dataIndex": "达成率",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "达成率"
+                        "data": 12,
+                        "name": "财务部"
                     }, {
-                        "dataIndex": "备注",
-                        "width": 100,
-                        "sort": 0,
-                        "title": "备注"
+                        "data": 9,
+                        "name": "产品规划部"
                     }],
-                    "pagesize": 0,
-                    "interval": 3,
-                    "title": {
-                        "text":"tabletitle",
-                        "style":"{}"
-                    },
-                    "headerrowsstyle": "{\"color\":\"#FFFF00\"}"
+                    "title": "部门员工统计"
                 }
-            }]
+            }
         }
     }]
 }

+ 9 - 10
kanban-client/app/data/testform.json

@@ -13,22 +13,21 @@
                         "config": {
                             "data": [
                                 {
-                                    "field": { "text": "公", "style": "{'color': \"red\"}"},
-                                    "value": { "text": "1000", "style": {"color": "red"}},
-                                    "width": 100,
-                                    "render": "function(f, v){var nv = v.text>900?'hah':v.text; return { field: f,value: {text: nv,style:v.style} }}"
+                                    "field": { "text": "公", "style": "{\"color\": \"red\"}"},
+                                    "value": { "text": "1000"},
+                                    "width": 100
                                 },
                                 {
-                                    "field": { "text": "公", "style": {"color": "red"}},
-                                    "value": { "text": "告", "style": {"color": "red"}}
+                                    "field": { "text": "公"},
+                                    "value": { "text": "告"}
                                 },
                                 {
-                                    "field": { "text": "公", "style": {"color": "red"}},
-                                    "value": { "text": "告", "style": {"color": "red"}}
+                                    "field": { "text": "公"},
+                                    "value": { "text": "告"}
                                 },
                                 {
-                                    "field": { "text": "公", "style": {"color": "red"}},
-                                    "value": { "text": "告", "style": {"color": "red"}}
+                                    "field": { "text": "公"},
+                                    "value": { "text": "告"}
                                 }
                             ],
                             "columns": 4,

+ 307 - 136
kanban-client/app/data/testtable.json

@@ -4,162 +4,333 @@
             "content": {
                 "items": [
                     {
+                        "layout": {
+                            "w": 100,
+                            "x": 0,
+                            "h": 100,
+                            "y": 0
+                        },
                         "type": "table",
                         "config": {
-                            "pagesize": 0,
-                            "columns": [
+                            "data": [
                                 {
-                                    "title": "时段",
-                                    "width": 150,
-                                    "dataIndex": "time"
+                                    "时段": "8~9",
+                                    "投入数": 0
                                 },
                                 {
-                                    "title": "计划数",
-                                    "dataIndex": "plan"
+                                    "时段": "8~9",
+                                    "投入数": 1
                                 },
                                 {
-                                    "title": "投入数",
-                                    "dataIndex": "input"
+                                    "时段": "8~9",
+                                    "投入数": 2
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 3
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 4
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 5
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 6
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 7
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 8
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 9
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 10
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 11
+                                },
+                                {
+                                    "时段": "8~9",
+                                    "投入数": 12
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 13
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 14
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 15
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 16
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 17
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 18
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 19
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 20
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 21
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 22
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 23
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 24
+                                },
+                                {
+                                    "时段": "9~10",
+                                    "投入数": 25
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 26
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 27
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 28
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 29
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 30
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 31
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 32
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 33
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 34
+                                },
+                                {
+                                    "时段": "10~11",
+                                    "投入数": 35
                                 },
                                 {
-                                    "title": "送检数",
-                                    "dataIndex": "check"
+                                    "时段": "10~11",
+                                    "投入数": 36
                                 },
                                 {
-                                    "title": "包装数",
-                                    "dataIndex": "pack"
+                                    "时段": "10~11",
+                                    "投入数": 37
                                 },
                                 {
-                                    "title": "达成率",
-                                    "dataIndex": "success",
-                                    "render": "function(value, record, index){let nv = value.replace(/%/, '');let style = {};if(nv < 100) {style = {color: 'red'};}else {style = {color: '#0000cd'};}return {children: value,props: {style: style}}}"
+                                    "时段": "10~11",
+                                    "投入数": 38
                                 },
                                 {
-                                    "title": "备注",
-                                    "dataIndex": "desc",
-                                    "render": "function(value, record, index){return{children:value,props:{style:{color: 'green'}}}}"
+                                    "时段": "11~12",
+                                    "投入数": 39
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 40
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 41
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 42
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 43
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 44
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 45
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 46
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 47
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 48
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 49
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 50
+                                },
+                                {
+                                    "时段": "11~12",
+                                    "投入数": 51
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 52
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 53
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 54
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 55
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 56
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 57
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 58
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 59
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 60
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 61
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 62
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 63
+                                },
+                                {
+                                    "时段": "上午",
+                                    "投入数": 64
+                                },
+                                {
+                                    "时段": "12~13",
+                                    "投入数": 65
+                                },
+                                {
+                                    "时段": "12~13",
+                                    "投入数": 66
                                 }
                             ],
-                            "data": [
+                            "columns": [
                                 {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "11"
-                                },
-                                {
-                                    "key": "2",
-                                    "time": "9-10",
-                                    "plan": "200",
-                                    "input": "200",
-                                    "check": "200",
-                                    "pack": "0",
-                                    "success": "100%",
-                                    "desc": "10"
-                                },
-                                {
-                                    "key": "3",
-                                    "time": "10-11",
-                                    "plan": "200",
-                                    "input": "203",
-                                    "check": "400",
-                                    "pack": "0",
-                                    "success": "120%",
-                                    "desc": "9"
-                                },
-                                {
-                                    "key": "4",
-                                    "time": "11-12",
-                                    "plan": "",
-                                    "input": "",
-                                    "check": "",
-                                    "pack": "",
-                                    "success": "",
-                                    "desc": "8"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "7"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "6"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "5"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "4"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "3"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "2"
-                                },
-                                {
-                                    "key": "1",
-                                    "time": "8-9",
-                                    "plan": "150",
-                                    "input": "160",
-                                    "check": "100",
-                                    "pack": "0",
-                                    "success": "70%",
-                                    "desc": "1"
+                                    "dataIndex": "时段",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "时段"
+                                },
+                                {
+                                    "dataIndex": "计划数",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "计划数"
+                                },
+                                {
+                                    "dataIndex": "投入数",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "投入数",
+                                    "render": "function(value,record,index){;if(value>200){return{children:value,props:{style:{\"color\":\"#99CC00\"}}}}else{return{children:value,props:{style:{}}}}}"
+                                },
+                                {
+                                    "dataIndex": "送检数",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "送检数"
+                                },
+                                {
+                                    "dataIndex": "包装数",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "包装数"
+                                },
+                                {
+                                    "dataIndex": "达成率",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "达成率"
+                                },
+                                {
+                                    "dataIndex": "备注",
+                                    "width": 100,
+                                    "sort": 0,
+                                    "title": "备注"
                                 }
                             ],
-                            "title": "function(){return {text: 'textAlign: left, height: 60, color: blue, fontSize: 16px, border: 1px solid white', style: {textAlign: 'left', height: 60, 'color': 'blue', fontSize: '16px', border: '1px solid white'}}}",
-                            "render": "function(value,record,index){if(1==1){return{children:value,props:{style:{}}}}}"
-                        },
-                        "layout": {
-                            "x": 0,
-                            "y": 0,
-                            "w": 100,
-                            "h": 50
+                            "pagesize": 0,
+                            "interval": 0,
+                            "title": {},
+                            "headerrowsstyle": "{\"color\":\"#FFFF00\"}"
                         }
                     }
                 ]

+ 5 - 0
kanban-client/app/index.html

@@ -2,6 +2,11 @@
 <html>
 <head lang="en">
   <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
+  <meta name="format-detection" content="telephone=no" />
+  <meta name="apple-mobile-web-app-capable" content="yes" />
+  <meta name="apple-mobile-web-app-status-bar-style" content="black">
+  <meta http-equiv="pragma" content="no-cache" />
   <title>Board</title>
 </head>
 <body style="margin:0px">

+ 1 - 1
kanban-client/app/main.dev.js

@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
 import Factory from './component/factory.dev.js';
 import DateFormatter from './utils/DateTimeUtils.js';
 
-var code = '601F25F0F23';
+var code = '63B27949A17';
 
 ReactDOM.render(
     <Factory code={[code]} />,

+ 6 - 4
kanban-client/app/src/Charts/ECharts.dev.js

@@ -47,8 +47,9 @@ export class ReactEchart extends React.Component {
 
     reset() {
         let node = this.echarts_react.echartsElement;
+        let option = reset(this.newProps.option, node, this.showCount);
         this.setState({
-            option: reset(this.newProps.option, node, this.showCount)
+            option: option
         });
     }
 
@@ -90,10 +91,11 @@ export class ReactEchart extends React.Component {
     }
 
     componentWillReceiveProps(nextProps) {
-        if(isEqual(nextProps.option.series, this.state.option.series)) {
-            this.newProps = nextProps;
-            return;
+        if(!isEqual(nextProps.option.series, this.state.option.series)) {
+            let echarts_instance = this.echarts_react.getEchartsInstance();
+            echarts_instance.clear();
         }
+        this.newProps = nextProps;
         this.reset();
     }
 

+ 4 - 3
kanban-client/app/src/Charts/ECharts.js

@@ -84,10 +84,11 @@ export class ReactEchart extends React.Component {
     }
 
     componentWillReceiveProps(nextProps) {
-        if(isEqual(nextProps.option.series, this.state.option.series)) {
-            this.newProps = nextProps;
-            return;
+        if(!isEqual(nextProps.option.series, this.state.option.series)) {
+            let echarts_instance = this.echarts_react.getEchartsInstance();
+            echarts_instance.clear();
         }
+        this.newProps = nextProps;
         this.reset();
     }
 

+ 170 - 0
kanban-client/app/src/Form/Form.dev.jsx

@@ -0,0 +1,170 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {isEmptyObject} from '../../utils/BaseUtils.js';
+import '../../assets/Form/index.less';
+
+export default class Form extends React.Component {
+    static propTypes = {
+        fontSize: PropTypes.number,
+        state: PropTypes.object,
+        fieldCls: PropTypes.string,
+        fieldStyle: PropTypes.object,
+        valueCls: PropTypes.string,
+        valueStyle: PropTypes.object,
+        data: PropTypes.array,
+        prefixCls: PropTypes.string,
+        cls: PropTypes.string,
+        style: PropTypes.object,
+        header: PropTypes.object,
+        columns: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+    }
+
+    static defaultProps = {
+        fontSize: 16,
+        state: {},
+        fieldCls: '',
+        fieldStyle: {},
+        valueCls: '',
+        valueStyle: {},
+        data: [],
+        prefixCls: 'rc-form',
+        cls: '',
+        style: {},
+        header: function() {return {text: '', style:{}}},
+        columns: 1
+    }
+
+    constructor(props) {
+        super(props);
+        this.state = props;
+        let oriState = props.state;
+        for (let key in oriState) {
+            this.state[key] = oriState[key];
+        }
+    }
+
+    getHeader() {
+        const { fontSize, header, prefixCls, columns } = this.state;
+        if (!header) {
+            return;
+        }
+        let helObj = header;
+        Object.assign(helObj.style, { fontSize: fontSize });
+        if (helObj) {
+            const headerEl = <thead className={`${prefixCls}-header`} key="form_header">
+                <tr>
+                    <td className={`${prefixCls}-header-content`} style={helObj.style} colSpan={'100%'}>{helObj.text}</td>
+                </tr>
+            </thead>;
+            return headerEl;
+        }
+    }
+
+    getContent() {
+        const { fontSize, prefixCls, fieldStyle, valueStyle } = this.state;
+        const { columns } = this.state;
+
+        let columnsData = this.getItemColumns();
+        const contentEl = <tbody style={{ fontSize: fontSize }} className={`${prefixCls}-content`} key="form_content">
+            {
+                columnsData.map((tr, i) => {return(
+                    <tr className={`${prefixCls}-tr`} key={`content_item_tr_${i}`}>
+                        {
+                            tr.map((td, i) => {
+                                let c = [];
+                                let colSpan = td.colSpan.replace('%','')/2 + '%';
+                                let field = td.render ? ((td.render(td.field.text, td.value.text)) ? td.render(td.field.text, td.value.text).field.text : '' ) : (typeof td.field === 'object' ? td.field.text : td.field);
+                                let value = td.render ? ((td.render(td.field.text, td.value.text)) ? td.render(td.field.text, td.value.text).value.text : '' ) : (typeof td.value === 'object' ? td.value.text : td.value);
+                                let currentFieldStyle = td.render ? ((td.render(td.field.text, td.value.text)) ? td.render(td.field.text, td.value.text).field.style : {} ) : (typeof td.field === 'object' ? (isEmptyObject(td.field.style) ? fieldStyle : td.field.style) : fieldStyle);
+                                let currentValueStyle = td.render ? ((td.render(td.field.text, td.value.text)) ? td.render(td.field.text, td.value.text).value.style : {} ) : (typeof td.value === 'object' ? (isEmptyObject(td.value.style) ? valueStyle : td.value.style) : valueStyle);
+                                
+                                return [
+                                    <td colSpan={colSpan} className={`${prefixCls}-item-field`} style={currentFieldStyle} > {field}</td>,
+                                    <td colSpan={colSpan} className={`${prefixCls}-item-value`} style={currentValueStyle} > {value}</td>
+                                ];
+                            })
+                        }
+
+                    </tr>
+                )})
+            }
+        </tbody>;
+        return contentEl;
+    }
+
+    getItemColumns() {
+        const { data, columns } = this.state;
+        let columnsData = [];
+        outer:
+        for (let i = 0; i < data.length;) {
+            let arr = [];
+            inner:
+            for (let j = 0; j < (columns < 0 ? 1 : columns) && i < data.length; j++) {
+                let w1 = data[i].width || 0;
+                arr.push(data[i]);
+                i++;
+                if (w1 >= 100) {
+                    break inner;
+                }
+            }
+            if (arr.length == 0) {
+                i++;
+            }
+            arr.map((a, x) => {
+                a.colSpan = `${100 / arr.length}%`
+            });
+            columnsData.push(arr);
+        }
+        return columnsData;
+    }
+
+    autoSize() {
+        let node = this.refs.body;
+        let thead = node.getElementsByTagName('thead')[0] || { offsetHeight: 0 };
+        let tbody = node.getElementsByTagName('tbody')[0];
+        if (tbody.offsetHeight + thead.offsetHeight <= (node.offsetHeight + 5)) {
+            return;
+        }
+        let trs = tbody.getElementsByTagName('tr');
+        let rowHeight = (node.offsetHeight - thead.offsetHeight) / trs.length;
+        for (let i = 0; i < trs.length; i++) {
+            trs[i].style.fontSize = `${rowHeight * .6}px`
+        };
+    }
+
+    componentDidMount() {
+        this.autoSize();
+    }
+
+    componentWillReceiveProps(nextProps) {
+        this.setState(nextProps, this.autoSize);
+    }
+
+    componentDidUpdate(prevProps) {
+    }
+
+    componentWillUnmount() {
+    }
+
+    render() {
+        const props = this.state;
+        const prefixCls = props.prefixCls;
+
+        let className = props.prefixCls;
+        if (props.cls) {
+            className += ` ${props.cls}`;
+        }
+
+        const header = this.getHeader();
+        const content = this.getContent();
+
+        return (
+            <div ref="body" className={className} style={props.style} key='form'>
+                <table className={`${prefixCls}-container`} style={props.style} key='form'>
+                    {header}
+                    {content}
+                </table>
+            </div>
+        );
+    }
+}

+ 3 - 0
kanban-client/app/src/Form/index.dev.js

@@ -0,0 +1,3 @@
+import Form from './Form.dev.jsx';
+
+export default Form;

+ 63 - 0
kanban-client/app/src/Title/Title.dev.jsx

@@ -0,0 +1,63 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import '../../assets/Title/index.less';
+
+export default class Title extends React.Component {
+  static propTypes = {
+    static: PropTypes.object,
+    prefixCls: PropTypes.string,
+    title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+    fontSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+  }
+
+  static defaultProps = {
+    prefixCls: 'rc-title',
+    title: '',
+    fontSize: 20
+  }
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+    };
+  }
+
+  componentDidMount() {
+    let height = this.getTitleHeight();
+    this.props.setTitleHeight(height);
+    
+  }
+  
+  componentWillReceiveProps(nextProps) {
+  }
+  
+  componentDidUpdate(prevProps) {
+    if(this.props.title == prevProps.title) {
+      return;
+    }
+    prevProps.setTitleHeight(this.getTitleHeight());
+  }
+
+  getTitle() {
+    const { title } = this.props;
+    return title;
+  }
+
+  getTitleHeight() {
+    return this.refs.title.offsetHeight;
+  }
+
+  render() {
+    const props = this.props;
+    const {prefixCls, fontSize} = props;
+
+    let className = prefixCls;
+
+    let title = this.getTitle();
+    return (
+      <div ref='title' className={className} key={prefixCls} dangerouslySetInnerHTML={{ __html: title }}>
+      </div>
+    );
+  }
+}

+ 4 - 0
kanban-client/app/src/Title/Title.jsx

@@ -32,6 +32,10 @@ export default class Title extends React.Component {
   }
 
   componentDidUpdate(prevProps) {
+    if(this.props.title == prevProps.title) {
+      return;
+    }
+    prevProps.setTitleHeight(this.getTitleHeight());
   }
 
   getTitle() {