├── .eslintignore
├── .gitignore
├── src
├── components
│ ├── login
│ │ ├── Login.less
│ │ └── Login.jsx
│ ├── sider
│ │ ├── Sider.less
│ │ └── Sider.jsx
│ ├── common
│ │ ├── Example.jsx
│ │ ├── CopyClipboard.jsx
│ │ ├── Common.less
│ │ ├── RetrieveForm.jsx
│ │ ├── Former.jsx
│ │ ├── UpdateForm.jsx
│ │ ├── CreateForm.jsx
│ │ ├── BDUploader.jsx
│ │ ├── CreateTextItem.jsx
│ │ ├── CreateFormItem.jsx
│ │ └── FeatureSetConfig.jsx
│ ├── main
│ │ ├── Main.less
│ │ └── Main.jsx
│ ├── header
│ │ ├── Header.jsx
│ │ └── Header.less
│ └── feature
│ │ ├── Feature2-2.jsx
│ │ ├── Feature2-1.jsx
│ │ ├── Feature3-1.jsx
│ │ ├── Feature1-6.jsx
│ │ ├── Feature3-2.jsx
│ │ ├── Feature1-1.jsx
│ │ ├── Feature1-2.jsx
│ │ ├── Feature1-1-1.jsx
│ │ ├── Feature1-3.jsx
│ │ ├── Feature1-4.jsx
│ │ ├── Feature1-5.jsx
│ │ ├── Feature5-2.jsx
│ │ ├── Feature5-1.jsx
│ │ ├── Feature3-3.jsx
│ │ └── Feature4-1.jsx
├── routes
│ ├── IndexPage.less
│ └── IndexPage.jsx
├── router.jsx
├── index.js
├── index.html
├── index.less
├── utils
│ └── util.js
└── config.js
├── proxy.config.js
├── .editorconfig
├── .eslintrc
├── package.json
├── webpack.config.js
├── mock
└── example.js
└── README.md
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/**/*-test.js
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/src/components/login/Login.less:
--------------------------------------------------------------------------------
1 | // sider 部分
2 | .sider {
3 | position: absolute;
4 | width: 240px;
5 | background-color: #f5f5f5;
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/src/components/sider/Sider.less:
--------------------------------------------------------------------------------
1 | // sider 部分
2 | .sider {
3 | position: absolute;
4 | width: 240px;
5 | background-color: #f5f5f5;
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/src/routes/IndexPage.less:
--------------------------------------------------------------------------------
1 | // 无权限样式
2 | .nopermission{
3 | font-size: 20px;
4 | font-weight: bold;
5 | color: #333;
6 | padding: 50px;
7 | text-align: center;
8 | }
--------------------------------------------------------------------------------
/proxy.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mock = {};
4 |
5 | require('fs').readdirSync(require('path').join(__dirname + '/mock'))
6 | .forEach(function (file) {
7 | Object.assign(mock, require('./mock/' + file));
8 | });
9 |
10 | module.exports = mock;
11 |
--------------------------------------------------------------------------------
/src/components/common/Example.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | // Stateless Functional Component
4 | const Example = (props) => {
5 | return (
6 |
7 | Example
8 |
9 | );
10 | };
11 |
12 | Example.propTypes = {
13 | };
14 |
15 | export default Example;
16 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/src/components/login/Login.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Menu, Icon } from 'antd';
3 | import { Link } from 'dva/router';
4 |
5 | function Login(props){
6 | return
7 | 您暂无权限处理该系统工作,请先
8 |
登录
9 | 或者找相关人员申请权限。
10 |
;
11 | };
12 |
13 | export default Login;
14 |
--------------------------------------------------------------------------------
/src/components/main/Main.less:
--------------------------------------------------------------------------------
1 | // main 部分
2 | .mainer {
3 | margin-left: 239px;
4 | border-left: 1px solid #e9e9e9;
5 |
6 | .title {
7 | padding: 15px 20px;
8 | border-bottom: 1px solid #ddd;
9 | }
10 |
11 | .item {
12 | position: relative;
13 | padding: 40px 30px;
14 | border-bottom: 1px solid #e6e6e6;
15 | }
16 | }
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/router.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { Router, Route} from 'dva/router';
3 | import IndexPage from './routes/IndexPage';
4 |
5 | // router 路由配置 可使用链接放置参数数据
6 | export default function({ history }) {
7 | return (
8 |
9 |
10 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file CMS平台主文件
3 | * @author niyingfeng
4 | * @doc https://github.com/dvajs/dva/blob/master/README_zh-CN.md
5 | */
6 |
7 | import './index.html';
8 | import './index.less';
9 | import dva from 'dva';
10 |
11 | // 1. Initialize
12 | const app = dva();
13 |
14 | // 2. Plugins
15 | // app.use({});
16 |
17 | // 3. Model
18 | // app.model(require('./models/example'));
19 |
20 | // 4. Router
21 | app.router(require('./router'));
22 |
23 | // 5. Start
24 | app.start('#root');
25 |
--------------------------------------------------------------------------------
/src/components/main/Main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Menu, Icon } from 'antd';
3 | import { Link } from 'dva/router'
4 |
5 | const Main = (props) => {
6 |
7 | let Feature = props.feature;
8 |
9 | return
10 | {
11 | props.title ?
12 |
{props.title}
:
13 | ''
14 | }
15 |
16 |
17 | }
18 |
19 | export default Main;
20 |
--------------------------------------------------------------------------------
/src/components/common/CopyClipboard.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 复制拷贝按钮
3 | */
4 | import React from 'react';
5 | import { Button, message } from 'antd';
6 | import CopyToClipboard from 'react-copy-to-clipboard';
7 |
8 | // 百度浏览器特定文件上传组件
9 | const CopyClipboard = (props) => {
10 | return message.success('复制成功')}>
12 | {
13 | props.type === 'link'?
14 | {props.title}:
15 |
16 |
17 | }
18 | ;
19 | }
20 |
21 | export default CopyClipboard;
22 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "eslint-config-airbnb",
4 | "rules": {
5 | "spaced-comment": [0],
6 | "no-unused-vars": [0],
7 | "no-empty": [0],
8 | "react/wrap-multilines": [0],
9 | "react/no-multi-comp": [0],
10 | "no-constant-condition": [0],
11 | "react/jsx-no-bind": [0],
12 | "react/prop-types": [0],
13 | "arrow-body-style": [0],
14 | "react/prefer-stateless-function": [0],
15 | "semi": [0],
16 | "global-require": [0],
17 | "no-shadow": [0],
18 | "no-useless-computed-key": [0],
19 | "no-underscore-dangle": [0]
20 | },
21 | "ecmaFeatures": {
22 | "experimentalObjectRestSpread": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/common/Common.less:
--------------------------------------------------------------------------------
1 | // 通用组件样式集合
2 |
3 | .normal {
4 | margin-top: 20px;
5 | }
6 | .search, .normal {
7 | .ant-form-item {
8 | margin-right: 25px;
9 | margin-bottom: 15px;
10 | > label:after {
11 | content: ":";
12 | position: relative;
13 | top: -.5px;
14 | margin: 0 8px 0 2px;
15 | }
16 | }
17 | }
18 |
19 | .create {
20 | text-align: right;
21 |
22 | > button {
23 | margin: 20px 0;
24 | }
25 |
26 | &:after {
27 | content: " ";
28 | display: table;
29 | clear: both;
30 | }
31 | }
32 |
33 | .uploadImg{
34 | max-width: 300px;
35 | max-height: 400px;
36 | }
--------------------------------------------------------------------------------
/src/components/header/Header.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Affix, Menu, Icon } from 'antd';
3 | import { Link } from 'dva/router';
4 |
5 | const HeadMenuItemCreat = (items) => {
6 | return items.map(function(item){
7 | return {item.title}
8 | });
9 | };
10 |
11 | function Header(props){
12 | return
13 |
14 |
15 | {props.title}
16 |
17 | {
18 | props.menu ?
19 |
20 | {
21 | HeadMenuItemCreat(props.menu)
22 | }
23 |
:
24 | ""
25 | }
26 |
27 |

28 |
{props.name}
29 |
30 |
;
31 | };
32 |
33 | export default Header;
34 |
--------------------------------------------------------------------------------
/src/components/header/Header.less:
--------------------------------------------------------------------------------
1 | // header 部分
2 | .header {
3 | position: relative;
4 | z-index: 1;
5 | padding: 15px 15px 15px 25px;
6 | border-bottom: 1px solid #e9e9e9;
7 | background-color: #f5f5f5;
8 |
9 | h2{
10 | display: inline-block;
11 | margin-right: 50px;
12 | }
13 | .icon {
14 | position: relative;
15 | top: 1px;
16 | padding-right: 10px;
17 | }
18 | .head-menu{
19 | display: inline-block;
20 |
21 | a{
22 | display: inline-block;
23 | font-size: 14px;
24 | padding: 5px 10px;
25 | color: rgba(0, 0, 0, 0.65);
26 | }
27 | }
28 | .aver {
29 | position: absolute;
30 | top: 10px;
31 | right: 20px;
32 |
33 | img {
34 | display: inline-block;
35 | height: 40px;
36 | margin-right: 10px;
37 | border-radius: 20px;
38 | }
39 |
40 | span {
41 | position: relative;
42 | top: -13px;
43 | font-size: 16px;
44 | color: #666;
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/index.less:
--------------------------------------------------------------------------------
1 |
2 | @import "~antd/lib/style/themes/default";
3 | //阿里的cdn 对百度域名屏蔽 字体扔到百度自己的服务器上处理
4 | @icon-url: "http://webapp.bdstatic.com/webapp/libs/iconfont2/iconfont";
5 | @import "~antd/lib/style/core/index.less";
6 | @import "~antd/lib/style/components.less";
7 |
8 | @import "components/header/Header.less";
9 | @import "components/main/Main.less";
10 | @import "components/sider/Sider.less";
11 | @import "components/common/Common.less";
12 |
13 | @import "routes/IndexPage.less";
14 |
15 | html,
16 | body,
17 | #root {
18 | height: 100%;
19 | }
20 |
21 |
22 | // 全局从定义样式
23 | // 重置antd 关于table的部分样式
24 | .ant-table{
25 | table{
26 | text-align: center;
27 |
28 | img {
29 | display: block;
30 | max-height: 100px;
31 | margin: 0 auto;
32 | }
33 | }
34 |
35 | .ant-table-thead > tr > th{
36 | text-align: center;
37 | }
38 | }
39 |
40 | .ant-form-inline .ant-form-item {
41 | margin-right: 30px;
42 | }
43 |
44 | .formLayout {
45 | position: absolute;
46 | z-index: 999;
47 | top: 0;
48 | right: 0;
49 | bottom: 0;
50 | left: 0;
51 | text-align: center;
52 | background-color: rgba(255, 255, 255, .75);
53 | }
--------------------------------------------------------------------------------
/src/components/common/RetrieveForm.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Button } from 'antd';
3 |
4 | import CFormItem from './CreateFormItem';
5 |
6 | const FormItem = Form.Item;
7 |
8 | let RForm = React.createClass({
9 | render: function() {
10 | const self = this;
11 | const RType = this.props.RType;
12 | const { getFieldDecorator } = this.props.form;
13 | return RType ?
14 | (
15 |
25 |
):
26 | ;
27 | },
28 |
29 | handleRetrieve: function(){
30 | this.props.submit(this.props.form.getFieldsValue());
31 | }
32 | });
33 | RForm = Form.create()(RForm);
34 |
35 | export default RForm;
36 |
--------------------------------------------------------------------------------
/src/components/sider/Sider.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Menu, Icon } from 'antd';
3 | import { Link } from 'dva/router';
4 |
5 | const MenuItemCreat = (items) => {
6 | return items.map(function(item){
7 | if(item.items){
8 | let title = {item.icon ? (): ''}{item.title};
9 |
10 | return
11 | {
12 | MenuItemCreat(item.items)
13 | }
14 |
15 | }else{
16 | return
17 | {item.title}
18 |
19 | }
20 | });
21 | };
22 |
23 | function Sider(props){
24 | return
25 |
33 | ;
34 | };
35 |
36 | export default Sider;
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "entry": {
4 | "index": "./src/index.js"
5 | },
6 | "dependencies": {
7 | "antd": "^2.3.0",
8 | "babel-plugin-import": "^1.0.1",
9 | "bce-sdk-js": "^0.1.7",
10 | "components": "^0.1.0",
11 | "dva": "^1.0.0",
12 | "echarts-for-react": "^1.1.5",
13 | "font": "0.0.4",
14 | "immutable": "^3.8.1",
15 | "moment": "^2.15.2",
16 | "react": "^15.1.0",
17 | "react-copy-to-clipboard": "^4.2.3",
18 | "react-dom": "^15.1.0",
19 | "react-tinymce": "^0.5.1",
20 | "reqwest": "^2.0.5",
21 | "routes": "^2.1.0",
22 | "src": "^1.1.2"
23 | },
24 | "devDependencies": {
25 | "atool-build": "^0.7.6",
26 | "atool-test-mocha": "^0.1.5",
27 | "babel-plugin-dev-expression": "^0.2.1",
28 | "babel-plugin-dva-hmr": "^0.1.0",
29 | "babel-plugin-transform-runtime": "^6.9.0",
30 | "babel-runtime": "^6.9.2",
31 | "dora": "0.3.x",
32 | "dora-plugin-proxy": "^0.7.0",
33 | "dora-plugin-webpack": "0.6.x",
34 | "dora-plugin-webpack-hmr": "^0.1.0",
35 | "expect": "^1.20.2",
36 | "redbox-react": "^1.2.10"
37 | },
38 | "scripts": {
39 | "start": "dora --plugins \"proxy,webpack,webpack-hmr\"",
40 | "build": "atool-build",
41 | "test": "atool-test-mocha ./src/**/*-test.js"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/common/Former.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * form 创建工具
3 | * 自动化生成整体form表单元素
4 | * 包括 创建,更新,查询,普通表单等
5 | * 依赖 CreateFormItem
6 | */
7 |
8 | import React from 'react';
9 | import { Form, Button } from 'antd';
10 |
11 | import CFormItem from './CreateFormItem';
12 |
13 | let Former = React.createClass({
14 | getInitialState: function() {
15 | return {
16 |
17 | };
18 | },
19 |
20 | render: function() {
21 | const self = this;
22 | const fields = this.props.fields;
23 | const updateItem = this.props.updateItem || {};
24 |
25 | // 详情见antd form 文档
26 | const { getFieldDecorator } = this.props.form;
27 |
28 | return
29 |
38 |
39 | },
40 |
41 | handleUpdate: function(){
42 | this.props.submit(this.props.form.getFieldsValue());
43 | },
44 |
45 | handleReset: function() {
46 | this.props.form.resetFields();
47 | }
48 | });
49 | Former = Form.create()(Former);
50 |
51 | export default Former;
52 |
53 |
--------------------------------------------------------------------------------
/src/utils/util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file CMS平台Util 功能文件
3 | * @author niyingfeng
4 | */
5 | // 自定义的配置数据
6 | // 处理时间格式数据
7 | // 处理自定义链接参数数据
8 |
9 | export default {
10 | DateFormat: function (date, fmt) {
11 | if (typeof date === 'string') {
12 | date = new Date(date);
13 | }
14 |
15 | let o = {
16 | 'M+': date.getMonth() + 1, // 月份
17 |
18 | 'D+': date.getDate(), // 日
19 | 'd+': date.getDate(), // 日
20 |
21 | 'h+': date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, // 小时 12小时制
22 | 'H+': date.getHours(), // 小时
23 |
24 | 'm+': date.getMinutes(), // 分
25 | 's+': date.getSeconds(), // 秒
26 | 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
27 | 'S': date.getMilliseconds() // 毫秒
28 | };
29 |
30 | // 需要按位数进行显示
31 | if (/(y+)/i.test(fmt)) {
32 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
33 | }
34 |
35 | for (let k in o) {
36 | if (new RegExp('(' + k + ')').test(fmt)) {
37 | fmt = fmt.replace(RegExp.$1,
38 | (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
39 | }
40 |
41 | }
42 | return fmt;
43 | },
44 |
45 | ParamsFixed: function (str) {
46 | let pObj = {};
47 | let pArr = str.split('&');
48 | for (let i = pArr.length - 1; i >= 0 && pArr[i]; i--) {
49 | let dataArr = pArr[i].split('=');
50 | pObj[dataArr[0]] = dataArr[1];
51 | }
52 |
53 | return pObj;
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/src/routes/IndexPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { Componnet } from 'react';
2 | import ReactDom from 'react-dom';
3 |
4 | import { connect } from 'dva';
5 | import { Link } from 'dva/router';
6 |
7 | import config from '../config';
8 |
9 | import Header from '../components/header/Header';
10 | import Sider from '../components/sider/Sider';
11 | import Main from '../components/main/Main';
12 |
13 | import Login from '../components/login/Login';
14 |
15 | //const components = config.main.components;
16 | const headerInfo = {
17 | ...config.header,
18 | name: config.userInfo.name,
19 | aver: config.userInfo.aver
20 | }
21 |
22 | const siderInfo = { ...config.sider };
23 |
24 | const mainInfo = {
25 | style: config.sider.style
26 | }
27 |
28 | const IndexInfo = {
29 | permission: config.userInfo.permission,
30 | loginUrl: config.userInfo.loginUrl
31 | }
32 |
33 | const App = (props) => {
34 |
35 | let featureId = props.params.FeatureId || config.sider.selectedKey;
36 |
37 | let featureInfo = {
38 | featureId: featureId,
39 | params: props.params.params,
40 |
41 | feature: config.main.components[featureId].component,
42 | title: config.main.components[featureId].title,
43 | }
44 |
45 | if(IndexInfo.permission){
46 | return
47 |
48 |
49 |
50 |
51 | }else{
52 | return
53 |
54 |
55 | }
56 | }
57 |
58 | export default App;
59 |
--------------------------------------------------------------------------------
/src/components/feature/Feature2-2.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | const simple_conf = {
8 |
9 | type: 'simpleObject',
10 |
11 | initData: function(callback){
12 | // 模拟数据
13 | Reqwest({
14 | url: '/api/example3',
15 | data: {},
16 |
17 | type: 'json',
18 | success: function (data) {
19 | let object = data.data;
20 | object.key = object.docid;
21 |
22 | callback(object);
23 | }
24 | });
25 | },
26 |
27 | Update:function(data, callback){
28 | console.log(data);
29 | callback(data);
30 | },
31 |
32 | UType:[
33 | {
34 | name: 'docid',
35 | label: '唯一标识',
36 | type: 'string',
37 | placeholder: '请输入标示名称'
38 | },{
39 | name: 'title',
40 | label: '标题',
41 | type: 'string',
42 | placeholder: '请输入标示名称'
43 | },{
44 | name: 'link',
45 | label: '链接',
46 | type: 'string'
47 | },{
48 | name: 'date',
49 | label: '日期',
50 | type: 'date'
51 | },{
52 | name: 'image',
53 | label: '图片',
54 | type: 'imageUpload'
55 | }
56 | ],
57 |
58 | operate:[
59 | {
60 | text: '确认修改',
61 | type: 'update',
62 | style: {
63 | 'marginRight': '30px',
64 | 'marginLeft': '80px'
65 | }
66 | }, {
67 | text: '展示数据',
68 | callback: function(item){
69 | console.log(item)
70 | }
71 | }
72 | ]
73 |
74 |
75 | }
76 |
77 | const Feature1 = FeatureSetConfig(simple_conf);
78 |
79 | export default Feature1;
80 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file mock文件
3 | * @author dva
4 | */
5 | const fs = require('fs');
6 | const path = require('path');
7 |
8 | module.exports = function (webpackConfig, env) {
9 | webpackConfig.babel.plugins.push('transform-runtime');
10 |
11 | // Support hmr
12 | if (env === 'development') {
13 | webpackConfig.devtool = '#eval';
14 | webpackConfig.babel.plugins.push(['dva-hmr', {
15 | entries: [
16 | './src/index.js'
17 | ]
18 | }]);
19 | }
20 | else {
21 | webpackConfig.babel.plugins.push('dev-expression');
22 | }
23 |
24 | // 尼玛处理了好久!!!!!不懂webpack 胡乱注释
25 | // 使用css modules 确实非常爽 但是TMD 谁能帮我在使用 CSS Modules的情况下
26 | // 解决字体文件 包括对百度域名屏蔽的问题 只能舍弃 CSS Modules 来进行解决
27 | // Support CSS Modules
28 | // Parse all less files as css module.
29 | // webpackConfig.module.loaders.forEach(function (loader, index) {
30 | // if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.less$') > -1) {
31 | // loader.include = /node_modules/;
32 | // loader.test = /\.less$/;
33 | // }
34 |
35 | // if (loader.test.toString() === '/\\.module\\.less$/') {
36 | // loader.exclude = /node_modules/;
37 | // loader.test = /\.less$/;
38 | // }
39 |
40 | // if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.css$') > -1) {
41 | // loader.include = /node_modules/;
42 | // loader.test = /\.css$/;
43 | // }
44 |
45 | // if (loader.test.toString() === '/\\.module\\.css$/') {
46 | // loader.exclude = /node_modules/;
47 | // loader.test = /\.css$/;
48 | // }
49 |
50 | // });
51 |
52 | // webpackConfig.babel.plugins.push(['import', {
53 | // libraryName: 'antd',
54 | // style: 'css'
55 | // }]);
56 |
57 | return webpackConfig;
58 | };
59 |
--------------------------------------------------------------------------------
/src/components/common/UpdateForm.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Modal, message } from 'antd';
3 |
4 | import CFormItem from './CreateFormItem';
5 |
6 |
7 | let UForm = React.createClass({
8 | getInitialState: function() {
9 | return {
10 |
11 | };
12 | },
13 |
14 | render: function() {
15 | const self = this;
16 | const UType = this.props.UType;
17 | const updateItem = this.props.updateItem;
18 |
19 | // 详情见antd form 文档
20 | const { getFieldDecorator } = this.props.form;
21 | const formItemLayout = {
22 | labelCol: { span: 6 },
23 | wrapperCol: { span: 18 },
24 | };
25 |
26 | return UType ?
27 |
28 |
29 |
38 |
39 |
:
40 |
41 | },
42 |
43 | handleUpdate: function(){
44 | this.props.submit(this.props.form.getFieldsValue());
45 | },
46 |
47 | handleReset: function() {
48 | this.props.form.resetFields();
49 | },
50 |
51 | hideModal: function() {
52 | this.props.hideForm();
53 | this.handleReset();
54 | }
55 | });
56 | UForm = Form.create()(UForm);
57 |
58 | export default UForm;
59 |
--------------------------------------------------------------------------------
/src/components/feature/Feature2-1.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | const simple_conf = {
8 |
9 | type: 'simpleObject',
10 |
11 | initData: function(callback){
12 | // 模拟数据
13 | Reqwest({
14 | url: '/api/example3',
15 | data: {},
16 |
17 | type: 'json',
18 | success: function (data) {
19 | let object = data.data;
20 | object.key = object.docid;
21 |
22 | callback(object);
23 | }
24 | });
25 | },
26 |
27 |
28 | // {
29 | // title 显示表题
30 | // dataIndex 显示数据中的key
31 | // type 展现形式 (string image link)
32 | // render 自定义展现形式 参数 (当前数据,当前对象数据)
33 | // }
34 |
35 | columns:[
36 | {
37 | title: '唯一标识',
38 | dataIndex: 'docid',
39 | type: 'string'
40 | },{
41 | title: '标题',
42 | dataIndex: 'title',
43 | type: 'string'
44 | },{
45 | title: '链接',
46 | dataIndex: 'link',
47 | type: 'link'
48 | // render: (text) => (
49 | // {text}
50 | // )
51 | },{
52 | title: '日期',
53 | dataIndex: 'date',
54 | type: 'string'
55 | },{
56 | title: '图片',
57 | dataIndex: 'image',
58 | type: 'image'
59 | }
60 | ],
61 |
62 | operate:[
63 | {
64 | text: '编辑数据',
65 | style: {
66 | 'marginLeft': '80px'
67 | },
68 | callback: function(item){
69 | console.log(item);
70 | location.hash = '#Feature2-2';
71 | }
72 | }
73 | ]
74 | }
75 |
76 | const Feature = FeatureSetConfig(simple_conf);
77 |
78 | export default Feature;
79 |
--------------------------------------------------------------------------------
/src/components/feature/Feature3-1.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | const graph_conf = {
8 |
9 | type: 'graphList', // tableList graphList simpleObject complexObject
10 |
11 | EchartStyle: {
12 | width: '100%',
13 | height: '450px'
14 | },
15 |
16 | // 初始化展现的数据,使用callback 回传列表数据
17 | // 需要手动添加唯一id key
18 | // callback 组件数据的回调函数(接受列表数据参数)
19 | initData: function(callback){
20 |
21 | // 参考echarts 参数
22 | var option = {
23 | title: {
24 | text: '堆叠区域图'
25 | },
26 | tooltip : {
27 | trigger: 'axis'
28 | },
29 | legend: {
30 | data:['邮件营销','联盟广告','视频广告']
31 | },
32 | toolbox: {
33 | feature: {
34 | saveAsImage: {}
35 | }
36 | },
37 | grid: {
38 | left: '3%',
39 | right: '4%',
40 | bottom: '3%',
41 | containLabel: true
42 | },
43 | xAxis : [
44 | {
45 | type : 'category',
46 | boundaryGap : false,
47 | data : ['周一','周二','周三','周四','周五','周六','周日']
48 | }
49 | ],
50 | yAxis : [
51 | {
52 | type : 'value'
53 | }
54 | ]
55 | }
56 |
57 | // 模拟数据
58 | Reqwest({
59 | url: '/api/example4',
60 | data: {},
61 |
62 | type: 'json',
63 | success: function (data) {
64 | option.series = data.data;
65 | option.series.forEach(function(item) {
66 | item.type = 'line';
67 | item.stack = '总量';
68 | });
69 |
70 | callback(option);
71 | }
72 | });
73 | }
74 |
75 | };
76 |
77 | const Feature = FeatureSetConfig(graph_conf);
78 |
79 | export default Feature;
80 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-6.jsx:
--------------------------------------------------------------------------------
1 | // 含有可操作 table 栏的数据展示
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 |
8 | const conf = {
9 |
10 | type: 'tableList',
11 |
12 | // 初始化页面的数据 回调函数传入 items 列表
13 | initData: function(callback){
14 |
15 | Reqwest({
16 | url: '/api/example',
17 | data: {},
18 |
19 | type: 'json',
20 | success: function (data) {
21 | let list = data.data;
22 | let i = 0;
23 | list.forEach(function(ele) {
24 | ele.key = i++;
25 | });
26 | callback(list);
27 | }
28 | });
29 |
30 | },
31 |
32 | // table 表单字段
33 | columns: [
34 | {
35 | title: 'KEY', // table header 文案
36 | dataIndex: 'key', // 数据对象内的属性,也做react vdom 的key
37 | type: 'string', // table 内显示的类型
38 | sort: true, // 是否需要排序
39 | }, {
40 | title: '标题',
41 | dataIndex: 'title',
42 | type: 'string'
43 | }, {
44 | title: '链接',
45 | dataIndex: 'link',
46 | type: 'link'
47 | }, {
48 | title: '操作',
49 | type: 'operate', // 操作的类型必须为 operate
50 | btns: [{
51 | text: 'console输出',
52 | callback: function(item){
53 | console.log(item)
54 | }
55 | },{
56 | text: '删除',
57 | type: 'delete'
58 | }], // 可选
59 | }
60 | ],
61 | // 删除操作
62 | Delete: function(data, callback){
63 | // 删除操作
64 | console.log(data);
65 |
66 | Reqwest({
67 | url: '/api/delete',
68 | data: {},
69 |
70 | type: 'json',
71 | success: function (data) {
72 | // 模拟请求删除成功的回调
73 | callback();
74 | }
75 | });
76 |
77 | }
78 |
79 | };
80 |
81 | const Feature = FeatureSetConfig(conf);
82 |
83 | export default Feature;
84 |
--------------------------------------------------------------------------------
/src/components/feature/Feature3-2.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | const graph_conf2 = {
8 |
9 | type: 'graphList', // tableList graphList simpleObject complexObject
10 | style: {
11 | width: '100%',
12 | height: '450px'
13 | },
14 |
15 | // 初始化展现的数据,使用callback 回传列表数据
16 | // 需要手动添加唯一id key
17 | // callback 组件数据的回调函数(接受列表数据参数)
18 | // 将回调数据掺入option
19 | initData: function(callback){
20 |
21 | // 参考echarts 参数
22 | var option = {
23 | title : {
24 | text: '某站点用户访问来源',
25 | subtext: '纯属虚构',
26 | x:'center'
27 | },
28 | tooltip : {
29 | trigger: 'item',
30 | formatter: "{a}
{b} : {c} ({d}%)"
31 | },
32 | legend: {
33 | orient: 'vertical',
34 | left: 'left',
35 | data: ['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
36 | }
37 | }
38 |
39 | // 模拟数据
40 | setTimeout(function(){
41 | option.series = [
42 | {
43 | name: '访问来源',
44 | type: 'pie',
45 | radius : '55%',
46 | center: ['50%', '60%'],
47 | data:[
48 | {value:335, name:'直接访问'},
49 | {value:310, name:'邮件营销'},
50 | {value:234, name:'联盟广告'},
51 | {value:135, name:'视频广告'},
52 | {value:1548, name:'搜索引擎'}
53 | ],
54 | itemStyle: {
55 | emphasis: {
56 | shadowBlur: 10,
57 | shadowOffsetX: 0,
58 | shadowColor: 'rgba(0, 0, 0, 0.5)'
59 | }
60 | }
61 | }
62 | ]
63 |
64 | callback(option);
65 | }, 500)
66 | }
67 |
68 | };
69 |
70 | const Feature = FeatureSetConfig(graph_conf2);
71 |
72 | export default Feature;
73 |
--------------------------------------------------------------------------------
/src/components/common/CreateForm.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Modal, Button } from 'antd';
3 |
4 | import CFormItem from './CreateFormItem';
5 |
6 | let CForm = React.createClass({
7 | getInitialState: function() {
8 | return { visible: false };
9 | },
10 |
11 | render: function() {
12 | const self = this;
13 | const CType = this.props.CType;
14 |
15 | const { getFieldDecorator } = this.props.form;
16 | const formItemLayout = {
17 | labelCol: { span: 6 },
18 | wrapperCol: { span: 18 },
19 | };
20 |
21 | return CType ?
22 |
23 |
24 |
25 |
33 |
34 |
:
35 |
36 | },
37 |
38 | handleCreate: function(){
39 |
40 | console.log('收到表单值:', this.props.form.getFieldsValue());
41 |
42 | this.props.form.validateFields((errors, values) => {
43 | if (!!errors) {
44 | console.log('Errors in form!!!');
45 | return;
46 | }else{
47 | console.log('Submit!!!');
48 | this.props.submit(values);
49 | this.hideModal();
50 | }
51 | });
52 | //this.props.submit(this.props.form.getFieldsValue());
53 |
54 | },
55 |
56 | handleReset: function() {
57 | this.props.form.resetFields();
58 | },
59 |
60 | showModal: function() {
61 | this.setState({ visible: true });
62 | },
63 |
64 | hideModal: function() {
65 | this.setState({ visible: false });
66 | this.handleReset();
67 | }
68 | });
69 |
70 | CForm = Form.create()(CForm);
71 |
72 | export default CForm;
73 |
--------------------------------------------------------------------------------
/src/components/common/BDUploader.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 百度图片上传react组件
3 | * 参数为 success 回调函数
4 | *
5 | */
6 |
7 | // 对于各个项目 重新定义图片上线组件接口 调整回调形式
8 |
9 | import React from 'react';
10 | import { Button, Icon, message } from 'antd';
11 | import baidubce from 'bce-sdk-js';
12 |
13 | let config = {
14 | endpoint: 'http://bj.bcebos.com', //传入Bucket所在区域域名
15 | credentials: {
16 | ak: '******', //您的AccessKey
17 | sk: '******' //您的SecretAccessKey
18 | }
19 | };
20 |
21 | let client = new baidubce.BosClient(config);
22 |
23 | const createKey = function(ext){
24 | let date = new Date();
25 |
26 | let year = date.getFullYear();
27 | let month = date.getMonth()+1;
28 | month = (month < 10) ? '0' + month: month;
29 |
30 | let day = date.getDate();
31 | day = (day < 10) ? '0' + day: day;
32 |
33 | return year + '/' + month + '/' + day + '/' + (+new Date())+ '.'+ext;
34 | }
35 |
36 | // 百度浏览器特定文件上传组件
37 | let BDUploader = React.createClass({
38 | getInitialState: function() {
39 | return {
40 |
41 | };
42 | },
43 |
44 | render: function() {
45 | return
46 |
49 |
50 |
;
51 | },
52 |
53 | openFileInput: function(e){
54 | this.refs.fileInput.click();
55 | },
56 | uploadImg: function(e){
57 | let self = this;
58 |
59 | let file = e.target.files[0]; // 获取要上传的文件
60 | let ext = file.name.split(/\./g).pop();
61 |
62 | let key = createKey(ext); // 保存到bos时的key,您可更改,默认以文件名作为key
63 | let mimeType = baidubce.MimeType.guess(ext);
64 |
65 | client.putObjectFromBlob("mbrowser", key, file, {
66 | 'Content-Type': /^text\//.test(mimeType)? mimeType+'; charset=UTF-8': mimeType
67 | }).then(function (res) {
68 | // 上传完成,添加您的代码
69 | let imgUrl = config.endpoint+'/v1/mbrowser/'+key;
70 | console.log('上传成功', imgUrl);
71 | self.props.success&&self.props.success(imgUrl);
72 | }).catch(function (err) {
73 | // 上传失败,添加您的代码
74 | self.props.error&&self.props.error(error);
75 | });
76 | }
77 | });
78 |
79 | export default BDUploader;
80 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-1.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | //import testData from '../common/test-data';
8 |
9 | // 增加(Create)、重新取得数据(Retrieve)、更新(Update)和删除(Delete)
10 | const table_conf = {
11 |
12 | type: 'tableList', // tableList graphList simpleObject complexObject
13 |
14 | // 初始化展现的数据,使用callback 回传列表数据
15 | // 需要手动添加唯一id key
16 | // callback 组件数据的回调函数(接受列表数据参数)
17 | initData: function(callback){
18 | // 接口调用数据形式
19 | Reqwest({
20 | url: '/api/example',
21 | data: {},
22 |
23 | type: 'json',
24 | success: function (data) {
25 | let list = data.data;
26 | list.forEach(function(ele) {
27 | ele.key = ele.id;
28 | });
29 | callback(list);
30 | }
31 | });
32 | },
33 |
34 | // table 列表展现配置
35 | // {
36 | // title table显示表题
37 | // dataIndex 显示数据中的key
38 | // type 展现形式 (string image link)
39 | // render 自定义展现形式 参数 (当前数据,当前对象数据)
40 | // sort 是否需要排序功能
41 | // width 自定义该列宽度 否则等分
42 | // }
43 | //
44 | // table 列表头标题
45 | columns: [
46 | {
47 | title: 'ID', // table header 文案
48 | dataIndex: 'id', // 数据对象内的属性,也做react vdom 的key
49 | type: 'string', // table 内显示的类型
50 | sort: true, // 是否需要排序
51 | },{
52 | title: 'DOCID', // table header 文案
53 | dataIndex: 'docid', // 数据对象内的属性,也做react vdom 的key
54 | type: 'string', // table 内显示的类型
55 | sort: true, // 是否需要排序
56 | }, {
57 | title: '来源',
58 | dataIndex: 'source',
59 | type: 'string'
60 | },{
61 | title: '标题',
62 | dataIndex: 'title',
63 | type: 'string'
64 | }, {
65 | title: '链接',
66 | dataIndex: 'link',
67 | type: 'link',
68 | render: (text) => (
69 | 链接
70 | ),
71 | },{
72 | title: '日期',
73 | dataIndex: 'date',
74 | type: 'string',
75 | },
76 | {
77 | title: '图片',
78 | dataIndex: 'image',
79 | type: 'image'
80 | }
81 | ]
82 |
83 | };
84 |
85 | const Feature = FeatureSetConfig(table_conf);
86 |
87 | export default Feature;
88 |
--------------------------------------------------------------------------------
/src/components/common/CreateTextItem.jsx:
--------------------------------------------------------------------------------
1 | // 普通数据展现的创建 目前只用于simple object 的数据展现
2 |
3 | import React from 'react';
4 | import moment from 'moment';
5 | import { Form, Select, Input, Button, Icon , DatePicker, TimePicker, Radio, Switch, Cascader, Checkbox } from 'antd';
6 | import { Upload, Modal, message } from 'antd';
7 |
8 | import BDUploader from './BDUploader';
9 |
10 | const FormItem = Form.Item;
11 | const Option = Select.Option;
12 | const RadioGroup = Radio.Group;
13 |
14 | let CTextItem = React.createClass({
15 | getInitialState: function() {
16 | return {
17 | img_url:''
18 | };
19 | },
20 |
21 | render: function() {
22 | const formItemLayout = this.props.formItemLayout || {};
23 | const item = this.props.item || {};
24 |
25 | if(item.render){
26 | return
30 |
31 | {item.render(item.value)}
32 |
33 | }else{
34 | switch (item.type){
35 | case 'string':
36 | return
40 |
41 | {item.value}
42 |
43 | break;
44 |
45 | case 'link':
46 | return
50 |
51 | {item.value}
52 |
53 |
54 | break;
55 |
56 | case 'image':
57 | return
61 |
62 | {item.value}
63 |
64 |
65 |
66 | break;
67 |
68 | default:
69 | return ;
70 | break;
71 | }
72 | }
73 |
74 | }
75 | });
76 |
77 | export default CTextItem;
78 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-2.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 | import Reqwest from 'reqwest';
4 |
5 | import CopyClipboard from '../common/CopyClipboard';
6 | import FeatureSetConfig from '../common/FeatureSetConfig';
7 |
8 | // 增加(Create)、重新取得数据(Retrieve)、更新(Update)和删除(Delete)
9 | const table_conf = {
10 |
11 | type: 'tableList', // tableList graphList simpleObject complexObject
12 |
13 | // 初始化展现的数据,使用callback 回传列表数据
14 | // 需要手动添加唯一id key
15 | // callback 组件数据的回调函数(接受列表数据参数)
16 | initData: function(callback){
17 | Reqwest({
18 | url: '/api/example2',
19 | data: {},
20 |
21 | type: 'json',
22 | success: function (data) {
23 | let list = data.data;
24 | list.forEach(function(ele) {
25 | ele.key = ele.id;
26 | });
27 | callback(list);
28 | }
29 | });
30 | },
31 |
32 | // table 列表展现配置
33 | // {
34 | // title table显示表题
35 | // dataIndex 显示数据中的key
36 | // type 展现形式 (string image link)
37 | // render 自定义展现形式 参数 (当前数据,当前对象数据)
38 | // sort 是否需要排序功能
39 | // width 自定义该列宽度 否则等分
40 | // }
41 | //
42 | // table 列表头标题
43 | columns: [
44 | {
45 | title: 'ID', // table header 文案
46 | dataIndex: 'id', // 数据对象内的属性,也做react vdom 的key
47 | type: 'string', // table 内显示的类型
48 | sort: true, // 是否需要排序
49 | width: 50
50 | },{
51 | title: 'NID', // table header 文案
52 | dataIndex: 'nid', // 数据对象内的属性,也做react vdom 的key
53 | type: 'string', // table 内显示的类型
54 | width: 180
55 | }, {
56 | title: '新闻标题',
57 | dataIndex: 'title',
58 | type: 'string',
59 |
60 | },{
61 | title: '落地页链接',
62 | render: (text, item) => ( 落地页链接),
63 | width: 80
64 | },{
65 | title: '最后修改时间',
66 | dataIndex: 'update_time',
67 | type: 'string',
68 | width: 150
69 | },{
70 | title: '操作',
71 | type: 'operate', // 操作的类型必须为 operate
72 | width: 150,
73 | btns: [{
74 | text: 'console输出',
75 | callback: function(item){
76 | console.log(item)
77 | }
78 | },{
79 | render: (text, item) => ()
80 | }],
81 | }
82 | ]
83 |
84 | };
85 |
86 | const Feature = FeatureSetConfig(table_conf);
87 |
88 | export default Feature;
89 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-1-1.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 | import Reqwest from 'reqwest';
4 |
5 | import CopyClipboard from '../common/CopyClipboard';
6 | import FeatureSetConfig from '../common/FeatureSetConfig';
7 |
8 | // 增加(Create)、重新取得数据(Retrieve)、更新(Update)和删除(Delete)
9 | const table_conf = {
10 |
11 | type: 'tableList', // tableList graphList simpleObject complexObject
12 |
13 | // 接口分页处理
14 | // callback 回传列表数据 第二参数接受 总数与每页数目
15 | // 需要手动添加唯一id key
16 | pageData: function(num, callback){
17 | Reqwest({
18 | url: '/api/example2',
19 | data: {
20 | page:num,
21 | pageSize: 20
22 | },
23 |
24 | type: 'json',
25 | success: function (data) {
26 | let list = data.data;
27 | list.forEach(function(ele) {
28 | ele.key = ele.id;
29 | });
30 | callback(list, {
31 | total: 399,
32 | pageSize: 20
33 | });
34 | }
35 | });
36 | },
37 |
38 | // table 列表展现配置
39 | // {
40 | // title table显示表题
41 | // dataIndex 显示数据中的key
42 | // type 展现形式 (string image link)
43 | // render 自定义展现形式 参数 (当前数据,当前对象数据)
44 | // sort 是否需要排序功能
45 | // width 自定义该列宽度 否则等分
46 | // }
47 | //
48 | // table 列表头标题
49 | columns: [
50 | {
51 | title: 'ID', // table header 文案
52 | dataIndex: 'id', // 数据对象内的属性,也做react vdom 的key
53 | type: 'string', // table 内显示的类型
54 | sort: true, // 是否需要排序
55 | width: 50
56 | },{
57 | title: 'NID', // table header 文案
58 | dataIndex: 'nid', // 数据对象内的属性,也做react vdom 的key
59 | type: 'string', // table 内显示的类型
60 | width: 180
61 | }, {
62 | title: '新闻标题',
63 | dataIndex: 'title',
64 | type: 'string',
65 |
66 | },{
67 | title: '落地页链接',
68 | render: (text, item) => ( 落地页链接),
69 | width: 80
70 | },{
71 | title: '最后修改时间',
72 | dataIndex: 'update_time',
73 | type: 'string',
74 | width: 150
75 | },{
76 | title: '操作',
77 | type: 'operate', // 操作的类型必须为 operate
78 | width: 150,
79 | btns: [{
80 | text: 'console输出',
81 | callback: function(item){
82 | console.log(item)
83 | }
84 | },{
85 | render: (text, item) => ()
86 | }],
87 | }
88 | ]
89 |
90 | };
91 |
92 | const Feature = FeatureSetConfig(table_conf);
93 |
94 | export default Feature;
95 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-3.jsx:
--------------------------------------------------------------------------------
1 | // 含有可操作 table 栏的数据展示
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 |
8 | const conf = {
9 |
10 | type: 'tableList',
11 |
12 | // 初始化页面的数据 回调函数传入 items 列表
13 | initData: function(callback){
14 |
15 | Reqwest({
16 | url: '/api/example',
17 | data: {},
18 |
19 | type: 'json',
20 | success: function (data) {
21 | let list = data.data;
22 | let i = 0;
23 | list.forEach(function(ele) {
24 | ele.key = i++;
25 | });
26 | callback(list);
27 | }
28 | });
29 |
30 | },
31 |
32 | // table 表单字段
33 | columns: [
34 | {
35 | title: 'KEY', // table header 文案
36 | dataIndex: 'key', // 数据对象内的属性,也做react vdom 的key
37 | type: 'string', // table 内显示的类型
38 | sort: true, // 是否需要排序
39 | }, {
40 | title: '标题',
41 | dataIndex: 'title',
42 | type: 'string'
43 | }, {
44 | title: '链接',
45 | dataIndex: 'link',
46 | type: 'link'
47 | }, {
48 | title: '操作',
49 | type: 'operate', // 操作的类型必须为 operate
50 | btns: [{
51 | text: 'console输出',
52 | callback: function(item){
53 | console.log(item)
54 | }
55 | }], // 可选
56 | }
57 | ],
58 |
59 | // 可设置的查询字段
60 | RType:[
61 | {
62 | name: 'id',
63 | label: '唯一标识',
64 | type: 'string',
65 | placeholder: '请输入标示名称'
66 | },{
67 | name: 'date',
68 | label: '项目开始时间',
69 | type: 'date'
70 | },{
71 | name: 'stype',
72 | label: '项目类型Select',
73 | type: 'select',
74 | defaultValue: 'one',
75 | options:[{
76 | text: '选项一',
77 | value: 'one'
78 | },{
79 | text: '选项二',
80 | value: 'two'
81 | },{
82 | text: '选项三',
83 | value: 'three'
84 | }]
85 | },{
86 | name: 'rtype',
87 | label: '项目类型Radio',
88 | type: 'radio',
89 | defaultValue: 'one',
90 | options:[{
91 | text: '选项一',
92 | value: 'one'
93 | },{
94 | text: '选项二',
95 | value: 'two'
96 | },{
97 | text: '选项三',
98 | value: 'three'
99 | }]
100 | },{
101 | name: 'ischange',
102 | label: '是否过滤',
103 | type: 'switch',
104 | defaultValue: false
105 | }
106 |
107 | ],
108 | // 查询操作回调
109 | Retrieve: function(data, callback){
110 |
111 | console.log(data);
112 |
113 | Reqwest({
114 | url: '/api/example2',
115 | data: {},
116 |
117 | type: 'json',
118 | success: function (data) {
119 | let list = data.data;
120 | let i = 0;
121 | list.forEach(function(ele) {
122 | ele.key = i++;
123 | });
124 |
125 | // 查询成功 传入列表数据
126 | callback(list);
127 | }
128 | });
129 | }
130 |
131 | };
132 |
133 | const Feature = FeatureSetConfig(conf);
134 |
135 | export default Feature;
136 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-4.jsx:
--------------------------------------------------------------------------------
1 | // 含有可操作 table 栏的数据展示
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 |
6 | import Immutable from 'immutable';
7 | import Reqwest from 'reqwest';
8 |
9 |
10 | const conf = {
11 |
12 | type: 'tableList',
13 |
14 | // 初始化页面的数据 回调函数传入 items 列表
15 | initData: function(callback){
16 |
17 | // 接口调用数据形式
18 | Reqwest({
19 | url: '/api/oneList',
20 | data: {},
21 |
22 | type: 'json',
23 | success: function (data) {
24 | let list = data.data;
25 | list.forEach(function(ele) {
26 | ele.key = ele.id;
27 | });
28 | callback(list);
29 | }
30 | });
31 |
32 | },
33 |
34 | columns: [
35 | {
36 | title: 'ID',
37 | dataIndex: 'id',
38 | type: 'string'
39 | }, {
40 | title: '邮箱',
41 | dataIndex: 'email',
42 | type: 'string'
43 | }, {
44 | title: '日期',
45 | dataIndex: 'date',
46 | type: 'string'
47 | },{
48 | title: '图片',
49 | dataIndex: 'image',
50 | type: 'image'
51 | },{
52 | title: 'ischange',
53 | dataIndex: 'ischange',
54 | type: 'string'
55 | },{
56 | title: 'rtype',
57 | dataIndex: 'rtype',
58 | type: 'string'
59 | },{
60 | title: 'stype',
61 | dataIndex: 'stype',
62 | type: 'string'
63 | },
64 | ],
65 |
66 | // 模拟添加数据的接口 回调
67 | Create: function(data, callback){
68 |
69 | // ... 操作添加数据的请求
70 | console.log(data);
71 |
72 | // 需要设置key
73 | data.key = data.id;
74 | data.date = data.date.format("YYYY-MM-DD hh:mm:ss");
75 | // 模拟请求创建成功的回调
76 | setTimeout(function(){
77 | callback(data);
78 | }, 1000);
79 | },
80 |
81 |
82 | // 创建项目所需的字段 与 更新项目所需的字段
83 | // rules 规范可见 https://github.com/yiminghe/async-validator
84 | CType: [
85 | {
86 | name: 'id',
87 | label: '唯一标识',
88 | type: 'string',
89 | placeholder: '请输入标示名称',
90 | rules: [{ required: true, min: 5, message: '用户名至少为 5 个字符' }]
91 | },{
92 | name: 'email',
93 | label: '唯一标识',
94 | type: 'string',
95 | placeholder: '请输入标示名称',
96 | rules: [{ required: true, type: 'email', message: '请输入正确的邮箱地址' }]
97 | },{
98 | name: 'date',
99 | label: '项目开始时间',
100 | type: 'date',
101 | },{
102 | name: 'stype',
103 | label: '项目类型Select',
104 | type: 'select',
105 | defaultValue: 'one',
106 | options:[{
107 | text: '选项一',
108 | value: 'one'
109 | },{
110 | text: '选项二',
111 | value: 'two'
112 | },{
113 | text: '选项三',
114 | value: 'three'
115 | }]
116 | },{
117 | name: 'rtype',
118 | label: '项目类型Radio',
119 | type: 'radio',
120 | defaultValue: 'one',
121 | options:[{
122 | text: '选项一',
123 | value: 'one'
124 | },{
125 | text: '选项二',
126 | value: 'two'
127 | },{
128 | text: '选项三',
129 | value: 'three'
130 | }]
131 | },{
132 | name: 'ischange',
133 | label: '是否过滤',
134 | type: 'switch'
135 | },{
136 | name: 'image',
137 | label: '背景图片',
138 | type: 'imageUpload'
139 | }
140 | ]
141 |
142 | };
143 |
144 | const Feature = FeatureSetConfig(conf);
145 |
146 | export default Feature;
147 |
--------------------------------------------------------------------------------
/src/components/feature/Feature1-5.jsx:
--------------------------------------------------------------------------------
1 | // 含有可操作 table 栏的数据展示
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 |
6 | import Immutable from 'immutable';
7 | import Reqwest from 'reqwest';
8 |
9 | const conf = {
10 |
11 | type: 'tableList',
12 |
13 | // 初始化页面的数据 回调函数传入 items 列表
14 | initData: function(callback){
15 |
16 | // 接口调用数据形式
17 | Reqwest({
18 | url: '/api/oneList',
19 | data: {},
20 |
21 | type: 'json',
22 | success: function (data) {
23 | let list = data.data;
24 | list.forEach(function(ele) {
25 | ele.key = ele.id;
26 | });
27 | callback(list);
28 | }
29 | });
30 |
31 | },
32 |
33 | columns: [
34 | {
35 | title: 'ID',
36 | dataIndex: 'id',
37 | type: 'string'
38 | }, {
39 | title: '邮箱',
40 | dataIndex: 'email',
41 | type: 'string'
42 | }, {
43 | title: '日期',
44 | dataIndex: 'date',
45 | type: 'string'
46 | },{
47 | title: '图片',
48 | dataIndex: 'image',
49 | type: 'image'
50 | },{
51 | title: 'ischange',
52 | dataIndex: 'ischange',
53 | type: 'string'
54 | },{
55 | title: 'rtype',
56 | dataIndex: 'rtype',
57 | type: 'string'
58 | },{
59 | title: 'stype',
60 | dataIndex: 'stype',
61 | type: 'string'
62 | },{
63 | title: '操作',
64 | type: 'operate', // 操作的类型必须为 operate
65 | btns: [{
66 | text: '更新',
67 | type: 'update'
68 | },{
69 | text: '展示',
70 | callback: function(item){
71 | console.log(item)
72 | }
73 | }], // 可选
74 |
75 | }
76 | ],
77 |
78 |
79 | Update:function(data, callback){
80 | console.log(data);
81 |
82 | // 这块请求更新数据 成功回调
83 | data.key = data.id;
84 | callback(data);
85 | },
86 |
87 |
88 | // 创建项目所需的字段 与 更新项目所需的字段
89 | // rules 规范可见 https://github.com/yiminghe/async-validator
90 | UType: [
91 | {
92 | name: 'id',
93 | label: '唯一标识',
94 | type: 'string',
95 | placeholder: '请输入标示名称',
96 | rules: [{ required: true, min: 5, message: '用户名至少为 5 个字符' }]
97 | },{
98 | name: 'email',
99 | label: '唯一标识',
100 | type: 'string',
101 | placeholder: '请输入标示名称',
102 | rules: [{ required: true, type: 'email', message: '请输入正确的邮箱地址' }]
103 | },{
104 | name: 'date',
105 | label: '项目开始时间',
106 | type: 'date',
107 | },{
108 | name: 'stype',
109 | label: '项目类型Select',
110 | type: 'select',
111 | defaultValue: 'one',
112 | options:[{
113 | text: '选项一',
114 | value: 'one'
115 | },{
116 | text: '选项二',
117 | value: 'two'
118 | },{
119 | text: '选项三',
120 | value: 'three'
121 | }]
122 | },{
123 | name: 'rtype',
124 | label: '项目类型Radio',
125 | type: 'radio',
126 | defaultValue: 'one',
127 | options:[{
128 | text: '选项一',
129 | value: 'one'
130 | },{
131 | text: '选项二',
132 | value: 'two'
133 | },{
134 | text: '选项三',
135 | value: 'three'
136 | }]
137 | },{
138 | name: 'ischange',
139 | label: '是否过滤',
140 | type: 'switch'
141 | },{
142 | name: 'image',
143 | label: '背景图片',
144 | type: 'imageUpload'
145 | }
146 | ]
147 |
148 | };
149 |
150 | const Feature = FeatureSetConfig(conf);
151 |
152 | export default Feature;
153 |
--------------------------------------------------------------------------------
/src/components/feature/Feature5-2.jsx:
--------------------------------------------------------------------------------
1 | // 具体文档参照 Tinymce
2 | import React from 'react';
3 | import Reqwest from 'reqwest';
4 |
5 | import BDUploader from '../common/BDUploader';
6 | import CFormItem from '../common/CreateFormItem';
7 |
8 | import { Form, Input, Button } from 'antd';
9 |
10 | const FormItem = Form.Item;
11 |
12 | let Feature = React.createClass({getInitialState: function(){
13 | return {
14 | imgUrl: '',
15 | valueString: ''
16 | }
17 | },
18 | render: function() {
19 |
20 | let fields = [
21 | {
22 | name: 'string',
23 | label: '唯一标识',
24 | type: 'string',
25 | placeholder: '请输入标示名称'
26 | },{
27 | name: 'date',
28 | label: '开始时间',
29 | type: 'date'
30 | },{
31 | name: 'select',
32 | label: '项目类型',
33 | type: 'select',
34 | defaultValue: 'one',
35 | options:[{
36 | text: '选项一',
37 | value: 'one'
38 | },{
39 | text: '选项二',
40 | value: 'two'
41 | },{
42 | text: '选项三',
43 | value: 'three'
44 | }]
45 | },{
46 | name: 'cascader',
47 | label: '项目类型',
48 | type: 'cascader',
49 | options:[{
50 | value: 'zhejiang',
51 | label: 'Zhejiang',
52 | children: [{
53 | value: 'hangzhou',
54 | label: 'Hangzhou',
55 | children: [{
56 | value: 'xihu',
57 | label: 'West Lake',
58 | }],
59 | }],
60 | },{
61 | value: 'jiangsu',
62 | label: 'Jiangsu',
63 | children: [{
64 | value: 'nanjing',
65 | label: 'Nanjing',
66 | children: [{
67 | value: 'zhonghuamen',
68 | label: 'Zhong Hua Men',
69 | }],
70 | }],
71 | }]
72 | },{
73 | name: 'checkbox',
74 | label: '项目类型',
75 | type: 'checkbox',
76 | defaultValue: ['Apple'],
77 | options:[
78 | { label: 'Apple', value: 'Apple' },
79 | { label: 'Pear', value: 'Pear' },
80 | { label: 'Orange', value: 'Orange' }]
81 | },{
82 | name: 'radio',
83 | label: '项目类型',
84 | type: 'radio',
85 | defaultValue: 'one',
86 | options:[{
87 | text: '选项一',
88 | value: 'one'
89 | },{
90 | text: '选项二',
91 | value: 'two'
92 | },{
93 | text: '选项三',
94 | value: 'three'
95 | }]
96 | },{
97 | name: 'switch',
98 | label: '是否过滤',
99 | type: 'switch',
100 | defaultValue: false
101 | }
102 | ];
103 |
104 | const { getFieldDecorator } = this.props.form;
105 |
106 | return
107 |
114 |
115 |
123 |
124 |
125 |
126 |
{this.state.imgUrl}
127 |
128 |
129 |
130 |
131 |
132 |
133 |
{this.state.valueString}
134 |
135 | },
136 |
137 | getFromData: function(){
138 | console.log(this.props.form.getFieldsValue());
139 |
140 | this.setState({
141 | valueString:JSON.stringify(this.props.form.getFieldsValue())
142 | });
143 | },
144 |
145 | uploadImgSuccess: function(url){
146 | this.setState({
147 | imgUrl:url
148 | });
149 | },
150 | });
151 |
152 | Feature = Form.create()(Feature);
153 | export default Feature;
--------------------------------------------------------------------------------
/src/components/feature/Feature5-1.jsx:
--------------------------------------------------------------------------------
1 | // 具体文档参照 Tinymce
2 | import React from 'react';
3 | import TinyMCE from 'react-tinymce';
4 | import Reqwest from 'reqwest';
5 |
6 | // import BDUploader from '../common/BDUploader';
7 | // import CFormItem from '../common/CreateFormItem';
8 |
9 | import { Form, Input, Button } from 'antd';
10 |
11 | // const FormItem = Form.Item;
12 |
13 | let Feature = React.createClass({
14 | getInitialState: function(){
15 | return {
16 | value: ''
17 | }
18 | },
19 | render: function() {
20 | let config = {
21 | content: this.state.value,
22 | config: {
23 | height: '250',
24 | plugins: [
25 | "advlist autolink lists charmap print preview hr anchor pagebreak spellchecker",
26 | "searchreplace wordcount visualblocks visualchars fullscreen insertdatetime nonbreaking",
27 | "save table contextmenu directionality emoticons paste textcolor"
28 | ],
29 | toolbar: "insertfile undo redo | styleselect fontselect fontsizeselect| bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | l | print preview fullpage | forecolor backcolor",
30 | },
31 | onChange: this.handleEditorChange
32 | };
33 |
34 | // let fields = [
35 | // {
36 | // name: 'id',
37 | // label: '唯一标识',
38 | // type: 'string',
39 | // placeholder: '请输入标示名称'
40 | // },{
41 | // name: 'date',
42 | // label: '开始时间',
43 | // type: 'date'
44 | // },{
45 | // name: 'stype',
46 | // label: '项目类型',
47 | // type: 'select',
48 | // defaultValue: 'one',
49 | // options:[{
50 | // text: '选项一',
51 | // value: 'one'
52 | // },{
53 | // text: '选项二',
54 | // value: 'two'
55 | // },{
56 | // text: '选项三',
57 | // value: 'three'
58 | // }]
59 | // },{
60 | // name: 'rtype',
61 | // label: '项目类型',
62 | // type: 'radio',
63 | // defaultValue: 'one',
64 | // options:[{
65 | // text: '选项一',
66 | // value: 'one'
67 | // },{
68 | // text: '选项二',
69 | // value: 'two'
70 | // },{
71 | // text: '选项三',
72 | // value: 'three'
73 | // }]
74 | // },{
75 | // name: 'ischange',
76 | // label: '是否过滤',
77 | // type: 'switch',
78 | // defaultValue: false
79 | // }
80 |
81 | // ];
82 |
83 | // const { getFieldDecorator } = this.props.form;
84 | // const updateItem = {};
85 |
86 | // return
87 | //
101 |
102 | //
111 |
112 | //
113 | //
114 | //
{this.state.imgUrl}
115 | //
116 | //
{this.states.value}
117 | //
118 | //
119 |
120 | return
121 |
{this.state.value}
122 |
123 |
124 | },
125 |
126 | // getFromData: function(){
127 | // console.log(this.props.form.getFieldsValue())
128 | // },
129 |
130 | // uploadImgSuccess: function(url){
131 | // this.setState({
132 | // imgUrl:url
133 | // });
134 | // },
135 | handleEditorChange: function(e){
136 | this.setState({
137 | value: this.getTinymceContent()
138 | });
139 | },
140 | setTinymceContent: function(value){
141 | tinymce.get(0).setContent(value);
142 | },
143 | getTinymceContent: function(){
144 | return tinymce.get(0).getContent();
145 | }
146 | });
147 |
148 | export default Feature;
--------------------------------------------------------------------------------
/mock/example.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const oneDate = {
4 | bdsourceid: "311010007",
5 | categoryid: "1",
6 | stype: 'one',
7 | date: "2016-09-01 18:12:45",
8 | docid: "9547448815187683782",
9 | image: "https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2106183011,3024965378&fm=80&w=179&h=119&img.JPEG",
10 | link: "http://www.chinanews.com/sh/2016/09-01/7991310.shtml",
11 | source: "社会新闻",
12 | summary: "蔡某妍在其遗书中写下受骗经过,此前,蔡某妍手机接收到一条中奖短信,点进去填写了相关信息,并按照指引打电话给对方,对方让她交钱,蔡某妍拒绝交钱。",
13 | title: "开学前夕疑遭电信诈骗学费 揭阳准女大学生留遗书自杀",
14 | weight: "99",
15 | src_type: "text"
16 | }
17 |
18 | const table2List = [
19 | {
20 | id: "1",
21 | title: "111111互联网金融最强监管政策来袭,行业强化约束正本清源",
22 | link: "http://news.xhby.net/system/2016/09/18/029642755.shtml",
23 | nid: "13606399328377680923",
24 | insert_time: "2016-09-19 19:31:40",
25 | update_time: "2016-09-19 19:32:10"
26 | }, {
27 | id: "2",
28 | title: "互联网金融最强监管政策来袭,行业强化约束正本清源",
29 | link: "http://news.xhby.net/system/2016/09/18/029642755.shtml",
30 | nid: "13606399328377680923",
31 | insert_time: "2016-09-19 19:30:39",
32 | update_time: "2016-09-19 19:30:39"
33 | }, {
34 | id: "3",
35 | title: "互联网金融最强监管政策来袭,行业强化约束正本清源",
36 | link: "http://news.xhby.net/system/2016/09/18/029642755.shtml",
37 | nid: "13606399328377680923",
38 | insert_time: "2016-09-19 19:30:31",
39 | update_time: "2016-09-19 19:30:31"
40 | }, {
41 | id: "4",
42 | title: "互联网金融最强监管政策来袭,行业强化约束正本清源",
43 | link: "http://news.xhby.net/system/2016/09/18/029642755.shtml",
44 | nid: "13606399328377680923",
45 | insert_time: "2016-09-19 18:07:44",
46 | update_time: "2016-09-19 18:07:44"
47 | }, {
48 | id: "5",
49 | title: "互联网金融最强监管政策来袭,行业强化约束正本清源",
50 | link: "http://news.xhby.net/system/2016/09/18/029642755.shtml",
51 | nid: "13606399328377680923",
52 | insert_time: "2016-09-19 18:07:29",
53 | update_time: "2016-09-19 18:07:29"
54 | }
55 | ];
56 |
57 | const graphList = [
58 | {
59 | name: '邮件营销',
60 | data: [120, 132, 101, 134, 90, 230, 210]
61 | }, {
62 | name: '联盟广告',
63 | data: [220, 182, 191, 234, 290, 330, 310]
64 | }, {
65 | name: '视频广告',
66 | data: [150, 232, 201, 154, 190, 330, 410]
67 | }
68 | ];
69 |
70 | const simpleObject = {
71 | bdsourceid: "316010032",
72 | categoryid: "1",
73 | date: "2016-06-29 10:27:00",
74 | docid: "16112285443883430307",
75 | images: [{
76 | height: "533",
77 | img: "http://img.cbs.baidu.com/imagecache/reader/mid/9/c/d/9cd6e6f4c45f3d5dcdf7dc3846ed546c.jpg",
78 | imgsize: "400,533",
79 | width: "400"
80 | }, {
81 | height: "300",
82 | img: "http://img.cbs.baidu.com/imagecache/reader/mid/8/e/6/8e62b06541d752bd3719107a1f5f0496.jpg",
83 | imgsize: "400,300",
84 | width: "400"
85 | }, {
86 | height: "533",
87 | img: "http://img.cbs.baidu.com/imagecache/reader/mid/f/9/2/f92664dedc81ce5c2d83c28aeff66eed.jpg",
88 | imgsize: "400,533",
89 | width: "400"
90 | }],
91 | images_bos: [{
92 | height: "533",
93 | img: "http://image.cbs.baidu.com/news_topic/5170f148dbd81ecb680dd385cfd0c333.jpg",
94 | imgsize: "400,533",
95 | width: "400"
96 | }, {
97 | height: "300",
98 | img: "http://image.cbs.baidu.com/news_topic/8e62b06541d752bd3719107a1f5f0496.jpg",
99 | imgsize: "400,300",
100 | width: "400"
101 | }, {
102 | height: "533",
103 | img: "http://image.cbs.baidu.com/news_topic/f92664dedc81ce5c2d83c28aeff66eed.jpg",
104 | imgsize: "400,533",
105 | width: "400"
106 | }],
107 | img: "http://img.cbs.baidu.com/imagecache/reader/mid/9/c/d/9cd6e6f4c45f3d5dcdf7dc3846ed546c.jpg",
108 | imgsize: "400,533",
109 | keyword: "",
110 | link: "http://news.ifeng.com/a/20160629/49259851_0.shtml",
111 | mark: "0",
112 | score: 89.52380952381,
113 | source: "凤凰新闻",
114 | src_type: "text",
115 | srctype: "0",
116 | summary: " 在谅解协议中,北青报记者看到,“鉴于被告人周凌俊在案发时有精神分裂症,控制能力差,并且开庭前积极赔偿给我全部损失(略),我对被告人周凌俊的行为表示谅解,请求法院对被告人周凌俊从轻、减轻、免除死刑刑事处罚…",
117 | title: "男子砍伤9人被判死刑 8受害人请求免除死刑(图)",
118 | topic_keyword: [{
119 | tag: "周凌俊",
120 | weight: 1
121 | }, {
122 | tag: "老周",
123 | weight: 0.52631578947368
124 | }, {
125 | tag: "北青报记者",
126 | weight: 0.50877192982456
127 | }],
128 | weight: "99",
129 | index: "1020",
130 | groupbegin: "0",
131 | listcount: 4
132 | };
133 |
134 | function createArrDate(data, times){
135 | let arr =[];
136 | for (; times >= 0; times--) {
137 | data.id = times;
138 | arr.push(JSON.parse(JSON.stringify(data)));
139 | }
140 | return arr;
141 | }
142 |
143 | module.exports = {
144 |
145 | 'GET /api/example': function (req, res) {
146 | setTimeout(function () {
147 | res.json({
148 | success: true,
149 | data: createArrDate(oneDate, 20),
150 | });
151 | }, 500);
152 | },
153 |
154 | 'GET /api/example2': function (req, res) {
155 | setTimeout(function () {
156 | res.json({
157 | success: true,
158 | data: table2List,
159 | });
160 | }, 500);
161 | },
162 |
163 | 'GET /api/example3': function (req, res) {
164 | setTimeout(function () {
165 | res.json({
166 | success: true,
167 | data: oneDate,
168 | });
169 | }, 500);
170 | },
171 |
172 | 'GET /api/example4': function (req, res) {
173 | setTimeout(function () {
174 | res.json({
175 | success: true,
176 | data: graphList,
177 | });
178 | }, 500);
179 | },
180 |
181 | 'GET /api/oneList': function (req, res) {
182 | setTimeout(function () {
183 | res.json({
184 | success: true,
185 | data: [{
186 | date:"2016-06-29 10:27:00",
187 | id:"ddassad",
188 | email:"asd@22.cn",
189 | image:"",
190 | ischange:"false",
191 | rtype:"one",
192 | stype:"one",
193 | }],
194 | });
195 | }, 500);
196 | },
197 |
198 | 'GET /api/delete': function (req, res) {
199 | setTimeout(function () {
200 | res.json({
201 | success: true
202 | });
203 | }, 500);
204 | },
205 |
206 | };
207 |
--------------------------------------------------------------------------------
/src/components/common/CreateFormItem.jsx:
--------------------------------------------------------------------------------
1 | // 表单独立项 用于对于表单字段的创建
2 |
3 |
4 | import React from 'react';
5 | import moment from 'moment';
6 | import { Form, Select, Input, Button, Icon , DatePicker, TimePicker, Radio, Switch, Cascader, Checkbox } from 'antd';
7 | import { Upload, Modal, message } from 'antd';
8 |
9 | import BDUploader from './BDUploader';
10 |
11 | const FormItem = Form.Item;
12 | const Option = Select.Option;
13 | const RadioGroup = Radio.Group;
14 |
15 | // 对于使用默认的时间戳
16 | const DefaultTime = new Date();
17 |
18 | let CFormItem = React.createClass({
19 | getInitialState: function() {
20 | return {
21 | img_url:''
22 | };
23 | },
24 |
25 | render: function() {
26 | const getFieldDecorator = this.props.getFieldDecorator;
27 | const formItemLayout = this.props.formItemLayout || {};
28 | const item = this.props.item || {};
29 |
30 | let defaultValue = item.defaultValue || '';
31 |
32 | switch (item.type){
33 | case 'string':
34 | return
38 |
39 | {getFieldDecorator(item.name, {rules:item.rules, initialValue:defaultValue})(
40 |
41 | )}
42 |
43 | break;
44 |
45 | case 'date':
46 | defaultValue = moment(defaultValue || DefaultTime, "YYYY-MM-DD hh:mm:ss");
47 |
48 | return
52 |
53 | {getFieldDecorator(item.name, { initialValue: defaultValue})(
54 |
55 | )}
56 |
57 | break;
58 |
59 | case 'select':
60 | return
64 |
65 | {getFieldDecorator(item.name, { initialValue: defaultValue })(
66 |
73 | )}
74 |
75 | break;
76 |
77 | case 'cascader':
78 | return
82 |
83 | {getFieldDecorator(item.name, { initialValue: defaultValue })(
84 |
85 | )}
86 |
87 |
88 | break;
89 |
90 | case 'radio':
91 | return
95 |
96 | {getFieldDecorator(item.name, { initialValue: defaultValue })(
97 |
98 | {
99 | item.options.map(function(item){
100 | return {item.text || item.value}
101 | })
102 | }
103 |
104 | )}
105 |
106 | break;
107 |
108 | case 'checkbox':
109 | return
113 |
114 | {getFieldDecorator(item.name, { initialValue: defaultValue })(
115 |
116 | )}
117 |
118 | break;
119 |
120 | case 'switch':
121 | return
125 |
126 | {getFieldDecorator(item.name, { initialValue: defaultValue})(
127 |
128 | )}
129 |
130 | break;
131 |
132 | case 'imageUpload':
133 | defaultValue = this.state.img_url || defaultValue || '';
134 | return
138 |
139 | {getFieldDecorator(item.name, { initialValue:defaultValue})(
140 |
141 | )}
142 |
143 |
144 |
145 |
146 |
147 | break;
148 |
149 | default:
150 | return '';
151 | break;
152 | }
153 | },
154 | uploadSuccess: function(url){
155 | console.log(url)
156 | this.setState({
157 | img_url: url
158 | })
159 | },
160 | changeImgUrl: function(e){
161 | console.log(e.target.value)
162 | this.setState({
163 | img_url: e.target.value
164 | })
165 | }
166 | });
167 |
168 | export default CFormItem;
169 |
--------------------------------------------------------------------------------
/src/components/feature/Feature3-3.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 |
7 | const graph_conf = {
8 |
9 | type: 'graphList', // tableList graphList simpleObject complexObject
10 |
11 | EchartStyle: {
12 | width: '100%',
13 | height: '450px'
14 | },
15 |
16 | // 初始化展现的数据,使用callback 回传列表数据
17 | // 需要手动添加唯一id key
18 | // callback 组件数据的回调函数(接受列表数据参数)
19 | initData: function(callback){
20 |
21 | // 参考echarts 参数
22 | var option = {
23 | title: {
24 | text: '堆叠区域图'
25 | },
26 | tooltip : {
27 | trigger: 'axis'
28 | },
29 | legend: {
30 | data:['邮件营销','联盟广告','视频广告']
31 | },
32 | toolbox: {
33 | feature: {
34 | saveAsImage: {}
35 | }
36 | },
37 | grid: {
38 | left: '3%',
39 | right: '4%',
40 | bottom: '3%',
41 | containLabel: true
42 | },
43 | xAxis : [
44 | {
45 | type : 'category',
46 | boundaryGap : false,
47 | data : ['周一','周二','周三','周四','周五','周六','周日']
48 | }
49 | ],
50 | yAxis : [
51 | {
52 | type : 'value'
53 | }
54 | ]
55 | }
56 |
57 | // 模拟数据
58 | Reqwest({
59 | url: '/api/example4',
60 | data: {},
61 |
62 | type: 'json',
63 | success: function (data) {
64 | option.series = data.data;
65 | option.series.forEach(function(item) {
66 | item.type = 'line';
67 | item.stack = '总量';
68 | });
69 |
70 | callback(option);
71 | }
72 | });
73 | }
74 |
75 | };
76 |
77 | const graph_conf2 = {
78 |
79 | type: 'graphList', // tableList graphList simpleObject complexObject
80 | style: {
81 | width: '100%',
82 | height: '450px'
83 | },
84 |
85 | // 初始化展现的数据,使用callback 回传列表数据
86 | // 需要手动添加唯一id key
87 | // callback 组件数据的回调函数(接受列表数据参数)
88 | // 将回调数据掺入option
89 | initData: function(callback){
90 |
91 | // 参考echarts 参数
92 | var option = {
93 | title : {
94 | text: '某站点用户访问来源',
95 | subtext: '纯属虚构',
96 | x:'center'
97 | },
98 | tooltip : {
99 | trigger: 'item',
100 | formatter: "{a}
{b} : {c} ({d}%)"
101 | },
102 | legend: {
103 | orient: 'vertical',
104 | left: 'left',
105 | data: ['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
106 | }
107 | }
108 |
109 | // 模拟数据
110 | setTimeout(function(){
111 | option.series = [
112 | {
113 | name: '访问来源',
114 | type: 'pie',
115 | radius : '55%',
116 | center: ['50%', '60%'],
117 | data:[
118 | {value:335, name:'直接访问'},
119 | {value:310, name:'邮件营销'},
120 | {value:234, name:'联盟广告'},
121 | {value:135, name:'视频广告'},
122 | {value:1548, name:'搜索引擎'}
123 | ],
124 | itemStyle: {
125 | emphasis: {
126 | shadowBlur: 10,
127 | shadowOffsetX: 0,
128 | shadowColor: 'rgba(0, 0, 0, 0.5)'
129 | }
130 | }
131 | }
132 | ]
133 |
134 | callback(option);
135 | }, 500)
136 | }
137 |
138 | };
139 |
140 | const graph_conf3 = {
141 |
142 | type: 'graphList', // tableList graphList simpleObject complexObject
143 | style: {
144 | width: '100%',
145 | height: '450px'
146 | },
147 |
148 | // 初始化展现的数据,使用callback 回传列表数据
149 | // 需要手动添加唯一id key
150 | // callback 组件数据的回调函数(接受列表数据参数)
151 | // 将回调数据掺入option
152 | initData: function(callback){
153 |
154 |
155 | var xAxisData = [];
156 | var data1 = [];
157 | var data2 = [];
158 | for (var i = 0; i < 100; i++) {
159 | xAxisData.push('类目' + i);
160 | data1.push((Math.sin(i / 5) * (i / 5 -10) + i / 6) * 5);
161 | data2.push((Math.cos(i / 5) * (i / 5 -10) + i / 6) * 5);
162 | }
163 |
164 | // 参考echarts 参数
165 | var option = {
166 | title: {
167 | text: '柱状图动画延迟'
168 | },
169 | legend: {
170 | data: ['bar', 'bar2'],
171 | align: 'left'
172 | },
173 | toolbox: {
174 | // y: 'bottom',
175 | feature: {
176 | magicType: {
177 | type: ['stack', 'tiled']
178 | },
179 | dataView: {},
180 | saveAsImage: {
181 | pixelRatio: 2
182 | }
183 | }
184 | },
185 | tooltip: {},
186 | xAxis: {
187 | data: xAxisData,
188 | silent: false,
189 | splitLine: {
190 | show: false
191 | }
192 | },
193 | yAxis: {
194 | },
195 | animationEasing: 'elasticOut',
196 | animationDelayUpdate: function (idx) {
197 | return idx * 5;
198 | }
199 | }
200 |
201 | // 模拟数据
202 | setTimeout(function(){
203 |
204 | option.series = [{
205 | name: 'bar',
206 | type: 'bar',
207 | data: data1,
208 | animationDelay: function (idx) {
209 | return idx * 10;
210 | }
211 | }, {
212 | name: 'bar2',
213 | type: 'bar',
214 | data: data2,
215 | animationDelay: function (idx) {
216 | return idx * 10 + 100;
217 | }
218 | }]
219 |
220 | callback(option);
221 | }, 500)
222 | }
223 |
224 | };
225 |
226 | const Feature1 = FeatureSetConfig(graph_conf);
227 | const Feature2 = FeatureSetConfig(graph_conf2);
228 | const Feature3 = FeatureSetConfig(graph_conf3);
229 |
230 | const Feature = (props) => {
231 | return
232 |
233 |
234 |
235 |
;
236 | }
237 |
238 | export default Feature;
239 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file CMS平台整体配置文件
3 | * @author niyingfeng
4 | *
5 | * header 管理后台头部配置
6 | * title String 标题
7 | * icon String 标题图标
8 | * style Object 自定义样式
9 | * menu Array 顶部横向菜单列表
10 | *
11 | * sider 管理后台侧栏配置
12 | * menu Array sider列表
13 | * openKeys Array 默认展开的sider区
14 | * selectedKey String 默认打开的功能区
15 | * style Object 自定义样式
16 | *
17 | * main 功能区域配置
18 | * components Object 配置sider对应功能区域组件
19 | * Feature1 Object 对应sider menu 中的功能key对 应功能组件
20 | * style Object 配置样式
21 | *
22 | * userInfo 登入用户信息
23 | * name 登入用户名
24 | * aver 登入用户头像
25 | * permission 是否权限
26 | * loginUrl 无权限时跳转的链接(对于一些通用登入权限系统)
27 | */
28 |
29 | const Config = {
30 | header: {
31 | title: '测试配置管理后台',
32 | icon: 'appstore',
33 | style: {
34 | backgroundColor: '#F5F5F5',
35 | color: '#666'
36 | },
37 | menu: [
38 | {title: '集合管理', key: 'bigset'}
39 | ]
40 | },
41 |
42 | sider: {
43 | menu: [
44 | {
45 | title: 'Table数据与功能展示',
46 | key: 'table',
47 | icon: 'bars',
48 | items: [
49 | {title: 'table数据展示前端分页', key: 'Feature1-1'},
50 | {title: 'table数据展示接口分页', key: 'Feature1-1-1'},
51 | {title: 'table数据展示项2', key: 'Feature1-2'},
52 | {title: 'table数据搜索数据操作', key: 'Feature1-3'},
53 | {title: 'table数据增加数据操作', key: 'Feature1-4'},
54 | {title: 'table数据修改数据操作', key: 'Feature1-5'},
55 | {title: 'table数据删除数据操作', key: 'Feature1-6'}
56 | ]
57 | },
58 | {
59 | title: 'simple对象数据与功能展示',
60 | key: 'object',
61 | icon: 'bars',
62 | items: [
63 | {title: 'simple对象数据展示项', key: 'Feature2-1'},
64 | {title: 'simple对象数据修改操作', key: 'Feature2-2'}
65 | ]
66 | },
67 | {
68 | title: '数据可视化功能展示',
69 | key: 'echarts',
70 | icon: 'bars',
71 | items: [
72 | {title: 'echarts 数据可视化1', key: 'Feature3-1'},
73 | {title: 'echarts 数据可视化2', key: 'Feature3-2'},
74 | {title: 'echarts 数据可视化3', key: 'Feature3-3'}
75 | ]
76 | },
77 | {
78 | title: '综合功能数据展示',
79 | key: 'complex',
80 | icon: 'bars',
81 | items: [
82 | {title: '综合数据展示', key: 'Feature4-1'}
83 | ]
84 | },
85 | {
86 | title: '综合自定义操作项目',
87 | key: 'customOperate',
88 | icon: 'bars',
89 | items: [
90 | {title: '富文本编辑功能展现', key: 'Feature5-1'},
91 | {title: '自组装FromUI组件方式', key: 'Feature5-2'}
92 | ]
93 | },
94 |
95 | // 格式示例
96 | // {
97 | // title: '导航1',
98 | // key: 'subTitle1',
99 | // icon: 'setting',
100 | // items: [
101 | // {title: '选项1', key: 'Feature1'},
102 | // {title: '选项2', key: 'Feature2'},
103 | // {title: '选项3', key: 'Feature3'},
104 | // {
105 | // title: '导航3',
106 | // key: 'subTitle3',
107 | // icon: ',
108 | // items: [
109 | // {title: '选项6', key: 'Feature6'},
110 | // {title: '选项7', key: 'Feature7'},
111 | // {title: '选项8', key: 'Feature8'}
112 | // ]
113 | // }
114 | // ]
115 | // },{
116 | // title: '导航2',
117 | // key: 'subTitle2',
118 | // icon: 'delete',
119 | // items: [
120 | // {title: '选项4', key: 'Feature4'}
121 | // ]
122 | // },{
123 | // title: '选项5',
124 | // key: 'Feature5'
125 | // }
126 |
127 | ],
128 | openKeys:['table','object','echarts','complex','customOperate'],
129 | selectedKey: 'Feature1-1',
130 | style: {}
131 | },
132 |
133 | main: {
134 | components: {
135 | 'bigset': {
136 | title: 'bigset 测试',
137 | component: require('./components/feature/Feature1-1')
138 | },
139 | 'Feature1-1': {
140 | title: 'table 普通列表数据展示 前端处理分页',
141 | component: require('./components/feature/Feature1-1')
142 | },
143 | 'Feature1-1-1': {
144 | title: 'table 普通列表数据展示 接口请求分页',
145 | component: require('./components/feature/Feature1-1-1')
146 | },
147 | 'Feature1-2': {
148 | title: 'table 具有相关操作数据展示',
149 | component: require('./components/feature/Feature1-2')
150 | },
151 | 'Feature1-3': {
152 | title: 'table 数据搜索数据操作',
153 | component: require('./components/feature/Feature1-3')
154 | },
155 | 'Feature1-4': {
156 | title: 'table 数据增加数据操作',
157 | component: require('./components/feature/Feature1-4')
158 | },
159 | 'Feature1-5': {
160 | title: 'table 数据更新数据操作',
161 | component: require('./components/feature/Feature1-5')
162 | },
163 | 'Feature1-6': {
164 | title: 'table 数据删除数据操作',
165 | component: require('./components/feature/Feature1-6')
166 | },
167 | 'Feature2-1': {
168 | title: 'simple对象 数据展示',
169 | component: require('./components/feature/Feature2-1')
170 | },
171 | 'Feature2-2': {
172 | title: 'simple对象数据修改操作',
173 | component: require('./components/feature/Feature2-2')
174 | },
175 | 'Feature3-1': {
176 | title: '数据可视化 数据展示',
177 | component: require('./components/feature/Feature3-1')
178 | },
179 | 'Feature3-2': {
180 | title: '数据可视化 数据展示',
181 | component: require('./components/feature/Feature3-2')
182 | },
183 | 'Feature3-3': {
184 | title: '数据可视化 数据展示',
185 | component: require('./components/feature/Feature3-3')
186 | },
187 | 'Feature4-1': {
188 | title: '综合数据展示',
189 | component: require('./components/feature/Feature4-1')
190 | },
191 | 'Feature5-1': {
192 | title: '富文本编辑区域',
193 | component: require('./components/feature/Feature5-1')
194 | },
195 | 'Feature5-2': {
196 | title: '自定义组装',
197 | component: require('./components/feature/Feature5-2')
198 | }
199 | },
200 | style: {}
201 | },
202 |
203 | userInfo:{
204 | name: BaiduInfo.name || '游客',
205 | aver: BaiduInfo.aver || 'http://himg.bdimg.com/sys/portrait/item/113e68695f79696e6766656e67525e.jpg',
206 | permission: BaiduInfo.permission,
207 | loginUrl: BaiduInfo.loginUrl
208 | }
209 | }
210 |
211 | export default Config;
--------------------------------------------------------------------------------
/src/components/feature/Feature4-1.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 |
4 | import FeatureSetConfig from '../common/FeatureSetConfig';
5 | import Reqwest from 'reqwest';
6 | import {message} from 'antd';
7 |
8 | const graph_conf = {
9 |
10 | type: 'graphList', // tableList graphList simpleObject complexObject
11 |
12 | EchartStyle: {
13 | width: '100%',
14 | height: '450px'
15 | },
16 |
17 | // 初始化展现的数据,使用callback 回传列表数据
18 | // 需要手动添加唯一id key
19 | // callback 组件数据的回调函数(接受列表数据参数)
20 | initData: function(callback){
21 |
22 | // 参考echarts 参数
23 | var option = {
24 | title: {
25 | text: '堆叠区域图'
26 | },
27 | tooltip : {
28 | trigger: 'axis'
29 | },
30 | legend: {
31 | data:['邮件营销','联盟广告','视频广告']
32 | },
33 | toolbox: {
34 | feature: {
35 | saveAsImage: {}
36 | }
37 | },
38 | grid: {
39 | left: '3%',
40 | right: '4%',
41 | bottom: '3%',
42 | containLabel: true
43 | },
44 | xAxis : [
45 | {
46 | type : 'category',
47 | boundaryGap : false,
48 | data : ['周一','周二','周三','周四','周五','周六','周日']
49 | }
50 | ],
51 | yAxis : [
52 | {
53 | type : 'value'
54 | }
55 | ]
56 | }
57 |
58 | // 模拟数据
59 | setTimeout(function(){
60 | option.series = testData.graphList;
61 | option.series.forEach(function(item) {
62 | item.type = 'line';
63 | item.stack = '总量'
64 | });
65 |
66 | callback(option);
67 | }, 1000)
68 | }
69 |
70 | };
71 |
72 | const graph_conf2 = {
73 |
74 | type: 'graphList', // tableList graphList simpleObject complexObject
75 | style: {
76 | width: '100%',
77 | height: '450px'
78 | },
79 |
80 | // 初始化展现的数据,使用callback 回传列表数据
81 | // 需要手动添加唯一id key
82 | // callback 组件数据的回调函数(接受列表数据参数)
83 | // 将回调数据掺入option
84 | initData: function(callback){
85 |
86 | // 参考echarts 参数
87 | var option = {
88 | title : {
89 | text: '某站点用户访问来源',
90 | subtext: '纯属虚构',
91 | x:'center'
92 | },
93 | tooltip : {
94 | trigger: 'item',
95 | formatter: "{a}
{b} : {c} ({d}%)"
96 | },
97 | legend: {
98 | orient: 'vertical',
99 | left: 'left',
100 | data: ['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
101 | }
102 | }
103 |
104 | // 模拟数据
105 | setTimeout(function(){
106 | option.series = [
107 | {
108 | name: '访问来源',
109 | type: 'pie',
110 | radius : '55%',
111 | center: ['50%', '60%'],
112 | data:[
113 | {value:335, name:'直接访问'},
114 | {value:310, name:'邮件营销'},
115 | {value:234, name:'联盟广告'},
116 | {value:135, name:'视频广告'},
117 | {value:1548, name:'搜索引擎'}
118 | ],
119 | itemStyle: {
120 | emphasis: {
121 | shadowBlur: 10,
122 | shadowOffsetX: 0,
123 | shadowColor: 'rgba(0, 0, 0, 0.5)'
124 | }
125 | }
126 | }
127 | ]
128 |
129 | callback(option);
130 | }, 1000)
131 | }
132 |
133 | };
134 |
135 | const graph_conf3 = {
136 |
137 | type: 'graphList', // tableList graphList simpleObject complexObject
138 | style: {
139 | width: '100%',
140 | height: '450px'
141 | },
142 |
143 | // 初始化展现的数据,使用callback 回传列表数据
144 | // 需要手动添加唯一id key
145 | // callback 组件数据的回调函数(接受列表数据参数)
146 | // 将回调数据掺入option
147 | initData: function(callback){
148 |
149 |
150 | var xAxisData = [];
151 | var data1 = [];
152 | var data2 = [];
153 | for (var i = 0; i < 100; i++) {
154 | xAxisData.push('类目' + i);
155 | data1.push((Math.sin(i / 5) * (i / 5 -10) + i / 6) * 5);
156 | data2.push((Math.cos(i / 5) * (i / 5 -10) + i / 6) * 5);
157 | }
158 |
159 | // 参考echarts 参数
160 | var option = {
161 | title: {
162 | text: '柱状图动画延迟'
163 | },
164 | legend: {
165 | data: ['bar', 'bar2'],
166 | align: 'left'
167 | },
168 | toolbox: {
169 | // y: 'bottom',
170 | feature: {
171 | magicType: {
172 | type: ['stack', 'tiled']
173 | },
174 | dataView: {},
175 | saveAsImage: {
176 | pixelRatio: 2
177 | }
178 | }
179 | },
180 | tooltip: {},
181 | xAxis: {
182 | data: xAxisData,
183 | silent: false,
184 | splitLine: {
185 | show: false
186 | }
187 | },
188 | yAxis: {
189 | },
190 | animationEasing: 'elasticOut',
191 | animationDelayUpdate: function (idx) {
192 | return idx * 5;
193 | }
194 | }
195 |
196 | // 模拟数据
197 | setTimeout(function(){
198 |
199 | option.series = [{
200 | name: 'bar',
201 | type: 'bar',
202 | data: data1,
203 | animationDelay: function (idx) {
204 | return idx * 10;
205 | }
206 | }, {
207 | name: 'bar2',
208 | type: 'bar',
209 | data: data2,
210 | animationDelay: function (idx) {
211 | return idx * 10 + 100;
212 | }
213 | }]
214 |
215 | callback(option);
216 | }, 1000)
217 | }
218 |
219 | };
220 |
221 | const table_conf = {
222 |
223 | type: 'tableList', // tableList graphList simpleObject complexObject
224 |
225 | // 初始化展现的数据,使用callback 回传列表数据
226 | // 需要手动添加唯一id key
227 | // callback 组件数据的回调函数(接受列表数据参数)
228 | initData: function(callback){
229 |
230 | // 模拟数据
231 | Reqwest({
232 | url: '/api/example',
233 | data: {},
234 |
235 | type: 'json',
236 | success: function (data) {
237 | let list = data.data;
238 | list.forEach(function(ele) {
239 | ele.key = Math.random();
240 | });
241 | callback(list);
242 | }
243 | });
244 | },
245 |
246 | columns: [
247 | {
248 | title: 'DOCID', // table header 文案
249 | dataIndex: 'docid', // 数据对象内的属性,也做react vdom 的key
250 | type: 'string', // table 内显示的类型
251 | sort: true, // 是否需要排序
252 | width:200
253 | }, {
254 | title: '标题',
255 | dataIndex: 'title',
256 | type: 'string'
257 | }, {
258 | title: '链接',
259 | dataIndex: 'link',
260 | type: 'link',
261 | render: (text) => (
262 | 链接
263 | ),
264 | width: 50
265 | },{
266 | title: '日期',
267 | dataIndex: 'date',
268 | type: 'string',
269 | width: 150
270 | },{
271 | title: '图片',
272 | dataIndex: 'img',
273 | type: 'image'
274 | }
275 | ]
276 |
277 | };
278 |
279 | const Feature1 = FeatureSetConfig(graph_conf2);
280 | const Feature2 = FeatureSetConfig(graph_conf3);
281 | const Feature3 = FeatureSetConfig(table_conf);
282 |
283 | const Feature = (props) => {
284 |
285 | return
286 |
287 |
288 |
289 |
290 | }
291 |
292 | export default Feature;
293 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # antd-auto (2.0版本建设中!!! 在1.0基础上扩展自定义形式的复杂性组件)
2 |
3 | 前端自动化配置搭建CMS系统框架。解决前端CMS系统开发成本问题,释放前端开发资源。
4 |
5 | ## 特性
6 |
7 | - 基于 dva 脚手架 [dva文档](https://github.com/dvajs/dva)
8 | - 基于 antd 2.0 UI组件 [ant.design文档](https://ant.design/docs/react/introduce)
9 | - 通过全局配置文件和页面配置文件,实现CMS系统的配置化开发
10 | - 开发与业务逻辑剥离,所见即所得,开发人员仅需提供数据以及传递数据,完全不涉及数据与UI操作上的处理
11 | - 特殊性功能可自实现开发处理
12 |
13 | ## 项目介绍
14 |
15 | 1. 实现前端只需提供数据便可以实现各种数据展现,包括table,simple objest,以及各类图形展现(引入echarts)
16 | 2. 提供数据操作接口,前端只需关心数据的接受与传递,便可以实现数据的增删改查,而无需再关心CMS内部的实现。暂时实现 table数据的增删改查,simple object数据的修改等
17 | 3. 在以上全自动话的基础上,可以实现自定义组装页面,目前功能包括,图片上传组件(需要正对自己项目调整接口),富文本编辑器(Tinymce),复制功能,antd UI 组件等。
18 |
19 | ## Start
20 |
21 | 克隆本项目,npm install 安装依赖,npm start 开始本地调试项目 开启 http://localhost:8989/便可以看到整体 DEMO 项目
22 |
23 | ## Build
24 | npm Build 开始构建压缩
25 | 如果 alicdn 对部分域名有访问限制,或者需要内网环境使用 在部署上线的时候需要注意下载字体自行部署
26 | 本项目修改 index.less 的 @font-face 即可
27 |
28 | 
29 |
30 | ## 目录结构
31 |
32 | ```bash
33 | ├── /mock/ # mock的接口文件
34 | ├── /dist/ # 项目构建输出目录
35 | ├── /src/ # 项目开发源码目录
36 | │ ├── /components/ # 项目组件
37 | │ │ ├── /common/ # 通用集成组件
38 | │ │ ├── /feature/ # 页面配置文件 (主要配置文件)
39 | │ │ ├── /login/ # 登录组件
40 | │ │ ├── /header/ # 头部组件
41 | │ │ ├── /main/ # 主体组件
42 | │ │ └── /sider/ # 边栏组件
43 | │ │
44 | │ ├── /routes/ # 路由组件
45 | │ ├── /utils/ # 工具函数
46 | │ ├── router.jsx # 路由配置
47 | │ ├── index.jsx # 入口文件
48 | │ ├── index.less # 样式主体文件
49 | │ ├── config.js # 全局配置文件(主要配置文件)
50 | │ └── index.html
51 | │
52 | ├── package.json # 项目信息
53 | └── proxy.config.js # 数据mock配置
54 | ```
55 |
56 | ## 功能列表
57 | - [ ] 登录页面
58 | - [x] table数据
59 | - [x] 展现配置化实现
60 | - [x] 查询配置化实现
61 | - [x] 新增配置化实现
62 | - [x] 更新配置化实现
63 | - [x] 删除配置化实现
64 | - [x] 对象数据
65 | - [x] 展现配置化实现
66 | - [x] 更新配置化实现
67 | - [x] 可视化图表
68 | - [x] 基于echarts的数据可视化配置实现
69 | - [x] 富文本编辑器
70 | - [x] 通用图片上传组件(须自行调整)
71 | - [x] 复制粘贴功能
72 |
73 |
74 | ## 整站配置文件详解
75 |
76 | ### src/config.js
77 |
78 | 需配置整体的后台系统数据,以及自定义的配置数据
79 |
80 | **header 管理系统头部配置(必要属性)**
81 |
82 | * title 管理系统显示的标题
83 | * icon 管理系统显示的icon可在 [icon](https://ant.design/components/icon/) 查看
84 | * style 自定义设置头部样式
85 |
86 | ```
87 | // header 示例
88 | header: {
89 | title: "测试配置管理后台",
90 | icon: "appstore",
91 | style: {
92 | padding: "15px 15px 15px 25px",
93 | borderBottom: "1px solid #E9E9E9",
94 | backgroundColor: "#F5F5F5"
95 | }
96 | }
97 | ```
98 |
99 | 
100 |
101 | **sider 管理后台侧栏配置(必要属性)**
102 |
103 | * menu sider列表 实现单层or多层级展现
104 | - title 展现的title
105 | - key sider中对应的选项(若为菜单主项,则在openKeys中使用选择是否打开,若为功能项,则对应 selectedKey,以及 main 中 components 值)
106 | - icon 展现的icon选项(可选)
107 | - items 功能栏目列表(可选 可设置多层结构)
108 |
109 | * openKeys 默认展开的sider主导航项目(对应menu项目主栏目中的key)
110 | * selectedKey 默认打开的目标功能页面key(对应menu项目功能栏目中的key)
111 | * style 自定义样式
112 |
113 | ```
114 | // sider 边栏导航配置示例
115 | sider: {
116 | // 层级列表
117 | menu: [
118 | {
119 | // 多级
120 | title: "导航1", // 主导航名称
121 | key: "subTitle1",
122 | icon: "setting",
123 | items: [
124 | {title: "选项1", key: "Feature1"},
125 | {title: "选项2", key: "Feature2"},
126 | {title: "选项3", key: "Feature3"},
127 | {
128 | title: "导航3",
129 | key: "subTitle3",
130 | icon: "",
131 | items: [
132 | {title: "选项6", key: "Feature6"},
133 | {title: "选项7", key: "Feature7"},
134 | {title: "选项8", key: "Feature8"}
135 | ]
136 | }
137 | ]
138 | },{
139 | // 单级
140 | title: "选项5",
141 | key: "Feature5"
142 | }
143 | ],
144 | // 默认打开的导航项目
145 | openKeys:['subTitle1'],
146 |
147 | // 默认功能页
148 | selectedKey: "Feature1",
149 |
150 | // 自定义样式
151 | style: {
152 | backgroundColor: "#F5F5F5"
153 | }
154 | }
155 | ```
156 |
157 | 
158 |
159 | **main 功能区域配置**
160 |
161 | * components 配置sider对应功能区域组件
162 | - FeatureKey Object 对应sider menu 中的功能key对应功能组件
163 |
164 | * title 功能区域标题显示名称
165 | * component 加载对应功能区域的feature模块
166 | * style 配置样式
167 |
168 | ```
169 | // main 示例
170 | main: {
171 | components: {
172 | // key 值对应 sider item中功能选项的 key
173 | "Feature1": {
174 | // 功能区域标题显示名称
175 | title: 'table 数据展示',
176 | // require 加载对应功能区域的feature模块
177 | component: require('./components/feature/Feature1')
178 | },
179 | "Feature2": {
180 | title: 'simple对象 数据展示',
181 | component: require('./components/feature/Feature2')
182 | }
183 | },
184 | style: {
185 | backgroundColor: "#F5F5F5"
186 | }
187 | }
188 | ```
189 |
190 | 
191 |
192 | **整体示例代码**
193 |
194 | ```
195 | // header 示例
196 | header: {
197 | title: "测试配置管理后台",
198 | icon: "appstore",
199 | style: {
200 | padding: "15px 15px 15px 25px",
201 | borderBottom: "1px solid #E9E9E9",
202 | backgroundColor: "#F5F5F5"
203 | }
204 | }
205 |
206 | // sider 边栏导航配置示例
207 | sider: {
208 | // 层级列表
209 | menu: [
210 | {
211 | // 多级
212 | title: "导航1", // 主导航名称
213 | key: "subTitle1",
214 | icon: "setting",
215 | items: [
216 | {title: "选项1", key: "Feature1"},
217 | {title: "选项2", key: "Feature2"},
218 | {title: "选项3", key: "Feature3"},
219 | {
220 | title: "导航3",
221 | key: "subTitle3",
222 | icon: "",
223 | items: [
224 | {title: "选项6", key: "Feature6"},
225 | {title: "选项7", key: "Feature7"},
226 | {title: "选项8", key: "Feature8"}
227 | ]
228 | }
229 | ]
230 | },{
231 | // 单级
232 | title: "选项5",
233 | key: "Feature5"
234 | }
235 | ],
236 | // 默认打开的导航项目
237 | openKeys:['subTitle1'],
238 |
239 | // 默认功能页
240 | selectedKey: "Feature1",
241 |
242 | // 自定义样式
243 | style: {
244 | backgroundColor: "#F5F5F5"
245 | }
246 | }
247 |
248 | // main 示例
249 | main: {
250 | components: {
251 | // key 值对应 sider item中功能选项的 key
252 | "Feature1": {
253 | // 功能区域标题显示名称
254 | title: 'table 数据展示',
255 | // require 加载对应功能区域的feature模块
256 | component: require('./components/feature/Feature1')
257 | },
258 | "Feature2": {
259 | title: 'simple对象 数据展示',
260 | component: require('./components/feature/Feature2')
261 | }
262 | },
263 | style: {
264 | backgroundColor: "#F5F5F5"
265 | }
266 | }
267 | ```
268 |
269 | ### src/components/feature/Feature.js
270 |
271 | **配置单独功能页面的配置文件**
272 |
273 | * table数据,单例数据,图标型数据的展现
274 | * 查询、创建、更新、删除表单自动化处理
275 | * 富文本编辑器功能使用
276 | * 独立的图片上传组件使用
277 | * 表单元素自定义使用
278 |
279 | **必要参数**
280 |
281 | * type (string) 对于数据展现形式, 目前有 tableList graphList simpleObject 三种类型
282 |
283 | ```
284 | // 对于数据展现形式 目前有 tableList graphList simpleObject 三种类型
285 | type: 'tableList', // tableList graphList simpleObject complexObject
286 | ```
287 |
288 | * initData (function) 初始化展现的数据,参数 callback 用于接受获取的数据
289 |
290 | ```
291 | // 初始化展现的数据,使用callback 回传列表数据
292 | // 需要手动添加唯一id key
293 | // callback 组件数据的回调函数(接受列表数据参数)
294 | initData: function(callback){
295 | // 同步或者异步获取原始数据
296 | // 数据需要确认唯一的 key(react 形式)
297 | // 若是 table 类型 则每一条数据均需要唯一的 key
298 | data.key = data.id;
299 | callback(data);
300 | }
301 | ```
302 |
303 | * pageData (function) 接口分页数据处理
304 |
305 | // 接口分页处理
306 | // callback 回传列表数据 第二参数接受 总数与每页数目
307 | // 需要手动添加唯一id key
308 | pageData: function(num, callback){
309 | Reqwest({
310 | url: '/api/example2',
311 | data: {
312 | page:num,
313 | pageSize: 20
314 | },
315 |
316 | type: 'json',
317 | success: function (data) {
318 | let list = data.data;
319 | list.forEach(function(ele) {
320 | ele.key = ele.id;
321 | });
322 | // 回调的第二个参数为数量总数 以及每页的数量
323 | callback(list, {
324 | total: 399,
325 | pageSize: 20
326 | });
327 | }
328 | });
329 | }
330 |
331 | **table类型 展现数据**
332 |
333 | * columns (Array) 数据展现类型为 tableList时,设置table表头字段设置
334 |
335 | ```
336 | // table 列表展现配置
337 | // {
338 | // title table显示表题
339 | // dataIndex 显示数据中的key
340 | // type 展现形式 (string image link)
341 | // render 自定义展现形式 参数 (当前数据,当前对象数据)
342 | // sort 是否需要排序功能
343 | // width 自定义该列宽度 否则等分
344 | // }
345 | columns: [
346 | {
347 | title: 'DOCID', // table header 文案
348 | dataIndex: 'docid', // 数据对象内的属性,也做react vdom 的key
349 | type: 'string', // table 内显示的类型
350 | sort: true, // 是否需要排序
351 | width:200,
352 | render: (text, item) => (
353 | {item.name}
354 | ),
355 | },
356 | // type为operate含有特殊含义 自动化的更新与删除,以及自定义操作回调函数
357 | // 为特殊的操作字段
358 | {
359 | title: '操作',
360 | type: 'operate', // 操作的类型必须为 operate
361 | width: 120,
362 | btns: [{
363 | text: '更新',
364 | type: 'update'
365 | },{
366 | text: '删除',
367 | type: 'delete'
368 | }, {
369 | text: '展示',
370 | callback: function(item){
371 | console.log(item)
372 | }
373 | }, {
374 | render: (text, item) => ()
375 | }
376 | }]
377 | }
378 | ]
379 | ```
380 |
381 | 
382 |
383 | **table类型 查询更新列表数据**
384 |
385 | * RType Array 展现的填写表单的数据字段。类型含有示例中的形式
386 |
387 | ```
388 | // table 查询字段
389 | // {
390 | // name 字段的name值
391 | // label 字段的展现内容
392 | // type 字段类型 (string date select cascader radio checkbox switch imageUpload)
393 | // placeholder input的placeholder内容
394 | // }
395 | RType: [
396 | {
397 | name: 'id',
398 | label: '唯一标识',
399 | type: 'string',
400 | placeholder: '请输入标示名称'
401 | },{
402 | name: 'date',
403 | label: '项目开始时间',
404 | type: 'date'
405 | },{
406 | name: 'stype',
407 | label: '项目类型Select',
408 | type: 'select',
409 | defaultValue: 'one',
410 | options:[{
411 | text: '选项一',
412 | value: 'one'
413 | },{
414 | text: '选项二',
415 | value: 'two'
416 | },{
417 | text: '选项三',
418 | value: 'three'
419 | }]
420 | },{
421 | name: 'rtype',
422 | label: '项目类型Radio',
423 | type: 'radio',
424 | defaultValue: 'one',
425 | options:[{
426 | text: '选项一',
427 | value: 'one'
428 | },{
429 | text: '选项二',
430 | value: 'two'
431 | },{
432 | text: '选项三',
433 | value: 'three'
434 | }]
435 | },{
436 | name: 'ischange',
437 | label: '是否过滤',
438 | type: 'switch',
439 | defaultValue: false
440 | }
441 |
442 | ]
443 | ```
444 |
445 | * Retrieve function 对于确认创建数据接口上报创建回调的函数
446 |
447 | ```
448 | Retrieve: function(data, callback){
449 | // 处理对于列表查询的数据请求
450 | console.log(data);
451 |
452 | // 查询成功之后执行callback回调
453 | // 同步或者异步获取原始数据
454 | // 数据需要确认唯一的 key(react 形式)
455 | // 若是 table 类型 则每一条数据均需要唯一的 key
456 | list.key = list.id;
457 | callback(list);
458 | }
459 | ```
460 |
461 | 
462 |
463 | **table类型 创建数据**
464 |
465 | 当数据类型为table 并且含有创建新数据的需求时
466 |
467 | * CType Array 展现的填写表单的数据字段。类型含有示例中的形式
468 |
469 | ```
470 | // table 创建新数据字段
471 | // {
472 | // name 字段的name值
473 | // label 字段的展现内容
474 | // type 字段类型 (string date select cascader radio checkbox switch imageUpload)
475 | // placeholder input的placeholder内容
476 | // }
477 | CType: [
478 | {
479 | name: 'docid',
480 | label: '唯一标识',
481 | type: 'string',
482 | placeholder: '请输入标示名称'
483 | },{
484 | name: 'date',
485 | label: '日期',
486 | type: 'date'
487 | },{
488 | name: 'img',
489 | label: '图片',
490 | type: 'imageUpload'
491 | }
492 | ]
493 | ```
494 |
495 | * Create function 对于确认创建数据接口上报创建回调的函数
496 |
497 | ```
498 | Create: function(data, callback){
499 | // 处理对于数据请求的创建
500 | console.log(data);
501 |
502 | // 创建成功之后执行callback回调
503 | callback();
504 | }
505 | ```
506 |
507 | 
508 |
509 | **table类型 更新数据**
510 |
511 | 当数据类型为table 并且含有更新数据的需求时
512 |
513 | * UType Array 展现的填写表单的数据字段。类型含有示例中的形式(类似创建数据)
514 |
515 | ```
516 | // table 更新数据字段
517 | // {
518 | // name 字段的name值
519 | // label 字段的展现内容
520 | // type 字段类型 (string date select cascader radio checkbox switch imageUpload)
521 | // placeholder input的placeholder内容
522 | // }
523 | CType: [
524 | {
525 | name: 'docid',
526 | label: '唯一标识',
527 | type: 'string',
528 | placeholder: '请输入标示名称'
529 | },{
530 | name: 'date',
531 | label: '日期',
532 | type: 'date'
533 | },{
534 | name: 'img',
535 | label: '图片',
536 | type: 'imageUpload'
537 | }
538 | ]
539 | ```
540 |
541 | * Update function 对于确认创建数据接口上报创建回调的函数
542 |
543 | ```
544 | Update: function(data, callback){
545 | // 处理对于数据请求的更新
546 | console.log(data);
547 |
548 | // 更新成功之后执行callback回调
549 | callback();
550 | }
551 | ```
552 |
553 | 
554 |
555 | **table类型 删除数据**
556 |
557 | 当数据类型为table 并且含有更新数据的需求时
558 |
559 | * Delete function 对于确认删除某条数据实例
560 |
561 | ```
562 | Delete: function(data, callback){
563 | // 删除操作
564 | console.log(data);
565 |
566 | Reqwest({
567 | url: '/api/delete',
568 | data: data.id,
569 |
570 | type: 'json',
571 | success: function (data) {
572 | // 模拟请求删除成功的回调
573 | callback();
574 | }
575 | });
576 |
577 | }
578 | ```
579 |
580 | 
581 |
582 |
583 | ## 其他组件
584 |
585 | ### 图片上传组件(需自定义调整)
586 |
587 | ### 复制文本组件
588 |
589 | ### 富文本编辑器组件(Tinymce基础功能接入)
590 |
591 | ### echarts 组件接入
592 |
593 |
594 | ## 学习文档
595 |
596 | [ES6 react 实践的技术图](https://github.com/dvajs/dva-knowledgemap)
597 |
598 | [dva 完成一个中型应用](https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/01-%E6%A6%82%E8%A6%81.md)
599 |
600 | [系统引用的UI组件文档 Ant Design of React](https://ant.design/docs/react/introduce)
601 |
602 |
603 | bibibibi~ 改版中!!!!!!!!!!!!!!!!
--------------------------------------------------------------------------------
/src/components/common/FeatureSetConfig.jsx:
--------------------------------------------------------------------------------
1 | // 纯数据展现情况列表
2 | import React from 'react';
3 | import ReactEcharts from 'echarts-for-react';
4 |
5 | import { Table, Form, Select, Input, Row, Col, Button, Icon } from 'antd';
6 | import { DatePicker, TimePicker, Radio, Switch} from 'antd';
7 | import { Upload, Modal, message, Spin} from 'antd';
8 |
9 | import { Link } from 'dva/router';
10 |
11 | import Immutable from 'immutable';
12 | import Reqwest from 'reqwest';
13 |
14 | import CFormItem from './CreateFormItem';
15 | import CTextItem from './CreateTextItem';
16 |
17 | // 搜索查询栏form 创建新item-form 更新form
18 | import UForm from './UpdateForm';
19 | import CForm from './CreateForm';
20 | import RForm from './RetrieveForm';
21 |
22 | const FormItem = Form.Item;
23 | const Option = Select.Option;
24 | const RadioGroup = Radio.Group;
25 |
26 |
27 | // 依赖 config 主题生成react 组件函数
28 | const FeatureSet = (config) => {
29 |
30 | let tableFeature = React.createClass({
31 | getInitialState: function(){
32 | return {
33 | columns: [],
34 | resultList: [],
35 | loading: false,
36 |
37 | updateFromShow: false,
38 | updateFromItem: {},
39 |
40 | total: 0,
41 | pageSize: 10
42 | }
43 | },
44 |
45 | componentWillMount: function(){
46 | this.setState({
47 | loading: true,
48 | columns: this.dealConfigColumns(config.columns)
49 | });
50 | },
51 |
52 | render: function() {
53 | const self = this;
54 |
55 | let table;
56 | if(config.pageData){
57 | const pagination = {
58 | total: this.state.total,
59 | pageSize: this.state.pageSize,
60 | onChange: function(num){
61 | self.setState({
62 | loading: true
63 | });
64 | self.getpageData(num);
65 | }
66 | }
67 |
68 | table = ;
69 | }else{
70 | table = ;
71 | }
72 |
73 | return
74 |
75 |
76 |
77 | {table}
78 |
79 | },
80 |
81 | // 预处理配置显示中的 colums 数据 用于anted的table配置
82 | dealConfigColumns: function(lists){
83 | const self = this;
84 |
85 | let columns = [];
86 | lists.forEach((item) => {
87 | let column = {
88 | title: item.title,
89 | dataIndex: item.dataIndex,
90 | key: item.dataIndex,
91 | width: item.width
92 | }
93 |
94 | if( item.type === 'operate' ){
95 | // 兼容单一形式与数组形式
96 | let btns = Array.isArray(item.btns)?item.btns:[item.btns];
97 |
98 | // 处理表单 操作 栏目以及回调函数
99 | column.render = item.render || function(txt, record){
100 | return
101 | {
102 | btns.map(function(btn,i) {
103 | if( btn.text ){
104 | return (
105 |
106 | {btn.text}
107 | {i!==btns.length-1?:''}
108 |
109 | );
110 | }else if( btn.render ){
111 | return (
112 |
113 | {btn.render(txt, record)}
114 | {i!==btns.length-1?:''}
115 |
116 | );
117 | }
118 |
119 |
120 | })
121 | }
122 |
123 | };
124 | }else if( !item.dataIndex ){
125 | item.dataIndex = 'NORMAL_INDEX';
126 | column.render = item.render || self.renderFunc[item.type];
127 | } else{
128 | column.render = item.render || self.renderFunc[item.type] || ((text) => ({text}));
129 | }
130 |
131 | if(item.sort){
132 | column.sorter = item.sorter || ((a, b) => a[item.dataIndex] - b[item.dataIndex]);
133 | }
134 | columns.push(column);
135 |
136 | });
137 |
138 | return columns;
139 |
140 | },
141 |
142 | // columns 类型对应的通用痛render
143 | renderFunc: {
144 | link: (text) => (
145 |
146 | {text}
147 | ),
148 |
149 | image: (url) => (
150 |
151 |
152 | )
153 | },
154 |
155 | handleCreate: function(info){
156 | const self = this;
157 |
158 | config.Create(info, function(item){
159 | // 初级接口的坑
160 | if(!item){
161 | config.initData(function(list){
162 | self.setState({
163 | loading: false,
164 | resultList: list
165 | });
166 | });
167 | return;
168 | }
169 |
170 | let lists = self.state.resultList;
171 | lists.unshift(item);
172 |
173 | self.setState({
174 | loading: false,
175 | resultList: lists
176 | });
177 | });
178 | },
179 |
180 | handleUpdate: function(info){
181 | const self = this;
182 | let result = Immutable.fromJS(self.state.resultList);
183 |
184 | let infoN = Immutable.fromJS(self.state.updateFromItem).merge(info).toJS();
185 | config.Update(infoN, function(item){
186 | let resultList = result.map(function(v, i){
187 | if(v.get('key') === item.key){
188 | return Immutable.fromJS(item);
189 | }else{
190 | return v;
191 | }
192 | });
193 | message.success('更新成功');
194 |
195 | self.setState({
196 | loading: false,
197 | updateFromShow: false,
198 | resultList: resultList.toJS()
199 | });
200 | });
201 | },
202 | hideUpdateForm: function(){
203 | this.setState({
204 | updateFromShow: false,
205 | updateFromItem: {}
206 | });
207 | },
208 |
209 | // 搜索更新处理
210 | handleRetrieve: function(info){
211 | const self = this;
212 | self.setState({
213 | loading: true
214 | });
215 |
216 | config.Retrieve(info, function(list){
217 | self.setState({
218 | loading: false,
219 | resultList: list
220 | });
221 | });
222 | },
223 |
224 | // table 操作列回调处理
225 | operateCallbacks: function(item, btn){
226 | const self = this;
227 |
228 | if(btn.type){
229 |
230 | let resultList;
231 | let type = btn.type;
232 | let itemI = Immutable.fromJS(item);
233 | let result = Immutable.fromJS(self.state.resultList);
234 |
235 | // table 操作栏目通用设定为 更新与删除 两项
236 | if(type === 'update'){
237 | this.setState({
238 | updateFromShow: true,
239 | updateFromItem: itemI.toJS()
240 | });
241 | }else if(type === 'delete'){
242 | this.setState({
243 | loading: true
244 | });
245 |
246 | config.Delete(itemI.toJS(), function(){
247 | resultList = result.filter(function(v, i){
248 | if(v.get('key') !== itemI.get('key')){
249 | return true;
250 | }
251 | });
252 | message.success('删除成功');
253 |
254 | self.setState({
255 | loading: false,
256 | resultList: resultList.toJS()
257 | });
258 | });
259 | }
260 |
261 |
262 | }else if(btn.callback){
263 | btn.callback(item);
264 | }
265 | },
266 |
267 | componentDidMount: function(){
268 | const self = this;
269 |
270 | // 处理接口分页的逻辑
271 | if(config.pageData){
272 | self.getpageData(1);
273 | }else{ // 处理 前端分页的逻辑
274 | config.initData(function(list){
275 | self.setState({
276 | loading: false,
277 | resultList: list
278 | });
279 | });
280 | }
281 | },
282 |
283 | getpageData: function(num){
284 | const self = this;
285 | self.setState({
286 | loading: true
287 | });
288 |
289 | config.pageData(num,function(list, info){
290 | self.setState({
291 | loading: false,
292 | resultList: list,
293 | total: info.total,
294 | pageSize: info.pageSize||10,
295 | });
296 | });
297 |
298 | }
299 | });
300 |
301 | let simpleFeature = React.createClass({
302 | getInitialState: function(){
303 | return {
304 | item:{},
305 | loading: false,
306 |
307 | updateFromShow: false,
308 | updateFromItem: {}
309 | }
310 | },
311 |
312 | componentWillMount: function(){
313 | },
314 |
315 | render: function() {
316 | const self = this;
317 | const itemInfo = this.state.item;
318 |
319 | const { getFieldDecorator } = this.props.form;
320 | const formItemLayout = {
321 | labelCol: { span: 3 },
322 | wrapperCol: { span: 18 },
323 | };
324 |
325 | const operate = config.operate || [];
326 |
327 | return
328 |
353 | {
354 | operate.map(function(btn){
355 | return
356 | })
357 | }
358 |
359 | },
360 |
361 | componentDidMount: function(){
362 | const self = this;
363 | self.setState({
364 | loading: true
365 | });
366 |
367 | config.initData(function(item){
368 | self.setState({
369 | item: item,
370 | loading: false
371 | });
372 | });
373 | },
374 |
375 | operateCallbacks: function(btn){
376 | const self = this;
377 |
378 | let itemI = Immutable.fromJS(this.props.form.getFieldsValue());
379 |
380 | if(btn.type === 'update'){
381 | const self = this;
382 |
383 | config.Update(itemI.toJS(), function(item){
384 | message.success('更新成功');
385 | self.setState({
386 | item: item
387 | });
388 | });
389 |
390 | }else if(btn.callback){
391 | btn.callback(itemI.toJS());
392 | }
393 | }
394 | });
395 | simpleFeature = Form.create()(simpleFeature);
396 |
397 |
398 | let graphFeature = React.createClass({
399 | getInitialState: function(){
400 | return {
401 | option: false
402 | }
403 | },
404 |
405 | componentWillMount: function(){
406 | },
407 |
408 | render: function() {
409 | const self = this;
410 | const itemInfo = this.state.item;
411 |
412 | const operate = config.operate || [];
413 |
414 | return
415 | {this.state.option?
416 | :
420 | ''}
421 |
422 | },
423 |
424 | componentDidMount: function(){
425 | const self = this;
426 |
427 | config.initData(function(option){
428 | self.setState({
429 | option: option
430 | });
431 | });
432 | }
433 | });
434 |
435 | switch (config.type){
436 | case 'tableList':
437 | return tableFeature;
438 | break;
439 |
440 | case 'graphList':
441 | return graphFeature;
442 | break;
443 |
444 | case 'simpleObject':
445 | return simpleFeature;
446 | break;
447 |
448 | case 'complexObject':
449 | return complexFeature;
450 | break;
451 |
452 | default:
453 | return tableFeature;
454 | break;
455 | }
456 | }
457 |
458 |
459 | export default FeatureSet;
460 |
--------------------------------------------------------------------------------