Ver código fonte

小程序后台

HW 4 anos atrás
pai
commit
ed3ad9786a

BIN
image/audio.png


+ 19 - 0
js/admin/index/content.jsx

@@ -47,6 +47,18 @@ import {hashHistory,Route,Router} from 'react-router';
 import {Layout} from 'antd';
 import '@/account/content.less';
 
+
+//小程序
+//用户管理
+import User from '@/administration/weapp/user';
+//产品管理
+import Product from '@/administration/weapp/product';
+//支付管理
+import Pay from '@/administration/weapp/pay';
+//产品类型
+import ProductSort from '@/administration/weapp/productSort';
+
+
 const { Content } = Layout;
 
 export default class ContentRouter extends React.Component {
@@ -72,6 +84,13 @@ export default class ContentRouter extends React.Component {
                     <Route path="/newList" component={NewList} />
                     <Route path="/firmList" component={FirmList} />
                     <Route path="/activity" component={Activity} />
+                    {/*小程序-用户管理*/}
+                    <Route path="/user" component={User} />
+                    <Route path="/pay" component={Pay} />
+                    <Route path="/product" component={Product} />
+                    <Route path="/productSort" component={ProductSort} />
+
+
                     <Route path="/jzmList" component={JzmList} />
                     <Route path="/mcjList" component={McjList} />
                     <Route path="/caseList" component={CaseList} />

+ 20 - 0
js/admin/menu.jsx

@@ -34,6 +34,26 @@ module.exports = {
             name: "访问客户",
             url: "customers",
             icon: "database"
+        },
+        {
+            name: "用户管理",
+            url: "user",
+            icon: "database"
+        },
+        {
+            name: "支付管理",
+            url: "pay",
+            icon: "database"
+        },
+        {
+            name: "产品管理",
+            url: "product",
+            icon: "database"
+        },
+        {
+            name: "产品类型管理",
+            url: "productSort",
+            icon: "database"
         }
     ]
 };

+ 183 - 0
js/component/administration/weapp/pay/index.jsx

@@ -0,0 +1,183 @@
+import React,{Component}from 'react';
+import {Button, DatePicker, Icon, Input, message, Select, Table} from "antd";
+import SpinContainer from "../../../SpinContainer";
+import $ from "jquery/src/ajax";
+import moment from "moment";
+
+const { RangePicker } = DatePicker;
+
+class Pay extends Component{
+    constructor(props) {
+        super(props);
+        this.state={
+            searchUserName: '',
+            searchPayState: '',
+            time: [],
+            loading: false,
+            columns:[
+                {
+                    title: '序号',
+                    dataIndex: 'key',
+                    key: 'key'
+                },
+                {
+                    title: '用户ID',
+                    dataIndex: 'id',
+                    key: 'id'
+                },
+                {
+                    title: '用户呢称',
+                    dataIndex: 'nickName',
+                    key: 'nickName'
+                },
+                {
+                    title: '电话',
+                    dataIndex: 'phone',
+                    key: 'phone'
+                },
+                {
+                    title: '发起支付时间',
+                    dataIndex: 'time',
+                    key: 'time'
+                },
+                {
+                    title: '金额',
+                    dataIndex: 'lv',
+                    key: 'lv'
+                },
+                {
+                    title: '支付状态',
+                    dataIndex: 'start',
+                    key: 'start'
+                },
+            ],
+            dataSource:[],
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+
+        }
+        this.search = this.search.bind(this);
+        this.reset = this.reset.bind(this);
+        this.tableRowClick = this.tableRowClick.bind(this);
+        this.loadData = this.loadData.bind(this);
+    }
+
+    search(){this.loadData();}
+
+    reset(){
+        this.setState({
+            searchUserName: '',
+            searchPayState: '',
+            time: [],
+        },()=>{
+            this.loadData();
+        })
+    }
+
+    tableRowClick(){
+
+    }
+
+    loadData(pageNo = 1) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/news/listNews",
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: 10,
+                userName: this.state.searchUserName || undefined,
+                payState: this.state.searchPayState || undefined,
+                payStart: this.state.time[0] || undefined,
+                payEnd: this.state.time[1] || undefined,
+            }
+        }).done((data1) => {
+            let theArr = [];
+            if (data1.error.length !== 0) {
+                message.warning(data1.error[0].message);
+            } else {
+                for (let i = 0; i < data1.data.list.length; i++) {
+                    data1.data.list[i].key = (data1.data.pageNo-1)*10+(i+1);
+                }
+                this.state.pagination.current = data1.data.pageNo;
+                this.state.pagination.total = data1.data.totalCount;
+            }
+            this.setState({
+                dataSource: data1.data.list,
+                pagination: this.state.pagination,
+            });
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this))
+    }
+
+    componentDidMount() {
+        this.loadData();
+    }
+
+    render() {
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span>支付管理</span>
+                </div>
+                <div className="user-search">
+                    <Input placeholder="用户关键字" value={this.state.searchUserName} onChange={(e) => { this.setState({ searchUserName: e.target.value }); }} />
+                    <Select
+                        placeholder="请选择支付状态"
+                        style={{ width: 120 }}
+                        value={this.state.searchPayState+"" || undefined}
+                        onChange={e => {
+                            this.setState({
+                                searchPayState: e
+                            });
+                        }}
+                    >
+                        <Option value="0">已支付</Option>
+                        <Option value="1">未支付</Option>
+                        <Option value="2">待付款</Option>
+                        <Option value="3">支付失败</Option>
+                    </Select>
+                    <span style={{ fontSize: 14 }} >提交日期:</span>
+                    <RangePicker
+                        value={[
+                            this.state.time[0] ? moment(this.state.time[0]) : null,
+                            this.state.time[1] ? moment(this.state.time[1]) : null
+                        ]}
+                        onChange={(data, dataString) => {
+                            this.setState({ time: dataString });
+                        }}
+                    />
+                    <Button type="primary" onClick={this.search} style={{marginLeft:'10px'}}>搜索</Button>
+                    <Button onClick={this.reset}>重置</Button>
+                </div>
+                <div className="patent-table">
+                    <SpinContainer spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                               dataSource={this.state.dataSource}
+                               pagination={this.state.pagination}
+                               onRowClick={this.tableRowClick} />
+                    </SpinContainer>
+                </div>
+            </div >
+        )
+    }
+}
+
+export default Pay;

