king
2020-09-15 0f75cd54d62aa6d623ff024ca787c85a578a5f38
2020-09-15
12个文件已修改
9个文件已添加
2个文件已删除
1367 ■■■■ 已修改文件
src/assets/css/main.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/bar.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/bar1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/mob-login1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/tabs.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/mob-login-2/index.jsx 423 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/mob-login-2/index.scss 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.scss 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tablabelform/index.jsx 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tablabelform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/index.jsx 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/index.scss 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/settingform/index.jsx 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/settingform/index.scss 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/searchcomponent/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss
@@ -304,6 +304,14 @@
        color: purple;
      }
    }
    .mk-popover-control::after {
      position: absolute;
      content: ' ';
      width: 100%;
      height: 10px;
      bottom: -10px;
      left: 0px;
    }
    .ant-popover-inner-content {
      padding: 5px 20px;
    }
src/assets/mobimg/bar.png

src/assets/mobimg/bar1.png

src/assets/mobimg/mob-login1.png

src/assets/mobimg/tabs.png
src/menu/components/chart/antv-bar/index.jsx
@@ -20,15 +20,12 @@
  static propTpyes = {
    config: PropTypes.object,
    card: PropTypes.object,
    editId: PropTypes.any,
    triggerEdit: PropTypes.func,
    updateConfig: PropTypes.func,
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,
    visible: true
    card: null
  }
  UNSAFE_componentWillMount () {
@@ -81,6 +78,7 @@
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
src/menu/components/chart/antv-bar/index.scss
@@ -1,7 +1,7 @@
.menu-line-chart-edit-box {
  position: relative;
  // margin-bottom: 0px;
  border: 1px solid #e8e8e8;
  box-sizing: border-box;
  
  .canvas {
    margin: 0px;
@@ -9,14 +9,14 @@
  }
  .chart-header {
    height: 50px;
    height: 45px;
    border-bottom: 1px solid #e8e8e8;
    overflow: hidden;
    .chart-title {
      font-size: 16px;
      float: left;
      line-height: 50px;
      line-height: 45px;
      margin-left: 10px;
    }
  }
@@ -36,3 +36,6 @@
    }
  }
}
.menu-line-chart-edit-box:hover {
  box-shadow: 0px 0px 2px #e8e8e8;
}
src/menu/components/chart/mob-login-2/index.jsx
File was deleted
src/menu/components/chart/mob-login-2/index.scss
File was deleted
src/menu/components/tabs/antv-tabs/index.jsx
New file
@@ -0,0 +1,224 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Tabs, Icon, Popover, Modal } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncComponent(() => import('../tabsetting'))
const TabLabelComponent = asyncComponent(() => import('../tablabelform'))
const { TabPane } = Tabs
const { confirm } = Modal
class antvBarLineChart extends Component {
  static propTpyes = {
    config: PropTypes.object,
    tabs: PropTypes.object,
    updateConfig: PropTypes.func,
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    tabs: null,
    editab: null,
    labelvisible: false
  }
  UNSAFE_componentWillMount () {
    const { tabs, config } = this.props
    if (tabs.isNew) {
      let name = ''
      let i = 1
      while (!name) {
        let _name = '标签页' + i
        if (config.components.filter(com => com.setting && com.setting.name === _name).length === 0) {
          name = _name
        }
        i++
      }
      let _tabs = {
        uuid: tabs.uuid,
        type: tabs.type,
        floor: tabs.floor,
        subtype: tabs.subtype,
        setting: {span: 12, position: 'top', tabStyle: 'line', name},
        subtabs: [{
          uuid: Utils.getuuid(),
          label: 'Tab 1',
          icon: '',
          subcomponents: [],
        }, {
          uuid: Utils.getuuid(),
          label: 'Tab 2',
          icon: '',
          subcomponents: [],
        }, {
          uuid: Utils.getuuid(),
          label: 'Tab 3',
          icon: '',
          subcomponents: [],
        }]
      }
      this.setState({
        tabs: _tabs
      })
      this.props.updateConfig(_tabs)
    } else {
      this.setState({
        tabs: fromJS(tabs).toJS()
      })
    }
  }
  componentDidMount () { }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.plot), fromJS(nextProps.plot))) {
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  updateComponent = (component) => {
    this.setState({
      tabs: component
    })
    this.props.updateConfig(component)
  }
  tabAdd = (e) => {
    e.stopPropagation()
    this.setState({
      editab: {
        uuid: '',
        label: '',
        icon: '',
        subcomponents: []
      },
      labelvisible: true
    })
  }
  editTab = (tab) => {
    this.setState({
      editab: tab,
      labelvisible: true
    })
  }
  tabLabelSubmit = () => {
    let tabs = fromJS(this.state.tabs).toJS()
    let editab = fromJS(this.state.editab).toJS()
    this.tabLabelRef.handleConfirm().then(res => {
      editab.label = res.label
      editab.icon = res.icon
      if (editab.uuid) {
        tabs.subtabs = tabs.subtabs.map(t => {
          if (t.uuid === editab.uuid) {
            return editab
          } else {
            return t
          }
        })
      } else {
        editab.uuid = Utils.getuuid()
        tabs.subtabs.push(editab)
      }
      this.setState({
        editab: null,
        labelvisible: false,
        tabs
      })
      this.props.updateConfig(tabs)
    })
  }
  delTab = (tab) => {
    let tabs = fromJS(this.state.tabs).toJS()
    const _this = this
    tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
    confirm({
      title: '确定删除标签?',
      content: '',
      onOk() {
        _this.setState({tabs})
        _this.props.updateConfig(tabs)
      },
      onCancel() {}
    })
  }
  moveSwitch = (index, index1) => {
    let tabs = fromJS(this.state.tabs).toJS()
    tabs.subtabs[index] = tabs.subtabs.splice(index1, 1, tabs.subtabs[index])[0]
    this.setState({tabs})
    this.props.updateConfig(tabs)
  }
  render() {
    const { tabs, dict, labelvisible, editab } = this.state
    return (
      <div className="menu-tabs-edit-box">
        <SettingComponent config={tabs} updateConfig={this.updateComponent} />
        <Tabs defaultActiveKey="1" tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
          {tabs.subtabs.map((tab, index) => (
            <TabPane tab={
              <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
                <div className="mk-popover-control">
                  <Icon className="edit" title="edit" type="edit" onClick={() => this.editTab(tab)} />
                  {index !== 0 ? <Icon className="edit" type="arrow-left" onClick={() => this.moveSwitch(index, index - 1)} /> : null}
                  {(index + 1) !== tabs.subtabs.length ? <Icon className="edit" type="arrow-right" onClick={() => this.moveSwitch(index, index + 1)} /> : null}
                  <Icon className="close" title="delete" type="close" onClick={() => this.delTab(tab)} />
                </div>
              } trigger="hover">
                <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span>
              </Popover>
            } key={tab.uuid}>
              Content of Tab Pane {tab.label}
            </TabPane>
          ))}
          <TabPane className="tab-add" disabled tab={<Icon onClick={this.tabAdd} type="plus" />} key="add"></TabPane>
        </Tabs>
        <Modal
          wrapClassName="popview-modal"
          title={'标签编辑'}
          visible={labelvisible}
          width={600}
          maskClosable={false}
          okText={dict['model.submit']}
          onOk={this.tabLabelSubmit}
          onCancel={() => { this.setState({ labelvisible: false }) }}
          destroyOnClose
        >
          <TabLabelComponent
            dict={dict}
            tab={editab}
            wrappedComponentRef={(inst) => this.tabLabelRef = inst}
          />
        </Modal>
      </div>
    )
  }
}
export default antvBarLineChart
src/menu/components/tabs/antv-tabs/index.scss
New file
@@ -0,0 +1,61 @@
.menu-tabs-edit-box {
  position: relative;
  box-sizing: border-box;
  .ant-tabs-tabpane-active {
    min-height: 200px;
  }
  .ant-tabs .ant-tabs-left-bar .ant-tabs-tab {
    padding: 0px;
    text-align: right;
    > span {
      display: inline-block;
      padding: 8px 24px;
    }
    .anticon-plus {
      padding: 8px 24px;
    }
  }
  .ant-tabs .ant-tabs-right-bar .ant-tabs-tab {
    padding: 0px;
    text-align: left;
    > span {
      display: inline-block;
      padding: 8px 24px;
    }
    .anticon-plus {
      padding: 8px 24px;
    }
  }
  .ant-tabs-tab {
    padding: 0px;
    text-align: center;
    > span {
      display: inline-block;
      padding: 12px 16px;
    }
    .anticon-plus {
      color: #26C281;
      padding: 12px 16px;
      margin-right: 0px;
      min-width: 100%;
      cursor: pointer;
    }
  }
  .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar {
    top: 0px;
  }
  .ant-tabs-card {
    .ant-tabs-card-bar .ant-tabs-tab:last-child {
      padding: 0px;
      border: 0px;
      background: transparent;
      .anticon-plus {
        padding: 12px 16px;
      }
    }
  }
}
.menu-tabs-edit-box:hover {
  box-shadow: 0px 0px 2px #e8e8e8;
}
src/menu/components/tabs/tablabelform/index.jsx
New file
@@ -0,0 +1,86 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Icon, Select } from 'antd'
// import { formRule } from '@/utils/option.js'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,   // 字典项
    tab: PropTypes.object,    // 数据源配置
  }
  state = {}
  UNSAFE_componentWillMount () {
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          resolve(values)
        } else {
          reject(err)
        }
      })
    })
  }
  render() {
    const { tab } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 12 }
      }
    }
    return (
      <Form {...formItemLayout}>
        <Row gutter={24}>
          <Col span={24}>
            <Form.Item label="名称">
              {getFieldDecorator('label', {
                initialValue: tab.label,
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + '名称!'
                  }
                ]
              })(<Input placeholder={''} autoComplete="off" />)}
            </Form.Item>
          </Col>
          <Col span={24}>
            <Form.Item label="图标">
              {getFieldDecorator('icon', {
                initialValue: tab.icon || ''
              })(
                <Select>
                  <Select.Option key="empty" value=""> 无 </Select.Option>
                  <Select.Option key="android" value="android"> <Icon type="android" /> </Select.Option>
                  <Select.Option key="apple" value="apple"> <Icon type="apple" /> </Select.Option>
                  <Select.Option key="windows" value="windows"> <Icon type="windows" /> </Select.Option>
                  <Select.Option key="alipay" value="alipay"> <Icon type="alipay" /> </Select.Option>
                </Select>
              )}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
  }
}
export default Form.create()(SettingForm)
src/menu/components/tabs/tablabelform/index.scss
src/menu/components/tabs/tabsetting/index.jsx
New file
@@ -0,0 +1,80 @@
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: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    visible: false,
    setting: null
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({setting: fromJS(config.setting).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({
        setting: res,
        visible: false
      })
      this.props.updateConfig({...config, setting: res})
    })
  }
  render () {
    const { visible, dict, setting } = this.state
    return (
      <div className="model-menu-tabs-setting">
        <Icon type="setting" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="model-datasource-verify-modal popview-modal"
          title={'标签页配置'}
          visible={visible}
          width={700}
          maskClosable={false}
          okText={dict['model.submit']}
          onOk={this.verifySubmit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          <SettingForm
            dict={dict}
            setting={setting}
            wrappedComponentRef={(inst) => this.verifyRef = inst}
          />
        </Modal>
      </div>
    )
  }
}
export default DataSource
src/menu/components/tabs/tabsetting/index.scss
New file
@@ -0,0 +1,94 @@
.model-menu-tabs-setting {
  position: absolute;
  right: 7px;
  top: 5px;
  z-index: 1;
  >.anticon-setting {
    font-size: 18px;
    padding: 10px;
  }
  .model-input-group-wrapper {
    padding: 0 20px;
    display: inline-block;
    width: 100%;
    text-align: start;
    vertical-align: top;
    margin-bottom: 15px;
    .model-input-wrapper {
      position: relative;
      display: table;
      width: 100%;
      border-collapse: separate;
      border-spacing: 0;
      .model-input-value {
        display: table-cell;
        width: 100%;
        border: 1px solid #d9d9d9;
        border-radius: 4px 0px 0px 4px;
        overflow: hidden;
        text-overflow:ellipsis;
        white-space: nowrap;
        padding: 2px 10px;
        color: #ffffff;
      }
      .model-input-group-addon {
        display: table-cell;
        width: 1px;
        position: relative;
        padding: 0 11px;
        color: rgba(0, 0, 0, 0.65);
        font-weight: normal;
        font-size: 14px;
        line-height: 1;
        text-align: center;
        background-color: #fafafa;
        border: 1px solid #d9d9d9;
        border-radius: 0px 4px 4px 0px;
        white-space: nowrap;
      }
      .model-input-insert {
        display: table-cell;
        width: 100%;
        border: 1px dotted #d9d9d9;
        border-radius: 4px;
        text-align: center;
        cursor: pointer;
        .anticon-plus {
          padding: 6px;
          font-size: 16px;
          color: rgb(38, 194, 129);
        }
      }
    }
    .anticon-setting {
      margin-right: 5px;
      padding: 6px;
      cursor: pointer;
    }
    .anticon-setting:hover {
      color: #1890ff;
    }
    .anticon-close {
      padding: 6px;
      cursor: pointer;
    }
    .anticon-close:hover {
      color: #ff4d4f;
    }
  }
}
.model-datasource-verify-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
    }
  }
}
src/menu/components/tabs/tabsetting/settingform/index.jsx
New file
@@ -0,0 +1,127 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd'
// import { formRule } from '@/utils/option.js'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,       // 字典项
    setting: PropTypes.object,    // 数据源配置
  }
  state = {}
  UNSAFE_componentWillMount () {
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          resolve(values)
        } else {
          reject(err)
        }
      })
    })
  }
  render() {
    const { setting } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <div className="model-datasource-setting-form-box">
        <Form {...formItemLayout} className="model-setting-form">
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="用于组件间的区分。">
                  <Icon type="question-circle" />
                  组件名称
                </Tooltip>
              }>
                {getFieldDecorator('name', {
                  initialValue: setting.name,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '组件名称!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
              }>
                {getFieldDecorator('span', {
                  initialValue: setting.span || 12,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="标签位置">
                {getFieldDecorator('position', {
                  initialValue: setting.position || 'top'
                })(
                  <Select>
                    <Select.Option key="top" value="top"> top </Select.Option>
                    <Select.Option key="bottom" value="bottom"> bottom </Select.Option>
                    <Select.Option key="left" value="left"> left </Select.Option>
                    <Select.Option key="right" value="right"> right </Select.Option>
                  </Select>
                )}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="标签位置为top时有效,默认值为line。">
                  <Icon type="question-circle" />
                  页签样式
                </Tooltip>
              }>
                {getFieldDecorator('tabStyle', {
                  initialValue: setting.tabStyle || 'line'
                })(
                  <Radio.Group>
                    <Radio value="line">line</Radio>
                    <Radio value="card">card</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(SettingForm)
src/menu/components/tabs/tabsetting/settingform/index.scss
New file
@@ -0,0 +1,24 @@
.model-datasource-setting-form-box {
  position: relative;
  .model-setting-form {
    .data-source {
      .ant-form-item-label {
        width: 11%;
      }
      .ant-form-item-control-wrapper {
        width: 89%;
      }
      .CodeMirror {
        height: 150px;
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 3px;
    }
  }
  .ant-input-number {
    width: 100%;
  }
}
src/menu/menushell/card.jsx
@@ -6,8 +6,9 @@
import './index.scss'
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const Card = ({ id, config, card, moveCard, findCard, editId, editCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
const Card = ({ id, config, card, moveCard, findCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'menu', id, originalIndex },
@@ -39,7 +40,9 @@
  const getCardComponent = () => {
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar config={config} card={card} triggerEdit={editCard} editId={editId} updateConfig={updateConfig} />)
      return (<AntvBar config={config} card={card} updateConfig={updateConfig} />)
    } else if (card.type === 'tabs') {
      return (<AntvTabs config={config} tabs={card} updateConfig={updateConfig} />)
    }
  }
src/menu/menushell/index.jsx
@@ -8,7 +8,7 @@
import Card from './card'
import './index.scss'
const Container = ({config, editId, handleList, editCard, deleteCard, doubleClickCard }) => {
const Container = ({config, handleList, deleteCard, doubleClickCard }) => {
  let target = null
  const [cards, setCards] = useState(config.components)
@@ -60,7 +60,8 @@
        uuid: Utils.getuuid(),
        type: item.component,
        subtype: item.subtype,
        isNew: true
        floor: 1,   // 组件的层级
        isNew: true // 新添加标志,用于初始化
      }
      
      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
@@ -88,9 +89,7 @@
          key={card.uuid}
          config={config}
          card={card}
          editId={editId}
          moveCard={moveCard}
          editCard={editCard}
          delCard={deleteCard}
          findCard={findCard}
          hasDrop={hasDrop}
src/menu/menushell/index.scss
@@ -28,7 +28,7 @@
    .remove-component {
      opacity: 1;
    }
    .model-datasource > .anticon-setting {
    .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
      opacity: 1;
    }
  }
@@ -36,7 +36,7 @@
    padding-top: 150px;
  }
  .model-datasource > .anticon-setting {
  .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
    font-size: 16px;
    padding: 5px;
    position: absolute;
src/menu/modelsource/option.jsx
@@ -4,11 +4,13 @@
import bar1 from '@/assets/mobimg/bar1.png'
import line from '@/assets/mobimg/line.png'
import line1 from '@/assets/mobimg/line1.png'
import tabs from '@/assets/mobimg/tabs.png'
// const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
// 组件配置信息
export const menuOptions = [
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs' },
  { type: 'menu', url: line, component: 'line', subtype: 'line' },
  { type: 'menu', url: line1, component: 'line', subtype: 'line1' },
  { type: 'menu', url: bar, component: 'bar', subtype: 'bar' },
src/menu/searchcomponent/index.scss
@@ -1,5 +1,5 @@
.model-custom-search-list {
  padding: 5px 0px 0px;
  padding: 0px;
  .anticon-question-circle {
    color: #c49f47;
src/tabviews/custom/index.jsx
@@ -141,6 +141,8 @@
      let params = []
      config.components.forEach(component => {
        if (!component.format) return // 没有动态数据
        let _customScript = ''
        component.scripts && component.scripts.forEach(script => {
          if (script.status !== 'false') {