123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- import React, { Component } from 'react';
- import pathToRegexp from 'path-to-regexp';
- import { connect } from 'dva';
- import { routerRedux } from 'dva/router';
- import {
- Form, Modal, Card, Button, Input, Switch, Select, Row, Col,
- } from 'antd';
- import {
- renderStatus, statusToBool, boolToStatus, genAbsolutePicUrl,
- } from '../../../utils/utils';
- import { Hotax } from '../../../utils/config';
- import AXDragSortTable from '../../../components/AXDragSortTable';
- import Selector from '../../../components/AXTableSelector/Selector';
- import FooterToolbar from '../../../components/FooterToolbar';
- import styles from './CourseCreate.less';
- const fieldLabels = {
- code: '课程编号',
- title: '课程标题',
- subTitle: '课程副标题',
- name: '课程全称',
- breadCrumb: '顶部导航名',
- merchant: '内容提供商',
- digest: '课程概要',
- detail: '课程详情',
- coverUrl: '课程封面图',
- bgUrl: '课程背景图',
- status: '课程状态',
- };
- const formItemLayout = {
- labelCol: {
- xs: { span: 24 },
- sm: { span: 3 },
- },
- wrapperCol: {
- xs: { span: 24 },
- sm: { span: 14 },
- md: { span: 12 },
- },
- };
- @connect(({ loading, product, lesson, resource, merchant }) => ({
- lesson,
- product,
- resource,
- merchant,
- lLoading: loading.models.lesson,
- pLoading: loading.models.product,
- rLoading: loading.models.resource,
- submitting: loading.models.product,
- }))
- @Form.create()
- export default class CourseItemCreatePage extends Component {
- state = {
- bgSelectorDestroy: true,
- coverSelectorDestroy: true,
- lessonSelectorDestroy: true,
- supportSelectorDestroy: true,
- };
- componentWillMount() {
- const match = pathToRegexp('/product/course/create').exec(this.props.location.pathname);
- if (match) {
- this.cleanPageState();
- }
- }
- componentDidMount() {
- const matchId = this.isEdit();
- if (matchId) {
- this.props.dispatch({
- type: 'product/fetchProductItem',
- payload: { pid: matchId },
- });
- }
- this.props.dispatch({
- type: 'merchant/fetchMerchantList',
- payload: { pageSize: 1000 }, // TODO 以后商户多了需要改写交互样式
- });
- }
- isEdit = () => {
- const { location } = this.props;
- const match = pathToRegexp('/product/course/edit/:id').exec(location.pathname);
- if (match) {
- return match[1];
- }
- return false;
- };
- cleanPageState = () => {
- this.props.dispatch({
- type: 'product/cleanItemState',
- payload: {},
- });
- };
- selectorDataFetcher = (name, params) => {
- switch (name) {
- case 'cover':
- this.props.dispatch({
- type: 'resource/fetchImageList',
- payload: params,
- });
- break;
- case 'bg':
- this.props.dispatch({
- type: 'resource/fetchImageList',
- payload: params,
- });
- break;
- case 'lesson':
- this.props.dispatch({
- type: 'lesson/fetchLessonList',
- payload: params,
- });
- break;
- case 'support':
- this.props.dispatch({
- type: 'product/fetchSupportList',
- payload: params,
- });
- break;
- default:
- break;
- }
- };
- currentItemFormatter = (name, rows) => {
- let payload;
- switch (name) {
- case 'cover':
- payload = { coverUrl: rows[0].path };
- break;
- case 'bg':
- payload = { bgUrl: rows[0].path };
- break;
- case 'lesson':
- payload = { subItemList: rows };
- break;
- case 'support':
- payload = { supportList: rows };
- break;
- default:
- break;
- }
- return payload;
- };
- handleSelectorModalShow = (name) => {
- this.setState({
- [`${name}SelectorDestroy`]: false,
- });
- this.selectorDataFetcher(name);
- };
- handleSelectorChange = (name, params) => {
- this.selectorDataFetcher(name, params);
- };
- handleSelectorFinish = (name, rows) => {
- this.setState({
- [`${name}SelectorDestroy`]: true,
- });
- const payload = this.currentItemFormatter(name, rows);
- this.props.dispatch({
- payload,
- type: 'product/fixCurrentItem',
- });
- };
- handleDragSortTableChange = (name, rows) => {
- const payload = this.currentItemFormatter(name, rows);
- this.props.dispatch({
- payload,
- type: 'product/fixCurrentItem',
- });
- };
- handleSelectorCancel = (name) => {
- this.setState({
- [`${name}SelectorDestroy`]: true,
- });
- };
- handlePageBack = () => {
- this.props.dispatch(routerRedux.push({
- pathname: '/product/course/list',
- state: this.props.location.state,
- }));
- };
- handlePageSubmit = (e) => {
- e.preventDefault();
- this.props.form.validateFieldsAndScroll((err, values) => {
- if (!err) {
- // 提取表单字段
- const { title, subTitle, name, status, ...rest } = values;
- const newName = `${title}_${subTitle}`;
- const newValues = { title, subTitle, name: newName, status: boolToStatus(status), ...rest };
- const { product } = this.props;
- const { currentItem } = product;
- const { bgUrl, coverUrl, subItemList, supportList } = currentItem;
- // 构造subList,supportIdList
- let subList;
- let supportIdList;
- if (subItemList) {
- subList = subItemList.map(
- item => ({ id: item.id, type: Hotax.PRODUCT_LESSON })
- );
- }
- if (supportList) {
- supportIdList = supportList.map(item => item.id);
- }
- const matchId = this.isEdit();
- if (matchId) {
- const params = {
- bgUrl,
- coverUrl,
- id: matchId,
- subItemList: subList,
- supportList: supportIdList,
- ...newValues,
- };
- this.props.dispatch({
- type: 'product/updateCourseItem',
- payload: params,
- states: this.props.location.state,
- });
- } else {
- const params = {
- bgUrl,
- coverUrl,
- subItemList: subList,
- supportList: supportIdList,
- ...newValues,
- };
- this.props.dispatch({
- type: 'product/createCourseItem',
- payload: params,
- states: this.props.location.state,
- });
- }
- }
- });
- };
- render() {
- const {
- form, submitting, rLoading, lLoading, pLoading, lesson, product, resource, merchant,
- } = this.props;
- const {
- lessonSelectorDestroy, supportSelectorDestroy, coverSelectorDestroy, bgSelectorDestroy,
- } = this.state;
- const { currentItem } = product;
- const {
- code, title, subTitle, name, digest, detail, status, coverUrl, bgUrl, cpId,
- breadCrumb, subItemList = [], supportList = [],
- } = currentItem;
- const { getFieldDecorator } = form;
- const lessonColumns = [{
- title: '课编号',
- dataIndex: 'code',
- key: 1,
- width: '20%',
- render: (text, record) => (
- <a
- className="a-link"
- target="_blank"
- rel="noopener noreferrer"
- href={`/product/lesson/edit/${record.id}`}
- >
- {text}
- </a>
- ),
- }, {
- title: '课名称',
- dataIndex: 'title',
- key: 2,
- width: '30%',
- render: (text, record) => (
- <a
- className="a-link"
- target="_blank"
- rel="noopener noreferrer"
- href={`/product/lesson/edit/${record.id}`}
- >
- {text}
- </a>
- ),
- }, {
- title: '状态',
- dataIndex: 'status',
- key: 3,
- render: text => renderStatus(text),
- }];
- const supportColumns = [{
- title: '配套编号',
- dataIndex: 'code',
- key: 1,
- width: '20%',
- render: (text, record) => (
- <a
- className="a-link"
- target="_blank"
- rel="noopener noreferrer"
- href={`/product/support/edit/${record.id}`}
- >
- {text}
- </a>
- ),
- }, {
- title: '配套名称',
- dataIndex: 'name',
- key: 2,
- width: '30%',
- render: (text, record) => (
- <a
- className="a-link"
- target="_blank"
- rel="noopener noreferrer"
- href={`/product/support/edit/${record.id}`}
- >
- {text}
- </a>
- ),
- }, {
- title: '配套状态',
- dataIndex: 'status',
- key: 3,
- render: text => renderStatus(text),
- }];
- const getMerchants = () => {
- const { list } = merchant;
- return list.map(item => ({
- text: item.name,
- key: item.id,
- }));
- };
- const getResourceModal = (isCover) => {
- return (
- <Modal
- width={1100}
- footer={null}
- visible
- title="图片资源"
- maskClosable={false}
- onCancel={() => this.handleSelectorCancel(isCover ? 'cover' : 'bg')}
- >
- <Selector
- multiple={false}
- loading={rLoading}
- selectorName="PictureSingle"
- list={resource.list}
- pageNo={resource.pageNo}
- pageSize={resource.pageSize}
- totalSize={resource.totalSize}
- onCancel={() => this.handleSelectorCancel(isCover ? 'cover' : 'bg')}
- onChange={data => this.handleSelectorChange(isCover ? 'cover' : 'bg', data)}
- onFinish={rows => this.handleSelectorFinish(isCover ? 'cover' : 'bg', rows)}
- />
- </Modal>
- );
- };
- const getLessonModal = () => {
- return (
- <Modal
- width={1100}
- footer={null}
- visible
- title="课资源"
- maskClosable={false}
- onCancel={() => this.handleSelectorCancel('lesson')}
- >
- <Selector
- multiple
- loading={lLoading}
- selectorName="Lesson"
- selectedRows={subItemList}
- list={lesson.list}
- pageNo={lesson.pageNo}
- pageSize={lesson.pageSize}
- totalSize={lesson.totalSize}
- onCancel={() => this.handleSelectorCancel('lesson')}
- onChange={data => this.handleSelectorChange('lesson', data)}
- onFinish={rows => this.handleSelectorFinish('lesson', rows)}
- />
- </Modal>
- );
- };
- const getSupportModal = () => {
- return (
- <Modal
- width={1100}
- footer={null}
- visible
- title="配套资源"
- maskClosable={false}
- onCancel={() => this.handleSelectorCancel('support')}
- >
- <Selector
- multiple
- loading={pLoading}
- selectorName="Support"
- selectedRows={supportList}
- list={product.list}
- pageNo={product.pageNo}
- pageSize={product.pageSize}
- totalSize={product.totalSize}
- onCancel={() => this.handleSelectorCancel('support')}
- onChange={data => this.handleSelectorChange('support', data)}
- onFinish={rows => this.handleSelectorFinish('support', rows)}
- />
- </Modal>
- );
- };
- const renderLessonCardName = () => {
- return (
- <Button
- type="primary"
- onClick={() => this.handleSelectorModalShow('lesson')}
- >课列表
- </Button>
- );
- };
- const renderSupportCardName = () => {
- return (
- <Button
- type="primary"
- onClick={() => this.handleSelectorModalShow('support')}
- >配套列表
- </Button>
- );
- };
- const renderCoverCardName = () => {
- return (
- <div className={styles.cardName}>
- <span>
- <a onClick={() => this.handleSelectorModalShow('cover')}>更换封面</a>
- </span>
- </div>
- );
- };
- const renderbgCardName = () => {
- return (
- <div className={styles.cardName}>
- <span>
- <a onClick={() => this.handleSelectorModalShow('bg')}>更换背景</a>
- </span>
- </div>
- );
- };
- return (
- <div>
- {/* 基础信息Card */}
- <Card title="基础信息" style={{ marginBottom: 16 }}>
- <Form>
- <Form.Item hasFeedback label={fieldLabels.code} {...formItemLayout}>
- {getFieldDecorator('code', {
- rules: [
- {
- required: true, message: '请填写课程编号',
- }, {
- pattern: /^[a-zA-Z0-9|-]+$/g, message: '编号包含非法字符',
- },
- ],
- initialValue: code,
- })(
- <Input placeholder="请输入" />
- )}
- </Form.Item>
- {this.isEdit() && (
- <Form.Item label={fieldLabels.name} {...formItemLayout}>
- {getFieldDecorator('name', {
- initialValue: name,
- })(
- <Input placeholder="根据标题及副标题自动生成完整名称,不必填写" disabled />
- )}
- </Form.Item>
- )}
- <Form.Item hasFeedback label={fieldLabels.title} {...formItemLayout}>
- {getFieldDecorator('title', {
- rules: [{ required: true, message: '请填写课程标题' }],
- initialValue: title,
- })(
- <Input placeholder="请输入" />
- )}
- </Form.Item>
- <Form.Item hasFeedback label={fieldLabels.subTitle} {...formItemLayout}>
- {getFieldDecorator('subTitle', {
- rules: [{ required: true, message: '请填写课程副标题' }],
- initialValue: subTitle,
- })(
- <Input placeholder="请输入" />
- )}
- </Form.Item>
- <Form.Item hasFeedback label={fieldLabels.breadCrumb} {...formItemLayout}>
- {getFieldDecorator('breadCrumb', {
- rules: [{ required: true, message: '请填写顶部导航名' }],
- initialValue: breadCrumb,
- })(
- <Input placeholder="请输入" />
- )}
- </Form.Item>
- <Form.Item hasFeedback label={fieldLabels.merchant} {...formItemLayout}>
- {getFieldDecorator('cpId', {
- rules: [{ required: true, message: '请选择供应商' }],
- initialValue: cpId,
- })(
- <Select placeholder="请选择">
- {
- getMerchants().map(item => (
- <Select.Option key={item.key} value={item.key}>
- {item.text}
- </Select.Option>
- ))
- }
- </Select>
- )}
- </Form.Item>
- <Form.Item label={fieldLabels.digest} {...formItemLayout}>
- {getFieldDecorator('digest', {
- initialValue: digest,
- })(
- <Input.TextArea rows={4} placeholder="请输入" />
- )}
- </Form.Item>
- <Form.Item label={fieldLabels.detail} {...formItemLayout}>
- {getFieldDecorator('detail', {
- initialValue: detail,
- })(
- <Input.TextArea rows={6} placeholder="请输入" />
- )}
- </Form.Item>
- <Form.Item label={fieldLabels.status} {...formItemLayout}>
- {getFieldDecorator('status', {
- valuePropName: 'checked',
- initialValue: statusToBool(status),
- })(
- <Switch
- checkedChildren="正常"
- unCheckedChildren="删除"
- />
- )}
- </Form.Item>
- </Form>
- </Card>
- {/* 封面及背景图选择Card */}
- <Card title="封面|背景" style={{ marginBottom: 16 }}>
- <Row gutter={16}>
- <Col
- md={{ span: 9, offset: 1 }}
- lg={{ span: 7, offset: 2 }}
- xl={{ span: 5, offset: 4 }}
- xxl={{ span: 3, offset: 6 }}
- >
- <Card
- hoverable
- title={renderCoverCardName()}
- >
- {
- coverUrl && (
- <div className={styles.cover}>
- <img src={genAbsolutePicUrl(coverUrl)} alt="" />
- </div>
- )
- }
- {!coverSelectorDestroy && getResourceModal(true)}
- </Card>
- </Col>
- <Col
- md={{ span: 9, offset: 2 }}
- lg={{ span: 7, offset: 4 }}
- xl={{ span: 5, offset: 4 }}
- xxl={{ span: 3, offset: 5 }}
- >
- <Card
- hoverable
- title={renderbgCardName()}
- >
- {
- bgUrl ? (
- <div className={styles.background}>
- <img src={genAbsolutePicUrl(bgUrl)} alt="" />
- </div>
- ) : null
- }
- {!bgSelectorDestroy && getResourceModal(false)}
- </Card>
- </Col>
- </Row>
- </Card>
- {/* 课列表选择Card */}
- <Card title={renderLessonCardName()} style={{ marginBottom: 16 }}>
- <AXDragSortTable
- columns={lessonColumns}
- data={subItemList}
- onChange={rows => this.handleDragSortTableChange('lesson', rows)}
- />
- {!lessonSelectorDestroy && getLessonModal()}
- </Card>
- {/* 周边配套选择Card */}
- <Card title={renderSupportCardName()} style={{ marginBottom: 70 }}>
- <AXDragSortTable
- columns={supportColumns}
- data={supportList}
- onChange={rows => this.handleDragSortTableChange('support', rows)}
- />
- {!supportSelectorDestroy && getSupportModal()}
- </Card>
- <FooterToolbar style={{ width: '100%' }}>
- <Button
- onClick={this.handlePageBack}
- style={{ marginRight: 10 }}
- >取消
- </Button>
- <Button
- type="primary"
- loading={submitting}
- onClick={this.handlePageSubmit}
- >提交
- </Button>
- </FooterToolbar>
- </div>
- );
- }
- }
|