+ 0 - 0
js/component/administration/weapp/pay/user.less


+ 409 - 0
js/component/administration/weapp/product/add.jsx

@@ -0,0 +1,409 @@
+import React,{Component} from 'react';
+import SpinContainer from "../../../SpinContainer";
+import {Button, Form, Icon, Input, message, Modal, Select, Upload} from "antd";
+import {beforeUploadFile,splitUrl} from "@/tools.js";
+import Editors from "@/richTextEditors";
+import $ from "jquery/src/ajax";
+
+const FormItem = Form.Item;
+
+//上传图片组件
+const PicturesWall = React.createClass({
+    getInitialState() {
+        return {
+            previewVisible: false,
+            previewImage: "",
+            fileList: this.props.pictureUrl,
+            type:''
+        };
+    },
+    getDefaultProps() {
+        return {
+            changeClick: this.modifyChange
+        };
+    },
+    handleCancel() {
+        this.setState({ previewVisible: false });
+    },
+    handlePreview(file) {
+        let type = '';
+        if(file.type){
+            let str = file.type;
+            let index = str.indexOf("/");
+            type =str.substring(0,index);
+        }else{
+            let str = file.url || file.thumbUrl;
+            let index = str.indexOf(".");
+            type =str.substring(index+1);
+        }
+        this.setState({
+            type,
+            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 style={{ display: "inline-block" }}>
+                <Upload
+                    accept={
+                        this.props.type ==='img' ? "image/*" :
+                            this.props.type ==='video' ?
+                                "video/mp4,video/rmvb,video/mkv,video/avi,audio/mp3" : ''}
+                    beforeUpload={beforeUploadFile}
+                    action={globalConfig.context + "/api/admin/customerCase/uploadFile"}
+                    data={{ sign: "purchase_picture" }}
+                    listType="picture-card"
+                    fileList={fileList}
+                    onPreview={this.handlePreview}
+                    onChange={this.handleChange}
+                >
+                    {fileList && fileList.length >= 1 ? null : uploadButton}
+                </Upload>
+                <Modal
+                    maskClosable={false}
+                    visible={previewVisible}
+                    footer={null}
+                    onCancel={this.handleCancel}
+                >
+                    {
+                        this.state.type=== 'image' ?
+                            <img alt="" style={{ width: "100%" }} src={previewImage} /> :
+                            this.state.type=== 'video' ?
+                                <video style={{width:'100%'}} controls="controls" autoPlay="" name="media">
+                                    <source src={previewImage} type="video/mp4"/>
+                                </video>:
+                                this.state.type=== 'audio' ?
+                                    <audio src={previewImage} controls="controls">Your browser does not support the audio element.</audio>: ''
+                    }
+                </Modal>
+            </div>
+        );
+    }
+});
+
+class Add extends Component{
+    constructor(props) {
+        super(props);
+        this.state={
+            loading: false,
+            projectType: '',
+            sort:'',
+            name:'',
+            pictureVideoUrl: '',
+            pictureImgUrl: '',
+            content: '',
+            amount: '',
+            projectList: [],
+            host: 0,
+        }
+        this.getOrgCodeUrl = this.getOrgCodeUrl.bind(this);
+        this.getVideoOrgCodeUrl = this.getVideoOrgCodeUrl.bind(this);
+        this.onOk = this.onOk.bind(this);
+        this.getProjectList = this.getProjectList.bind(this);
+    }
+
+    componentDidMount() {
+        this.getProjectList();
+    }
+
+    getOrgCodeUrl(e) {
+        this.setState({ pictureImgUrl: e });
+    }
+
+    getVideoOrgCodeUrl(e) {
+        this.setState({ pictureVideoUrl: e });
+    }
+
+    onOk(releaseStatus = 0){
+        if(!this.state.name){
+            message.warning('请输入产品名称');
+            return false;
+        }
+        if(isNaN(parseInt(this.state.projectType))){
+            message.warning('请输入产品分类');
+            return false;
+        }
+        if(isNaN(parseInt(this.state.amount))){
+            message.warning('请输入正确的金额');
+            return false;
+        }
+        if(this.state.pictureVideoUrl.length === 0){
+            message.warning('请上传视频/音频');
+            return false;
+        }
+        if(this.state.pictureImgUrl.length === 0){
+            message.warning('请上传略缩图');
+            return false;
+        }
+        if(!this.state.content){
+            message.warning('请输入简介');
+            return false;
+        }
+        this.setState({
+            loading: true
+        });
+        let url = this.props.id ? "/api/admin/project/update" : "/api/admin/project/add"
+        $.ajax({
+            method: "post",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + url,
+            data: {
+                name: this.state.name || undefined,
+                sort:this.state.sort || undefined,
+                content: this.state.content || undefined,
+                id: this.props.id || undefined,
+                type: this.state.projectType,
+                amount: this.state.amount || undefined,
+                commodityUrl: this.state.pictureVideoUrl[0].response.data || undefined,
+                thumbnailUrl: this.state.pictureImgUrl[0].response.data || undefined,
+                host: this.state.host,
+                releaseStatus,
+            },
+            success: function(data) {
+                if (data.error && data.error.length) {
+                    message.warning(data.error[0].message);
+                } else {
+                    message.success(this.state.id ? '修改成功' : '添加成功');
+                    this.props.onOk();
+                }
+            }.bind(this)
+        }).always(
+            function() {
+                this.setState({
+                    loading: false
+                });
+            }.bind(this)
+        );
+    }
+
+    getProjectList() {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/open/projectList",
+            data: {}
+        }).done((data1) => {
+            if (data1.error.length !== 0) {
+                message.warning(data1.error[0].message);
+            } else {
+                this.setState({
+                    projectList: data1.data,
+                },()=>{
+                    if(this.props.infor){
+                        this.setState({
+                            name: this.props.infor.name,
+                            sort:this.props.infor.sort,
+                            content: this.props.infor.content,
+                            projectType: this.props.infor.type,
+                            amount: this.props.infor.amount,
+                            pictureVideoUrl: this.props.infor.commodityUrl ? splitUrl(this.props.infor.commodityUrl, ',', globalConfig.avatarHost + '/upload') : [],
+                            pictureImgUrl: this.props.infor.thumbnailUrl ? splitUrl(this.props.infor.thumbnailUrl, ',', globalConfig.avatarHost + '/upload') : [],
+                            host: this.props.infor.host,
+                        })
+                    }
+                });
+            }
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this))
+    }
+
+    render() {
+        return (
+            <Modal
+                className="customeDetails"
+                title={this.props.id ? "修改产品" : "添加产品"}
+                okText={"保存"}
+                width="1050"
+                visible={this.props.visible}
+                onCancel={this.props.onCancel}
+                footer={false}
+            >
+                <Form
+                    layout="horizontal"
+                    id="demand-form"
+                >
+                    <SpinContainer spinning={this.state.loading}>
+                        <div className="clearfix">
+                            <FormItem
+                                className="half-item"
+                                labelCol={{ span: 8 }}
+                                wrapperCol={{ span: 12 }}
+                                label="产品名称"
+                            >
+                                <Input
+                                    placeholder="请输入产品名称"
+                                    value={this.state.name}
+                                    onChange={(e) => {
+                                        this.setState({ name: e.target.value });
+                                    }}
+                                />
+                            </FormItem>
+                            <FormItem
+                                className="half-item"
+                                labelCol={{ span: 8 }}
+                                wrapperCol={{ span: 12 }}
+                                label="产品分类"
+                            >
+                                <Select
+                                    value={this.state.projectType}
+                                    placeholder="请选择产品分类"
+                                    onChange={e => {
+                                        this.setState({
+                                            projectType: e
+                                        });
+                                    }}
+                                >
+                                    {
+                                        this.state.projectList.map((v,k)=>(
+                                            <Option key={k} value={v.id}>{v.name}</Option>
+                                        ))
+                                    }
+                                </Select>
+                            </FormItem>
+                            <FormItem
+                                className="half-item"
+                                labelCol={{ span: 8 }}
+                                wrapperCol={{ span: 12 }}
+                                label="产品金额"
+                            >
+                                <Input
+                                    type={'number'}
+                                    placeholder="请输入产品金额"
+                                    value={this.state.amount}
+                                    onChange={(e) => {
+                                        this.setState({ amount: e.target.value });
+                                    }}
+                                />
+                            </FormItem>
+                            <FormItem
+                                className="half-item"
+                                labelCol={{ span: 8 }}
+                                wrapperCol={{ span: 12 }}
+                                label="是否发布到首页"
+                            >
+                                <Select
+                                    value={this.state.host}
+                                    placeholder="是否发布到首页"
+                                    onChange={e => {
+                                        this.setState({
+                                            host: e
+                                        });
+                                    }}
+                                >
+                                    <Option value={0}>否</Option>
+                                    <Option value={1}>是</Option>
+                                </Select>
+                            </FormItem>
+                            <FormItem
+                                className="half-item"
+                                labelCol={{ span: 8 }}
+                                wrapperCol={{ span: 12 }}
+                                label="排序"
+                            >
+                                <Input
+                                    placeholder="请输入排序"
+                                    value={this.state.sort}
+                                    onChange={e => {
+                                        this.setState({
+                                            sort: e.target.value
+                                        });
+                                    }}
+                                />
+                                <p>数字越大,排序越前</p>
+                            </FormItem>
+                            <div className="clearfix">
+                                <FormItem
+                                    className="half-item"
+                                    labelCol={{ span: 8 }}
+                                    wrapperCol={{ span: 12 }}
+                                    label="缩略图"
+                                >
+                                    <PicturesWall
+                                        type={'img'}
+                                        fileList={this.getOrgCodeUrl}
+                                        pictureUrl={this.state.pictureImgUrl}
+                                    />
+                                </FormItem>
+                            </div>
+                            <div className="clearfix">
+                                <FormItem
+                                    className="half-item"
+                                    labelCol={{ span: 8 }}
+                                    wrapperCol={{ span: 12 }}
+                                    label="视频/音频"
+                                >
+                                    <PicturesWall
+                                        type={'video'}
+                                        fileList={this.getVideoOrgCodeUrl}
+                                        pictureUrl={this.state.pictureVideoUrl}
+                                    />
+                                    <p>支持<span style={{color:'#F00'}}>MP3/MP4/RMVB/MKV/AVI</span></p>
+                                </FormItem>
+                            </div>
+                            <div className="clearfix">
+                                <FormItem
+                                    labelCol={{ span: 4 }}
+                                    wrapperCol={{ span: 18 }}
+                                    label="简介"
+                                >
+                                    <Editors
+                                        textContent={this.state.content}
+                                        uploadUrl={"/api/admin/news/uploadFile"}
+                                        globalConfig={globalConfig.uploadPath}
+                                        placeholder="内容(编辑器,支持图文音频等)"
+                                        handleRichText={value => {
+                                            this.setState({ content: value });
+                                        }}
+                                    />
+                                </FormItem>
+                            </div>
+                        </div>
+                        <div style={{display:'flex',justifyContent: 'center'}}>
+                            <Button
+                                type="primary"
+                                onClick={()=>{
+                                    this.onOk();
+                                }}>
+                                保存
+                            </Button>
+                            <Button
+                                type="primary"
+                                style={{marginLeft:'30px'}}
+                                onClick={()=>{
+                                    this.onOk(1);
+                                }}>
+                                保存并发布
+                            </Button>
+                        </div>
+                    </SpinContainer>
+                </Form>
+            </Modal>
+        )
+    }
+}
+
+export default Add;

