From ab10e496feff0d7de81af939cd7ca1973e1ea220 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 14 一月 2022 18:46:02 +0800
Subject: [PATCH] 2022-01-14

---
 src/components/normalform/modalform/index.jsx                   |   13 
 src/views/pcdesign/index.jsx                                    |    3 
 src/pc/components/login/normal-login/loginform.jsx              |   16 
 src/menu/components/card/cardcellcomponent/dragaction/index.jsx |    7 
 src/menu/components/card/cardcomponent/index.jsx                |   31 +-
 src/menu/components/share/actioncomponent/dragaction/index.jsx  |    7 
 src/pc/components/login/normal-login/index.jsx                  |    9 
 src/pc/components/login/normal-login/options.jsx                |   62 ++--
 /dev/null                                                       |    0 
 src/components/normalform/modalform/mkTable/index.jsx           |  417 ++++++++++++++++++++++++++++++++
 src/components/normalform/modalform/mkTable/index.scss          |  108 ++++++++
 src/views/mobdesign/index.jsx                                   |    3 
 src/menu/components/card/cardcomponent/options.jsx              |   48 +++
 13 files changed, 657 insertions(+), 67 deletions(-)

diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index bc471f7..7162b0c 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -13,6 +13,7 @@
 const { TextArea } = Input
 
 const MKRadio = asyncComponent(() => import('./mkRadio'))
+const MKTable = asyncComponent(() => import('./mkTable'))
 const MKCheckbox = asyncComponent(() => import('./mkCheckbox'))
 const StyleInput = asyncComponent(() => import('./styleInput'))
 const MKFileUpload = asyncComponent(() => import('@/tabviews/zshare/fileupload'))
