From 9a60da3f80eacbaadb98b6c9697aeffcc8affe57 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 08 四月 2021 18:36:41 +0800
Subject: [PATCH] 2021-04-08

---
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx |   16 +
 src/tabviews/custom/components/card/cardcellList/index.jsx               |   13 
 src/pc/modulesource/option.jsx                                           |    2 
 src/assets/mobimg/login.png                                              |    0 
 src/menu/stylecontroller/index.jsx                                       |   18 
 src/pc/components/login/normal-login/loginform.jsx                       |  130 +++++++++
 src/pc/menushell/card.jsx                                                |    3 
 src/pc/components/login/wrapsetting/settingform/index.scss               |   11 
 src/pc/menushell/index.jsx                                               |    5 
 src/pc/components/login/normal-login/index.jsx                           |  149 ++++++++++
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx           |   13 
 src/menu/components/card/cardcellcomponent/formconfig.jsx                |   16 +
 src/tabviews/custom/components/share/normalTable/index.jsx               |   14 
 src/pc/components/login/wrapsetting/index.scss                           |    7 
 src/pc/components/login/wrapsetting/settingform/index.jsx                |  253 ++++++++++++++++++
 src/pc/components/login/wrapsetting/index.jsx                            |   83 +++++
 src/pc/components/login/normal-login/index.scss                          |   58 ++++
 17 files changed, 757 insertions(+), 34 deletions(-)

diff --git a/src/assets/mobimg/login.png b/src/assets/mobimg/login.png
new file mode 100644
index 0000000..13c10ee
--- /dev/null
+++ b/src/assets/mobimg/login.png
Binary files differ
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index 96b6549..126104c 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -18,6 +18,11 @@
 const QrCode = asyncComponent(() => import('@/components/qrcode'))
 const Video = asyncComponent(() => import('@/components/video'))
 const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
+const PicRadio = {
+  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
+  '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
+  '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
+}
 
 const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks, doubleClickCard }) => {
   const originalIndex = findCard(id).index
@@ -85,12 +90,8 @@
         _imagestyle.borderRadius = card.style.borderRadius
       }
 