+ 399 - 0
js/component/administration/weapp/product/index.jsx

@@ -0,0 +1,399 @@
+import React,{Component}from 'react';
+import {Button, DatePicker, Icon, Input, message, Modal, Popconfirm, Select, Table} from "antd";
+import SpinContainer from "../../../SpinContainer";
+import $ from "jquery/src/ajax";
+import moment from "moment";
+import Add from './add';
+import {getPicPath} from "@/tools.js";
+
+const { RangePicker } = DatePicker;
+
+class Product extends Component{
+    constructor(props) {
+        super(props);
+        this.state={
+            pageNo: 1,
+            searchUserName: '',
+            time: [],
+            loading: false,
+            imgeditvisible: false,
+            maximg: '',
+            columns:[
+                {
+                    title: '序号',
+                    dataIndex: 'key',
+                    key: 'key'
+                },
+                {
+                    title: '产品分类',
+                    dataIndex: 'typeName',
+                    key: 'typeName'
+                },
+                {
+                    title: '产品ID',
+                    dataIndex: 'id',
+                    key: 'id'
+                },
+                {
+                    title: '产品缩略图',
+                    dataIndex: 'thumbnailUrl',
+                    key: 'thumbnailUrl',
+                    render: url => {
+                        let path = getPicPath(globalConfig.avatarUploadHost, url);
+                        return (
+                            <div style={{
+                                display: 'flex',
+                                alignItems: 'center',
+                                justifyContent: 'center',
+                            }}>
+                                <img src={path} style={{ width: "100px", height: 50 }} />
+                                <Button
+                                    className="buttonimg"
+                                    style={{ marginLeft: 10 }}
+                                    onClick={e => {
+                                        e.stopPropagation();
+                                        this.setState({
+                                            imgeditvisible: true,
+                                            maximg: path,
+                                        })
+                                    }}
+                                >
+                                    查看大图
+                                </Button>
+                            </div>
+                        );
+                    }
+                },
+                {
+                    title: '产品名称',
+                    dataIndex: 'name',
+                    key: 'name'
+                },
+                {
+                    title: '金额',
+                    dataIndex: 'amount',
+                    key: 'amount'
+                },
+                {
+                    title: '排序',
+                    dataIndex: 'sort',
+                    key: 'sort'
+                },
+                {
+                    title: '上传时间',
+                    dataIndex: 'createTimes',
+                    key: 'createTimes'
+                },
+                {
+                    title: '是否发布',
+                    dataIndex: 'releaseStatus',
+                    key: 'releaseStatus',
+                    render: (text, record) => {
+                        return (
+                            text === 0 ? '否' : text === 1 ? '是' : '未知'
+                        )
+                    }
+                },
+                {
+                    title: '是否首页',
+                    dataIndex: 'host',
+                    key: 'host',
+                    render: (text, record) => {
+                        return (
+                            text === 0 ? '否' : text === 1 ? '是' : '未知'
+                        )
+                    }
+                },
+                {
+                    title: "操作",
+                    dataIndex: "aab",
+                    key: "aab",
+                    render: (text, record) => {
+                        return (
+                            <div>
+                                <Button
+                                    type="primary"
+                                    onClick={(e) => {
+                                        e.stopPropagation();
+                                        this.edit(record);
+                                    }}
+                                >
+                                    编辑
+                                </Button>
+                                <Popconfirm
+                                    placement="top"
+                                    title={"是否确认删除?"}
+                                    onConfirm={e => {
+                                        e.stopPropagation();
+                                        this.delete(record.id);
+                                    }}
+                                    okText="确认"
+                                    cancelText="取消"
+                                >
+                                    <Button
+                                        type="primary"
+                                        style={{ marginLeft: 10,background:'#f00' }}
+                                        onClick={(e)=>{
+                                            e.stopPropagation();
+                                        }}
+                                    >
+                                        删除
+                                    </Button>
+                                </Popconfirm>
+                                <Popconfirm
+                                    placement="top"
+                                    title={record.host === 0 ? "是否确认推荐首页?" : "是否确认从首页撤下?"}
+                                    onConfirm={e => {
+                                        this.homeOperation(record.id,record.host === 0 ? 1 : 0);
+                                    }}
+                                    okText="确认"
+                                    cancelText="取消"
+                                >
+                                    <Button
+                                        type="primary"
+                                        style={{ marginLeft: 10 }}
+                                        onClick={(e)=>{
+                                            e.stopPropagation();
+                                        }}
+                                    >
+                                        {record.host === 0 ? "推荐首页" : '首页撤下'}
+                                    </Button>
+                                </Popconfirm>
+                            </div>
+                        );
+                    }
+                }
+            ],
+            dataSource:[],
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+            visible:false,
+
+        }
+        this.search = this.search.bind(this);
+        this.reset = this.reset.bind(this);
+        this.tableRowClick = this.tableRowClick.bind(this);
+        this.loadData = this.loadData.bind(this);
+        this.addProduct = this.addProduct.bind(this);
+        this.onCancel = this.onCancel.bind(this);
+        this.edit = this.edit.bind(this);
+        this.delete = this.delete.bind(this);
+        this.homeOperation = this.homeOperation.bind(this);
+    }
+
+    search(){this.loadData();}
+
+    reset(){
+        this.setState({
+            searchUserName: '',
+            time: [],
+        },()=>{
+            this.loadData();
+        })
+    }
+
+    tableRowClick(value){
+        console.log(value)
+        this.setState({
+            visible:true,
+            id:value.id,
+            infor:value,
+        })
+    }
+
+    edit(value){
+        this.setState({
+            visible:true,
+            id:value.id,
+            infor:value,
+        })
+    }
+
+    loadData(pageNo = 1) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/project/list",
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: 10,
+                userName: this.state.searchUserName || undefined,
+                payState: this.state.searchPayState || undefined,
+                payStart: this.state.time[0] || undefined,
+                payEnd: this.state.time[1] || undefined,
+            }
+        }).done((data1) => {
+            if (data1.error.length !== 0) {
+                message.warning(data1.error[0].message);
+            } else {
+                for (let i = 0; i < data1.data.list.length; i++) {
+                    data1.data.list[i].key = (data1.data.pageNo-1)*10+(i+1);
+                }
+                this.state.pagination.current = data1.data.pageNo;
+                this.state.pagination.total = data1.data.totalCount;
+            }
+            this.setState({
+                dataSource: data1.data.list,
+                pagination: this.state.pagination,
+                pageNo: data1.data.pageNo
+            });
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this))
+    }
+
+    addProduct(){
+        this.setState({visible:false});
+        this.loadData(this.state.pageNo)
+    }
+
+    onCancel(){
+        this.setState({
+            visible:false,
+            id:'',
+            infor:'',
+        })
+    }
+
+    homeOperation(id,host){
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "post",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/project/update",
+            data: {
+                id,
+                host
+            },
+            success: function(data) {
+                if (data.error && data.error.length) {
+                    message.warning(data.error[0].message);
+                } else {
+                    message.warning('操作成功');
+                    this.loadData(this.state.pageNo);
+                }
+            }.bind(this)
+        }).always(
+            function() {
+                this.setState({
+                    loading: false
+                });
+            }.bind(this)
+        );
+    }
+
+    delete(id){
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "post",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/project/delete",
+            data: {
+                id
+            },
+            success: function(data) {
+                if (data.error && data.error.length) {
+                    message.warning(data.error[0].message);
+                } else {
+                    message.warning('删除成功');
+                    this.loadData(this.state.pageNo);
+                }
+            }.bind(this)
+        }).always(
+            function() {
+                this.setState({
+                    loading: false
+                });
+            }.bind(this)
+        );
+    }
+
+    componentDidMount() {
+        this.loadData();
+    }
+
+    imghandleCancel() {
+        this.setState({
+            imgeditvisible: false
+        });
+    }
+
+    render() {
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span>产品管理</span>
+                </div>
+                <div className="user-search">
+                    <Input placeholder="产品关键字" value={this.state.searchUserName} onChange={(e) => { this.setState({ searchUserName: e.target.value }); }} />
+                    <span style={{ fontSize: 14 }} >提交日期:</span>
+                    <RangePicker
+                        value={[
+                            this.state.time[0] ? moment(this.state.time[0]) : null,
+                            this.state.time[1] ? moment(this.state.time[1]) : null
+                        ]}
+                        onChange={(data, dataString) => {
+                            this.setState({ time: dataString });
+                        }}
+                    />
+                    <Button type="primary" onClick={this.search} style={{marginLeft:'10px'}}>搜索</Button>
+                    <Button onClick={this.reset}>重置</Button>
+                    <Button
+                        type="primary"
+                        onClick={()=>{this.setState({visible:true})}}
+                        style={{ marginLeft: "100px" }}
+                    >
+                        新增产品
+                    </Button>
+                </div>
+                <div className="patent-table">
+                    <SpinContainer spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                               dataSource={this.state.dataSource}
+                               pagination={this.state.pagination}
+                               onRowClick={this.tableRowClick} />
+                    </SpinContainer>
+                </div>
+                {this.state.visible ? <Add
+                    id={this.state.id}
+                    infor={this.state.infor}
+                    visible={this.state.visible}
+                    onOk={this.addProduct}
+                    onCancel={this.onCancel}
+                /> : null}
+                <Modal
+                    visible={this.state.imgeditvisible}
+                    onCancel={()=>{this.imghandleCancel()}}
+                    onOk={()=>{this.imghandleCancel()}}
+                    footer={false}
+                >
+                    <img style={{ width: "100%" }} src={this.state.maximg} />
+                </Modal>
+            </div >
+        )
+    }
+}
+
+export default Product;

