Browse Source

update 客户端需求和成果完成

yee 7 years ago
parent
commit
cf03923b96

+ 10 - 0
entry.js

@@ -10,6 +10,8 @@ module.exports = {
     'user/account/index': './js/user/account/index.js',
     'user/account/set': './js/user/account/set.js',
     'user/account/services': './js/user/account/services.js',
+    'user/account/achievement': './js/user/account/achievement.js',
+    'user/account/demand': './js/user/account/demand.js',
     //admin
     'admin/index': './js/admin/index.js',
     'admin/login': './js/admin/login.js',
@@ -60,6 +62,14 @@ module.exports = {
       'webpack/hot/only-dev-server',
       './js/user/account/services.js'
     ],
+    'user/account/achievement': ['webpack-dev-server/client?http://127.0.0.1:80', // WebpackDevServer host and port
+      'webpack/hot/only-dev-server',
+      './js/user/account/achievement.js'
+    ],
+    'user/account/demand': ['webpack-dev-server/client?http://127.0.0.1:80', // WebpackDevServer host and port
+      'webpack/hot/only-dev-server',
+      './js/user/account/demand.js'
+    ],
     //admin
     'admin/index': ['webpack-dev-server/client?http://127.0.0.1:80', // WebpackDevServer host and port
       'webpack/hot/only-dev-server',

+ 47 - 0
js/component/account/achievement/content.jsx

@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import '../content.less';
+import LeftTab from './leftTab';
+import TechAchievement from './techAchievement';
+
+
+class Content extends Component {
+    constructor() {
+        super();
+        this.state = {
+            loading: false,
+            component: 'div'
+        };
+    }
+    componentWillMount() {
+        if (window.location.hash) {
+            this.getKey(window.location.hash.substr(1));
+        } else {
+            this.getKey("techAchievement");
+        };
+    }
+    getKey(key) {
+        switch (key) {
+            case 'techAchievement':
+                require.ensure([], () => {
+                    const TechDemand = require('./techAchievement').default;
+                    this.setState({
+                        component: TechAchievement
+                    });
+                });
+                break;
+        };
+        window.location.hash = key;
+    }
+    render() {
+        return (
+            <div className="acc-content">
+                <LeftTab handlekey={this.getKey.bind(this)} />
+                <div className="content-right">
+                    <this.state.component />
+                </div>
+            </div>
+        )
+    }
+}
+
+export default Content;

+ 40 - 0
js/component/account/achievement/leftTab.jsx

@@ -0,0 +1,40 @@
+import React from 'react';
+import { Menu, Icon } from 'antd';
+import '../leftTab.less';
+const SubMenu = Menu.SubMenu;
+const MenuItemGroup = Menu.ItemGroup;
+
+
+const LeftTab = React.createClass({
+    getInitialState() {
+        return {
+            current: 'techAchievement'
+        };
+    },
+    handleClick(e) {
+        this.props.handlekey(e.key);
+        this.setState({
+            current: e.key,
+        });
+    },
+    componentWillMount() {
+        if (window.location.hash) {
+            this.state.current = window.location.hash.substr(1);
+        };
+    },
+    render() {
+        return (
+            <Menu onClick={this.handleClick}
+                selectedKeys={[this.state.current]}
+                mode="vertical"
+                className="account-left"
+            >
+                <Menu.Item key="techAchievement">
+                    科技成果列表
+                </Menu.Item>
+            </Menu>
+        );
+    },
+});
+
+export default LeftTab;

+ 325 - 0
js/component/account/achievement/techAchievement.jsx

@@ -0,0 +1,325 @@
+import React from 'react';
+import { Icon, Button, Input, Select, Spin, Table, Switch, message, DatePicker, Modal } from 'antd';
+import ajax from 'jquery/src/ajax/xhr.js';
+import $ from 'jquery/src/ajax';
+import moment from 'moment';
+import './techAchievement.less';
+import TechAchievementDesc from './techAchievementDesc.jsx';
+import { provinceArr, achievementCategoryList } from '../../dataDic.js';
+import { companySearch, getAchievementCategory } from '../../tools.js';
+
+const AchievementList = React.createClass({
+    loadData(pageNo) {
+        this.state.data = [];
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + '/api/user/achievement/list',
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: this.state.pagination.pageSize,
+                serialNumber: this.state.serialNumber, //编号
+                name: this.state.name, //名称
+                keyword: this.state.keyword, // 关键词
+                category: this.state.category, //类型(0--专利, 2--软著, 3--项目, 4--版权, 5--工业设计, 6--配方, 7--非标)
+                ownerType: this.state.ownerType, //所有人类型(0-个人,1-组织)
+                status: this.state.status ? Number(this.state.status) : undefined, //状态
+                releaseDateStartDate: this.state.releaseDate[0],
+                releaseDateEndDate: this.state.releaseDate[1],
+                releaseStatus: this.state.releaseStatus ? Number(this.state.releaseStatus) : undefined, //是否发布(0--未发布,1--已发布)
+            },
+            success: function (data) {
+                let theArr = [];
+                if (!data.data && !data.data.list) {
+                    if (data.error && data.error.length) {
+                        message.warning(data.error[0].message);
+                    };
+                } else {
+                    for (let i = 0; i < data.data.list.length; i++) {
+                        let thisdata = data.data.list[i];
+                        theArr.push({
+                            key: i,
+                            id: thisdata.id,
+                            serialNumber: thisdata.serialNumber,
+                            dataCategory: thisdata.dataCategory,
+                            name: thisdata.name,
+                            keyword: thisdata.keyword,
+                            category: thisdata.category,
+                            ownerName: thisdata.ownerName,
+                            ownerType: thisdata.ownerType,
+                            ownerMobile: thisdata.ownerMobile,
+                            status: thisdata.status,
+                            releaseDate: thisdata.releaseDate,
+                            releaseDateFormattedDate: thisdata.releaseDateFormattedDate
+                        });
+                    };
+                }
+                this.state.pagination.current = data.data.pageNo;
+                this.state.pagination.total = data.data.totalCount;
+                this.setState({
+                    dataSource: theArr,
+                    pagination: this.state.pagination
+                });
+            }.bind(this),
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this));
+    },
+    getInitialState() {
+        return {
+            searchMore: true,
+            validityPeriodDate: [],
+            releaseDate: [],
+            selectedRowKeys: [],
+            selectedRows: [],
+            loading: false,
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+            columns: [
+                {
+                    title: '编号',
+                    dataIndex: 'serialNumber',
+                    key: 'serialNumber',
+                }, {
+                    title: '名称',
+                    dataIndex: 'name',
+                    key: 'name',
+                }, {
+                    title: '关键字',
+                    dataIndex: 'keyword',
+                    key: 'keyword',
+                }, {
+                    title: '类型',
+                    dataIndex: 'category',
+                    key: 'category',
+                    render: text => { return getAchievementCategory(text); }
+                }, {
+                    title: '所有人名称',
+                    dataIndex: 'ownerName',
+                    key: 'ownerName',
+                }, {
+                    title: '所有人类型',
+                    dataIndex: 'ownerType',
+                    key: 'ownerType',
+                    render: text => {
+                        switch (text) {
+                            case "0":
+                                return <span>个人</span>;
+                            case "1":
+                                return <span>组织</span>
+                        }
+                    }
+                }, {
+                    title: '所有人联系方式',
+                    dataIndex: 'ownerMobile',
+                    key: 'ownerMobile',
+                }, {
+                    title: '状态',
+                    dataIndex: 'status',
+                    key: 'status',
+                    render: text => {
+                        switch (text) {
+                            case "0":
+                                return <span>进行中</span>;
+                            case "1":
+                                return <span>未解决</span>;
+                            case "2":
+                                return <span>已解决</span>;
+                        }
+                    }
+                }, {
+                    title: '发布时间',
+                    dataIndex: 'releaseDateFormattedDate',
+                    key: 'releaseDateFormattedDate',
+                }
+            ],
+            dataSource: [],
+            searchTime: [,]
+        };
+    },
+    componentWillMount() {
+        let theArr = [];
+        achievementCategoryList.map(function (item) {
+            theArr.push(
+                <Select.Option value={item.value} key={item.key}>{item.key}</Select.Option>
+            )
+        });
+        this.state.achievementCategoryOption = theArr;
+        this.loadData();
+    },
+    tableRowClick(record, index) {
+        this.state.RowData = record;
+        this.setState({
+            showDesc: true
+        });
+    },
+    delectRow() {
+        let deletedIds = [];
+        for (let idx = 0; idx < this.state.selectedRows.length; idx++) {
+            let rowItem = this.state.selectedRows[idx];
+            if (rowItem.id) {
+                deletedIds.push(rowItem.id)
+            };
+        };
+        this.setState({
+            selectedRowKeys: [],
+            loading: deletedIds.length > 0
+        });
+        $.ajax({
+            method: "POST",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/user/achievement/delete",
+            data: {
+                ids: deletedIds
+            }
+        }).done(function (data) {
+            if (!data.error.length) {
+                message.success('删除成功!');
+                this.setState({
+                    loading: false,
+                });
+            } else {
+                message.warning(data.error[0].message);
+            };
+            this.loadData();
+        }.bind(this));
+    },
+    addClick() {
+        this.state.RowData = {};
+        this.setState({
+            showDesc: true
+        });
+    },
+    closeDesc(e, s) {
+        this.state.showDesc = e;
+        if (s) {
+            this.loadData();
+        };
+    },
+    search() {
+        this.loadData();
+    },
+    reset() {
+        this.state.serialNumber = undefined;
+        this.state.name = undefined;
+        this.state.keyword = undefined;
+        this.state.category = undefined;
+        this.state.ownerType = undefined;
+        this.state.status = undefined;
+        this.state.releaseStatus = undefined;
+        this.state.releaseDate = [];
+        this.loadData();
+    },
+    searchSwitch() {
+        this.setState({
+            searchMore: !this.state.searchMore
+        });
+    },
+    render() {
+        const rowSelection = {
+            selectedRowKeys: this.state.selectedRowKeys,
+            onChange: (selectedRowKeys, selectedRows) => {
+                this.setState({
+                    selectedRows: selectedRows,
+                    selectedRowKeys: selectedRowKeys
+                });
+            }
+        };
+        const hasSelected = this.state.selectedRowKeys.length > 0;
+        const { RangePicker } = DatePicker;
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span>科技成果管理</span>
+                    <div className="patent-addNew">
+                        <Button type="primary" onClick={this.addClick}>发布成果<Icon type="plus" /></Button>
+                    </div>
+                </div>
+                <div className="user-search">
+                    <Input placeholder="编号"
+                        value={this.state.serialNumber}
+                        onChange={(e) => { this.setState({ serialNumber: e.target.value }); }} />
+                    <Input placeholder="名称"
+                        value={this.state.name}
+                        onChange={(e) => { this.setState({ name: e.target.value }); }} />
+                    <Input placeholder="关键字"
+                        value={this.state.keyword}
+                        onChange={(e) => { this.setState({ keyword: e.target.value }); }} />
+                    <Select placeholder="选择类型" style={{ width: 160 }}
+                        value={this.state.category}
+                        onChange={(e) => { this.setState({ category: e }) }}>
+                        {this.state.achievementCategoryOption}
+                    </Select>
+                    <Select placeholder="选择所有人类型"
+                        style={{ width: 120 }}
+                        value={this.state.ownerType}
+                        onChange={(e) => { this.setState({ ownerType: e }) }}>
+                        <Select.Option value="0" >个人</Select.Option>
+                        <Select.Option value="1" >组织</Select.Option>
+                    </Select>
+                    <Select placeholder="选择成果状态" style={{ width: 120 }}
+                        value={this.state.status}
+                        onChange={(e) => { this.setState({ status: e }) }}>
+                        <Select.Option value="0" >进行中</Select.Option>
+                        <Select.Option value="1" >未解决</Select.Option>
+                        <Select.Option value="2" >已解决</Select.Option>
+                    </Select>
+                    <Select placeholder="选择是否发布" style={{ width: 120 }}
+                        value={this.state.releaseStatus}
+                        onChange={(e) => { this.setState({ releaseStatus: e }) }}>
+                        <Select.Option value="0" >未发布</Select.Option>
+                        <Select.Option value="1" >已发布</Select.Option>
+                    </Select>
+                    <Button type="primary" onClick={this.search}>搜索</Button>
+                    <Button onClick={this.reset}>重置</Button>
+                    <Button style={{ background: "#3fcf9e", border: "none", color: "#fff" }}
+                        disabled={!hasSelected}
+                        onClick={this.delectRow}>删除<Icon type="minus" /></Button>
+                    <span>更多搜索<Switch defaultChecked={false} onChange={this.searchSwitch} /></span>
+                    <div className="search-more" style={this.state.searchMore ? { display: 'none' } : {}}>
+                        <p>
+                            <span>发布时间 :</span>
+                            <RangePicker
+                                value={[this.state.releaseDate[0] ? moment(this.state.releaseDate[0]) : null,
+                                this.state.releaseDate[1] ? moment(this.state.releaseDate[1]) : null]}
+                                onChange={(data, dataString) => { this.setState({ releaseDate: dataString }); }} />
+                        </p>
+                    </div>
+                </div>
+                <div className="patent-table">
+                    <Spin spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                            dataSource={this.state.dataSource}
+                            rowSelection={rowSelection}
+                            pagination={this.state.pagination}
+                            onRowClick={this.tableRowClick} />
+                    </Spin>
+                </div>
+                <TechAchievementDesc
+                    data={this.state.RowData}
+                    achievementCategoryOption={this.state.achievementCategoryOption}
+                    showDesc={this.state.showDesc}
+                    closeDesc={this.closeDesc} />
+            </div >
+        );
+    }
+});
+
+export default AchievementList;