@@ -66,13 +67,19 @@
           validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item)
         }]
       } else if (item.type === 'textarea') {
-        let _rules = [
+        item.rules = [
           {
             required: item.required,
             message: item.label + '涓嶅彲涓虹┖!'
           }
         ]
-        item.rules = _rules
+      } else if (item.type === 'table') {
+        item.rules = [
+          {
+            required: item.required,
+            message: '璇锋坊鍔�' + item.label + '!'
+          }
+        ]
       } else {
         item.rules = [
           {
@@ -253,6 +260,8 @@
         content = (<MkEditIcon allowClear={item.allowClear}/>)
       } else if (item.type === 'source') {
         content = (<SourceComponent type="" placement="right"/>)
+      } else if (item.type === 'table') {
+        content = (<MKTable columns={item.columns || []}/>)
       }
 
       if (!content) return
diff --git a/src/components/normalform/modalform/mkTable/index.jsx b/src/components/normalform/modalform/mkTable/index.jsx
new file mode 100644
index 0000000..053316f
--- /dev/null
+++ b/src/components/normalform/modalform/mkTable/index.jsx
@@ -0,0 +1,417 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { DndProvider, DragSource, DropTarget } from 'react-dnd'
+import { Table, Input, InputNumber, Popconfirm, Form, Select, Radio, Cascader, notification, Typography, Button } from 'antd'
+import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
+
+import Utils from '@/utils/utils.js'
+import ColorSketch from '@/mob/colorsketch'
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
+const EditableContext = React.createContext()
+let dragingIndex = -1
+const { Paragraph } = Typography
+
+class BodyRow extends React.Component {
+  render() {
+    const { isOver, moveAble, connectDragSource, connectDropTarget, moveRow, ...restProps } = this.props
+
+    let { className } = restProps
+    if (isOver && moveAble) {
+      if (restProps.index > dragingIndex) {
+        className += ' drop-over-downward'
+      }
+      if (restProps.index < dragingIndex) {
+        className += ' drop-over-upward'
+      }
+    }
+
+    if (moveAble) {
+      return connectDragSource(
+        connectDropTarget(<tr {...restProps} className={className} style={{ ...restProps.style, cursor: 'move' }} />),
+      )
+    } else {
+      return (<tr {...restProps} className={className} style={restProps.style} />)
+    }
+  }
+}
+
+const rowSource = {
+  beginDrag(props) {
+    dragingIndex = props.index
+    return {
+      index: props.index,
+    }
+  }
+}
+
+const rowTarget = {
+  drop(props, monitor) {
+    const dragIndex = monitor.getItem().index
+    const hoverIndex = props.index
+
+    if (dragIndex === hoverIndex) {
+      return
+    }
+
+    props.moveRow(dragIndex, hoverIndex)
+
+    monitor.getItem().index = hoverIndex
+  },
+}
+
+const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
+  connectDropTarget: connect.dropTarget(),
+  isOver: monitor.isOver(),
+}))(
+  DragSource('row', rowSource, connect => ({
+    connectDragSource: connect.dragSource(),
+  }))(BodyRow),
+)
+
+class EditableCell extends Component {
+  getInput = (form) => {
+    const { inputType, options, min, max, unlimit } = this.props
+
+    if (inputType === 'number' && unlimit) {
+      return <InputNumber onPressEnter={() => this.getValue(form)} />
+    } else if (inputType === 'number') {
+      return <InputNumber min={min} max={max} precision={0} onPressEnter={() => this.getValue(form)} />
+    } else if (inputType === 'color') {
+      return <ColorSketch />
+    } else if (inputType === 'icon') {
+      return <MkEditIcon allowClear/>
+    } else if (inputType === 'select') {
+      return (
+        <Select>
+          {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
+        </Select>
+      )
+    } else if (inputType === 'multiStr') {
+      return (
+        <Select mode="multiple">
+          {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
+        </Select>
+      )
+    } else if (inputType === 'cascader') {
+      return (
+        <Cascader options={options} placeholder=""/>
+      )
+    } else if (inputType === 'radio') {
+      return (
+        <Radio.Group>
+          {options.map((item, i) => (<Radio key={i} value={item.field || item.value}> {item.label || item.text} </Radio>))}
+        </Radio.Group>
+      )
+    } else {
+      return <Input onPressEnter={() => this.getValue(form)}/>
+    }
+  }
+
+  getValue = (form) => {
+    form.validateFields((error, row) => {
+      if (error) {
+        return
+      }
+      this.props.onSave(row)
+    })
+  }
+
+  renderCell = (form) => {
+    const { getFieldDecorator } = form
+    const { editing, dataIndex, title, record, children, className, required, inputType } = this.props
+
+    return (
+      <td className={className}>
+        {editing ? (
+          <Form.Item style={{ margin: 0 }}>
+            {getFieldDecorator(dataIndex, {
+              rules: [
+                {
+                  required: required,
+                  message: ['number', 'text', 'input'].includes(inputType) ? `璇疯緭鍏� ${title}!` : `璇烽�夋嫨 ${title}!`,
+                }
+              ],
+              initialValue: inputType === 'multiStr' ? (record[dataIndex] ? record[dataIndex].split(',') : []) : record[dataIndex],
+            })(this.getInput(form))}
+          </Form.Item>
+        ) : (
+          children
+        )}
+      </td>
+    )
+  }
+
+  render() {
+    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
+  }
+}
+
+class EditTable extends Component {
+  static propTpyes = {
+    columns: PropTypes.array,       // 鏄剧ず鍒�
+    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
+  }
+
+  state = {
+    data: [],
+    editLine: null,
+    editingKey: '',
+    visible: false,
+    columns: []
+  }
+
+  UNSAFE_componentWillMount () {
+    let columns = fromJS(this.props.columns).toJS()
+
+    let operation = {
+      title: '鎿嶄綔',
+      dataIndex: 'operation',
+      width: '120px',
+      render: (text, record) => {
+        const { editingKey } = this.state
+        const editable = this.isEditing(record)
+        return editable ? (
+          <div style={{textAlign: 'center', minWidth: '110px'}}>
+            <EditableContext.Consumer>
+              {form => (
+                <span onClick={() => this.save(form)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
+                  淇濆瓨
+                </span>
+              )}
+            </EditableContext.Consumer>
+            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>鍙栨秷</span>
+          </div>
+        ) : (
+          <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px', whiteSpace: 'nowrap'}}>
+            <span className="primary" onClick={() => {editingKey === '' && this.edit(record)}}><EditOutlined /></span>
+            {editingKey === '' ? <Popconfirm
+              overlayClassName="popover-confirm"
+              title="纭畾鍒犻櫎鍚�?"
+              onConfirm={() => this.handleDelete(record.uuid)
+            }>
+              <span className="danger"><DeleteOutlined /></span>
+            </Popconfirm> : null}
+            {editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
+          </div>
+        )
+      }
+    }
+
+    columns.push(operation)
+
+    this.setState({
+      data: fromJS(this.props.value || []).toJS(),
+      operation,
+      columns
+    })
+  }
+
+  // shouldComponentUpdate (nextProps, nextState) {
+  //   return !is(fromJS(this.state), fromJS(nextState))
+  // }
+
+  isEditing = record => record.uuid === this.state.editingKey
+
+  cancel = () => {
+    this.setState({ editingKey: '', data: this.state.data.filter(item => !item.isnew) })
+  }
+
+  handleDelete = (uuid) => {
+    const { data } = this.state
+    let _data = data.filter(item => uuid !== item.uuid)
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.props.onChange(_data)
+    })
+  }
+
+  save(form) {
+    form.validateFields((error, row) => {
+      if (error) {
+        return;
+      }
+      this.execSave(row)
+    })
+  }
+
+  execSave = (row) => {
+    const { columns, editLine } = this.state
+
+    let newData = [...this.state.data]
+    let record = {...editLine, ...row}
+    let index = newData.findIndex(item => record.uuid === item.uuid)
+
+    if (index === -1) return
+
+    let unique = true
+    columns.forEach(col => {
+      if (col.unique !== true || !unique) return
+
+      let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
+
+      if (_index > -1) {
+        notification.warning({
+          top: 92,
+          message: col.title + '涓嶅彲閲嶅锛�',
+          duration: 5
+        })
+        unique = false
+      }
+    })
+
+    if (!unique) return
+
+    columns.forEach(col => {
+      if (!col.extends) return
+
+      if (col.extends === 'Menu') {
+        let menu = record[col.dataIndex]
+        let fId = menu[0] || ''
+        let sId = menu[1] || ''
+        let tId = menu[2] || ''
+        let label = ''
+        
+        col.options.forEach(f => {
+          if (!fId || fId !== f.value) return
+          label = f.label
+
+          f.children.forEach(s => {
+            if (!sId || sId !== s.value) return
+            label += ' / ' + s.label
+
+            s.children.forEach(t => {
+              if (!tId || tId !== t.value) return
+              label += ' / ' + t.label
+
+              record.MenuID = t.MenuID
+              record.MenuName = t.MenuName
+              record.MenuNo = t.MenuNo
+              record.tabType = t.type
+              record.label = label
+            })
+          })
+        })
+      } else {
+        let key = record[col.dataIndex]
+        let option = col.options.filter(m => m.value === key)[0]
+
+        if (option) {
+          col.extends.forEach(n => {
+            record[n.value] = option[n.key]
+          })
+        }
+      }
+    })
+
+    delete record.isnew
+
+    newData.splice(index, 1, record)
+    this.setState({ data: newData, editingKey: '', editLine: null }, () => {
+      this.props.onChange(newData)
+    })
+  }
+
+  edit(item) {
+    this.setState({ editLine: item, editingKey: item.uuid })
+  }
+
+  addline = () => {
+    let item = {
+      uuid: Utils.getuuid(),
+      isnew: true
+    }
+
+    this.setState({ data: [...this.state.data, item], editingKey: '' }, () => {
+      this.setState({ editLine: item, editingKey: item.uuid })
+    })
+  }
+
+  moveRow = (dragIndex, hoverIndex) => {
+    const { editingKey } = this.state
+    let _data = fromJS(this.state.data).toJS()
+
+    if (editingKey) return
+
+    _data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.props.onChange(_data)
+    })
+  }
+
+  render() {
+    let components = {
+      body: {
+        cell: EditableCell
+      }
+    }
+
+    let moveprops = {}
+    components.body.row = DragableBodyRow
+    moveprops.moveAble = !this.state.editingKey
+    moveprops.moveRow = this.moveRow
+    
+    let  columns = this.state.columns.map(col => {
+      if (col.copy) {
+        col.render = (text) => (<Paragraph copyable>{text}</Paragraph>)
+      }
+      if (!col.editable) return col
+      return {
+        ...col,
+        onCell: record => ({
+          record,
+          inputType: col.inputType,
+          dataIndex: col.dataIndex,
+          options: col.options || [],
+          min: col.min || 0,
+          max: col.max || 500,
+          unlimit: col.unlimit,
+          required: col.required !== false ? true : false,
+          title: col.title,
+          editing: this.isEditing(record),
+          onSave: this.execSave,
+        }),
+      }
+    })
+
+    const data = this.state.data.map((item, index) => {
+      item.$index = index + 1
+
+      return item
+    })
+
+    return (
+      <EditableContext.Provider value={this.props.form}>
+        <div className="modal-editable-table">
+          <Button disabled={!!this.state.editingKey} type="link" onClick={this.addline}><PlusOutlined style={{}}/></Button>
+          <DndProvider>
+            <Table
+              bordered
+              rowKey="uuid"
+              size="middle"
+              components={components}
+              dataSource={data}
+              columns={columns}
+              rowClassName="editable-row"
+              pagination={false}
+              onRow={(record, index) => ({
+                index,
+                ...moveprops
+              })}
+            />
+          </DndProvider>
+        </div>
+      </EditableContext.Provider>
+    )
+  }
+}
+
+export default Form.create()(EditTable)
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkTable/index.scss b/src/components/normalform/modalform/mkTable/index.scss
new file mode 100644
index 0000000..d4bba52
--- /dev/null
+++ b/src/components/normalform/modalform/mkTable/index.scss
@@ -0,0 +1,108 @@
+.modal-editable-table {
+  position: relative;
+  margin-bottom: 5px;
+
+  >.ant-btn {
+    position: absolute;
+    right: 0px;
+    top: -26px;
+    font-size: 18px;
+    color: #26C281;
+    z-index: 1;
+    height: 28px;
+  }
+  .editable-row {
+    .ant-form-explain {
+      position: absolute;
+      font-size: 12px;
+      margin-top: -4px;
+    }
+    .color-sketch-block {
+      width: 200px;
+      position: relative;
+      top: 8px;
+    }
+    .ant-select {
+      width: 100%;
+    }
+    > td {
+      padding: 14px 10px;
+    }
+    > td:last-child {
+      padding: 0px;
+    }
+  }
+  .mk-index {
+    text-align: center;
+    white-space: nowrap;
+  }
+
+  thead tr th:last-child {
+    text-align: center;
+  }
+  .edit-operation-btn {
+    display: block;
+    text-align: center;
+    span {
+      margin-right: 10px;
+      cursor: pointer;
+      font-size: 16px;
+      padding: 5px;
+    }
+    .primary {
+      color: #1890ff;
+    }
+    .copy {
+      color: #26C281;
+    }
+    .danger {
+      color: #ff4d4f;
+    }
+    span:last-child {
+      margin-right: 0px;
+    }
+  }
+  .edit-operation-btn.disabled {
+    cursor: default;
+    span {
+      cursor: default;
+    }
+    .primary {
+      color: rgba(0, 0, 0, .25);
+    }
+    .danger {
+      color: rgba(0, 0, 0, .25);
+    }
+    .copy {
+      color: rgba(0, 0, 0, .25);
+    }
+  }
+  .ant-empty {
+    margin: 0;
+  }
+  tr.drop-over-downward td {
+    border-bottom: 2px dashed #1890ff;
+  }
+  tr.drop-over-upward td {
+    border-top: 2px dashed #1890ff;
+  }
+  .copy-control {
+    display: inline-block;
+    position: absolute;
+    right: 10px;
+    top: 2px;
+
+    .anticon-copy {
+      margin-right: 7px;
+      color: #26C281;
+    }
+    .anticon-snippets {
+      color: purple;
+    }
+    .anticon-delete {
+      margin-left: 7px;
+      color: #ff4d4f;
+    }
+  }
+}
+
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
index bc62df0..abb9604 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -47,6 +47,13 @@
 
     let _val = fromJS(copycard).toJS()
 
