瀏覽代碼

feat: 海报优化

邵剑恒 4 年之前
父節點
當前提交
fa876967f4

+ 1 - 1
.env

@@ -1,7 +1,7 @@
 # 是否自动打开浏览器
 BROWSER=none
 # 是否在在使用 build、dev 命令时进行 eslint 校验
-ESLINT=1
+# ESLINT=1
 # 设置反向代理域名
 # for login
 TARGET=http://yapi.wpt.la/mock/62/test/

+ 195 - 36
src/pages/poster/edit/$id$.js

@@ -1,18 +1,20 @@
 /* eslint-disable camelcase */
 import React from 'react'
-import { Button, Form, Input, Select, Slider, Switch, InputNumber, Icon, Popover, Modal, message } from 'antd'
+import { Button, Form, Input, Select, Slider, Switch,Row,Col, InputNumber, Icon, Popover, Modal, message } from 'antd'
 import { Rnd } from 'react-rnd'
-import { ImagePreview } from 'wptpc-design'
+import { ImagePreview, JsonPage } from 'wptpc-design'
 
 import isEmpty from 'lodash/isEmpty'
 // import { connect } from 'dva'
 
 import RcColorPicker from 'rc-color-picker'
 import 'rc-color-picker/assets/index.css'
-import { create, fetchDetail, update } from './service'
+import { create, fetchDetail, update,fontList } from './service'
 
 import styles from './index.less'
-
+const IconFont = Icon.createFromIconfontCN({
+  scriptUrl: '//at.alicdn.com/t/font_2018233_fl4w8ponsnu.js',
+});
 const { Option } = Select
 const { confirm } = Modal
 
@@ -32,12 +34,91 @@ export default class Edit extends React.PureComponent {
     },
     element: [],
     activeObjectIndex: 0,
+    canvasArea:false,// 鼠标是否在画布区域
     editName: '',
     imgs: [], // 预览图片的url
-    previwVisible: false // 预览框是否展示
+    previwVisible: false, // 预览框是否展示
+    fontList:[],//字体列表
   }