+ 0 - 0
js/component/administration/weapp/product/user.less


+ 254 - 0
js/component/administration/weapp/productSort/index.jsx

@@ -0,0 +1,254 @@
+import React,{Component}from 'react';
+import {Button, DatePicker, Form, Icon, Input, message, Modal, Popconfirm, Select, Table} from "antd";
+import SpinContainer from "../../../SpinContainer";
+import $ from "jquery/src/ajax";
+import moment from "moment";
+
+const FormItem = Form.Item;
+
+class ProductSort extends Component{
+    constructor(props) {
+        super(props);
+        this.state={
+            loading: false,
+            id:'',
+            name:'',
+            columns:[
+                {
+                    title: '序号',
+                    dataIndex: 'key',
+                    key: 'key'
+                },
+                {
+                    title: '产品类型',
+                    dataIndex: 'name',
+                    key: 'name'
+                },
+                {
+                    title: "操作",
+                    dataIndex: "aab",
+                    key: "aab",
+                    render: (text, record) => (
+                        <Popconfirm
+                            placement="top"
+                            title={"是否确认删除?"}
+                            onConfirm={e => {
+                                e.stopPropagation();
+                                this.delete(record.id);
+                            }}
+                            okText="确认"
+                            cancelText="取消"
+                        >
+                            <Button
+                                type="primary"
+                                style={{marginLeft: 10,borderColor:'#f00', background: '#f00'}}
+                                onClick={(e) => {
+                                    e.stopPropagation();
+                                }}
+                            >
+                                删除
+                            </Button>
+                        </Popconfirm>
+                    )
+                }
+            ],
+            dataSource:[],
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+            visible:false,
+        }
+        this.tableRowClick = this.tableRowClick.bind(this);
+        this.loadData = this.loadData.bind(this);
+        this.onCancel = this.onCancel.bind(this);
+        this.onOk = this.onOk.bind(this);
+        this.delete = this.delete.bind(this);
+    }
+
+    tableRowClick(value){
+        this.setState({
+            visible: true,
+            id:value.id,
+            name:value.name,
+        })
+    }
+
+    delete(id){
+        $.ajax({
+            method: "post",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/projectType/delete",
+            data: {
+                id: id
+            },
+            success: function(data) {
+                if (data.error && data.error.length) {
+                    message.warning(data.error[0].message);
+                } else {
+                    message.success('删除成功');
+                    this.loadData();
+                }
+            }.bind(this)
+        }).always(
+            function() {
+                this.setState({
+                    loading: false
+                });
+            }.bind(this)
+        );
+    }
+
+    loadData(pageNo = 1) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/open/projectList",
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: 10,
+            }
+        }).done((data1) => {
+            let theArr = [];
+            if (data1.error.length !== 0) {
+                message.warning(data1.error[0].message);
+            } else {
+                for (let i = 0; i < data1.data.length; i++) {
+                    data1.data[i].key = i+1;
+                }
+                this.state.pagination.current = data1.data.pageNo;
+                this.state.pagination.total = data1.data.totalCount;
+            }
+            this.setState({
+                dataSource: data1.data,
+                pagination: this.state.pagination,
+            });
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this))
+    }
+
+    componentDidMount() {
+        this.loadData();
+    }
+
+    onOk(){
+        if(!this.state.name){
+            message.warning('请填写产品类型')
+            return;
+        }
+        $.ajax({
+            method: "post",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + this.state.id ? "/api/admin/projectType/update" : "/api/admin/projectType/add",
+            data: {
+                id: this.state.id || undefined,
+                name: this.state.name,
+            },
+            success: function(data) {
+                if (data.error && data.error.length) {
+                    message.warning(data.error[0].message);
+                } else {
+                    message.success(this.state.id ? '修改成功' : '添加成功');
+                    this.setState({
+                        visible: false,
+                        id:'',
+                        name:'',
+                    },()=>{
+                        this.loadData();
+                    })
+                }
+            }.bind(this)
+        }).always(
+            function() {
+                this.setState({
+                    loading: false
+                });
+            }.bind(this)
+        );
+    }
+
+    onCancel(){
+        this.setState({
+            visible: false,
+            id:'',
+            name:'',
+        })
+    }
+
+    render() {
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span style={{ flex:1 }}>产品类型管理</span>
+                    <Button
+                        type="primary"
+                        onClick={()=>{this.setState({visible:true})}}
+                        style={{marginLeft:'30px'}}
+                    >
+                        新增产品
+                    </Button>
+                </div>
+                <div className="patent-table">
+                    <SpinContainer spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                               dataSource={this.state.dataSource}
+                               pagination={false}
+                               onRowClick={this.tableRowClick} />
+                    </SpinContainer>
+                </div>
+                <Modal
+                    className="customeDetails"
+                    title={this.state.id ? "修改产品类型" : "添加产品类型"}
+                    okText={"保存"}
+                    width="400"
+                    visible={this.state.visible}
+                    onOk={this.onOk}
+                    onCancel={this.onCancel}
+                >
+                    <Form
+                        layout="horizontal"
+                        id="demand-form"
+                    >
+                        <SpinContainer spinning={this.state.loading}>
+                            <div className="clearfix">
+                                <FormItem
+                                    className="half-item"
+                                    labelCol={{ span: 8 }}
+                                    wrapperCol={{ span: 14 }}
+                                    label="类型名称"
+                                >
+                                    <Input
+                                        placeholder="请输入类型名称"
+                                        value={this.state.name}
+                                        onChange={(e) => {
+                                            this.setState({ name: e.target.value });
+                                        }}
+                                    />
+                                </FormItem>
+                            </div>
+                        </SpinContainer>
+                    </Form>
+                </Modal>
+            </div >
+        )
+    }
+}
+
+export default ProductSort;