+    if (_val.control) {
+      _val.control = ''
+      
+      delete _val.controlField
+      delete _val.controlVal
+    }
+
     copycard.uuid = Utils.getuuid()
     copycard.originCard = card
 
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index 6dbb4eb..491e76d 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -14,7 +14,6 @@
 
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
-const CardMenus = asyncComponent(() => import('./menus-wrap'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteController = asyncIconComponent(() => import('@/components/paste'))
 
@@ -195,7 +194,7 @@
         }
       })
     }
-    return getSettingForm(card.setting, cards.subtype, buttons, card.$cardType, cards.columns)
+    return getSettingForm(card.setting, cards.subtype, buttons, card.$cardType, cards.columns, card.menus)
   }
 
   updateSetting = (res) => {
@@ -221,18 +220,26 @@
       })
     }
 
+    let _card = {...card, setting: res}
+
+    if (res.menus) {
+      _card.menus = res.menus
+
+      delete res.menus
+    }
+
     this.setState({
-      card: {...card, setting: res}
+      card: _card
     })
 
     if (side === 'back' && res.type === 'simple') {
       this.setState({
         side: 'front',
-        elements: fromJS(card.elements).toJS()
+        elements: fromJS(_card.elements).toJS()
       })
     }
 
-    this.props.updateElement({...card, setting: res})
+    this.props.updateElement(_card)
   }
 
   paste = (element, resolve) => {
@@ -281,19 +288,9 @@
         return
       }
       MKEmitter.emit('changeEditMenu', {MenuID: card.setting.menu})