+  keyPress = event => {
+    const { activeObjectIndex,canvasArea } = this.state
+    const activeObject=this.state.element[activeObjectIndex] || {}
+    const e = event || window.event;
+    const { keyCode } = e;
+    var ctrlKey = e.ctrlKey || e.metaKey;
+    // console.log("🚀 ~ file: $id$.js ~ line 45 ~ Edit ~ ctrlKey", ctrlKey)
+    // console.log("🚀 ~ file: $id$.js ~ line 44 ~ Edit ~ keyCode", keyCode)
 
-  componentDidMount () {
+    if (ctrlKey && keyCode === 90) {
+      e.preventDefault();
+      this.reback = true;
+      // 撤销
+      let list = [];
+      if (localStorage.getItem('posterElement') && JSON.parse(localStorage.getItem('posterElement'))?.length > 0) {
+        list = JSON.parse(localStorage.getItem('posterElement'));
+        if (this.state.id&&list.length===1) {
+          this.reback = false;
+          return
+        }
+        list = list.slice(0, -1);
+        let obj = list.slice(-1)[0];
+        if (!obj) {
+          this.setState({
+            name: '',
+            description: '',
+            bg: {
+              type: 'bg',
+              w: 750,
+              h: 1000,
+              c: '#eaeaea'
+            },
+            element: [],
+          })
+        } else {
+          this.setState(obj)
+        }
+        localStorage.setItem('posterElement', JSON.stringify(list));
+      }
+    }
+    if (!canvasArea) {
+      return
+    }
+    // e.preventDefault(); 不能提取到最外面,有位只有按下方向键才需要阻止默认事件
+    if (keyCode === 37) {
+      e.preventDefault();
+      //左
+      this.updateElement(activeObjectIndex, { dx: activeObject.dx-1 })
+    }
+    if (keyCode === 38) {
+      e.preventDefault();
+      //上
+      this.updateElement(activeObjectIndex, { dy: activeObject.dy-1 })
+    }
+    if (keyCode === 39) {
+      e.preventDefault();
+      // 右
+      this.updateElement(activeObjectIndex, { dx: activeObject.dx+1 })
+
+    }
+    if (keyCode === 40) {
+      e.preventDefault();
+      //下
+      this.updateElement(activeObjectIndex, { dy: activeObject.dy+1 })
+
+    }
+  };
+  // 添加监听键盘事件 防止长按多次发送用keyup
+  addKeyUpEvent = () => {
+    window.addEventListener('keydown', this.keyPress);
+  };
+
+  // 移除监听键盘事件
+  removeKeyUpEvent = () => {
+    window.removeEventListener('keydowm', this.keyPress);
+  };
+  componentDidMount() {
+    this.addKeyUpEvent();
+    localStorage.setItem("posterElement",'')
     this.setState({ posterHeight: document.body.clientHeight - document.getElementById('poster').offsetTop - 35 })
     if (this.props.match.params.id) {
       fetchDetail({ id: this.props.match.params.id }).then(res => {
@@ -46,9 +127,48 @@ export default class Edit extends React.PureComponent {
           this.setState({ name: name, description: description, element: element, id: id, bg: bg, imgs: [preview] })
         }
       })
+      fontList().then(res => {
+        if (res.code === 0) {
+          this.setState({fontList:res.data})
+        }
+      })
     }
   }
+  componentDidUpdate(prevProps, prevState) {
+    const { name, description, bg, element } = this.state;
+    const { name: nameprev, description: descriptionprev, bg: bgprev, element: elementprev } = prevState;
+    console.log(name,nameprev,111);
+    if (name === nameprev && description === descriptionprev && JSON.stringify(bg) === JSON.stringify(bgprev) && JSON.stringify(element) === JSON.stringify(elementprev)) {
+      return
+    }
 
+    const temListStr = localStorage.getItem('posterElement');
+    let obj={}
+    let list = [];
+    if (temListStr) {
+      list = JSON.parse(temListStr);
+    }
+    // 撤销的时候就不再去储存值了
+    if (this.reback) {
+      this.reback = false;
+      return
+    }
+    list.push({
+      element: element,
+      name: name,
+      description: description,
+      bg:bg,
+    })
+    // 最多储存 30 步的操作
+    if (list.length >30) {
+      list=list.slice(-30)
+    }
+    localStorage.setItem('posterElement',JSON.stringify(list))
+  }
+  componentWillUnmount() {
+    this.removeKeyUpEvent();
+    localStorage.setItem('posterElement','')
+  }
   updateBgState = (value) => {
     this.setState({ bg: { ...this.state.bg, ...value } })
   }
@@ -112,6 +232,19 @@ export default class Edit extends React.PureComponent {
           // align: 'both-align'
         })
         break
+      case 'mat':
+        _ele.push({
+          type: 'mat',
+          path: '#mat_' + (this.state.element.filter(item => item.type === 'mat').length + 1) + '#',
+          content: 'https://cdn01t.weipaitang.com/img/20200407u1hmwwai-75so-tvze-5z15-oynukyk8esad-W1125H1500/w/640',
+          w: '100',
+          h: '100',
+          dx: dx + 15,
+          dy: dy + 15,
+          round: 'false'
+          // align: 'both-align'
+        })
+        break
       case 'qr':
         _ele.push({
           content: '我是预览二维码',
@@ -162,7 +295,16 @@ export default class Edit extends React.PureComponent {
       }
     })
   }