+ 0 - 0
js/component/administration/weapp/productSort/user.less


+ 147 - 0
js/component/administration/weapp/user/index.jsx

@@ -0,0 +1,147 @@
+import React,{Component}from 'react';
+import {Button, Icon, Input, message, Table} from "antd";
+import SpinContainer from "../../../SpinContainer";
+import $ from "jquery/src/ajax";
+
+class User extends Component{
+    constructor(props) {
+        super(props);
+        this.state={
+            searchUserName: '',
+            loading: false,
+            columns:[
+                {
+                    title: '序号',
+                    dataIndex: 'key',
+                    key: 'key'
+                },
+                {
+                    title: '用户ID',
+                    dataIndex: 'id',
+                    key: 'id'
+                },
+                {
+                    title: '用户呢称',
+                    dataIndex: 'nickname',
+                    key: 'nickname'
+                },
+                {
+                    title: '电话',
+                    dataIndex: 'phone',
+                    key: 'phone'
+                },
+                {
+                    title: '注册时间',
+                    dataIndex: 'createTimes',
+                    key: 'createTimes'
+                },
+                {
+                    title: '是否购买',
+                    dataIndex: 'buy',
+                    key: 'buy',
+                    render: (text, record) => {
+                        return text === 0 ? '无' : '是'
+                    }
+                },
+            ],
+            dataSource:[],
+            pagination: {
+                defaultCurrent: 1,
+                defaultPageSize: 10,
+                showQuickJumper: true,
+                pageSize: 10,
+                onChange: function (page) {
+                    this.loadData(page);
+                }.bind(this),
+                showTotal: function (total) {
+                    return '共' + total + '条数据';
+                }
+            },
+
+        }
+        this.search = this.search.bind(this);
+        this.reset = this.reset.bind(this);
+        this.tableRowClick = this.tableRowClick.bind(this);
+        this.loadData = this.loadData.bind(this);
+    }
+
+    search(){this.loadData();}
+
+    reset(){
+        this.setState({
+            searchUserName: ''
+        },()=>{
+            this.loadData();
+        })
+    }
+
+    tableRowClick(){
+
+    }
+
+    loadData(pageNo = 1) {
+        this.setState({
+            loading: true
+        });
+        $.ajax({
+            method: "get",
+            dataType: "json",
+            crossDomain: false,
+            url: globalConfig.context + "/api/admin/userList",
+            data: {
+                pageNo: pageNo || 1,
+                pageSize: 10,
+                userName: this.state.searchUserName || undefined,
+            }
+        }).done((data1) => {
+            let theArr = [];
+            if (data1.error.length !== 0) {
+                message.warning(data1.error[0].message);
+            } else {
+                for (let i = 0; i < data1.data.list.length; i++) {
+                    data1.data.list[i].key = (data1.data.pageNo-1)*10+(i+1);
+                }
+                this.state.pagination.current = data1.data.pageNo;
+                this.state.pagination.total = data1.data.totalCount;
+            }
+            this.setState({
+                dataSource: data1.data.list,
+                pagination: this.state.pagination,
+            });
+        }).always(function () {
+            this.setState({
+                loading: false
+            });
+        }.bind(this))
+    }
+
+    componentDidMount() {
+        this.loadData();
+    }
+
+    render() {
+        return (
+            <div className="user-content" >
+                <div className="content-title">
+                    <span>用户管理</span>
+                </div>
+                <div className="user-search">
+                    <Input placeholder="用户关键字" value={this.state.searchUserName}
+                           onChange={(e) => { this.setState({ searchUserName: e.target.value }); }} />
+                    <Button type="primary" onClick={this.search}>搜索</Button>
+                    <Button onClick={this.reset}>重置</Button>
+                </div>
+                <div className="patent-table">
+                    <SpinContainer spinning={this.state.loading}>
+                        <Table columns={this.state.columns}
+                               dataSource={this.state.dataSource}
+                               pagination={this.state.pagination}
+                               onRowClick={this.tableRowClick} />
+                    </SpinContainer>
+                </div>
+            </div >
+        )
+    }
+}
+
+export default User;