+ 72 - 0
js/component/account/achievement/techAchievement.less

@@ -0,0 +1,72 @@
+.user-content {
+    background: #fff;
+    padding: 20px;
+    .content-title {
+        color: #333;
+        font-size: 16px;
+    }
+    .user-search {
+        margin-bottom: 10px;
+        >input {
+            width: 140px;
+        }
+        >input,
+        >button,
+        .ant-select {
+            margin-right: 10px;
+            margin-top: 10px;
+        }
+        .ant-switch {
+            margin-left: 10px;
+        }
+        .search-more {
+            margin: 10px 0;
+            >p {
+                span {
+                    margin-right: 10px
+                }
+            }
+        }
+    }
+}
+
+.patent-addNew {
+    float: right;
+    margin-left: 20px;
+    button {
+        background: #ea0862;
+        color: #fff;
+        border: none;
+        border-radius: 4px;
+        padding: 6px 10px;
+        margin-left: 20px;
+    }
+    button:hover {
+        background: #ea0862;
+    }
+}
+
+#demand-form {
+    .half-item {
+        float: left;
+        width: 50%;
+        margin-bottom: 10px;
+    }
+    .item-title {
+        line-height: 30px;
+        font-size: 14px;
+        color: #666;
+    }
+    .form-title {
+        font-size: 16px;
+        color: #333;
+    }
+    .keyWord-tips {
+        >button {
+            vertical-align: middle;
+        }
+    }
+    .set-submit {
+        margin-right: 20px;
+    }
+}

+ 870 - 0
js/component/account/achievement/techAchievementDesc.jsx