-
+  // 动态的加载字体
+  // loadFonts= async ()=> {
+  //   const font = new FontFace(
+  //     "font84",
+  //     "url(https://cdn.weipaitang.com/static/public/202012016ac3fed2-0fe8-fed20fe8-56d0-cdacb08d7de0.ttf)"
+  //   );
+  //   await font.load();
+  //   document.fonts.add(font);
+  //   document.body.classList.add("fonts-loaded");
+  // }
   render () {
     const { bg: { w: bgWidth, h: bgHeight, c: bgColor }, activeObjectIndex, element, name, description, imgs, previwVisible } = this.state
     const activeObject = element[activeObjectIndex] || {}
@@ -208,17 +350,26 @@ export default class Edit extends React.PureComponent {
             </div>
             <div className={styles.box}>
               <h2>元素</h2>
-              <ul className={styles.elem}>
+              <div style={{ fontSize: 18,cursor:"pointer" }} >
+                <Row >
+                  <Col span={12} onClick={() => this.addShape('text')}><IconFont type='iconwenben'/><span style={{display:'inline-block', margin:5}}>文本</span></Col>
+                  <Col span={12} onClick={() => this.addShape('pic')}><Icon type="picture" /><span style={{display:'inline-block', margin:5}}>图片</span></Col>
+                  <Col span={12} onClick={() => this.addShape('qr')}><Icon type="qrcode" /><span style={{display:'inline-block', margin:5}}>二维码</span></Col>
+                  <Col span={12} onClick={() => this.addShape('mat')}><IconFont type='iconsucai'/><span style={{display:'inline-block', margin:5}}>素材</span></Col>
+                </Row>
+              </div>
+              {/* <ul className={styles.elem}>
                 <li onClick={() => this.addShape('text')}><img src="https://cdn.weipaitang.com/static/20200416b0b57798-76f7-779876f7-9088-1d2665151e70-W200H200" />文字</li>
                 <li className={styles.pic} onClick={() => this.addShape('pic')}><img src="https://cdn.weipaitang.com/static/20200416a625b5f0-c5a1-b5f0c5a1-7472-58fbb8d4fb83-W200H200"/>图片</li>
                 <li className={styles.qr} onClick={() => this.addShape('qr')}><img src="https://cdn.weipaitang.com/static/20200416360ff7ff-c855-f7ffc855-0070-1542fd7ea01e-W200H200"/>二维码</li>
-              </ul>
+              </ul> */}
             </div>
             <div className={styles.box}>
               <h2>图层列表</h2>
               <ul className={styles.layer}>
                 {
                   unique(group).map((_item) => {
+                    console.log(_element,'_element');
                     return <React.Fragment>
                       <div>分组:{_item || '未分组'}</div>
                       {
@@ -226,7 +377,14 @@ export default class Edit extends React.PureComponent {
                           <li
                             className={`${activeObjectIndex === item.index ? styles.selected : ''} ${styles[item.type]}`}
                             onClick={() => this.setState({ activeObjectIndex: item.index })}>
-                            {(item.type === 'pic' ? item.path : item.t || '').toString().replace(/#/g, '')}
+                            <div className={styles.tem} style={{ display: 'inline-block', verticalAlign: -2, backgroundColor: '#1890ff05' }} >
+                              {item.type === 'pic'&&<Icon type="picture"  />}
+                              {item.type === 'mat'&&<IconFont type="iconsucai"  />}
+                              {item.type === 'text'&&<IconFont type="iconwenben" />}
+                              {item.type === 'qr' && <Icon type="qrcode" />}
+                              {item.isTemplate ? <IconFont type="iconmu"  />:<IconFont type="iconkongbai"  />}
+                            </div>
+                            {((item.type === 'pic'||item.type === 'mat') ? item.path : item.t || '').toString().replace(/#/g, '')}
                             <Popover placement="right" content={<div><p onClick={() => this.setState({ visible: true, editIndex: item.index, editType: item.type, editName: item.type === 'pic' ? item.path : item.t || '' })}>重命名</p><p onClick={() => this.delElement(item.index, item.type === 'pic' ? item.path : item.t)}>删除</p></div>}>
                               <Icon type="setting" theme="filled" />
                             </Popover>
@@ -240,7 +398,7 @@ export default class Edit extends React.PureComponent {
               </ul>
             </div>
           </div>
-          <div className={styles.middle}>
+          <div className={styles.middle} onMouseEnter={()=>{this.setState({canvasArea:true})}} onMouseLeave={()=>{this.setState({canvasArea:false})}}>
             <div id="canvas" style={{
               position: 'relative',
               width: Number(bgWidth),
@@ -366,33 +524,22 @@ export default class Edit extends React.PureComponent {
             {
               activeObject.type === 'text' && (
                 <div className={styles.box}>
-                  <h2>文字</h2>
+                  <h2>
+                    <span>文字</span>
+                    <span style={{float:'right',fontSize:14}}>
+                      <span style={{marginRight:5}}>设置为母版</span>
+                      <Switch checked={activeObject.isTemplate||false}  onChange={(checked) => this.updateElement(activeObjectIndex, { isTemplate: checked })}/>
+                    </span>
+                  </h2>
                   <Form layout="vertical">
                     <Form.Item label="内容">
                       <Input.TextArea rows={3} value={activeObject.content} onChange={(e) => this.updateElement(activeObjectIndex, { content: e.target.value })}/>
                     </Form.Item>
                     <Form.Item label="字体">
                       <Select value={activeObject.font} onChange={(value) => this.updateElement(activeObjectIndex, { font: value })}>
-                        <Option value="msyh">msyh</Option>
-                        <Option value="msyhbd">msyhbd</Option>
-                        <Option value="NotoSerifCJK.ttc">NotoSerifCJK</Option>
-                        <Option value="PingFang.ttc">PingFang</Option>
-                        <Option value="pingfang-sc-semibold">pingfang-sc-semibold</Option>
-                        <Option value="pingfang_jiancu">pingfang_jiancu</Option>
-                        <Option value="pingfang_jianxi">pingfang_jianxi</Option>
-                        <Option value="pingfang_regular">pingfang_regular</Option>
-                        <Option value="PingFang_SC">PingFang_SC</Option>
-                        <Option value="pingfang_sc_medium">pingfang_sc_medium</Option>
-                        <Option value="pingfang_sc_semibold">pingfang_sc_semibold</Option>
-                        <Option value="simhei">simhei</Option>
-                        <Option value="SourceHanSansCN-Normal">SourceHanSansCN-Normal</Option>
-                        <Option value="喜鹊招牌体">喜鹊招牌体</Option>
-                        <Option value="喜鹊燕书体(简繁体)">喜鹊燕书体(简繁体)</Option>
-                        <Option value="Songti.ttc">Songti</Option>
-                        <Option value="SourceHanSansCN-Regular.otf">SourceHanSansCN-Regular</Option>
-                        <Option value="喜鹊聚珍体regular">喜鹊聚珍体regular</Option>
-                        <Option value="思源宋体.otf">思源宋体</Option>
-                        <Option value="方正正粗黑简体">方正正粗黑简体</Option>
+                        {(this.state.fontList || []).map(item => {
+                          return <Option value={item.value}>{ item.option}</Option>
+                        })}
                       </Select>
                     </Form.Item>
                     <div style={{ display: 'flex' }}>
@@ -488,7 +635,13 @@ export default class Edit extends React.PureComponent {
             {
               activeObject.type === 'qr' && (
                 <div className={styles.box}>
-                  <h2>二维码</h2>
+                  <h2>
+                    <span>二维码</span>
+                    <span style={{float:'right',fontSize:14}}>
+                      <span style={{marginRight:5}}>设置为母版</span>
+                      <Switch checked={activeObject.isTemplate||false}  onChange={(checked) => this.updateElement(activeObjectIndex, { isTemplate: checked })}/>
+                    </span>
+                  </h2>
                   <Form layout="vertical">
                     <Form.Item label="内容">
                       <Input value={activeObject.content} onChange={(e) => this.updateElement(activeObjectIndex, { content: e.target.value })}/>
@@ -529,7 +682,7 @@ export default class Edit extends React.PureComponent {
                           unCheckedChildren="关"
                         />
                       </Form.Item>
-                      <Form.Item label="相对位置" style={{ flex: 1 }}>
+                      <Form.Item label="浮动位置" style={{ flex: 1 }}>
                         <Switch
                           checked={activeObject.relative}
                           onChange={(checked) => this.updateElement(activeObjectIndex, { relative: checked })}
@@ -551,9 +704,15 @@ export default class Edit extends React.PureComponent {
             }
 
             {
-              activeObject.type === 'pic' && (
+              (activeObject.type === 'pic'||activeObject.type === 'mat') && (
                 <div className={styles.box}>
-                  <h2>图片</h2>
+                  <h2>
+                    <span>{activeObject.type === 'pic' ? "图片" : "素材"}</span>
+                    <span style={{float:'right',fontSize:14}}>
+                      <span style={{marginRight:5}}>设置为母版</span>
+                      <Switch checked={activeObject.isTemplate||false}  onChange={(checked) => this.updateElement(activeObjectIndex, { isTemplate: checked })}/>
+                    </span>
+                  </h2>
                   <Form layout="vertical">
                     <Form.Item label="路径">
                       <Input value={activeObject.content} onChange={(e) => this.updateElement(activeObjectIndex, { content: e.target.value })}/>

+ 19 - 14
src/pages/poster/edit/index.less

@@ -102,7 +102,7 @@
     font-size: 700;
   }
   li{
-    padding-left: 20px;
+    // padding-left: 20px;
     cursor: pointer;
     // border-left: 5px solid red;
     i{
@@ -111,20 +111,25 @@
       display: none;
       margin-right: 5px;
     }
+    .tem{
+      i{
+        display: inline-block;
+      }
+    }
   }
-  li::before{
-    content: "::";
-    color: red;
-    display: inline-block;
-    width: 1em;
-    margin-left: -1em
-  }
-  li.pic::before{
-    color: blue;
-  }
-  li.qr:before{
-    color: #000;
-  }
+  // li::before{
+  //   content: "::";
+  //   color: red;
+  //   display: inline-block;
+  //   width: 1em;
+  //   margin-left: -1em
+  // }
+  // li.pic::before{
+  //   color: blue;
+  // }
+  // li.qr:before{
+  //   color: #000;
+  // }
   li:hover{
     background-color:#1890ff;
     opacity: 0.6;

+ 6 - 0
src/pages/poster/edit/service.js

@@ -17,3 +17,9 @@ export async function update (params) {
   const url = `${dc}/api/poster/update`
   return fetchApi(url, params)
 }
+
+// 字体列表
+export async function fontList (params) {
+  const url = `${dc}/api/poster/font-list`
+  return fetchApiGet(url, params)
+}

+ 86 - 0
src/pages/poster/list/components/JsonExport/index.js

@@ -0,0 +1,86 @@
+import React, { useState, useEffect, useReducer } from 'react';
+import { Modal, Input, message, Form, Select, Spin, Button, Row } from 'antd';
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { tuple } from 'antd/lib/_util/type';
+import { getJsonService } from './service';
+
+export default function JsonExport({ routerParams = {}, record, refresh }) {
+  const [visible, setvisible] = useState(false);
+  const [spinning, setSpinning] = useState(false);
+  const [textJson, setTextJson] = useState('');
+
+  const { TextArea } = Input;
+
+  // 复制按钮
+  const onExportPower2JsonModalCancel = () => {
+    setTextJson();
+    setvisible(false);
+  };
+  const onExportPower2JsonModalCopy = (text, result) => {
+    if (result) {
+      message.success('复制成功!');
+      onExportPower2JsonModalCancel();
+    } else {
+      message.warning('复制失败,请手动复制!');
+    }
+  };
+  const getJson = id => {
+    setSpinning(true);
+    getJsonService({ id }).then(res => {
+      if (res?.code === 0) {
+        setTextJson(JSON.stringify(res.data));
+      }
+      setSpinning(false);
+    });
+  };
+
+  return (
+    <div
+      style={{ display: 'inline-block' }}
+      onClick={e => {
+        e.stopPropagation();
+      }}
+    >
+      <Modal
+        title={`导出`}
+        maskClosable={false}
+        destroyOnClose
+        visible={visible}
+        width={700}
+        footer={[
+          <Button key="back" onClick={onExportPower2JsonModalCancel}>
+            关闭
+          </Button>,
+          <CopyToClipboard key="copy" text={textJson} onCopy={onExportPower2JsonModalCopy}>
+            <div style={{ display: 'inline-block', marginLeft: '10px' }}>
+              <Button key="submit" type="primary">
+                拷贝
+              </Button>
+            </div>
+          </CopyToClipboard>,
+        ]}
+        onCancel={onExportPower2JsonModalCancel}
+      >
+        {/* <BindTable id={record.id} platform={routerParams.platform} /> */}
+        <Spin spinning={spinning}>
+          <Row gutter={12}>
+            <TextArea
+              placeholder="需要批量导出的菜单数据结构"
+              rows={15}
+              value={textJson}
+              readOnly
+            />
+          </Row>
+        </Spin>
+      </Modal>
+      <div
+        onClick={() => {
+          getJson(record.id);
+          setvisible(true);
+        }}
+      >
+        <a> 导出 </a>
+      </div>
+    </div>
+  );
+}

+ 12 - 0
src/pages/poster/list/components/JsonExport/service.js

@@ -0,0 +1,12 @@
+import {  fetchApi_get as fetchApiGet } from '@/apis/'
+import { dc } from '@/conf/config'
+
+// export async function batchbindrole(params) {
+//   return request({url: `${auth}/user/batchbindrole`, params});
+// }
+
+// 新增改写词
+export async function getJsonService(params) {
+  const url = `${dc}/api/poster/export`;
+  return fetchApiGet(url, params);
+}

+ 72 - 0
src/pages/poster/list/components/JsonImport/index.js

@@ -0,0 +1,72 @@
+import React, { useState } from 'react';
+import { Modal, Input, message, Button, Row } from 'antd';
+import { subJsonService } from './service';
+
+export default function JsonImport({ refresh }) {
+  const [visible, setvisible] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [areaChange, setAreaChange] = useState('');
+
+  const { TextArea } = Input;
+
+  const onExportPower2JsonModalCancel = () => {
+    setAreaChange();
+    setvisible(false);
+  };
+
+  const submitJson = () => {
+    setLoading(true);
+    const param = JSON.parse(areaChange);
+    subJsonService(param).then(res => {
+      if (res?.code === 0) {
+        message.success('导入成功');
+        refresh();
+      }
+      setLoading(false);
+      onExportPower2JsonModalCancel();
+    });
+  };
+  const textOnChange = e => {
+    setAreaChange(e.target.value);
+  };
+  return (
+    <div style={{ display: 'inline-block' }}>
+      <Modal
+        title="导入"
+        maskClosable={false}
+        destroyOnClose
+        visible={visible}
+        width={700}
+        footer={[
+          <Button key="back" onClick={onExportPower2JsonModalCancel}>
+            关闭
+          </Button>,
+          <Button type="primary" key="submmit" onClick={submitJson} loading={loading}>
+            确定
+          </Button>,
+        ]}
+        onCancel={onExportPower2JsonModalCancel}
+      >
+        <Row gutter={12}>
+          <TextArea
+            placeholder="需要导出的数据结构"
+            rows={15}
+            value={areaChange}
+            onChange={(e, record) => {
+              textOnChange(e, record);
+            }}
+          />
+        </Row>
+      </Modal>
+      <div
+        onClick={() => {
+          setvisible(true);
+        }}
+      >
+        <Button type="primary" style={{ marginLeft: 10 }}>
+          导入
+        </Button>
+      </div>
+    </div>
+  );
+}

+ 12 - 0
src/pages/poster/list/components/JsonImport/service.js

@@ -0,0 +1,12 @@
+import { fetchApi } from '@/apis/'
+import { dc } from '@/conf/config'
+
+
+
+
+// 提交json
+export async function subJsonService (params) {
+  const url = `${dc}/api/poster/create`
+  console.log(fetchApi,'fetchApi');
+  return fetchApi(url, params)
+}

+ 68 - 16
src/pages/poster/list/index.js

@@ -1,7 +1,7 @@
 /* eslint-disable no-return-assign */
 /* eslint-disable camelcase */
 import React, { Component, Fragment } from 'react'
-import { Divider, Modal, message } from 'antd'
+import { Divider, Modal, message,Button,Tag } from 'antd'
 import { FilterTable, ImagePreview } from 'wptpc-design'
 import { connect } from 'dva'
 import { routerRedux } from 'dva/router'
@@ -10,8 +10,9 @@ import ConfigModal from './components/ConfigModal'
 import CopyTemplateModal from './components/CopyTemplateModal'
 import { dc } from '@/conf/config'
 import { fetchApi_get } from '@/apis/'
-
-import { delTemplateAction } from './services'
+import ExportPower from './components/JsonExport';
+import ImportPower from './components/JsonImport';
+import { delTemplateAction,changePosterState } from './services'
 
 // less
 import styles from './index.less'
@@ -74,7 +75,24 @@ class Poster extends Component {
       }
     })
   }
-
+  changeState = (status, id) => {
+    Modal.confirm({
+      title: status === 0 ? '确定要禁用该海报模板吗' : '确定要启用该海报模板吗',
+      onOk: () => {
+        changePosterState({ status, id }).then(res => {
+          if (res.code === 0) {
+            if (status === 0) {
+              debugger
+              message.success('已禁用')
+            } else if (status === 0) {
+              message.success('已启用')
+            }
+            this.refresh();
+          }
+        })
+      }
+    })
+  }
   render () {
     // 搜索框配置
     const filterSettingConfig = {
@@ -95,6 +113,17 @@ class Poster extends Component {
         type: 'input',
         key: 'keyword',
         placeholder: '模板id,模板标识'
+      },
+      {
+        label: '状态',
+        type: 'select',
+        key: 'state',
+        option: [
+          { label: '全部', value: '' },
+          { label: '启用', value: 1 },
+          { label: '禁用', value: 0 },
+        ],
+        defaultValue: '',
       }]
       // 查询前触发的函数,进行参数整合
       // beforeSearchFunc: (data) => {
@@ -105,6 +134,7 @@ class Poster extends Component {
     const tableSettingConfig = {
       // key
       rowKey: 'id',
+      bordered: true,
       // 设置分页信息
       // piganition: {
       //   pageSize: 10,
@@ -115,7 +145,8 @@ class Poster extends Component {
         dataIndex: 'id'
       }, {
         title: '海报缩略图',
-        dataIndex: 'preview',
+          dataIndex: 'preview',
+        width:100,
         render: (_, record) => <img src={_} className={styles.previewImg} onClick={this.previewImg.bind(this, record)} />
       }, {
         title: '海报标识',
@@ -123,16 +154,43 @@ class Poster extends Component {
       }, {
         title: '海报描述',
         dataIndex: 'description'
-      }, {
+      },{
+        title: '状态',
+        dataIndex: 'stateName',
+        render: (t, record) => {
+          if (record.state === 1) {
+            return <Tag color='green'>{t}</Tag>
+          } else {
+            return <Tag color='red' >{t}</Tag>
+          }
+        }
+      },{
+        title: '创建人',
+        dataIndex: 'creator'
+      },{
+        title: '最后修改人',
+        dataIndex: 'updater'
+      },{
         title: '操作',
         dataIndex: 'actions',
         render: (_, record) => {
+          const { id } = record
           return (
             <Fragment>
               <a href={`/poster/edit/${record.id}`}>编辑</a>
+              {record.state === 0 && <>
+                <Divider type="vertical" />
+                <a onClick={this.changeState.bind(this,1,id)}>启用</a>
+              </>}
+              {record.state === 1 && <>
+                <Divider type="vertical" />
+                <a onClick={this.changeState.bind(this,0,id)}>禁用</a>
+              </>}
               <Divider type="vertical" />
               <a onClick={this.delImg.bind(this, record)}>删除</a>
               <Divider type="vertical" />
+              <ExportPower record={ record}/>
+              <Divider type="vertical" />
               <a onClick={this.handleConfig.bind(this, record)}>查看配置</a>
               <Divider type="vertical" />
               <a onClick={this.handleCopyTemplate.bind(this, record)}>复制模版</a>
@@ -140,16 +198,10 @@ class Poster extends Component {
           )
         }
       }],
-      // 放在搜索和列表之间额外按钮
-      batchBtns: [{
-        key: 'craeteBtn',
-        label: '创建',
-        type: 'primary',
-        onClick: (e) => {
-          this.props.dispatch(routerRedux.push({ pathname: '/poster/edit' }))
-          // TODO:暂时没有创建功能
-        }
-      }],
+      batchBtnsJxs: [
+        <Button type='primary'  onClick={(e) => { this.props.dispatch(routerRedux.push({ pathname: '/poster/edit' })) }}>创建</Button>,
+        <ImportPower refresh={ this.refresh}/>
+      ],
       // 刷新页面
       getRefresh: refresh => {
         this.refresh = refresh

+ 1 - 0
src/pages/poster/list/index.less

@@ -1,5 +1,6 @@
 .poster {}
 .previewImg{
   width: 80px;
+  height: 80px;
   object-fit: cover;
 }

+ 6 - 0
src/pages/poster/list/services.js

@@ -19,3 +19,9 @@ export async function delTemplateAction (params) {
   const url = `${dc}/api/poster/delete`
   return fetchApiGet(url, params)
 }
+
+// 改变模板状态
+export async function changePosterState (params) {
+  const url = `${dc}/api/poster/check-status`
+  return fetchApiGet(url, params)
+}