+ 0 - 0
js/component/administration/weapp/user/user.less


+ 108 - 17
js/component/richTextEditors.jsx

@@ -1,11 +1,42 @@
 import React from 'react';
 import theme from 'react-quill/dist/quill.snow.css';
 import { message } from 'antd';
-import ReactQuill from 'react-quill';
-
+import ReactQuill,{Quill} from 'react-quill';
 import ajax from 'jquery/src/ajax/xhr.js';
 import $ from 'jquery/src/ajax';
 
+
+let BlockEmbed = Quill.import('blots/block/embed');
+class AppPanelEmbed extends BlockEmbed {
+    static create(value) {
+        const node = super.create(value);
+        node.setAttribute('contenteditable', 'false');
+        node.setAttribute('width', '100%');
+        //   设置自定义html
+        node.innerHTML = this.transformValue(value)
+        return node;
+    }
+
+    static transformValue(value) {
+        let handleArr = value.split('\n')
+        handleArr = handleArr.map(e => e.replace(/^[\s]+/, '')
+            .replace(/[\s]+$/, ''))
+        return handleArr.join('')
+    }
+
+    // 返回节点自身的value值 用于撤销操作
+    static value(node) {
+        return node.innerHTML
+    }
+}
+// blotName
+AppPanelEmbed.blotName = 'AppPanelEmbed';
+// class名将用于匹配blot名称
+AppPanelEmbed.className = 'embed-innerApp';
+// 标签类型自定义
+AppPanelEmbed.tagName = 'p';
+Quill.register(AppPanelEmbed);
+
 var RichTextUploadUrl, RichTextUploadSign;
 //上传图片
 function uploadImg(s) {
@@ -26,10 +57,15 @@ function uploadImg(s) {
                 message.warning(data.error[0].message);
             } else {
                 const cursorPosition = s.quill.getSelection().index
+                // s.quill.insertEmbed(
+                //     cursorPosition,
+                //     "image",
+                //     globalConfig.avatarUploadHost + data.data
+                // );
                 s.quill.insertEmbed(
-                  cursorPosition,
-                  "image",
-                  globalConfig.avatarUploadHost + data.data
+                    cursorPosition,
+                    'AppPanelEmbed',
+                    `<img style="width: 100%" src="${globalConfig.avatarUploadHost + data.data}"/>`
                 );
                 s.quill.setSelection(cursorPosition + 1)
             };
@@ -46,6 +82,50 @@ function fileSelect() {
     }
     uploader.click();
 }