-    } else if (card.setting.click === 'menus' && card.menus && card.menus.length > 0 && cards.subtype === 'datacard' && card.$cardType !== 'extendCard' && (appType === 'mob' || appType === 'pc')) {
+    } else if (card.setting.click === 'menus' && card.menus && card.menus.length > 0 && cards.subtype === 'datacard' && appType) {
       this.setState({visible: true})
     }
-  }
-
-  updateMenus = (res) => {
-    const { card } = this.state
-
-    this.setState({
-      card: {...card, menus: res}
-    })
-
-    this.props.updateElement({...card, menus: res})
   }
 
   render() {
@@ -326,8 +323,6 @@
                 <NormalForm title="鍗$墖璁剧疆" width={800} update={this.updateSetting} getForms={this.getSettingForms}>
                   <EditOutlined className="edit" title="缂栬緫"/>
                 </NormalForm>
-                {cards.subtype === 'datacard' && card.$cardType !== 'extendCard' && card.setting.click === 'menus' ?
-                  <CardMenus card={card} updateMenus={this.updateMenus}/> : null}
                 <CopyComponent type="cardcell" card={card}/>
                 <PasteController options={['action', 'customCardElement']} updateConfig={this.paste} />
                 <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/index.jsx b/src/menu/components/card/cardcomponent/menus-wrap/index.jsx
deleted file mode 100644
index 72d3457..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/index.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal } from 'antd'
-import { MenuOutlined } from '@ant-design/icons'
-
-import MenusForm from './menus'
-import './index.scss'
-
-class MenusWrap extends Component {
-  static propTpyes = {
-    card: PropTypes.object,
-    updateMenus: PropTypes.func
-  }
-
-  state = {
-    visible: false,
-    menus: [],
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  trigger = () => {
-    const { card } = this.props
-
-    let appType = sessionStorage.getItem('appType') || ''
-    let menulist = []
-
-    if (appType) {
-      menulist = sessionStorage.getItem('appMenus')
-      if (menulist) {
-        try {
-          menulist = JSON.parse(menulist)
-        } catch (e) {
-          menulist = []
-        }
-      } else {
-        menulist = []
-      }
-      if (appType === 'mob') {
-        menulist.push({
-          value: 'IM', label: '鍗虫椂閫氫俊锛堢郴缁熼〉锛�'
-        })
-      }
-    } else {
-      menulist = sessionStorage.getItem('fstMenuList')
-      if (menulist) {
-        try {
-          menulist = JSON.parse(menulist)
-        } catch (e) {
-          menulist = []
-        }
-      } else {
-        menulist = []
-      }
-    }
-    this.setState({
-      appType,
-      menulist,
-      visible: true,
-      menus: card.menus || []
-    })
-  }
-
-  submit = () => {
-    this.setState({
-      visible: false
-    })
-    this.props.updateMenus(this.state.menus)
-  }
-
-  update = (menus) => {
-    this.setState({menus})
-  }
-
-  render() {
-    const { visible, menus, appType, menulist } = this.state
-
-    return (
-      <>
-        <MenuOutlined title="鑿滃崟缁�" onClick={this.trigger}/>
-        <Modal
-          title="鑿滃崟缁�"
-          wrapClassName="menus-field-modal"
-          visible={visible}
-          width={900}
-          maskClosable={false}
-          onOk={this.submit}
-          onCancel={() => { this.setState({ visible: false })}}
-          destroyOnClose
-        >
-          <MenusForm menus={menus} appType={appType} menulist={menulist} update={this.update}/>
-        </Modal>
-      </>
-    )
-  }
-}
-
-export default MenusWrap
\ No newline at end of file
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/index.scss b/src/menu/components/card/cardcomponent/menus-wrap/index.scss
deleted file mode 100644
index 52caa86..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/index.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.menus-field-modal {
-  .ant-modal {
-    top: 70px;
-  }
-  .ant-modal-body {
-    min-height: 150px;
-    padding-top: 40px;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.jsx b/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.jsx
deleted file mode 100644
index dd9adcd..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Button, Input, Select, Cascader, notification } from 'antd'
-// import './index.scss'
-
-class MenusColumn extends Component {
-  static propTpyes = {
-    menus: PropTypes.array,
-    appType: PropTypes.string,
-    menulist: PropTypes.array,
-    columnChange: PropTypes.func
-  }
-
-  handleConfirm = () => {
-    const { appType, menus, menulist } = this.props
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    this.props.form.validateFieldsAndScroll((err, values) => {
-      if (!err) {
-        if (menus.filter(item => item.sign === values.sign).length > 0) {
-          notification.warning({
-            top: 92,
-            message: '鏍囪瘑宸插瓨鍦紒',
-            duration: 2
-          })
-          return
-        }
-
-        if (!appType) {
-          let fId = values.menu[0] || ''
-          let sId = values.menu[1] || ''
-          let tId = values.menu[2] || ''
-          let label = ''
-
-          menulist.forEach(f => {
-            if (!fId || fId !== f.value) return
-            label = f.label
-
-            f.children.forEach(s => {
-              if (!sId || sId !== s.value) return
-              label += ' / ' + s.label
-
-              s.children.forEach(t => {
-                if (!tId || tId !== t.value) return
-                label += ' / ' + t.label
-  
-                values.MenuID = t.MenuID
-                values.MenuName = t.MenuName
-                values.MenuNo = t.MenuNo
-                values.tabType = t.type
-                values.label = label
-              })
-            })
-          })
-        } else {
-          menulist.forEach(f => {
-            if (values.menu !== f.value) return
-            values.label = f.label
-          })
-        }
-
-        this.props.columnChange(values)
-        this.props.form.setFieldsValue({
-          sign: '',
-          menu: appType ? '' : []
-        })
-      }
-    })
-  }
-
-  render() {
-    const { appType, menulist } = this.props
-    const { getFieldDecorator } = this.props.form
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <Form {...formItemLayout} className="verify-form">
-        <Row gutter={24}>
-          <Col span={10}>
-            <Form.Item label="鏍囪瘑">
-              {getFieldDecorator('sign', {
-                initialValue: ''
-              })(<Input placeholder="" autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={10}>
-            <Form.Item label="鑿滃崟">
-              {getFieldDecorator('menu', {
-                initialValue: appType ? '' : [],
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鑿滃崟!'
-                  }
-                ]
-              })(appType ? <Select>
-                {menulist.map((item, i) => (<Select.Option key={i} value={item.value}> {item.label || item.text} </Select.Option>))}
-              </Select> : <Cascader options={menulist} placeholder=""/>)}
-            </Form.Item>
-          </Col>
-          <Col span={4} className="add">
-            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
-              娣诲姞
-            </Button>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MenusColumn)
\ No newline at end of file
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.scss b/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/menus/columnform/index.scss
+++ /dev/null
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/menus/index.jsx b/src/menu/components/card/cardcomponent/menus-wrap/menus/index.jsx
deleted file mode 100644
index a37b890..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/menus/index.jsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-
-import Utils from '@/utils/utils.js'
-import ColumnForm from './columnform'
-import asyncComponent from '@/utils/asyncComponent'
-// import './index.scss'
-
-const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
-
-class CardMenus extends Component {
-  static propTpyes = {
-    appType: PropTypes.string,
-    menulist: PropTypes.array,
-    menus: PropTypes.array,
-    update: PropTypes.func
-  }
-
-  state = {
-    columns: [
-      {
-        title: '鏍囪瘑',
-        dataIndex: 'sign',
-        inputType: 'input',
-        editable: true,
-        unique: true,
-        required: false,
-        width: '35%'
-      },
-      {
-        title: '鑿滃崟',
-        dataIndex: 'menu',
-        inputType: !this.props.appType ? 'cascader' : 'select',
-        editable: true,
-        required: true,
-        width: '35%',
-        render: (text, record) => record.label,
-        options: this.props.menulist
-      }
-    ]
-  }
-
-  UNSAFE_componentWillMount() {
-    const { menus } = this.props
-
-    this.setState({
-      menus: fromJS(menus).toJS()
-    })
-  }
-
-  columnChange = (values) => {
-    const { menus } = this.state
-    values.uuid = Utils.getuuid()
-    let _menus = [...menus, values]
-
-    this.setState({menus: _menus})
-    this.props.update(_menus)
-  }
-
-  changeColumns = (columns) => {
-    const { appType, menulist } = this.props
-    const { menus } = this.state
-
-    let m = {}
-    menus.forEach(item => {
-      m[item.uuid] = item
-    })
-
-    columns = columns.map(col => {
-      let ori = m[col.uuid]
-      if (ori && is(fromJS({...col, $index: 1}), fromJS({...ori, $index: 1}))) return col
-      if (!appType) {
-        let fId = col.menu[0] || ''
-        let sId = col.menu[1] || ''
-        let tId = col.menu[2] || ''
-        let label = ''
-        
-        menulist.forEach(f => {
-          if (!fId || fId !== f.value) return
-          label = f.label
-
-          f.children.forEach(s => {
-            if (!sId || sId !== s.value) return
-            label += ' / ' + s.label
-
-            s.children.forEach(t => {
-              if (!tId || tId !== t.value) return
-              label += ' / ' + t.label
-
-              col.MenuID = t.MenuID
-              col.MenuName = t.MenuName
-              col.MenuNo = t.MenuNo
-              col.tabType = t.type
-              col.label = label
-            })
-          })
-        })
-      } else {
-        menulist.forEach(f => {
-          if (col.menu !== f.value) return
-          col.label = f.label
-        })
-      }
-      return col
-    })
-    
-    this.setState({menus: columns})
-    this.props.update(columns)
-  }
-
-  render() {
-    const { appType, menulist } = this.props
-    const { menus, columns } = this.state
-
-    return (
-      <div style={{minHeight: '250px'}}>
-        <ColumnForm appType={appType} menus={menus} menulist={menulist} columnChange={this.columnChange}/>
-        <EditTable actions={['edit', 'move', 'copy', 'del']} type={appType + 'cardmenus'} data={menus} columns={columns} onChange={this.changeColumns}/>
-      </div>
-    )
-  }
-}
-
-export default CardMenus
\ No newline at end of file
diff --git a/src/menu/components/card/cardcomponent/menus-wrap/menus/index.scss b/src/menu/components/card/cardcomponent/menus-wrap/menus/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/menu/components/card/cardcomponent/menus-wrap/menus/index.scss
+++ /dev/null
diff --git a/src/menu/components/card/cardcomponent/options.jsx b/src/menu/components/card/cardcomponent/options.jsx
index cdd3e50..b4bdd99 100644
--- a/src/menu/components/card/cardcomponent/options.jsx
+++ b/src/menu/components/card/cardcomponent/options.jsx
@@ -1,26 +1,25 @@
 /**
  * @description Setting琛ㄥ崟閰嶇疆淇℃伅
  */
-export default function (setting, subtype, buttons = [], cardType, columns) {
+export default function (setting, subtype, buttons = [], cardType, columns, menus = []) {
   let appType = sessionStorage.getItem('appType')
   let hasMenus = subtype === 'datacard' && cardType !== 'extendCard'
 
   let menulist = []
-  let appmenulist = []
 
   if (appType) {
-    appmenulist = sessionStorage.getItem('appMenus')
-    if (appmenulist) {
+    menulist = sessionStorage.getItem('appMenus')
+    if (menulist) {
       try {
-        appmenulist = JSON.parse(appmenulist)
+        menulist = JSON.parse(menulist)
       } catch (e) {
-        appmenulist = []
+        menulist = []
       }
     } else {
-      appmenulist = []
+      menulist = []
     }
     if (appType === 'mob' && (subtype === 'datacard' || subtype === 'propcard') && cardType !== 'extendCard') { // 鏁版嵁鍗″彲鎵撳紑鍗虫椂閫氫俊
-      appmenulist.push({
+      menulist.push({
         value: 'IM', label: '鍗虫椂閫氫俊锛堢郴缁熼〉锛�'
       })
     }
@@ -118,6 +117,7 @@
         {field: 'joint', values: ['menu', 'link', 'menus']},
         {field: 'linkbtn', values: ['button']},
         {field: 'menuType', values: ['menus']},
+        {field: 'menus', values: ['menus']},
       ]
     },
     {
@@ -134,7 +134,7 @@
       label: '鍏宠仈鑿滃崟',
       initval: setting.menu || (appType ? '' : []),
       required: true,
-      options: appType ? appmenulist : menulist,
+      options: menulist,
     },
     {
       type: 'textarea',
@@ -188,6 +188,36 @@
         {value: 'hover', label: '鎮诞鏄剧ず'},
       ],
       forbid: appType === 'mob'
+    },
+    {
+      type: 'table',
+      field: 'menus',
+      label: '鑿滃崟缁�',
+      initval: menus,
+      required: true,
+      span: 24,
+      columns: [
+        {
+          title: '鏍囪瘑',
+          dataIndex: 'sign',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          required: false,
+          width: '35%'
+        },
+        {
+          title: '鑿滃崟',
+          dataIndex: 'menu',
+          inputType: !appType ? 'cascader' : 'select',
+          editable: true,
+          required: true,
+          extends: !appType ? 'Menu' : [{key: 'label', value: 'label'}],
+          width: '35%',
+          render: (text, record) => record.label,
+          options: menulist
+        }
+      ]
     }
   ]
 
diff --git a/src/menu/components/share/actioncomponent/dragaction/index.jsx b/src/menu/components/share/actioncomponent/dragaction/index.jsx
index cdbc07a..e834be6 100644
--- a/src/menu/components/share/actioncomponent/dragaction/index.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -63,6 +63,13 @@
 
     let _val = fromJS(copycard).toJS()
 
+    if (_val.control) {
+      _val.control = ''
+      
+      delete _val.controlField
+      delete _val.controlVal
+    }
+
     copycard.uuid = Utils.getuuid()
     copycard.originCard = card
 
diff --git a/src/pc/components/login/normal-login/index.jsx b/src/pc/components/login/normal-login/index.jsx
index 59c4bed..48d29f8 100644
--- a/src/pc/components/login/normal-login/index.jsx
+++ b/src/pc/components/login/normal-login/index.jsx
@@ -75,6 +75,9 @@
       if (_card.loginWays.length === 2) {
         _card.loginWays.push({type: 'app_scan', label: '鎵爜鐧诲綍'})
       }
+      if (_card.wrap.link && _card.wrap.link === 'menu') {
+        _card.wrap.linkmenu = _card.uuid
+      }
       this.setState({
         card: _card
       })
@@ -141,9 +144,9 @@
   }
 
   getWrapForms = () => {
-    const { wrap } = this.state.card
+    const { card } = this.state
 
-    return getWrapForm(wrap)
+    return getWrapForm(card.wrap)
   }
 
   updateWrap = (res) => {
@@ -185,7 +188,7 @@
         } trigger="hover">
           <ToolOutlined />
         </Popover>
-        <LoginForm loginWays={card.loginWays} wrap={card.wrap} menuId={card.uuid} />
+        <LoginForm loginWays={card.loginWays} wrap={card.wrap} />
       </div>
     )
   }
diff --git a/src/pc/components/login/normal-login/loginform.jsx b/src/pc/components/login/normal-login/loginform.jsx
index bfcf920..bb7c058 100644
--- a/src/pc/components/login/normal-login/loginform.jsx
+++ b/src/pc/components/login/normal-login/loginform.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Input, Button, Checkbox } from 'antd'
+import { Form, Input, Button, Checkbox, notification } from 'antd'
 import { QrcodeOutlined, UserOutlined, LockOutlined } from '@ant-design/icons'
 
 import asyncElementComponent from '@/utils/asyncComponent'
@@ -12,7 +12,6 @@
 
 class LoginTabForm extends Component {
   static propTpyes = {
-    menuId: PropTypes.string,
     loginWays: PropTypes.array,
     wrap: PropTypes.array,
   }
@@ -80,10 +79,19 @@
   }
 
   changeMenu = () => {
-    const { wrap, menuId } = this.props
+    const { wrap } = this.props
+
+    if (!wrap.linkmenu) {
+      notification.warning({
+        top: 92,
+        message: '璇疯缃叧鑱旇彍鍗曪紒',
+        duration: 5
+      })
+      return
+    }
 
     MKEmitter.emit('changeEditMenu', {
-      MenuID: wrap.link === 'linkmenu' ? wrap.linkmenu : menuId,
+      MenuID: wrap.linkmenu,
       copyMenuId: '',
       MenuNo: '',
       MenuName: ''
diff --git a/src/pc/components/login/normal-login/options.jsx b/src/pc/components/login/normal-login/options.jsx
index bfb426f..295099c 100644
--- a/src/pc/components/login/normal-login/options.jsx
+++ b/src/pc/components/login/normal-login/options.jsx
@@ -57,6 +57,23 @@
       ]
     },
     {
+      type: 'select',
+      field: 'linkmenu',
+      label: '鍏宠仈鑿滃崟',
+      initval: wrap.linkmenu || '',
+      required: true,
+      options: menulist
+    },
+    {
+      type: 'select', // $楠岃瘉鐮�$  $mob$  $send_type$
+      field: 'tempId',
+      label: '鐭俊妯℃澘',
+      initval: wrap.tempId || '',
+      tooltip: '鐭俊妯℃澘鍙湪 浜戠郴缁�->搴旂敤鏈嶅姟->寮�鍙戣�呬腑蹇�->鐭俊妯℃澘 澶勬坊鍔犮��',
+      required: true,
+      options: msgTemps
+    },
+    {
       type: 'number',
       field: 'width',
       label: '瀹藉害',
@@ -87,37 +104,20 @@
       required: false,
       options: ['px', 'vh', 'vw', '%']
     },
-    {
-      type: 'radio',
-      field: 'link',
-      label: '閾炬帴',
-      initval: wrap.link || 'menu',
-      required: false,
-      options: [
-        {value: 'menu', label: '鑿滃崟'},
-        {value: 'linkmenu', label: '鍏宠仈鑿滃崟'},
-      ],
-      controlFields: [
-        {field: 'linkmenu', values: ['linkmenu']}
-      ]
-    },
-    {
-      type: 'select',
-      field: 'linkmenu',
-      label: '鍏宠仈鑿滃崟',
-      initval: wrap.linkmenu || '',
-      required: true,
-      options: menulist
-    },
-    {
-      type: 'select', // $楠岃瘉鐮�$  $mob$  $send_type$
-      field: 'tempId',
-      label: '鐭俊妯℃澘',
-      initval: wrap.tempId || '',
-      tooltip: '鐭俊妯℃澘鍙湪 浜戠郴缁�->搴旂敤鏈嶅姟->寮�鍙戣�呬腑蹇�->鐭俊妯℃澘 澶勬坊鍔犮��',
-      required: true,
-      options: msgTemps
-    },
+    // {
+    //   type: 'radio',
+    //   field: 'link',
+    //   label: '閾炬帴',
+    //   initval: wrap.link || 'menu',
+    //   required: false,
+    //   options: [
+    //     {value: 'menu', label: '鑿滃崟'},
+    //     {value: 'linkmenu', label: '鍏宠仈鑿滃崟'},
+    //   ],
+    //   controlFields: [
+    //     {field: 'linkmenu', values: ['linkmenu']}
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'shortcut',
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 4e4ed5b..76a8309 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -1277,6 +1277,9 @@
         } else if (item.subtype === 'propcard' && item.subcards.length === 0) {
           error = `缁勪欢銆�${item.name}銆嬩腑鍗$墖涓嶅彲涓虹┖锛乣
           return
+        } else if (item.type === 'login' && !item.wrap.linkmenu && item.wrap.link !== 'menu') {
+          error = '鐧诲綍缁勪欢鏈缃叧鑱旇彍鍗曪紒'
+          return
         }
         if (item.wrap && item.wrap.pagestyle === 'slide') {
           swipes.push(item.name)
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index be624a1..174afee 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -1479,6 +1479,9 @@
         } else if (item.subtype === 'propcard' && item.subcards.length === 0) {
           error = `缁勪欢銆�${item.name}銆嬩腑鍗$墖涓嶅彲涓虹┖锛乣
           return
+        } else if (item.type === 'login' && !item.wrap.linkmenu && item.wrap.link !== 'menu') {
+          error = '鐧诲綍缁勪欢鏈缃叧鑱旇彍鍗曪紒'
+          return
         }
         
         if (['propcard', 'brafteditor', 'sandbox', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return

--
Gitblit v1.8.0