-      if (card.lenWidRadio === '16:9') {
-        _imagestyle.paddingTop = '56.25%'
-      } else if (card.lenWidRadio === '3:2') {
-        _imagestyle.paddingTop = '66.67%'
-      } else if (card.lenWidRadio === '4:3') {
-        _imagestyle.paddingTop = '75%'
+      if (PicRadio[card.lenWidRadio]) {
+        _imagestyle.paddingTop = PicRadio[card.lenWidRadio]
       } else {
         _imagestyle.paddingTop = '100%'
       }
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index b81da36..f3bfb6d 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -293,9 +293,21 @@
       required: true,
       options: [
         { value: '1:1', text: '1:1' },
-        { value: '3:2', text: '3:2' },
         { value: '4:3', text: '4:3' },
-        { value: '16:9', text: '16:9' }
+        { value: '3:2', text: '3:2' },
+        { value: '16:9', text: '16:9' },
+        { value: '2:1', text: '2:1' },
+        { value: '3:1', text: '3:1' },
+        { value: '4:1', text: '4:1' },
+        { value: '5:1', text: '5:1' },
+        { value: '6:1', text: '6:1' },
+        { value: '7:1', text: '7:1' },
+        { value: '8:1', text: '8:1' },
+        { value: '9:1', text: '9:1' },
+        { value: '10:1', text: '10:1' },
+        { value: '3:4', text: '3:4' },
+        { value: '2:3', text: '2:3' },
+        { value: '9:16', text: '9:16' },
       ]
     },
     {
diff --git a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
index 46484ca..09abffc 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -255,9 +255,21 @@
       required: true,
       options: [
         { value: '1:1', text: '1:1' },
-        { value: '3:2', text: '3:2' },
         { value: '4:3', text: '4:3' },
-        { value: '16:9', text: '16:9' }
+        { value: '3:2', text: '3:2' },
+        { value: '16:9', text: '16:9' },
+        { value: '2:1', text: '2:1' },
+        { value: '3:1', text: '3:1' },
+        { value: '4:1', text: '4:1' },
+        { value: '5:1', text: '5:1' },
+        { value: '6:1', text: '6:1' },
+        { value: '7:1', text: '7:1' },
+        { value: '8:1', text: '8:1' },
+        { value: '9:1', text: '9:1' },
+        { value: '10:1', text: '10:1' },
+        { value: '3:4', text: '3:4' },
+        { value: '2:3', text: '2:3' },
+        { value: '9:16', text: '9:16' },
       ]
     },
     {
diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx
index 595e8ff..7f9e282 100644
--- a/src/menu/stylecontroller/index.jsx
+++ b/src/menu/stylecontroller/index.jsx
@@ -329,7 +329,7 @@
                     label={<Icon title="瀹藉害" type="column-width" />}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw']} onChange={this.changeWidth}/>
+                    <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw', '%']} onChange={this.changeWidth}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -557,7 +557,7 @@
                     label={<Icon title="涓婅竟璺�" type="arrow-up"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/>
+                    <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -566,7 +566,7 @@
                     label={<Icon title="涓嬭竟璺�" type="arrow-down"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/>
+                    <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -575,7 +575,7 @@
                     label={<Icon title="宸﹁竟璺�" type="arrow-left"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/>
+                    <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -584,7 +584,7 @@
                     label={<Icon title="鍙宠竟璺�" type="arrow-right"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
+                    <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -595,7 +595,7 @@
                     label={<Icon title="涓婅竟璺�" type="arrow-up"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/>
+                    <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -604,7 +604,7 @@
                     label={<Icon title="涓嬭竟璺�" type="arrow-down"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/>
+                    <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -613,7 +613,7 @@
                     label={<Icon title="宸﹁竟璺�" type="arrow-left"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/>
+                    <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -622,7 +622,7 @@
                     label={<Icon title="鍙宠竟璺�" type="arrow-right"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
+                    <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
diff --git a/src/pc/components/login/normal-login/index.jsx b/src/pc/components/login/normal-login/index.jsx
new file mode 100644
index 0000000..0458169
--- /dev/null
+++ b/src/pc/components/login/normal-login/index.jsx
@@ -0,0 +1,149 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Popover } from 'antd'
+
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import asyncComponent from '@/utils/asyncComponent'
+
+import MKEmitter from '@/utils/events.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import './index.scss'
+
+const LoginForm = asyncComponent(() => import('./loginform'))
+const WrapComponent = asyncIconComponent(() => import('../wrapsetting'))
+
+class PropCardEditComponent extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    deletecomponent: PropTypes.func,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    card: null,
+    back: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        floor: card.floor,
+        tabId: card.tabId || '',
+        parentId: card.parentId || '',
+        dataName: card.dataName || '',
+        width: card.width || 24,
+        name: card.name,
+        subtype: card.subtype,
+        wrap: { name: card.name, width: card.width || 24, title: '', switch: 'false', datatype: 'static' },
+        style: { background: '#ffffff', width: '330px', borderRadius: '4px', marginLeft: '55vw' },
+        loginWays: [
+          {type: 'uname_pwd', label: '璐﹀彿瀵嗙爜', remember: 'true', disabled: false, labelStyle: {}, submitStyle: {}, submitLabel: '鐧诲綍'},
+          {type: 'sms_vcode', label: '鐭俊楠岃瘉鐮�', disabled: true, labelStyle: {}, submitStyle: {}, submitLabel: '鐧诲綍'}
+        ]
+      }
+
+      if (card.config) {
+        let config = fromJS(card.config).toJS()
+
+        _card.wrap = config.wrap
+        _card.wrap.name = card.name
+        _card.style = config.style
+      }
+      this.setState({
+        card: _card
+      })
+      this.props.updateConfig(_card)
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('submitStyle', this.getStyle)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('submitStyle', this.getStyle)
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (component) => {
+    this.setState({
+      card: component
+    })
+
+    component.width = component.wrap.width
+    component.name = component.wrap.name
+
+    this.props.updateConfig(component)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', [card.uuid], ['width', 'background', 'border', 'padding', 'margin'], card.style)
+  }
+
+  getStyle = (comIds, style) => {
+    const { card } = this.state
+
+    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
+
+    let _card = {...card, style}
+
+    this.setState({
+      card: _card
+    })
+    
+    this.props.updateConfig(_card)
+  }
+
+  clickComponent = (e) => {
+    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
+      e.stopPropagation()
+      MKEmitter.emit('clickComponent', this.state.card)
+    }
+  }
+
+  render() {
+    const { card, dict } = this.state
+
+    return (
+      <div className="login-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <WrapComponent config={card} updateConfig={this.updateComponent} />
+            <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
+            <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
+          </div>
+        } trigger="hover">
+          <Icon type="tool" />
+        </Popover>
+        <LoginForm loginWays={card.loginWays} dict={dict} />
+      </div>
+    )
+  }
+}
+
+export default PropCardEditComponent
\ No newline at end of file
diff --git a/src/pc/components/login/normal-login/index.scss b/src/pc/components/login/normal-login/index.scss
new file mode 100644
index 0000000..17eeab1
--- /dev/null
+++ b/src/pc/components/login/normal-login/index.scss
@@ -0,0 +1,58 @@
+.login-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 100px;
+  
+  .card-control {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    .anticon-tool {
+      right: auto;
+      left: 1px;
+      padding: 1px;
+    }
+  }
+  .anticon-tool {
+    position: absolute;
+    z-index: 2;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+  .login-edit-form {
+    .ant-form-item {
+      font-size: 16px;
+      margin: 0 15px 15px;
+      .ant-input {
+        height: 35px;
+      }
+    }
+    button:not(.vercode) {
+      width: 100%;
+      height: 40px;
+      line-height: 1;
+      font-size: 18px;
+      margin-bottom: 25px;
+    }
+    .ant-form-item:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+.login-edit-box::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.login-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/pc/components/login/normal-login/loginform.jsx b/src/pc/components/login/normal-login/loginform.jsx
new file mode 100644
index 0000000..5bac83d
--- /dev/null
+++ b/src/pc/components/login/normal-login/loginform.jsx
@@ -0,0 +1,130 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Form, Icon, Input, Button, Checkbox, Tabs } from 'antd'
+
+import './index.scss'
+
+const { TabPane } = Tabs
+
+class LoginTabForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,
+    loginWays: PropTypes.array,
+  }
+
+  state = {
+    activeKey: 'uname_pwd',
+    username: '',
+    password: '',
+    loginWays: [],
+    smsId: '',
+    verdisabled: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { loginWays } = this.props
+
+    let smsId = ''
+    let _loginWays = []
+    loginWays.forEach(item => {
+      if (item.type === 'sms_vcode') {
+        smsId = item.smsId
+        _loginWays.push(item)
+      } else if (item.type === 'uname_pwd') {
+        _loginWays.push(item)
+      }
+    })
+
+    this.setState({
+      smsId: smsId,
+      loginWays: _loginWays,
+      activeKey: _loginWays[0].type,
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.props.loginWays), fromJS(nextProps.loginWays))) {
+      let smsId = ''
+      let _loginWays = []
+      nextProps.loginWays.forEach(item => {
+        if (item.type === 'sms_vcode') {
+          smsId = item.smsId
+          _loginWays.push(item)
+        } else if (item.type === 'uname_pwd') {
+          _loginWays.push(item)
+        }
+      })
+
+      this.setState({
+        smsId: smsId,
+        loginWays: _loginWays,
+        activeKey: _loginWays[0].type
+      })
+    }
+  }
+
+  onChangeTab = (activeKey) => {
+    this.setState({activeKey})
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { activeKey, verdisabled, loginWays } = this.state
+
+    return (
+      <Form className="login-edit-form">
+        <Tabs type="card" activeKey={activeKey} onChange={this.onChangeTab}>
+          {loginWays.map(item => (<TabPane tab={item.label} key={item.type}></TabPane>))}
+        </Tabs>
+        <div className="form-item-wrap">
+          {activeKey === 'uname_pwd' ? <Form.Item>
+            <Input
+              prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
+              placeholder="鐢ㄦ埛鍚�"
+              autoComplete="off"
+            />
+          </Form.Item> : null}
+          {activeKey === 'uname_pwd' ? <Form.Item>
+            <Input.Password placeholder="瀵嗙爜" prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} />
+          </Form.Item> : null}
+          {activeKey === 'sms_vcode' ? <Form.Item>
+            <Input
+              placeholder="鎵嬫満鍙�"
+              autoComplete="off"
+            />
+          </Form.Item> : null}
+          {activeKey === 'sms_vcode' ? <Form.Item>
+            <Input
+              addonAfter={
+                <Button type="link" className="vercode" size="small" disabled={verdisabled}>
+                  鑾峰彇楠岃瘉鐮�
+                </Button>
+              }
+              placeholder="楠岃瘉鐮�"
+              autoComplete="off"
+            />
+          </Form.Item> : null}
+          {activeKey === 'uname_pwd' ? <Form.Item className="minline">
+            <Checkbox>璁颁綇瀵嗙爜</Checkbox>
+          </Form.Item> : null}
+          {['uname_pwd', 'sms_vcode'].includes(activeKey) ? <Form.Item className="btn-login">
+            <Button type="primary" htmlType="submit" className="login-form-button">
+              鐧诲綍
+            </Button>
+          </Form.Item> : null}
+        </div>
+      </Form>
+    )
+  }
+}
+
+export default LoginTabForm
\ No newline at end of file
diff --git a/src/pc/components/login/wrapsetting/index.jsx b/src/pc/components/login/wrapsetting/index.jsx
new file mode 100644
index 0000000..81346a6
--- /dev/null
+++ b/src/pc/components/login/wrapsetting/index.jsx
@@ -0,0 +1,83 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Modal } from 'antd'
+
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import SettingForm from './settingform'
+import './index.scss'
+
+class DataSource extends Component {
+  static propTpyes = {
+    config: PropTypes.any,
+    updateConfig: PropTypes.func
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    visible: false,
+    wrap: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    this.setState({wrap: fromJS(config.wrap).toJS()})
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  editDataSource = () => {
+    this.setState({
+      visible: true
+    })
+  }
+
+  verifySubmit = () => {
+    const { config } = this.props
+
+    this.verifyRef.handleConfirm().then(res => {
+
+      this.setState({
+        wrap: res,
+        visible: false
+      })
+      this.props.updateConfig({...config, wrap: res})
+    })
+  }
+
+  render () {
+    const { config } = this.props
+    const { visible, dict, wrap } = this.state
+
+    return (
+      <div className="model-menu-setting-wrap">
+        <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} />
+        <Modal
+          wrapClassName="popview-modal"
+          title={config.type === 'table' ? '琛ㄦ牸璁剧疆' : '鍗$墖璁剧疆'}
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <SettingForm
+            dict={dict}
+            wrap={wrap}
+            config={config}
+            inputSubmit={this.verifySubmit}
+            wrappedComponentRef={(inst) => this.verifyRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default DataSource
\ No newline at end of file
diff --git a/src/pc/components/login/wrapsetting/index.scss b/src/pc/components/login/wrapsetting/index.scss
new file mode 100644
index 0000000..04372e6
--- /dev/null
+++ b/src/pc/components/login/wrapsetting/index.scss
@@ -0,0 +1,7 @@
+.model-menu-setting-wrap {
+  display: inline-block;
+
+  >.anticon-edit {
+    color: #1890ff;
+  }
+}
\ No newline at end of file
diff --git a/src/pc/components/login/wrapsetting/settingform/index.jsx b/src/pc/components/login/wrapsetting/settingform/index.jsx
new file mode 100644
index 0000000..08b58e2
--- /dev/null
+++ b/src/pc/components/login/wrapsetting/settingform/index.jsx
@@ -0,0 +1,253 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd'
+
+import './index.scss'
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,      // 瀛楀吀椤�
+    config: PropTypes.object,    // 鍗$墖琛屼俊鎭�
+    wrap: PropTypes.object,      // 鏁版嵁婧愰厤缃�
+    inputSubmit: PropTypes.func  // 鍥炶溅浜嬩欢
+  }
+
+  state = {
+    roleList: []
+  }
+
+  UNSAFE_componentWillMount () {
+    let roleList = sessionStorage.getItem('sysRoles')
+    if (roleList) {
+      try {
+        roleList = JSON.parse(roleList)
+      } catch {
+        roleList = []
+      }
+    } else {
+      roleList = []
+    }
+
+    this.setState({roleList})
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  render() {
+    const { wrap, config } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { roleList } = this.state
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div className="model-menu-setting-form">
+        <Form {...formItemLayout}>
+          <Row gutter={24}>
+            <Col span={12}>
+              <Form.Item label="鏍囬">
+                {getFieldDecorator('title', {
+                  initialValue: wrap.title || ''
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�">
+                  <Icon type="question-circle" />
+                  缁勪欢鍚嶇О
+                </Tooltip>
+              }>
+                {getFieldDecorator('name', {
+                  initialValue: wrap.name,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��">
+                  <Icon type="question-circle" />
+                  瀹藉害
+                </Tooltip>
+              }>
+                {getFieldDecorator('width', {
+                  initialValue: wrap.width || 24,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '瀹藉害!'
+                    }
+                  ]
+                })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            {config.subtype === 'propcard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��">
+                  <Icon type="question-circle" />
+                  鏁版嵁鏉ユ簮
+                </Tooltip>
+              }>
+                {getFieldDecorator('datatype', {
+                  initialValue: wrap.datatype || 'dynamic'
+                })(
+                  <Radio.Group>
+                    <Radio value="dynamic">鍔ㄦ��</Radio>
+                    <Radio value="static">闈欐��</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype === 'datacard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏁版嵁婧愪腑閫夋嫨鍒嗛〉鏃舵湁鏁堛��">
+                  <Icon type="question-circle" />
+                  鍒嗛〉椋庢牸
+                </Tooltip>
+              }>
+                {getFieldDecorator('pagestyle', {
+                  initialValue: wrap.pagestyle || 'page'
+                })(
+                  <Radio.Group>
+                    <Radio value="page">椤电爜</Radio>
+                    <Radio value="switch">宸﹀彸鍒囨崲</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype !== 'tablecard' ? <Col span={12}>
+              <Form.Item label="鍗$墖灞炴��">
+                {getFieldDecorator('cardType', {
+                  initialValue: wrap.cardType || ''
+                })(
+                  <Radio.Group style={{whiteSpace: 'nowrap'}}>
+                    <Radio key="" value=""> 涓嶅彲閫� </Radio>
+                    <Radio key="radio" value={'radio'}> 鍗曢�� </Radio>
+                    {config.subtype !== 'propcard' ? <Radio key="checkbox" value={'checkbox'}> 澶氶�� </Radio> : null}
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype !== 'tablecard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="璁剧疆涓哄眳涓榻愭垨鍙冲榻愶紝鍙湪鍗$墖涓�1琛屾椂鏈夋晥銆�">
+                  <Icon type="question-circle" />
+                  鍗$墖鎺掑垪
+                </Tooltip>
+              }>
+                {getFieldDecorator('cardFloat', {
+                  initialValue: wrap.cardFloat || 'left'
+                })(
+                  <Radio.Group style={{whiteSpace: 'nowrap'}}>
+                    <Radio key="left" value="left"> 宸﹀榻� </Radio>
+                    <Radio key="center" value="center"> 灞呬腑 </Radio>
+                    <Radio key="right" value="right"> 鍙冲榻� </Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype !== 'tablecard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��">
+                  <Icon type="question-circle" />
+                  鍗$墖鏀惧ぇ
+                </Tooltip>
+              }>
+                {getFieldDecorator('scale', {
+                  initialValue: wrap.scale || 'false'
+                })(
+                  <Radio.Group>
+                    <Radio key="false" value="false"> 鍚� </Radio>
+                    <Radio key="true" value="true"> 鏄� </Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype === 'tablecard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="琛ㄦ牸楂樺害锛岃秴鍑烘椂婊氬姩锛岄珮搴︿负绌烘椂鏍规嵁鍐呭鑷�傚簲銆�">
+                  <Icon type="question-circle" />
+                  楂樺害
+                </Tooltip>
+              }>
+                {getFieldDecorator('height', {
+                  initialValue: wrap.height
+                })(<InputNumber min={100} max={2000} precision={0} onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col> : null}
+            {config.subtype === 'propcard' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆�">
+                  <Icon type="question-circle" />
+                  缁勪欢绫诲瀷
+                </Tooltip>
+              }>
+                {getFieldDecorator('printType', {
+                  initialValue: wrap.printType || 'content'
+                })(
+                  <Radio.Group>
+                    <Radio value="content">鍐呭</Radio>
+                    <Radio value="headerOrfooter">椤电湁/椤佃剼</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            <Col span={12}>
+              <Form.Item label="榛戝悕鍗�">
+                {getFieldDecorator('blacklist', {
+                  initialValue: wrap.blacklist || []
+                })(
+                  <Select
+                    showSearch
+                    mode="multiple"
+                    filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  >
+                    {roleList.map(option =>
+                      <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option>
+                    )}
+                  </Select>
+                )}
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/pc/components/login/wrapsetting/settingform/index.scss b/src/pc/components/login/wrapsetting/settingform/index.scss
new file mode 100644
index 0000000..159130b
--- /dev/null
+++ b/src/pc/components/login/wrapsetting/settingform/index.scss
@@ -0,0 +1,11 @@
+.model-menu-setting-form {
+  position: relative;
+
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+}
\ No newline at end of file
diff --git a/src/pc/menushell/card.jsx b/src/pc/menushell/card.jsx
index 843c8c5..cd6aa65 100644
--- a/src/pc/menushell/card.jsx
+++ b/src/pc/menushell/card.jsx
@@ -17,6 +17,7 @@
 const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
 const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox'))
 const NormalNavbar = asyncComponent(() => import('@/pc/components/navbar/normal-navbar'))
+const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login'))
 const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card'))
 const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card'))
 
@@ -88,6 +89,8 @@
       return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'code') {
       return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'login') {
+      return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
   return (
diff --git a/src/pc/menushell/index.jsx b/src/pc/menushell/index.jsx
index 29be748..969e9ab 100644
--- a/src/pc/menushell/index.jsx
+++ b/src/pc/menushell/index.jsx
@@ -49,7 +49,7 @@
     let uuids = MenuUtils.getDelButtonIds(card)
 
     confirm({
-      title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋,
+      title: `纭畾鍒犻櫎${card.name ? `銆�${card.name}銆媊 : '缁勪欢'}鍚楋紵`,
       content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '',
       onOk() {
         MKEmitter.emit('delButtons', uuids)
@@ -102,7 +102,8 @@
         code: '鑷畾涔�',
         navbar: '瀵艰埅鏍�',
         carousel: '杞挱',
-        card: '鍗$墖'
+        card: '鍗$墖',
+        login: '鐧诲綍'
       }
       let i = 1
       
diff --git a/src/pc/modulesource/option.jsx b/src/pc/modulesource/option.jsx
index 8e94aea..189416d 100644
--- a/src/pc/modulesource/option.jsx
+++ b/src/pc/modulesource/option.jsx
@@ -18,6 +18,7 @@
 import Carousel from '@/assets/mobimg/carousel.png'
 import Carousel1 from '@/assets/mobimg/carousel1.png'
 import form from '@/assets/mobimg/form.png'
+import Login from '@/assets/mobimg/login.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -41,4 +42,5 @@
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
   { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 },
+  { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '鐧诲綍', width: 24 },
 ]
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 525c471..62deb90 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -21,6 +21,11 @@
 const BarCode = asyncElementComponent(() => import('@/components/barcode'))
 const QrCode = asyncElementComponent(() => import('@/components/qrcode'))
 const Video = asyncComponent(() => import('@/components/video'))
+const PicRadio = {
+  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
+  '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
+  '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
+}
 
 class CardCellComponent extends Component {
   static propTpyes = {
@@ -443,12 +448,8 @@
         _imagestyle.borderRadius = _style.borderRadius
       }
 
-      if (card.lenWidRadio === '16:9') {
-        _imagestyle.paddingTop = '56.25%'
-      } else if (card.lenWidRadio === '3:2') {
-        _imagestyle.paddingTop = '66.67%'
-      } else if (card.lenWidRadio === '4:3') {
-        _imagestyle.paddingTop = '75%'
+      if (PicRadio[card.lenWidRadio]) {
+        _imagestyle.paddingTop = PicRadio[card.lenWidRadio]
       } else {
         _imagestyle.paddingTop = '100%'
       }
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index f471844..24682cc 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -15,7 +15,11 @@
 
 const { Paragraph } = Typography
 const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
-
+const PicRadio = {
+  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
+  '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
+  '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
+}
 class BodyRow extends React.Component {
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.props.data), fromJS(nextProps.data)) || !is(fromJS(this.props.className), fromJS(nextProps.className))
@@ -272,12 +276,8 @@
       let cols = 24 / (col.picSort || 1)
       let paddingTop = '100%'
 
-      if (col.lenWidRadio === '16:9') {
-        paddingTop = '56.25%'
-      } else if (col.lenWidRadio === '3:2') {
-        paddingTop = '66.67%'
-      } else if (col.lenWidRadio === '4:3') {
-        paddingTop = '75%'
+      if (PicRadio[col.lenWidRadio]) {
+        paddingTop = PicRadio[col.lenWidRadio]
       }
 
       resProps.children = (

--
Gitblit v1.8.0