@@ -0,0 +1,870 @@
+import React from 'react';
+import { Icon, Tooltip, Modal, message, Spin, Upload, Input, InputNumber, Select, DatePicker, Button, Radio, Form, Cascader, Tag } from 'antd';
+import moment from 'moment';
+import './techAchievement.less';
+import ajax from 'jquery/src/ajax/xhr.js';
+import $ from 'jquery/src/ajax';
+import { IndustryObject } from '../../DicIndustryList.js';
+import { beforeUploadFile, splitUrl, companySearch } from '../../tools.js';
+
+const KeyWordTagGroup = React.createClass({
+    getInitialState() {
+        return {
+            tags: [],
+            inputVisible: false,
+            inputValue: ''
+        };
+    },
+    handleClose(removedTag) {
+        const tags = this.state.tags.filter(tag => tag !== removedTag);
+        this.props.tagsArr(tags);
+        this.setState({ tags });
+    },
+    showInput() {
+        this.setState({ inputVisible: true }, () => this.input.focus());
+    },
+    handleInputChange(e) {
+        this.setState({ inputValue: e.target.value });
+    },
+    handleInputConfirm() {
+        const state = this.state;
+        const inputValue = state.inputValue;
+        let tags = state.tags;
+        if (inputValue && tags.indexOf(inputValue) === -1) {
+            tags = [...tags, inputValue];
+        }
+        this.props.tagsArr(tags);
+        this.setState({
+            tags,
+            inputVisible: false,
+            inputValue: '',
+        });
+    },
+    componentWillMount() {
+        this.state.tags = this.props.keyWordArr;
+    },
+    componentWillReceiveProps(nextProps) {
+        if (this.props.keyWordArr != nextProps.keyWordArr) {
+            this.state.tags = nextProps.keyWordArr;
+        };
+    },
+    render() {
+        const { tags, inputVisible, inputValue } = this.state;
+        return (
+            <div className="keyWord-tips">
+                {tags.map((tag, index) => {
+                    const isLongTag = tag.length > 10;
+                    const tagElem = (
+                        <Tag key={tag} closable={index !== -1} afterClose={() => this.handleClose(tag)}>
+                            {isLongTag ? `${tag.slice(0, 10)}...` : tag}
+                        </Tag>
+                    );
+                    return isLongTag ? <Tooltip title={tag}>{tagElem}</Tooltip> : tagElem;
+                })}
+                {inputVisible && (
+                    <Input
+                        ref={input => this.input = input}
+                        type="text"
+                        style={{ width: 78 }}
+                        value={inputValue}
+                        onChange={this.handleInputChange}
+                        onBlur={this.handleInputConfirm}
+                        onPressEnter={this.handleInputConfirm}
+                    />
+                )}
+                {!inputVisible && <Button className="addtips" type="dashed" disabled={tags.length > 9 ? true : false} onClick={this.showInput}>+ 新关键词</Button>}
+            </div>
+        );
+    }
+});
+
+const PicturesWall = React.createClass({
+    getInitialState() {
+        return {
+            previewVisible: false,
+            previewImage: '',
+            fileList: [],
+        }
+    },
+    handleCancel() {
+        this.setState({ previewVisible: false })
+    },
+    handlePreview(file) {
+        this.setState({
+            previewImage: file.url || file.thumbUrl,
+            previewVisible: true,
+        });
+    },
+    handleChange(info) {
+        let fileList = info.fileList;
+        this.setState({ fileList });
+        this.props.fileList(fileList);
+    },
+    componentWillReceiveProps(nextProps) {
+        this.state.fileList = nextProps.pictureUrl;
+    },
+    render() {
+        const { previewVisible, previewImage, fileList } = this.state;
+        const uploadButton = (
+            <div>
+                <Icon type="plus" />
+                <div className="ant-upload-text">点击上传</div>
+            </div>
+        );
+        return (
+            <div className="clearfix">
+                <Upload
+                    action={globalConfig.context + "/api/user/achievement/uploadPicture"}
+                    data={{ 'sign': this.props.pictureSign }}
+                    listType="picture-card"
+                    fileList={fileList}
+                    onPreview={this.handlePreview}
+                    onChange={this.handleChange} >
+                    {fileList.length >= 5 ? null : uploadButton}
+                </Upload>
+                <Modal maskClosable={false} visible={previewVisible} footer={null} onCancel={this.handleCancel}>
+                    <img alt="example" style={{ width: '100%' }} src={previewImage} />
+                </Modal>
+            </div>
+        );
+    }
+});
+
+const AchievementDetailForm = Form.create()(React.createClass({
+    getInitialState() {
+        return {
+            visible: false,
+            loading: false,
+            textFileList: [],
+            techPlanFileList: [],
+            businessPlanFileList: [],
+            maturityPictureUrl: [],
+            technicalPictureUrl: [],
+            tags: []
+        };
+    },
+    loadData(id) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/user/achievement/detail",
+            data: {
+                id: id
+            },
+            success: function (data) {
+                let thisData = data.data;
+                if (!thisData) {
+                    if (data.error && data.error.length) {
+                        message.warning(data.error[0].message);
+                    };
+                    thisData = {};
+                };
+                let d = new Date()
+                if (thisData && thisData.dateOfBirthMonth && thisData.dateOfBirthYear) {
+                    d.setMonth(thisData.dateOfBirthMonth - 1);
+                    d.setYear(parseInt(thisData.dateOfBirthYear));
+                };
+                this.setState({
+                    data: thisData,
+                    orgDisplay: thisData.ownerType,
+                    tags: thisData.keyword ? thisData.keyword.split(",") : [],
+                    technicalPictureUrl: thisData.technicalPictureUrl ? splitUrl(thisData.technicalPictureUrl, ',', globalConfig.avatarHost + '/upload') : [],
+                    maturityPictureUrl: thisData.maturityPictureUrl ? splitUrl(thisData.maturityPictureUrl, ',', globalConfig.avatarHost + '/upload') : []
+                });
+            }.bind(this),
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this));
+    },
+    getTagsArr(e) {
+        this.setState({ tags: e });
+    },
+    getMaturityPictureUrl(e) {
+        this.setState({ maturityPictureUrl: e });
+    },
+    getTechnicalPictureUrl(e) {
+        this.setState({ technicalPictureUrl: e });
+    },
+    handleSubmit(e) {
+        e.preventDefault();
+        this.props.form.validateFields((err, values) => {
+            //keyword长度判断
+            if (this.state.tags.length < 3) {
+                message.warning('关键词数量不能小于3个!');
+                return;
+            };
+            //url转化
+            let theTechnicalPictureUrl = [];
+            if (this.state.technicalPictureUrl.length) {
+                let picArr = [];
+                this.state.technicalPictureUrl.map(function (item) {
+                    picArr.push(item.response.data);
+                });
+                theTechnicalPictureUrl = picArr.join(",");
+            };
+            let theMaturityPictureUrl = [];
+            if (this.state.maturityPictureUrl.length) {
+                let picArr = [];
+                this.state.maturityPictureUrl.map(function (item) {
+                    picArr.push(item.response.data);
+                });
+                theMaturityPictureUrl = picArr.join(",");
+            };
+            if (!err) {
+                this.setState({
+                    loading: true
+                });
+                $.ajax({
+                    method: "POST",
+                    dataType: "json",
+                    crossDomain: false,
+                    url: this.props.data.id ? globalConfig.context + '/api/user/achievement/update' : globalConfig.context + '/api/user/achievement/apply',
+                    data: {
+                        id: this.props.data.id,
+                        dataCategory: values.dataCategory,
+                        serialNumber: this.props.data.serialNumber,
+                        name: values.name,
+                        keyword: this.state.tags ? this.state.tags.join(",") : [],
+                        category: values.category,
+                        summary: values.summary,
+                        introduction: values.introduction,
+                        technicalPictureUrl: theTechnicalPictureUrl,
+                        fieldA: values.field ? values.field[0] : undefined,
+                        fieldB: values.field ? values.field[1] : undefined,
+                        maturity: values.maturity,
+                        maturityPictureUrl: theMaturityPictureUrl,
+                        maturityTextFileUrl: this.state.maturityTextFileUrl,
+                        maturityVideoUrl: values.maturityVideoUrl,
+                        innovation: values.innovation,
+                        ownerName: values.ownerName,
+                        ownerType: values.ownerType,
+                        ownerIdNumber: values.ownerIdNumber,
+                        ownerMobile: values.ownerMobile,
+                        ownerEmail: values.ownerEmail,
+                        ownerPostalAddress: values.ownerPostalAddress,
+                        cooperationMode: values.cooperationMode,
+                        transferMode: values.transferMode,
+                        bargainingMode: values.bargainingMode,
+                        transferPrice: values.transferPrice,
+                        technicalScene: values.technicalScene,
+                        breakthrough: values.breakthrough,
+                        patentCase: values.patentCase,
+                        awards: values.awards,
+                        teamDes: values.teamDes,
+                        parameter: values.parameter,
+                        orgId: values.orgId,
+                        orgName: values.orgName,
+                        orgAddress: values.orgAddress,
+                        orgEmail: values.orgEmail,
+                        orgContacts: values.orgContacts,
+                        orgContactsMobile: values.orgContactsMobile,
+                        releaseStatus: values.releaseStatus,
+                        techPlanUrl: this.state.techPlanUrl,
+                        businessPlanUrl: this.state.businessPlanUrl
+                    }
+                }).done(function (data) {
+                    if (!data.error.length) {
+                        message.success('保存成功!');
+                        this.setState({
+                            visible: false
+                        });
+                        this.props.handleOk();
+                    } else {
+                        message.warning(data.error[0].message);
+                    }
+                }.bind(this));
+            }
+        });
+    },
+    componentWillMount() {
+        if (this.props.data.id) {
+            this.loadData(this.props.data.id);
+        } else {
+            this.state.data = {};
+        };
+    },
+    componentWillReceiveProps(nextProps) {
+        if (!this.props.visible && nextProps.visible) {
+            this.state.textFileList = [];
+            this.state.techPlanFileList = [];
+            this.state.businessPlanFileList = [];
+            if (nextProps.data.id) {
+                this.loadData(nextProps.data.id);
+            } else {
+                this.state.data = {};
+                this.state.tags = [];
+                this.state.maturityPictureUrl = [];
+                this.state.technicalPictureUrl = [];
+            };
+            this.props.form.resetFields();
+        };
+    },
+    render() {
+        const theData = this.state.data || {};
+        const { getFieldDecorator } = this.props.form;
+        const FormItem = Form.Item
+        const formItemLayout = {
+            labelCol: { span: 8 },
+            wrapperCol: { span: 14 },
+        };
+        return (
+            <Form horizontal onSubmit={this.handleSubmit} id="demand-form">
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="编号" >
+                        <span>{theData.serialNumber}</span>
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="名称" >
+                        {getFieldDecorator('name', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.name
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="数据类别" >
+                        {getFieldDecorator('dataCategory', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.dataCategory
+                        })(
+                            <Select placeholder="选择数据类型" style={{ width: 160 }} >
+                                <Select.Option value="0" >成果</Select.Option>
+                                <Select.Option value="1" >技术</Select.Option>
+                                <Select.Option value="2" >项目</Select.Option>
+                            </Select>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="类型" >
+                        {getFieldDecorator('category', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.category
+                        })(
+                            <Select style={{ width: 160 }} placeholder="请选择成果类型">
+                                {this.props.achievementCategoryOption}
+                            </Select>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="是否发布" >
+                        {getFieldDecorator('releaseStatus', {
+                            initialValue: theData.releaseStatus
+                        })(
+                            <Radio.Group>
+                                <Radio value="0">未发布</Radio>
+                                <Radio value="1">发布</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="发布时间" >
+                        <span>{theData.releaseDateFormattedDate}</span>
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="关键词" >
+                    <KeyWordTagGroup
+                        keyWordArr={this.state.tags}
+                        tagsArr={this.getTagsArr}
+                        visible={this.props.visible} />
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="摘要" >
+                    {getFieldDecorator('summary', {
+                        initialValue: theData.summary
+                    })(
+                        <Input type="textarea" rows={4} />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="成果简介" >
+                    {getFieldDecorator('introduction', {
+                        initialValue: theData.introduction
+                    })(
+                        <Input type="textarea" rows={4} placeholder="项目成果简介;项目核心创新点;项目详细用途;预期效益说明;主要技术(性能)指标;市场前景;应用范围;发展历程。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术图片" >
+                    <PicturesWall
+                        pictureSign="achievement_technical_picture"
+                        fileList={this.getTechnicalPictureUrl}
+                        pictureUrl={this.state.technicalPictureUrl} />
+                    <p>图片建议:专利证书或专利申请书图片、技术图纸、样品图片、技术相关网络图片;成熟度处于非研发阶段的项目,必须上传样品图片,如未上传,成熟度将视为处在研发阶段。</p>
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="应用领域" >
+                    {getFieldDecorator('field', {
+                        rules: [{ type: 'array', required: true, message: '此项为必填项!' }],
+                        initialValue: [theData.fieldA, theData.fieldB]
+                    })(
+                        <Cascader style={{ width: 300 }} options={IndustryObject} placeholder="应用领域" />
+                        )}
+                </FormItem>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="成熟度" >
+                        {getFieldDecorator('maturity', {
+                            initialValue: theData.maturity
+                        })(
+                            <Select placeholder="选择成熟度" style={{ width: 160 }} >
+                                <Select.Option value="0" >正在研发</Select.Option>
+                                <Select.Option value="1" >已有样品</Select.Option>
+                                <Select.Option value="2" >通过小试</Select.Option>
+                                <Select.Option value="3" >通过中试</Select.Option>
+                                <Select.Option value="4" >可以量产</Select.Option>
+                            </Select>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="创新度" >
+                        {getFieldDecorator('innovation', {
+                            initialValue: theData.innovation
+                        })(
+                            <Select placeholder="选择创新度" style={{ width: 160 }} >
+                                <Select.Option value="0" >行业先进</Select.Option>
+                                <Select.Option value="1" >行业领先</Select.Option>
+                                <Select.Option value="2" >国内先进</Select.Option>
+                                <Select.Option value="3" >国内领先</Select.Option>
+                                <Select.Option value="4" >国际先进</Select.Option>
+                                <Select.Option value="5" >国际领先</Select.Option>
+                            </Select>
+                            )}
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="成熟度证明材料(图片)" >
+                    <PicturesWall
+                        pictureSign="achievement_maturity_picture"
+                        fileList={this.getMaturityPictureUrl}
+                        pictureUrl={this.state.maturityPictureUrl} />
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 6 }}
+                    label="成熟度证明材料(文本)" >
+                    <Upload
+                        name="ratepay"
+                        action={globalConfig.context + "/api/user/achievement/uploadTextFile"}
+                        data={{ 'sign': 'achievement_maturity_text_file' }}
+                        beforeUpload={beforeUploadFile}
+                        fileList={this.state.textFileList}
+                        onChange={(info) => {
+                            if (info.file.status !== 'uploading') {
+                                console.log(info.file, info.fileList);
+                            }
+                            if (info.file.status === 'done') {
+                                if (!info.file.response.error.length) {
+                                    message.success(`${info.file.name} 文件上传成功!`);
+                                } else {
+                                    message.warning(info.file.response.error[0].message);
+                                    return;
+                                };
+                                this.state.maturityTextFileUrl = info.file.response.data;
+                            } else if (info.file.status === 'error') {
+                                message.error(`${info.file.name} 文件上传失败。`);
+                            };
+                            this.setState({ textFileList: info.fileList.slice(-1) });
+                        }} >
+                        <Button><Icon type="upload" /> 上传需求文本文件 </Button>
+                    </Upload>
+                    <p style={{ marginTop: '10px' }}>{theData.maturityTextFileUrl ?
+                        <span className="download-file">
+                            <a onClick={() => { window.open(globalConfig.context + '/api/user/achievement/download?id=' + this.props.data.id + '&sign=achievement_maturity_text_file') }}>成熟度证明材料(文本文件)</a>
+                        </span>
+                        : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="成熟度证明材料(视频地址)" >
+                    {getFieldDecorator('maturityVideoUrl', {
+                        initialValue: theData.maturityVideoUrl
+                    })(
+                        <Input />
+                        )}
+                </FormItem>
+                <div className="clearfix" >
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="成果所有人名称" >
+                        {getFieldDecorator('ownerName', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerName
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所有人证件号" >
+                        {getFieldDecorator('ownerIdNumber', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerIdNumber
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所有人联系电话" >
+                        {getFieldDecorator('ownerMobile', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerMobile
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所有人电子邮箱" >
+                        {getFieldDecorator('ownerEmail', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerEmail
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所有人通信地址" >
+                        {getFieldDecorator('ownerPostalAddress', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerPostalAddress
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                </div>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所有人类型" >
+                        {getFieldDecorator('ownerType', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.ownerType
+                        })(
+                            <Radio.Group onChange={(e) => { this.setState({ orgDisplay: e.target.value }); }}>
+                                <Radio value="0">个人</Radio>
+                                <Radio value="1">组织</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                </div>
+                <div className="clearfix" style={{ display: this.state.orgDisplay == '1' ? 'block' : 'none' }}>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所属组织名称" >
+                        {getFieldDecorator('orgName', {
+                            initialValue: theData.orgName
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所属组织地址" >
+                        {getFieldDecorator('orgAddress', {
+                            initialValue: theData.orgAddress
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所属组织邮箱" >
+                        {getFieldDecorator('orgEmail', {
+                            initialValue: theData.orgEmail
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所属组织联系人名称" >
+                        {getFieldDecorator('orgContacts', {
+                            initialValue: theData.orgContacts
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="所属组织联系人电话" >
+                        {getFieldDecorator('orgContactsMobile', {
+                            initialValue: theData.orgContactsMobile
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                </div>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="合作方式" >
+                        {getFieldDecorator('cooperationMode', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.cooperationMode
+                        })(
+                            <Radio.Group>
+                                <Radio value="0">技术转让</Radio>
+                                <Radio value="1">授权生产</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="转让方式" >
+                        {getFieldDecorator('transferMode', {
+                            initialValue: theData.transferMode
+                        })(
+                            <Select placeholder="选择转让方式" style={{ width: 160 }} >
+                                <Select.Option value="0" >完全转让</Select.Option>
+                                <Select.Option value="1" >许可转让</Select.Option>
+                                <Select.Option value="2" >技术入股</Select.Option>
+                            </Select>
+                            )}
+                    </FormItem>
+                </div>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="议价方式" >
+                        {getFieldDecorator('bargainingMode', {
+                            initialValue: theData.bargainingMode
+                        })(
+                            <Radio.Group>
+                                <Radio value="0">面议</Radio>
+                                <Radio value="1">定价</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="转让价格" >
+                        {getFieldDecorator('transferPrice', {
+                            initialValue: theData.transferPrice
+                        })(
+                            <InputNumber />
+                            )}
+                        <span style={{ marginLeft: '20px' }}>万元</span>
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术场景" >
+                    {getFieldDecorator('technicalScene', {
+                        initialValue: theData.technicalScene
+                    })(
+                        <Input type="textarea" rows={2} placeholder="说明解决了什么问题。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术突破" >
+                    {getFieldDecorator('breakthrough', {
+                        initialValue: theData.breakthrough
+                    })(
+                        <Input type="textarea" rows={2} placeholder="说明该技术成果突破性的研究。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="专利情况" >
+                    {getFieldDecorator('patentCase', {
+                        initialValue: theData.patentCase
+                    })(
+                        <Input type="textarea" rows={2} placeholder="一个“技术”可能由多个专利构成,需要说明技术-专利的关系。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="获奖情况" >
+                    {getFieldDecorator('awards', {
+                        initialValue: theData.awards
+                    })(
+                        <Input type="textarea" rows={2} placeholder="一个“技术”可能存在社会奖励情况,需要说明社会奖励情况。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术团队情况" >
+                    {getFieldDecorator('teamDes', {
+                        initialValue: theData.teamDes
+                    })(
+                        <Input type="textarea" rows={2} placeholder="一个“技术”、“项目”可能存在团队,需要说明团队情况。" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术参数" >
+                    {getFieldDecorator('parameter', {
+                        initialValue: theData.parameter
+                    })(
+                        <Input type="textarea" rows={2} placeholder="描述技术参数信息" />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 6 }}
+                    label="技术方案" >
+                    <Upload
+                        name="ratepay"
+                        action={globalConfig.context + "/api/user/achievement/uploadTextFile"}
+                        data={{ 'sign': 'achievement_tech_plan' }}
+                        beforeUpload={beforeUploadFile}
+                        fileList={this.state.techPlanFileList}
+                        onChange={(info) => {
+                            if (info.file.status !== 'uploading') {
+                                console.log(info.file, info.fileList);
+                            }
+                            if (info.file.status === 'done') {
+                                if (!info.file.response.error.length) {
+                                    message.success(`${info.file.name} 文件上传成功!`);
+                                } else {
+                                    message.warning(info.file.response.error[0].message);
+                                    return;
+                                };
+                                this.state.techPlanUrl = info.file.response.data;
+                            } else if (info.file.status === 'error') {
+                                message.error(`${info.file.name} 文件上传失败。`);
+                            };
+                            this.setState({ techPlanFileList: info.fileList.slice(-1) });
+                        }} >
+                        <Button><Icon type="upload" /> 上传技术方案文件 </Button>
+                    </Upload>
+                    <p style={{ marginTop: '10px' }}>{theData.techPlanUrl ?
+                        <span className="download-file">
+                            <a onClick={() => { window.open(globalConfig.context + '/api/user/achievement/download?id=' + this.props.data.id + '&sign=achievement_tech_plan') }}>技术方案</a>
+                        </span>
+                        : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 6 }}
+                    label="商业计划书" >
+                    <Upload
+                        name="ratepay"
+                        action={globalConfig.context + "/api/user/achievement/uploadTextFile"}
+                        data={{ 'sign': 'achievement_business_plan' }}
+                        beforeUpload={beforeUploadFile}
+                        fileList={this.state.businessPlanFileList}
+                        onChange={(info) => {
+                            if (info.file.status !== 'uploading') {
+                                console.log(info.file, info.fileList);
+                            }
+                            if (info.file.status === 'done') {
+                                if (!info.file.response.error.length) {
+                                    message.success(`${info.file.name} 文件上传成功!`);
+                                } else {
+                                    message.warning(info.file.response.error[0].message);
+                                    return;
+                                };
+                                this.state.businessPlanUrl = info.file.response.data;
+                            } else if (info.file.status === 'error') {
+                                message.error(`${info.file.name} 文件上传失败。`);
+                            };
+                            this.setState({ businessPlanFileList: info.fileList.slice(-1) });
+                        }} >
+                        <Button><Icon type="upload" /> 上传商业计划书文件 </Button>
+                    </Upload>
+                    <p style={{ marginTop: '10px' }}>{theData.businessPlanUrl ?
+                        <span className="download-file">
+                            <a onClick={() => { window.open(globalConfig.context + '/api/user/achievement/download?id=' + this.props.data.id + '&sign=achievement_business_plan') }}>商业计划书</a>
+                        </span>
+                        : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
+                </FormItem>
+                <FormItem wrapperCol={{ span: 12, offset: 3 }}>
+                    <Button className="set-submit" type="primary" htmlType="submit">保存</Button>
+                    <Button className="set-submit" type="ghost" onClick={this.props.closeDesc}>取消</Button>
+                </FormItem>
+            </Form >
+        )
+    }
+}));
+
+const AchievementDetail = React.createClass({
+    getInitialState() {
+        return {
+            visible: false
+        };
+    },
+    showModal() {
+        this.setState({
+            visible: true,
+        });
+    },
+    handleCancel(e) {
+        this.setState({
+            visible: false,
+        });
+        this.props.closeDesc(false);
+    },
+    handleOk(e) {
+        this.setState({
+            visible: false,
+        });
+        this.props.closeDesc(false, true);
+    },
+    componentWillReceiveProps(nextProps) {
+        this.state.visible = nextProps.showDesc;
+    },
+    render() {
+        if (this.props.data) {
+            return (
+                <div className="patent-desc">
+                    <Modal maskClosable={false} title="成果详情" visible={this.state.visible}
+                        onOk={this.checkPatentProcess} onCancel={this.handleCancel}
+                        width='1000px'
+                        footer=''
+                        className="admin-desc-content">
+                        <AchievementDetailForm
+                            data={this.props.data}
+                            achievementCategoryOption={this.props.achievementCategoryOption}
+                            closeDesc={this.handleCancel}
+                            visible={this.state.visible}
+                            handleOk={this.handleOk} />
+                    </Modal>
+                </div>
+            );
+        } else {
+            return <div></div>
+        }
+    },
+});
+
+export default AchievementDetail;

+ 47 - 0
js/component/account/demand/content.jsx

@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import '../content.less';
+import LeftTab from './leftTab';
+import TechDemand from './techDemand';
+
+
+class Content extends Component {
+    constructor() {
+        super();
+        this.state = {
+            loading: false,
+            component: 'div'
+        };
+    }
+    componentWillMount() {
+        if (window.location.hash) {
+            this.getKey(window.location.hash.substr(1));
+        } else {
+            this.getKey("techDemand");
+        };
+    }
+    getKey(key) {
+        switch (key) {
+            case 'techDemand':
+                require.ensure([], () => {
+                    const TechDemand = require('./techDemand').default;
+                    this.setState({
+                        component: TechDemand
+                    });
+                });
+                break;
+        };
+        window.location.hash = key;
+    }
+    render() {
+        return (
+            <div className="acc-content">
+                <LeftTab handlekey={this.getKey.bind(this)} />
+                <div className="content-right">
+                    <this.state.component />
+                </div>
+            </div>
+        )
+    }
+}
+
+export default Content;

+ 40 - 0
js/component/account/demand/leftTab.jsx

@@ -0,0 +1,40 @@
+import React from 'react';
+import { Menu, Icon } from 'antd';
+import '../leftTab.less';
+const SubMenu = Menu.SubMenu;
+const MenuItemGroup = Menu.ItemGroup;
+
+
+const LeftTab = React.createClass({
+    getInitialState() {
+        return {
+            current: 'techDemand'
+        };
+    },
+    handleClick(e) {
+        this.props.handlekey(e.key);
+        this.setState({
+            current: e.key,
+        });
+    },
+    componentWillMount() {
+        if (window.location.hash) {
+            this.state.current = window.location.hash.substr(1);
+        };
+    },
+    render() {
+        return (
+            <Menu onClick={this.handleClick}
+                selectedKeys={[this.state.current]}
+                mode="vertical"
+                className="account-left"
+            >
+                <Menu.Item key="techDemand">
+                    科技需求列表
+                </Menu.Item>
+            </Menu>
+        );
+    },
+});
+
+export default LeftTab;

+ 311 - 0
js/component/account/demand/techDemand.jsx

@@ -0,0 +1,311 @@
+import React from 'react';
+import { Icon, Button, Input, Select, Spin, Table, Switch, message, DatePicker, Modal } from 'antd';
+import ajax from 'jquery/src/ajax/xhr.js';
+import $ from 'jquery/src/ajax';
+import moment from 'moment';
+import './techDemand.less';
+import TechDemandDesc from './techDemandDesc.jsx';
+import { provinceArr, demandTypeList } from '../../dataDic.js';
+import { companySearch, getDemandType } from '../../tools.js';
+
+const DemandList = React.createClass({
+    loadData(pageNo) {
+        this.state.data = [];
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/user/demand/list",
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: this.state.pagination.pageSize,
+                serialNumber: this.state.serialNumber,
+                name: this.state.name,
+                keyword: this.state.keyword,
+                demandType: this.state.demandType ? Number(this.state.demandType) : undefined,
+                status: this.state.status ? Number(this.state.status) : undefined,
+                releaseStatus: this.state.releaseStatus ? Number(this.state.releaseStatus) : undefined,
+                validityPeriodStartDate: this.state.validityPeriodDate[0],
+                validityPeriodEndDate: this.state.validityPeriodDate[1],
+                releaseDateStartDate: this.state.releaseDate[0],
+                releaseDateEndDate: this.state.releaseDate[1],
+            },
+            success: function (data) {
+                let theArr = [];
+                if (!data.data && !data.data.list) {
+                    if (data.error && data.error.length) {
+                        message.warning(data.error[0].message);
+                    };
+                } else {
+                    for (let i = 0; i < data.data.list.length; i++) {
+                        let thisdata = data.data.list[i];
+                        theArr.push({
+                            key: i,
+                            id: thisdata.id,
+                            serialNumber: thisdata.serialNumber,
+                            dataCategory: thisdata.dataCategory,
+                            name: thisdata.name,
+                            keyword: thisdata.keyword,
+                            releaseDate: thisdata.releaseDate,
+                            demandType: thisdata.demandType,
+                            validityPeriod: thisdata.validityPeriod,
+                            status: thisdata.status,
+                            releaseStatus: thisdata.releaseStatus,
+                            employerId: thisdata.employerId,
+                            releaseDateFormattedDate: thisdata.releaseDateFormattedDate,
+                            validityPeriodFormattedDate: thisdata.validityPeriodFormattedDate
+                        });
+                    };
+                }
+                this.state.pagination.current = data.data.pageNo;
+                this.state.pagination.total = data.data.totalCount;
+                this.setState({
+                    dataSource: theArr,
+                    pagination: this.state.pagination
+                });
+            }.bind(this),
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this));
+    },
+    getInitialState() {
+        return {
+            searchMore: true,
+            validityPeriodDate: [],
+            releaseDate: [],
+            selectedRowKeys: [],
+            selectedRows: [],
+            loading: false,
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+            columns: [
+                {
+                    title: '编号',
+                    dataIndex: 'serialNumber',
+                    key: 'serialNumber',
+                }, {
+                    title: '需求名称',
+                    dataIndex: 'name',
+                    key: 'name',
+                }, {
+                    title: '关键字',
+                    dataIndex: 'keyword',
+                    key: 'keyword',
+                }, {
+                    title: '需求类型',
+                    dataIndex: 'demandType',
+                    key: 'demandType',
+                    render: text => { return getDemandType(text); }
+                }, {
+                    title: '需求状态',
+                    dataIndex: 'status',
+                    key: 'status',
+                    render: text => {
+                        switch (text) {
+                            case "0":
+                                return <span>进行中</span>;
+                            case "1":
+                                return <span>未解决</span>;
+                            case "2":
+                                return <span>已解决</span>;
+                        }
+                    }
+                }, {
+                    title: '有效期限',
+                    dataIndex: 'validityPeriodFormattedDate',
+                    key: 'validityPeriodFormattedDate',
+                }, {
+                    title: '发布时间',
+                    dataIndex: 'releaseDateFormattedDate',
+                    key: 'releaseDateFormattedDate',
+                }
+            ],
+            dataSource: [],
+            searchTime: [,]
+        };
+    },
+    componentWillMount() {
+        let theArr = [];
+        demandTypeList.map(function (item) {
+            theArr.push(
+                <Select.Option value={item.value} key={item.key}>{item.key}</Select.Option>
+            )
+        });
+        this.state.demandTypeOption = theArr;
+        this.loadData();
+    },
+    tableRowClick(record, index) {
+        this.state.RowData = record;
+        this.setState({
+            showDesc: true
+        });
+    },
+    delectRow() {
+        let deletedIds = [];
+        for (let idx = 0; idx < this.state.selectedRows.length; idx++) {
+            let rowItem = this.state.selectedRows[idx];
+            if (rowItem.id) {
+                deletedIds.push(rowItem.id)
+            };
+        };
+        this.setState({
+            selectedRowKeys: [],
+            loading: deletedIds.length > 0
+        });
+        $.ajax({
+            method: "POST",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/user/demand/delete",
+            data: {
+                ids: deletedIds
+            }
+        }).done(function (data) {
+            if (!data.error.length) {
+                message.success('删除成功!');
+                this.setState({
+                    loading: false,
+                });
+            } else {
+                message.warning(data.error[0].message);
+            };
+            this.loadData();
+        }.bind(this));
+    },
+    addClick() {
+        this.state.RowData = {};
+        this.setState({
+            showDesc: true
+        });
+    },
+    closeDesc(e, s) {
+        this.state.showDesc = e;
+        if (s) {
+            this.loadData();
+        };
+    },
+    search() {
+        this.loadData();
+    },
+    reset() {
+        this.state.serialNumber = undefined;
+        this.state.name = undefined;
+        this.state.keyword = undefined;
+        this.state.demandType = undefined;
+        this.state.username = undefined;
+        this.state.status = undefined;
+        this.state.releaseStatus = undefined;
+        this.state.validityPeriodDate = [];
+        this.state.releaseDate = [];
+        this.loadData();
+    },
+    searchSwitch() {
+        this.setState({
+            searchMore: !this.state.searchMore
+        });
+    },
+    render() {
+        const rowSelection = {
+            selectedRowKeys: this.state.selectedRowKeys,
+            onChange: (selectedRowKeys, selectedRows) => {
+                this.setState({
+                    selectedRows: selectedRows,
+                    selectedRowKeys: selectedRowKeys
+                });
+            }
+        };
+        const hasSelected = this.state.selectedRowKeys.length > 0;
+        const { RangePicker } = DatePicker;
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span>科技需求管理</span>
+                    <div className="patent-addNew">
+                        <Button type="primary" onClick={this.addClick}>新增需求<Icon type="plus" /></Button>
+                    </div>
+                </div>
+                <div className="user-search">
+                    <Input placeholder="需求编号"
+                        value={this.state.serialNumber}
+                        onChange={(e) => { this.setState({ serialNumber: e.target.value }); }} />
+                    <Input placeholder="需求名称"
+                        value={this.state.name}
+                        onChange={(e) => { this.setState({ name: e.target.value }); }} />
+                    <Input placeholder="关键字"
+                        value={this.state.keyword}
+                        onChange={(e) => { this.setState({ keyword: e.target.value }); }} />
+                    <Select placeholder="选择需求类型"
+                        style={{ width: 120 }}
+                        value={this.state.demandType}
+                        onChange={(e) => { this.setState({ demandType: e }) }}>
+                        {this.state.demandTypeOption}
+                    </Select>
+                    <Select placeholder="选择需求状态" style={{ width: 120 }}
+                        value={this.state.status}
+                        onChange={(e) => { this.setState({ status: e }) }}>
+                        <Select.Option value="0" >进行中</Select.Option>
+                        <Select.Option value="1" >未解决</Select.Option>
+                        <Select.Option value="2" >已解决</Select.Option>
+                    </Select>
+                    <Select placeholder="选择是否发布" style={{ width: 120 }}
+                        value={this.state.releaseStatus}
+                        onChange={(e) => { this.setState({ releaseStatus: e }) }}>
+                        <Select.Option value="0" >未发布</Select.Option>
+                        <Select.Option value="1" >已发布</Select.Option>
+                    </Select>
+                    <Button type="primary" onClick={this.search}>搜索</Button>
+                    <Button onClick={this.reset}>重置</Button>
+                    <Button style={{ background: "#3fcf9e", border: "none", color: "#fff" }}
+                        disabled={!hasSelected}
+                        onClick={this.delectRow}>删除<Icon type="minus" /></Button>
+                    <span>更多搜索<Switch defaultChecked={false} onChange={this.searchSwitch} /></span>
+                    <div className="search-more" style={this.state.searchMore ? { display: 'none' } : {}}>
+                        <p>
+                            <span>有效期限 :</span>
+                            <RangePicker
+                                value={[this.state.validityPeriodDate[0] ? moment(this.state.validityPeriodDate[0]) : null,
+                                this.state.validityPeriodDate[1] ? moment(this.state.validityPeriodDate[1]) : null]}
+                                onChange={(data, dataString) => { this.setState({ validityPeriodDate: dataString }); }} />
+                            <span>发布时间 :</span>
+                            <RangePicker
+                                value={[this.state.releaseDate[0] ? moment(this.state.releaseDate[0]) : null,
+                                this.state.releaseDate[1] ? moment(this.state.releaseDate[1]) : null]}
+                                onChange={(data, dataString) => { this.setState({ releaseDate: dataString }); }} />
+                        </p>
+                    </div>
+                </div>
+                <div className="patent-table">
+                    <Spin spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                            dataSource={this.state.dataSource}
+                            rowSelection={rowSelection}
+                            pagination={this.state.pagination}
+                            onRowClick={this.tableRowClick} />
+                    </Spin>
+                </div>
+                <TechDemandDesc
+                    data={this.state.RowData}
+                    demandTypeOption={this.state.demandTypeOption}
+                    showDesc={this.state.showDesc}
+                    closeDesc={this.closeDesc} />
+            </div >
+        );
+    }
+});
+
+export default DemandList;

+ 72 - 0
js/component/account/demand/techDemand.less

@@ -0,0 +1,72 @@
+.user-content {
+    background: #fff;
+    padding: 20px;
+    .content-title {
+        color: #333;
+        font-size: 16px;
+    }
+    .user-search {
+        margin-bottom: 10px;
+        >input {
+            width: 140px;
+        }
+        >input,
+        >button,
+        .ant-select {
+            margin-right: 10px;
+            margin-top: 10px;
+        }
+        .ant-switch {
+            margin-left: 10px;
+        }
+        .search-more {
+            margin: 10px 0;
+            >p {
+                span {
+                    margin-right: 10px
+                }
+            }
+        }
+    }
+}
+
+.patent-addNew {
+    float: right;
+    margin-left: 20px;
+    button {
+        background: #ea0862;
+        color: #fff;
+        border: none;
+        border-radius: 4px;
+        padding: 6px 10px;
+        margin-left: 20px;
+    }
+    button:hover {
+        background: #ea0862;
+    }
+}
+
+#demand-form {
+    .half-item {
+        float: left;
+        width: 50%;
+        margin-bottom: 10px;
+    }
+    .item-title {
+        line-height: 30px;
+        font-size: 14px;
+        color: #666;
+    }
+    .form-title {
+        font-size: 16px;
+        color: #333;
+    }
+    .keyWord-tips {
+        >button {
+            vertical-align: middle;
+        }
+    }
+    .set-submit {
+        margin-right: 20px;
+    }
+}

+ 625 - 0
js/component/account/demand/techDemandDesc.jsx

@@ -0,0 +1,625 @@
+import React from 'react';
+import { Icon, Tooltip, Modal, message, Spin, Upload, Input, InputNumber, Select, DatePicker, Button, Radio, Form, Cascader, Tag } from 'antd';
+import moment from 'moment';
+import './techDemand.less';
+import ajax from 'jquery/src/ajax/xhr.js';
+import $ from 'jquery/src/ajax';
+import { IndustryObject } from '../../DicIndustryList.js';
+import { beforeUploadFile, splitUrl, companySearch } from '../../tools.js';
+
+const KeyWordTagGroup = React.createClass({
+    getInitialState() {
+        return {
+            tags: [],
+            inputVisible: false,
+            inputValue: ''
+        };
+    },
+    handleClose(removedTag) {
+        const tags = this.state.tags.filter(tag => tag !== removedTag);
+        this.props.tagsArr(tags);
+        this.setState({ tags });
+    },
+    showInput() {
+        this.setState({ inputVisible: true }, () => this.input.focus());
+    },
+    handleInputChange(e) {
+        this.setState({ inputValue: e.target.value });
+    },
+    handleInputConfirm() {
+        const state = this.state;
+        const inputValue = state.inputValue;
+        let tags = state.tags;
+        if (inputValue && tags.indexOf(inputValue) === -1) {
+            tags = [...tags, inputValue];
+        }
+        this.props.tagsArr(tags);
+        this.setState({
+            tags,
+            inputVisible: false,
+            inputValue: '',
+        });
+    },
+    componentWillMount() {
+        this.state.tags = this.props.keyWordArr;
+    },
+    componentWillReceiveProps(nextProps) {
+        if (this.props.keyWordArr != nextProps.keyWordArr) {
+            this.state.tags = nextProps.keyWordArr;
+        };
+    },
+    render() {
+        const { tags, inputVisible, inputValue } = this.state;
+        return (
+            <div className="keyWord-tips">
+                {tags.map((tag, index) => {
+                    const isLongTag = tag.length > 10;
+                    const tagElem = (
+                        <Tag key={tag} closable={index !== -1} afterClose={() => this.handleClose(tag)}>
+                            {isLongTag ? `${tag.slice(0, 10)}...` : tag}
+                        </Tag>
+                    );
+                    return isLongTag ? <Tooltip title={tag}>{tagElem}</Tooltip> : tagElem;
+                })}
+                {inputVisible && (
+                    <Input
+                        ref={input => this.input = input}
+                        type="text"
+                        style={{ width: 78 }}
+                        value={inputValue}
+                        onChange={this.handleInputChange}
+                        onBlur={this.handleInputConfirm}
+                        onPressEnter={this.handleInputConfirm}
+                    />
+                )}
+                {!inputVisible && <Button className="addtips" type="dashed" disabled={tags.length > 9 ? true : false} onClick={this.showInput}>+ 新关键词</Button>}
+            </div>
+        );
+    }
+});
+
+const PicturesWall = React.createClass({
+    getInitialState() {
+        return {
+            previewVisible: false,
+            previewImage: '',
+            fileList: [],
+        }
+    },
+    handleCancel() {
+        this.setState({ previewVisible: false })
+    },
+    handlePreview(file) {
+        this.setState({
+            previewImage: file.url || file.thumbUrl,
+            previewVisible: true,
+        });
+    },
+    handleChange(info) {
+        let fileList = info.fileList;
+        this.setState({ fileList });
+        this.props.fileList(fileList);
+    },
+    componentWillReceiveProps(nextProps) {
+        this.state.fileList = nextProps.pictureUrl;
+    },
+    render() {
+        const { previewVisible, previewImage, fileList } = this.state;
+        const uploadButton = (
+            <div>
+                <Icon type="plus" />
+                <div className="ant-upload-text">点击上传</div>
+            </div>
+        );
+        return (
+            <div className="clearfix">
+                <Upload
+                    action={globalConfig.context + "/api/user/demand/uploadPicture"}
+                    data={{ 'sign': 'demand_picture' }}
+                    listType="picture-card"
+                    fileList={fileList}
+                    onPreview={this.handlePreview}
+                    onChange={this.handleChange} >
+                    {fileList.length >= 5 ? null : uploadButton}
+                </Upload>
+                <Modal maskClosable={false} visible={previewVisible} footer={null} onCancel={this.handleCancel}>
+                    <img alt="example" style={{ width: '100%' }} src={previewImage} />
+                </Modal>
+            </div>
+        );
+    }
+});
+
+const DemandDetailForm = Form.create()(React.createClass({
+    getInitialState() {
+        return {
+            visible: false,
+            loading: false,
+            textFileList: [],
+            videoFileList: [],
+            pictureUrl: [],
+            tags: []
+        };
+    },
+    loadData(id) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + (window.userData.type == 0 ? '/api/user/demand/userDemandDetail' : '/api/user/demand/orgDemandDetail'),
+            data: {
+                id: id
+            },
+            success: function (data) {
+                let thisData = data.data;
+                if (!thisData) {
+                    if (data.error && data.error.length) {
+                        message.warning(data.error[0].message);
+                    };
+                    thisData = {};
+                };
+                let d = new Date()
+                if (thisData && thisData.dateOfBirthMonth && thisData.dateOfBirthYear) {
+                    d.setMonth(thisData.dateOfBirthMonth - 1);
+                    d.setYear(parseInt(thisData.dateOfBirthYear));
+                };
+                this.setState({
+                    data: thisData,
+                    tags: thisData.keyword ? thisData.keyword.split(",") : [],
+                    pictureUrl: thisData.pictureUrl ? splitUrl(thisData.pictureUrl, ',', globalConfig.avatarHost + '/upload') : []
+                });
+            }.bind(this),
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this));
+    },
+    getContactsList() {
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/user/cognizance/getContacts",
+            success: function (data) {
+                let theOption = [];
+                if (data.error.length || !data.data) {
+                    return;
+                };
+                for (let item in data.data) {
+                    let theData = data.data[item];
+                    theOption.push(
+                        <Select.Option value={item} key={theData}>{theData}</Select.Option>
+                    );
+                };
+                this.setState({
+                    contactsOption: theOption
+                });
+            }.bind(this),
+        });
+    },
+    getTagsArr(e) {
+        this.setState({ tags: e });
+    },
+    getPictureUrl(e) {
+        this.setState({ pictureUrl: e });
+    },
+    handleSubmit(e) {
+        e.preventDefault();
+        this.props.form.validateFields((err, values) => {
+            //keyword长度判断
+            if (this.state.tags.length < 3) {
+                message.warning('关键词数量不能小于3个!');
+            };
+            //url转化
+            let thePictureUrl = [];
+            if (this.state.pictureUrl.length) {
+                let picArr = [];
+                this.state.pictureUrl.map(function (item) {
+                    picArr.push(item.response.data);
+                });
+                thePictureUrl = picArr.join(",");
+            };
+            if (!err) {
+                this.setState({
+                    loading: true
+                });
+                $.ajax({
+                    method: "POST",
+                    dataType: "json",
+                    crossDomain: false,
+                    url: this.props.data.id ? globalConfig.context + '/api/user/demand/update' : globalConfig.context + '/api/user/demand/apply',
+                    data: {
+                        id: this.props.data.id,
+                        dataCategory: window.userData.type ? Number(window.userData.type) : undefined,
+                        serialNumber: this.props.data.serialNumber,
+                        name: values.name,
+                        keyword: this.state.tags ? this.state.tags.join(",") : [],
+                        industryCategoryA: values.industryCategory ? values.industryCategory[0] : undefined,
+                        industryCategoryB: values.industryCategory ? values.industryCategory[1] : undefined,
+                        demandType: values.demandType,
+                        problemDes: values.problemDes,
+                        technicalRequirements: values.technicalRequirements,
+                        pictureUrl: thePictureUrl,
+                        textFileUrl: this.state.textFileUrl,
+                        videoUrl: values.videoUrl,
+                        fixedBudget: values.fixedBudget,
+                        fixedCycle: values.fixedCycle,
+                        peopleNumber: values.peopleNumber,
+                        fixedScheme: values.fixedScheme,
+                        costEscrow: values.costEscrow,
+                        budgetCost: values.budgetCost,
+                        releaseStatus: values.releaseStatus,
+                        principalId: values.principalId,
+                        validityPeriodFormattedDate: values.validityPeriod ? values.validityPeriod.format('YYYY-MM-DD') : undefined,
+                        //
+                        contacts: values.contacts,
+                        status: this.state.status
+                    }
+                }).done(function (data) {
+                    if (!data.error.length) {
+                        message.success('保存成功!');
+                        this.setState({
+                            visible: false
+                        });
+                        this.props.handleOk();
+                    } else {
+                        message.warning(data.error[0].message);
+                    }
+                }.bind(this));
+            }
+        });
+    },
+    componentWillMount() {
+        if (window.userData.type == "1") {
+            this.getContactsList();
+        };
+        if (this.props.data.id) {
+            this.loadData(this.props.data.id);
+        } else {
+            this.state.data = {};
+        };
+    },
+    componentWillReceiveProps(nextProps) {
+        if (!this.props.visible && nextProps.visible) {
+            this.state.textFileList = [];
+            this.state.videoFileList = [];
+            if (nextProps.data.id) {
+                this.loadData(nextProps.data.id);
+            } else {
+                this.state.data = {};
+                this.state.tags = [];
+                this.state.pictureUrl = [];
+            };
+            this.props.form.resetFields();
+        };
+    },
+    render() {
+        const theData = this.state.data || {};
+        const { getFieldDecorator } = this.props.form;
+        const FormItem = Form.Item
+        const formItemLayout = {
+            labelCol: { span: 6 },
+            wrapperCol: { span: 12 },
+        };
+        return (
+            <Form horizontal onSubmit={this.handleSubmit} id="demand-form">
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="编号" >
+                        <span>{theData.serialNumber}</span>
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="需求名称" >
+                        {getFieldDecorator('name', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.name
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    {window.userData.type == "1" ? <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="联系人" >
+                        {getFieldDecorator('contacts', {
+                            initialValue: theData.contacts
+                        })(
+                            <Select style={{ width: 260 }}
+                                placeholder="请选择联系人"
+                                notFoundContent="未获取到联系人列表"
+                                showSearch
+                                filterOption={companySearch}>
+                                {this.state.contactsOption}
+                            </Select>
+                            )}
+                    </FormItem> : <div></div>}
+                </div>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="是否发布" >
+                        {getFieldDecorator('releaseStatus', {
+                            initialValue: theData.releaseStatus
+                        })(
+                            <Radio.Group>
+                                <Radio value="0">未发布</Radio>
+                                <Radio value="1">发布</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="发布时间" >
+                        <span>{theData.releaseDateFormattedDate}</span>
+                    </FormItem>
+                </div>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="需求状态" >
+                        {(() => {
+                            if (theData.status > 1) {
+                                return <Radio.Group
+                                    value={this.state.status}
+                                    onChange={(e) => { this.setState({ status: e }); }}>
+                                    <Radio value="2">未解决</Radio>
+                                    <Radio value="3">已解决</Radio>
+                                </Radio.Group>
+                            } else {
+                                switch (theData.status) {
+                                    case "0":
+                                        return <span>草稿</span>;
+                                    case "1":
+                                        return <span>进行中</span>;
+                                };
+                            };
+                        })()}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="需求创建时间" >
+                        <span>{theData.createTimeFormattedDate}</span>
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 20 }}
+                    label="关键词" >
+                    <KeyWordTagGroup
+                        keyWordArr={this.state.tags}
+                        tagsArr={this.getTagsArr}
+                        visible={this.props.visible} />
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="行业类别" >
+                    {getFieldDecorator('industryCategory', {
+                        rules: [{ type: 'array', required: true, message: '此项为必填项!' }],
+                        initialValue: [theData.industryCategoryA, theData.industryCategoryB]
+                    })(
+                        <Cascader style={{ width: 300 }} options={IndustryObject} placeholder="请选择一个行业" />
+                        )}
+                </FormItem>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="需求类型" >
+                        {getFieldDecorator('demandType', {
+                            rules: [{ required: true, message: '此项为必填项!' }],
+                            initialValue: theData.demandType
+                        })(
+                            <Select style={{ width: 160 }} placeholder="请选择需求类型">
+                                {this.props.demandTypeOption}
+                            </Select>
+                            )}
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="问题说明" >
+                    {getFieldDecorator('problemDes', {
+                        rules: [{ required: true, message: '此项为必填项!' }],
+                        initialValue: theData.problemDes
+                    })(
+                        <Input type="textarea" rows={4} />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="技术指标要求" >
+                    {getFieldDecorator('technicalRequirements', {
+                        initialValue: theData.technicalRequirements
+                    })(
+                        <Input type="textarea" rows={2} />
+                        )}
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="需求文件(图片)" >
+                    <PicturesWall
+                        uid={theData.uid}
+                        fileList={this.getPictureUrl}
+                        pictureUrl={this.state.pictureUrl}
+                        visible={this.props.visible} />
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 6 }}
+                    label="需求文件(文本)" >
+                    <Upload
+                        name="ratepay"
+                        action={globalConfig.context + "/api/user/demand/uploadTextFile"}
+                        data={{ 'sign': 'demand_text_file'}}
+                        beforeUpload={beforeUploadFile}
+                        fileList={this.state.textFileList}
+                        onChange={(info) => {
+                            if (info.file.status !== 'uploading') {
+                                console.log(info.file, info.fileList);
+                            }
+                            if (info.file.status === 'done') {
+                                if (!info.file.response.error.length) {
+                                    message.success(`${info.file.name} 文件上传成功!`);
+                                } else {
+                                    message.warning(info.file.response.error[0].message);
+                                    return;
+                                };
+                                this.state.textFileUrl = info.file.response.data;
+                            } else if (info.file.status === 'error') {
+                                message.error(`${info.file.name} 文件上传失败。`);
+                            };
+                            this.setState({ textFileList: info.fileList.slice(-1) });
+                        }} >
+                        <Button><Icon type="upload" /> 上传需求文本文件 </Button>
+                    </Upload>
+                    <p style={{ marginTop: '10px' }}>{theData.textFileUrl ?
+                        <span className="download-file">
+                            <a onClick={() => { window.open(globalConfig.context + '/api/user/demand/download?id=' + this.props.data.id) }}>需求文件(文本文件)</a>
+                        </span>
+                        : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
+                </FormItem>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="需求文件(视频地址)" >
+                    {getFieldDecorator('videoUrl', {
+                        initialValue: theData.videoUrl
+                    })(
+                        <Input />
+                        )}
+                </FormItem>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="固定周期" >
+                        {getFieldDecorator('fixedCycle', {
+                            initialValue: theData.fixedCycle
+                        })(
+                            <Input />
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="固定人数" >
+                        {getFieldDecorator('peopleNumber', {
+                            initialValue: theData.peopleNumber
+                        })(
+                            <InputNumber />
+                            )}
+                        <span style={{ marginLeft: '20px' }}>人</span>
+                    </FormItem>
+                </div>
+                <FormItem
+                    labelCol={{ span: 3 }}
+                    wrapperCol={{ span: 18 }}
+                    label="固定方案" >
+                    {getFieldDecorator('fixedScheme', {
+                        initialValue: theData.fixedScheme
+                    })(
+                        <Input type="textarea" rows={2} />
+                        )}
+                </FormItem>
+                <div className="clearfix">
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="预算费用" >
+                        {getFieldDecorator('budgetCost', {
+                            initialValue: theData.budgetCost
+                        })(
+                            <InputNumber />
+                            )}
+                        <span style={{ marginLeft: '20px' }}>万元</span>
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="费用托管" >
+                        {getFieldDecorator('costEscrow', {
+                            initialValue: theData.costEscrow
+                        })(
+                            <Radio.Group>
+                                <Radio value={0}>否</Radio>
+                                <Radio value={1}>是</Radio>
+                            </Radio.Group>
+                            )}
+                    </FormItem>
+                    <FormItem className="half-item"
+                        {...formItemLayout}
+                        label="有效期限" >
+                        {getFieldDecorator('validityPeriod', {
+                            initialValue: theData.validityPeriod ? moment(theData.validityPeriod) : null
+                        })(
+                            <DatePicker />
+                            )}
+                    </FormItem>
+                </div>
+                <FormItem wrapperCol={{ span: 12, offset: 3 }}>
+                    <Button className="set-submit" type="primary" htmlType="submit">保存</Button>
+                    <Button className="set-submit" type="ghost" onClick={this.props.closeDesc}>取消</Button>
+                </FormItem>
+            </Form >
+        )
+    }
+}));
+
+const DemandDetail = React.createClass({
+    getInitialState() {
+        return {
+            visible: false
+        };
+    },
+    showModal() {
+        this.setState({
+            visible: true,
+        });
+    },
+    handleCancel(e) {
+        this.setState({
+            visible: false,
+        });
+        this.props.closeDesc(false);
+    },
+    handleOk(e) {
+        this.setState({
+            visible: false,
+        });
+        this.props.closeDesc(false, true);
+    },
+    componentWillReceiveProps(nextProps) {
+        this.state.visible = nextProps.showDesc;
+    },
+    render() {
+        if (this.props.data) {
+            return (
+                <div className="patent-desc">
+                    <Modal maskClosable={false} title="用户需求详情" visible={this.state.visible}
+                        onOk={this.checkPatentProcess} onCancel={this.handleCancel}
+                        width='1000px'
+                        footer=''
+                        className="admin-desc-content">
+                        <DemandDetailForm
+                            data={this.props.data}
+                            detailApiUrl={this.props.detailApiUrl}
+                            companyOption={this.props.companyOption}
+                            userOption={this.props.userOption}
+                            demandTypeOption={this.props.demandTypeOption}
+                            closeDesc={this.handleCancel}
+                            visible={this.state.visible}
+                            handleOk={this.handleOk} />
+                    </Modal>
+                </div>
+            );
+        } else {
+            return <div></div>
+        }
+    },
+});
+
+export default DemandDetail;

+ 31 - 43
js/component/account/services/contract/contract.jsx

@@ -12,7 +12,6 @@ import './contract.less';
 
 const Contract = React.createClass({
     loadData(pageNo) {
-        this.state.data = [];
         this.setState({
             loading: true
         });
@@ -26,7 +25,7 @@ const Contract = React.createClass({
                 pageSize: this.state.pagination.pageSize,
                 type: this.state.contractType,
                 status: this.state.contractState,
-                contractId: this.state.contractId,
+                serialNumber: this.state.serialNumber,
                 startDateFormattedDate: this.state.startDateFormattedDate,
                 endDateFormattedDate: this.state.endDateFormattedDate,
             },
@@ -52,7 +51,7 @@ const Contract = React.createClass({
                         status: thisdata.status,
                         completeDate: thisdata.completeDate,
                         signDateFormattedDate: thisdata.signDateFormattedDate,
-                        completeDateFormattedDate: thisdata.completeDateFormattedDate,
+                        completeDateFormattedDate: thisdata.completeDateFormattedDate
                     });
                 };
                 this.state.pagination.defaultCurrent = data.data.pageNo;
@@ -68,42 +67,34 @@ const Contract = React.createClass({
             });
         }.bind(this));
     },
-    getStateList() {
-        this.setState({
-            loading: true
-        });
+    getContactsList() {
         $.ajax({
             method: "get",
             dataType: "json",
             crossDomain: false,
-            url: globalConfig.context + "/api/admin/contract/status",
+            url: globalConfig.context + "/api/user/cognizance/getContacts",
             success: function (data) {
-                if (!data.data) {
-                    if (data.error && data.error.length) {
-                        message.warning(data.error[0].message);
-                        return;
-                    };
+                let theOption = [];
+                if (data.error.length || !data.data) {
+                    return;
                 };
-                let _me = this, theArr = [];
-                for (var item in data.data) {
-                    theArr.push(
-                        <Select.Option value={item} key={item}>{data.data[item]}</Select.Option>
-                    )
+                for (let item in data.data) {
+                    let theData = data.data[item];
+                    theOption.push(
+                        <Select.Option value={item} key={theData}>{theData}</Select.Option>
+                    );
                 };
                 this.setState({
-                    statusOption: theArr
+                    contactsOption: theOption,
+                    contactsList: data.data
                 });
             }.bind(this),
-        }).always(function () {
-            this.setState({
-                loading: false
-            });
-        }.bind(this));
+        });
     },
     getInitialState() {
         return {
             visible: false,
-            data: [],
+            contactsList: {},
             loading: false,
             showAdd: false,
             showDesc: false,
@@ -128,14 +119,6 @@ const Contract = React.createClass({
                     dataIndex: 'serialNumber',
                     key: 'serialNumber',
                 }, {
-                    title: '省份',
-                    dataIndex: 'province',
-                    key: 'province',
-                }, {
-                    title: '公司名称',
-                    dataIndex: 'unitName',
-                    key: 'unitName',
-                }, {
                     title: '签订时间',
                     dataIndex: 'signDateFormattedDate',
                     key: 'signDateFormattedDate',
@@ -150,13 +133,14 @@ const Contract = React.createClass({
                     key: 'type',
                     render: (text) => { return getContractType(text) }
                 }, {
-                    title: '创建人',
-                    dataIndex: 'founder',
-                    key: 'founder'
+                    title: '联系人',
+                    dataIndex: 'contacts',
+                    key: 'contacts',
+                    render: (text) => { return this.state.contactsList[text] }
                 }, {
-                    title: '技术员',
-                    dataIndex: 'techPrincipal',
-                    key: 'techPrincipal',
+                    title: '完成时间',
+                    dataIndex: 'completeDateFormattedDate',
+                    key: 'completeDateFormattedDate',
                 }, {
                     title: '描述',
                     dataIndex: 'describe',
@@ -183,7 +167,7 @@ const Contract = React.createClass({
             stateOption: sArr
         });
         this.loadData();
-        this.getStateList();
+        this.getContactsList();
         // if (window.location.search) {
         //     let theArr = getSearchUrl(window.location.search);
         //     if (theArr.length > 1) {
@@ -217,8 +201,9 @@ const Contract = React.createClass({
         };
     },
     addClick() {
+        this.state.RowData = {};
         this.setState({
-            showAdd: true
+            showAdd: true,
         });
     },
     closeAdd(e, s) {
@@ -240,7 +225,7 @@ const Contract = React.createClass({
     reset() {
         this.state.contractState = undefined;
         this.state.contractType = undefined;
-        this.state.contractId = undefined;
+        this.state.serialNumber = undefined;
         this.state.startDateFormattedDate = [];
         this.state.endDateFormattedDate = [];
         this.loadData();
@@ -261,6 +246,9 @@ const Contract = React.createClass({
                             closeAdd={this.closeAdd} />
                     </div>
                     <div className="foster-query">
+                        <Input value={this.state.serialNumber}
+                            placeholder="输入合同编号"
+                            onChange={(e) => { this.setState({ serialNumber: e.target.value }); }} />
                         <Select placeholder="选择一个合同类型"
                             style={{ width: 200 }}
                             value={this.state.contractType}
@@ -270,7 +258,7 @@ const Contract = React.createClass({
                             {this.state.typeOption}
                         </Select>
                         <Select style={{ width: 120 }}
-                            value={this.state.searchStatus}
+                            value={this.state.contractState}
                             onChange={(e) => { this.setState({ contractState: e }) }}
                             placeholder="选择一个状态">
                             {this.state.stateOption}

+ 13 - 46
js/component/account/services/contract/contractAdd.jsx

@@ -6,29 +6,6 @@ import ajax from 'jquery/src/ajax/xhr.js'
 import $ from 'jquery/src/ajax';
 
 const ContractAddFrom = Form.create()(React.createClass({
-    getContactsList() {
-        $.ajax({
-            method: "get",
-            dataType: "json",
-            crossDomain: false,
-            url: globalConfig.context + "/api/user/cognizance/getContacts",
-            success: function (data) {
-                let theOption = [];
-                if (data.error.length || !data.data) {
-                    return;
-                };
-                for (let item in data.data) {
-                    let theData = data.data[item];
-                    theOption.push(
-                        <Select.Option value={item} key={theData}>{theData}</Select.Option>
-                    );
-                };
-                this.setState({
-                    contactsOption: theOption
-                });
-            }.bind(this),
-        });
-    },
     getInitialState() {
         return {
             loading: false,
@@ -47,7 +24,7 @@ const ContractAddFrom = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/detail",
+            url: globalConfig.context + "/api/user/contract/detail",
             data: {
                 id: id || this.props.data.id
             }
@@ -80,8 +57,7 @@ const ContractAddFrom = Form.create()(React.createClass({
             )
         };
         this.state.yearOption = theArr;
-        if (this.props.data.id) {
-            this.getContactsList();
+        if (this.props.data && this.props.data.id) {
             this.loadData(this.props.data.id);
         } else {
             this.state.data = {};
@@ -93,8 +69,7 @@ const ContractAddFrom = Form.create()(React.createClass({
     },
     componentWillReceiveProps(nextProps) {
         if (!this.props.visible && nextProps.visible) {
-            if (nextProps.data.id) {
-                this.getContactsList();
+            if (nextProps.data && nextProps.data.id) {
                 this.loadData(nextProps.data.id);
             } else {
                 this.state.data = {};
@@ -115,9 +90,8 @@ const ContractAddFrom = Form.create()(React.createClass({
                     method: "POST",
                     dataType: "json",
                     crossDomain: false,
-                    url: globalConfig.context + "/api/admin/contract/apply",
+                    url: globalConfig.context + (this.state.data.id ? "/api/user/contract/update" : "/api/user/contract/apply"),
                     data: {
-                        "uid": this.state.data.uid || values.uid,
                         "id": this.state.data.id,
                         "contacts": values.contacts, //联系人
                         "type": values.type, //合同类型
@@ -157,11 +131,6 @@ const ContractAddFrom = Form.create()(React.createClass({
                 <div className="clearfix">
                     <FormItem className="half-item"
                         {...formItemLayout}
-                        label="公司名称" >
-                        <span>{theData.unitName}</span>
-                    </FormItem>
-                    <FormItem className="half-item"
-                        {...formItemLayout}
                         label="联系人" >
                         {getFieldDecorator('contacts', {
                             initialValue: theData.contacts
@@ -169,7 +138,7 @@ const ContractAddFrom = Form.create()(React.createClass({
                             <Select placeholder="请选择联系人"
                                 style={{ width: 260 }}
                                 notFoundContent="未获取到联系人列表">
-                                {this.state.contactsOption}
+                                {this.props.contactsOption}
                             </Select>
                             )}
                     </FormItem>
@@ -199,7 +168,7 @@ const ContractAddFrom = Form.create()(React.createClass({
                         )}
                 </FormItem>
                 <div className="clearfix">
-                    <span style={{ float: "left", lineHeight: '32px', marginRight:'20px' }}>
+                    <span style={{ float: "left", lineHeight: '32px', marginRight: '20px' }}>
                         <Checkbox checked={this.state.highTechCheck} onChange={(e) => {
                             this.setState({ highTechCheck: e.target.checked });
                         }}></Checkbox>
@@ -219,7 +188,7 @@ const ContractAddFrom = Form.create()(React.createClass({
                     </FormItem>
                 </div>
                 <div className="clearfix">
-                    <span style={{ float: "left", lineHeight: '32px', marginRight:'20px' }}>
+                    <span style={{ float: "left", lineHeight: '32px', marginRight: '20px' }}>
                         <Checkbox checked={this.state.patentCheck} onChange={(e) => {
                             this.setState({ patentCheck: e.target.checked });
                         }}></Checkbox>
@@ -235,7 +204,7 @@ const ContractAddFrom = Form.create()(React.createClass({
                     </FormItem>
                 </div>
                 <div className="clearfix">
-                    <span style={{ float: "left", lineHeight: '32px', marginRight:'20px' }}>
+                    <span style={{ float: "left", lineHeight: '32px', marginRight: '20px' }}>
                         <Checkbox checked={this.state.copyrightCheck} onChange={(e) => {
                             this.setState({ copyrightCheck: e.target.checked });
                         }}></Checkbox>
@@ -251,7 +220,7 @@ const ContractAddFrom = Form.create()(React.createClass({
                     </FormItem>
                 </div>
                 <div className="clearfix">
-                    <span style={{ float: "left", lineHeight: '32px', marginRight:'20px' }}>
+                    <span style={{ float: "left", lineHeight: '32px', marginRight: '20px' }}>
                         <Checkbox checked={this.state.techProjectCheck} onChange={(e) => {
                             this.setState({ techProjectCheck: e.target.checked });
                         }}></Checkbox>
@@ -297,9 +266,6 @@ const ContractAdd = React.createClass({
         this.props.closeAdd(false);
     },
     componentWillReceiveProps(nextProps) {
-        if (nextProps.showAdd && nextProps.data) {
-            this.state.data = nextProps.data;
-        };
         this.state.visible = nextProps.showAdd;
     },
     spinChange(e) {
@@ -310,7 +276,7 @@ const ContractAdd = React.createClass({
     render() {
         return (
             <div className="patent-addNew">
-                <Button className="patent-addNew" type="primary" onClick={this.showModal}>申请合同<Icon type="plus" /></Button>
+                <Button className="patent-addNew" type="primary" onClick={this.props.onClick}>申请合同<Icon type="plus" /></Button>
                 <Spin spinning={this.state.loading} className='spin-box'>
                     <Modal maskClosable={false} title="合同详情"
                         visible={this.state.visible}
@@ -322,9 +288,10 @@ const ContractAdd = React.createClass({
                             spinState={this.spinChange}
                             closeModal={this.handleCancel}
                             visible={this.state.visible}
-                            data={this.state.data}
+                            data={this.props.data}
                             okClick={() => { this.props.closeAdd(false, true) }}
-                            typeOption={this.props.typeOption} />
+                            typeOption={this.props.typeOption}
+                            contactsOption={this.props.contactsOption} />
                     </Modal>
                 </Spin>
             </div>

+ 8 - 8
js/component/account/services/contract/contractDetail.jsx

@@ -5,7 +5,7 @@ import ajax from 'jquery/src/ajax/xhr.js';
 import $ from 'jquery/src/ajax';
 import moment from 'moment';
 import { copyrightStateList } from '../../../dataDic.js';
-import { companySearch, getCopyrightState, getPatentType, getPatentState, gethighTechState, getTechnologyState } from '../../../tools.js';
+import { companySearch, getCopyrightState, getPatentType, getPatentState, getCognizanceState, getTechnologyState } from '../../../tools.js';
 
 const ContractDetailForm = Form.create()(React.createClass({
     getInitialState() {
@@ -129,7 +129,7 @@ const ContractDetailForm = Form.create()(React.createClass({
                     title: '申请状态',
                     dataIndex: 'state',
                     key: 'state',
-                    render: (text) => { return gethighTechState(text) },
+                    render: (text) => { return getCognizanceState(text) },
                     width: 200
                 }, {
                     title: '证书编号',
@@ -187,7 +187,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/log",
+            url: globalConfig.context + "/api/user/contract/log",
             data: {
                 cid: id || this.props.data.id
             }
@@ -196,7 +196,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/detail",
+            url: globalConfig.context + "/api/user/contract/detail",
             data: {
                 id: id || this.props.data.id
             }
@@ -244,7 +244,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/techProject",
+            url: globalConfig.context + "/api/user/contract/techProject",
             data: {
                 contractId: id || this.props.data.id
             }
@@ -253,7 +253,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/cognizance",
+            url: globalConfig.context + "/api/user/contract/cognizance",
             data: {
                 contractId: id || this.props.data.id
             }
@@ -262,7 +262,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/copyright",
+            url: globalConfig.context + "/api/user/contract/copyright",
             data: {
                 contractId: id || this.props.data.id
             }
@@ -271,7 +271,7 @@ const ContractDetailForm = Form.create()(React.createClass({
             dataType: "json",
             crossDomain: false,
             cache: false,
-            url: globalConfig.context + "/api/admin/contract/patent",
+            url: globalConfig.context + "/api/user/contract/patent",
             data: {
                 contractId: id || this.props.data.id
             }

+ 3 - 3
js/component/account/topTab.jsx

@@ -39,9 +39,9 @@ const TopTab = React.createClass({
                     <Row>
                         <Col className={this.props.active === 'set' ? 'active' : ''} span={3}><a href={globalConfig.context + "/user/account/set.html"}>账号设置</a></Col>
                         <Col className={this.props.active === 'services' ? 'active' : ''} span={3}><a href={globalConfig.context + "/user/account/services.html"}>科技服务</a></Col>
-                        <Col className={this.props.active === 'achievement' ? 'active' : ''} span={3}><a href="./set.html">科技成果</a></Col>
-                        <Col className={this.props.active === 'demand' ? 'active' : ''} span={3}><a href="./set.html">科技需求</a></Col>
-                        <Col className={this.props.active === 'idea' ? 'active' : ''} span={3}><a href="./set.html">科技思想</a></Col>
+                        <Col className={this.props.active === 'achievement' ? 'active' : ''} span={3}><a href={globalConfig.context + "/user/account/achievement.html"}>科技成果</a></Col>
+                        <Col className={this.props.active === 'demand' ? 'active' : ''} span={3}><a href={globalConfig.context + "/user/account/demand.html"}>科技需求</a></Col>
+                        <Col className={this.props.active === 'idea' ? 'active' : ''} span={3}><a href={globalConfig.context + "/user/account/idea.html"}>科技思想</a></Col>
                     </Row>
                 </div>
             </div >

+ 1 - 1
js/component/manageCenter/achievement/techAchievementDesc.jsx

@@ -531,7 +531,7 @@ const AchievementDetailForm = Form.create()(React.createClass({
                     </Upload>
                     <p style={{ marginTop: '10px' }}>{theData.maturityTextFileUrl ?
                         <span className="download-file">
-                            <a onClick={() => { window.open(globalConfig.context + '/api/admin/achievement/download?id=' + this.props.data.id) }}>成熟度证明材料(文本文件)</a>
+                            <a onClick={() => { window.open(globalConfig.context + '/api/admin/achievement/download?id=' + this.props.data.id + '&sign=achievement_maturity_text_file') }}>成熟度证明材料(文本文件)</a>
                         </span>
                         : <span><Icon type="exclamation-circle" style={{ color: '#ffbf00', marginRight: '6px' }} />未上传!</span>}</p>
                 </FormItem>

+ 2 - 2
js/component/manageCenter/servicesManage/contract/contractAdd.jsx

@@ -86,7 +86,7 @@ const ContractAddFrom = Form.create()(React.createClass({
             )
         };
         this.state.yearOption = theArr;
-        if (this.props.data.uid && this.props.data.id) {
+        if (this.props.data && this.props.data.uid && this.props.data.id) {
             this.getContactsList(this.props.data.uid);
             this.loadData(this.props.data.id);
         } else {
@@ -99,7 +99,7 @@ const ContractAddFrom = Form.create()(React.createClass({
     },
     componentWillReceiveProps(nextProps) {
         if (!this.props.visible && nextProps.visible) {
-            if (nextProps.data.uid && nextProps.data.id) {
+            if (nextProps.data && nextProps.data.uid && nextProps.data.id) {
                 this.getContactsList(nextProps.data.uid);
                 this.loadData(nextProps.data.id);
             } else {

+ 16 - 0
js/user/account/achievement.js

@@ -0,0 +1,16 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import '../../../css/base.less';
+
+import TopTab from '../../component/account/topTab.jsx';
+import Footer from '../../component/account/bottom.jsx';
+import Content from '../../component/account/achievement/content.jsx';
+
+ReactDOM.render(
+    <div className="wrap clearfix">
+        <TopTab active={'achievement'}/>
+        <Content />
+        <Footer />
+    </div>,
+    document.getElementById('root')
+)

+ 16 - 0
js/user/account/demand.js

@@ -0,0 +1,16 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import '../../../css/base.less';
+
+import TopTab from '../../component/account/topTab.jsx';
+import Footer from '../../component/account/bottom.jsx';
+import Content from '../../component/account/demand/content.jsx';
+
+ReactDOM.render(
+    <div className="wrap clearfix">
+        <TopTab active={'demand'}/>
+        <Content />
+        <Footer />
+    </div>,
+    document.getElementById('root')
+)

+ 12 - 1
webpack.config.js

@@ -69,13 +69,24 @@ module.exports = (function () {
             template: './template/template.html',
             chunks: ['user/account/set', 'vendors']
         }),
-        //user-account-services-patent
         new HtmlWebpackPlugin({
             title: '用户中心-科技服务',
             filename: 'user/account/services.html',
             template: './template/template.html',
             chunks: ['user/account/services', 'vendors']
         }),
+        new HtmlWebpackPlugin({
+            title: '用户中心-科技服务',
+            filename: 'user/account/achievement.html',
+            template: './template/template.html',
+            chunks: ['user/account/achievement', 'vendors']
+        }),
+        new HtmlWebpackPlugin({
+            title: '用户中心-科技服务',
+            filename: 'user/account/demand.html',
+            template: './template/template.html',
+            chunks: ['user/account/demand', 'vendors']
+        }),
 
         //admin
         new HtmlWebpackPlugin({