+//音频文件选择
+function fileSelectAudio() {
+    let uploader = document.getElementById("fileToUploadAudio");
+    if (!uploader.onchange) {
+        uploader.onchange = () => {
+            uploadAudio(this)
+        }
+    }
+    uploader.click();
+}
+//音频文件上传
+function uploadAudio(s) {
+    let myform = new FormData()
+    let file = document.getElementById("fileToUploadAudio").files[0]
+    if (!file) { return; };
+    myform.append('file', file);
+    myform.append('sign', RichTextUploadSign);
+    $.ajax({
+        method: "post",
+        dataType: "json",
+        url: location.origin + RichTextUploadUrl,
+        data: myform,
+        contentType: false,
+        processData: false,
+        success: function (data) {
+            if (data.error && data.error.length) {
+                message.warning(data.error[0].message);
+            } else {
+                const cursorPosition = s.quill.getSelection().index
+                s.quill.insertEmbed(
+                    cursorPosition,
+                    'AppPanelEmbed',
+                    `<audio src="${globalConfig.avatarUploadHost + data.data}" controls="controls">Your browser does not support the audio element.</audio>`
+                );
+                s.quill.setSelection(cursorPosition + 1)
+            };
+
+        },
+        error: function(XMLHttpRequest, textStatus, errorThrown){
+            //查看错误信息
+            message("上传失败");
+        }
+    })
+}
 //视频文件选择
 function fileSelectVideo() {
     let uploader = document.getElementById("fileToUploadVideo");
@@ -75,10 +155,15 @@ function uploadVideo(s) {
                 message.warning(data.error[0].message);
             } else {
                 const cursorPosition = s.quill.getSelection().index
-                s.quill.insertEmbed( cursorPosition, "video", globalConfig.avatarUploadHost + data.data );
+                s.quill.insertEmbed(
+                    cursorPosition,
+                    'AppPanelEmbed',
+                    `<video style="width:100%" controls="" autoPlay="" name="media">
+                            <source src=${globalConfig.avatarUploadHost + data.data} type="video/mp4">
+                    </video>`
+                );
                 s.quill.setSelection(cursorPosition + 1)
             };
-            console.log("上传成功")
 
         },
         error: function(XMLHttpRequest, textStatus, errorThrown){
@@ -98,16 +183,20 @@ const Editors = React.createClass({
     handleRichText(value) {
         this.setState({ value: value });
         this.props.handleRichText(value);
+        // this.props.handleRichText(value.replace(/iframe/g, 'video'));
+    },
+    componentDidMount() {
+        document.getElementsByClassName('ql-audio')[0].style = 'background: url("../../image/audio.png") no-repeat;background-size: contain;'
     },
     componentWillMount() {
         RichTextUploadUrl = this.props.uploadUrl;
         RichTextUploadSign = this.props.uploadSign;
     },
     componentWillReceiveProps(nextProps) {
-            this.state.theBool = true;
-            // if(nextProps.textContent){
-                this.state.value = nextProps.textContent;
-            // }
+        this.state.theBool = true;
+        // if(nextProps.textContent){
+        this.state.value = nextProps.textContent || '';
+        // }
     },
     render() {
         const modules = {
@@ -125,10 +214,11 @@ const Editors = React.createClass({
                     //  [{ 'font': [] }],
                     [{ 'align': [] }],
                     ['link', 'image','video'],
-                    ['clean']
+                    ['clean'],
+                    ['audio'],
                 ],
-                handlers: { 'image': fileSelect ,'video': fileSelectVideo}
-            }
+                handlers: { 'image': fileSelect ,'video': fileSelectVideo,'audio':fileSelectAudio}
+            },
         };
         const formats = [
             'size', 'header',
@@ -136,7 +226,7 @@ const Editors = React.createClass({
             'list', 'bullet', 'indent',
             'color', 'background',
             'align',
-            'link', 'image','video'
+            'link', 'image','video','AppPanelEmbed','clean'
         ];
         return (
             <div>
@@ -148,8 +238,9 @@ const Editors = React.createClass({
                     placeholder='请填写内容!'
                     onChange={this.handleRichText}
                 />
-                <input type="file" name="fileToUpload" id="fileToUpload" placeholder='请填写内容!' style={{ "display": "none" }} />
-                 <input type="file" name="fileToUploadVideo" id="fileToUploadVideo" placeholder='请填写视频!' style={{ "display": "none" }} />
+                <input accept="image/*" type="file" name="fileToUpload" id="fileToUpload" placeholder='请填写内容!' style={{ "display": "none" }} />
+                <input accept="video/*" type="file" name="fileToUploadVideo" id="fileToUploadVideo" placeholder='请填写视频!' style={{ "display": "none" }} />
+                <input accept="audio/*" type="file" name="fileToUploadAudio" id="fileToUploadAudio" placeholder='请选择音频!' style={{ "display": "none" }} />
             </div>
         )
     },