king
2019-09-25 27821f7b598e9e87de8fb179bdcbfdc5e2cb31fa
2019-09-25update
14个文件已修改
1个文件已添加
427 ■■■■ 已修改文件
package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mainAction/index.jsx 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mainTable/index.jsx 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mainTable/index.scss 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.jsx 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/login.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/main.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/login.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/main.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/options.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -142,5 +142,6 @@
    "presets": [
      "react-app"
    ]
  }
  },
  "homepage": "."
}
src/api/index.js
@@ -1,18 +1,20 @@
import axios from 'axios'
import qs from 'qs'
axios.defaults.crossDomain = true
axios.defaults.headers.common['token'] = 'token'
// axios.defaults.headers.common['token'] = 'token'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.withCredentials = true
axios.interceptors.request.use((config) => {
  config.url = config.url || '/dostar'
  config.method = 'post'
  config.data = config.data || {}
  if (config.url !== '/login') {
    config.data.userid = sessionStorage.getItem('UserID') || ''
  config.headers.token = sessionStorage.getItem('TOKEN') || ''
  if (config.url.includes('LoginAndRedirect')) {
    config.data = qs.stringify(config.data)
  } else {
    config.data = JSON.stringify(config.data)
  }
  config.data = JSON.stringify(config.data)
  return config
}, (error) => {
  return Promise.reject(error)
@@ -27,11 +29,40 @@
class Api {
  constructor() {
    if (process.env.NODE_ENV === 'production') {
      axios.defaults.baseURL = document.location.origin + '/' + window.Glob.Service
      axios.defaults.baseURL = document.location.origin + '/MKWMS'
    } else {
      axios.defaults.baseURL = 'http://127.0.0.1:8888'
    }
  }
  /**
   * @description 系统授权
   */
  systemauth (appId, timestamp) {
    return axios({
      // url: 'http://minkesoft.com/mksepc/webapi/dostar',
      url: '/mksepc',
      data: {
        func: 'sEmpowerCloud_Get_LinkUrl',
        userid: '',
        AppID: appId,
        TimeStamp: timestamp
      }
    })
  }
  // /**
  //  * @description 登录系统
  //  */
  // loginsystem (username, password) {
  //   return axios({
  //     url: 'http://qingqiumarket.cn/MKWMS/zh-CN/Home/LoginAndRedirect',
  //     data: {
  //       Username: username,
  //       Password: password
  //     }
  //   })
  // }
  /**
   * @description 登录系统
@@ -53,7 +84,8 @@
    return axios({
      url: '/dostar',
      data: {
        func: 'logout'
        func: 'logout',
        userid: sessionStorage.getItem('UserID')
      }
    })
  }
@@ -66,6 +98,7 @@
      url: '/dostar',
      data: {
        func: 'ResetPassword',
        userid: sessionStorage.getItem('UserID'),
        OriginPwd: originpwd,
        NewPwd: newpwd
      }
@@ -79,7 +112,8 @@
    return axios({
      url: '/dostar',
      data: {
        func: 'GetTopMenus'
        func: 'GetTopMenus',
        userid: sessionStorage.getItem('UserID')
      }
    })
  }
@@ -93,6 +127,7 @@
      url: '/dostar',
      data: {
        func: 'GetSubMenus',
        userid: sessionStorage.getItem('UserID'),
        ParentID: menuId
      }
    })
@@ -107,6 +142,7 @@
      url: '/dostar',
      data: {
        func: 'GetMainConfigs',
        userid: sessionStorage.getItem('UserID'),
        MenuNo: MenuNo
      }
    })
@@ -121,6 +157,7 @@
      url: '/dostar',
      data: {
        func: 'GetMainData',
        userid: sessionStorage.getItem('UserID'),
        MenuNo: MenuNo,
        PageIndex: pageIndex,
        PageSize: pageSize,
@@ -130,6 +167,18 @@
      }
    })
  }
  /**
   * @description 获取页面列表数据
   * @param {String} param 提交参数
   */
  setActionSubmit (param) {
    param.userid = sessionStorage.getItem('UserID')
    return axios({
      url: '/dostar',
      data: param
    })
  }
}
export default new Api()
src/components/header/index.jsx
@@ -27,7 +27,7 @@
  state = {
    menulist: null,
    visible: false,
    dict: (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
    confirmLoading: false
  }
@@ -98,7 +98,6 @@
        return Api.logoutsystem().then(res => {
          if (res.status) {
            sessionStorage.removeItem('UserID')
            sessionStorage.removeItem('lang')
            _this.props.resetState()
            _this.props.history.replace('/login')
          } else {
@@ -120,15 +119,17 @@
    let result = await Api.getMainMenuData()
    if (result.status) {
      this.setState({
        menulist: result.data.map((menu, index) => { // 增加索引,用于打开新页面时查询菜单
          menu.index = index
          return menu
        })
        menulist: result.data
      })
      let param = sessionStorage.getItem('view_param') // 是否为打开新页面
      if (param) {
        let i = parseInt(param.split('&')[0])
        this.props.modifyMainMenu(result.data[i] || result.data[0])
        // 通过url中menuid筛选出选中的主菜单
        let id = param.split('&')[0]
        let _menu = result.data.filter(item => item.MenuID === id)[0]
        if (!_menu) {
          sessionStorage.removeItem('view_param')
        }
        this.props.modifyMainMenu(_menu || result.data[0])
      } else {
        this.props.modifyMainMenu(result.data[0])
      }
src/components/mainAction/index.jsx
@@ -1,13 +1,15 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
// import { is, fromJS } from 'immutable'
import { Button, Affix, Modal } from 'antd'
import { Button, Affix, Modal, notification } from 'antd'
import Api from '@/api'
import './index.scss'
const { confirm } = Modal
class MainAction extends Component {
  static propTpyes = {
    MenuNo: PropTypes.string,
    actions: PropTypes.array, // 搜索条件列表
    dict: PropTypes.object, // 字典项
    fixed: PropTypes.any
@@ -16,20 +18,47 @@
  state = {
  }
  refreshdata = () => {
    this.props.refreshdata()
  }
  actionTrigger = (item) => {
    let _this = this
    let data = this.props.gettableselected()
    if (item.Ot === 'required' && (!data || data.length === 0)) {
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: this.props.dict['main.action.confirm.selectline']
      })
      return
    }
    if (item.Action === 'Prompt' || item.Action === 'Delete') {
      confirm({
        title: this.props.dict['main.action.confirm.tip'],
        // content: 'Some descriptions',
        onOk() {
          return new Promise((resolve, reject) => {
            setTimeout(Math.random() > 0.5 ? resolve : reject, 1000)
          }).catch(() => console.log('Oops errors!'))
          return Api.setActionSubmit({
            func: 'SetActionSubmitSuccess'
            // func: 'SetActionSubmitError'
          }).then((res) => {
            if (res.status) {
              notification.success({
                top: 92,
                message: _this.props.dict['main.action.confirm.success']
                // duration: 0
                // description:
              })
              _this.refreshdata()
            } else {
              notification.error({
                top: 92,
                message: res.message
              })
            }
          })
        },
        onCancel() {
          console.log('Cancel')
        }
        onCancel() {}
      })
    }
  }
@@ -47,7 +76,7 @@
    if (this.props.fixed) { // 按钮是否固定在头部
      return (
        <Affix offsetTop={48}>
          <div className="button-list">
          <div className="button-list" id={this.props.MenuNo + 'mainaction'}>
            {this.props.actions.map((item, index) => {
              return (
                <Button
src/components/mainTable/index.jsx
@@ -1,10 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Table, Icon, message } from 'antd'
// import { is, fromJS } from 'immutable'
import { Table, Icon, message, Affix } from 'antd'
import './index.scss'
export default class MainTable extends Component {
  static propTpyes = {
    MenuNo: PropTypes.string, // 菜单参数
    fixed: PropTypes.object, // 表格头部是否固定于页面上方
    loading: PropTypes.bool,
    total: PropTypes.number,
    select: PropTypes.object,
@@ -59,15 +62,22 @@
  }
  changeRow = (record, index) => {
    // 点击整行,触发切换
    // 点击整行,触发切换,判断是否可选,单选或多选,进行对应操作
    if (!this.props.select || !this.props.select.selectable) return
    let newkeys = JSON.parse(JSON.stringify(this.state.selectedRowKeys))
    let _re = newkeys.includes(index)
    if (_re) {
      newkeys = newkeys.filter(item => item !== index)
    if (this.props.select.selectType === 'radio') {
      this.setState({ selectedRowKeys: [index] })
    } else {
      newkeys.push(index)
      if (_re) {
        newkeys = newkeys.filter(item => item !== index)
      } else {
        newkeys.push(index)
      }
      this.setState({ selectedRowKeys: newkeys })
    }
    this.setState({ selectedRowKeys: newkeys })
  }
  changeTable = (pagination, filters, sorter) => {
@@ -77,6 +87,13 @@
      selectedRowKeys: []
    })
    this.props.refreshdata(pagination, filters, sorter)
  }
  resetTable = () => {
    this.setState({
      pageIndex: 1,
      selectedRowKeys: []
    })
  }
  render() {
@@ -89,8 +106,37 @@
        onChange: this.onSelectChange
      }
    }
    let offset = null
    if (this.props.fixed.fixtable) {
      // 表格头部固定于顶部时,判断距顶部高度
      if (!this.props.fixed.fixaction) {
        offset = 48
      } else {
        let box = document.getElementById(this.props.MenuNo + 'mainaction')
        if (box) {
          offset = 48 + box.offsetHeight
        } else {
          offset = 105
        }
      }
    }
    return (
      <div className="main-table">
        {this.props.fixed.fixtable && <Affix offsetTop={offset} className="fix-header">
          <Table
            bordered={true}
            rowSelection={rowSelection}
            size="middle"
            columns={this.state.columns.map(column => {
              return {
                align: column.align,
                dataIndex: column.dataIndex,
                title: column.title,
                width: column.width
              }
            })}
          />
        </Affix>}
        <Table
          bordered={true}
          rowSelection={rowSelection}
src/components/mainTable/index.scss
@@ -47,4 +47,21 @@
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
  .fix-header {
    .ant-table-body {
      min-height: unset
    }
    .ant-table-placeholder {
      display: none;
    }
    .ant-table-wrapper {
      display: none;
    }
    .ant-affix .ant-table-wrapper {
      display: block;
    }
    // .ant-table-column-sorter, .anticon-filter {
    //   display: none;
    // }
  }
}
src/components/sidemenu/index.jsx
@@ -29,7 +29,7 @@
    let result = await Api.getSubMenuData(menu.MenuID)
    if (result.status) {
      let param = sessionStorage.getItem('view_param') // 是否为打开新页面
      let msg = sessionStorage.getItem('UserID') + '&' + sessionStorage.getItem('lang')
      let msg = sessionStorage.getItem('UserID')
      let submenuindex = 0 // 展开二级菜单索引
      let tabindex = null // 打开的tab页
      if (param) {
@@ -43,7 +43,7 @@
        subMenulist: result.data.map((item, i) => {
          if (item.children) {
            item.children = item.children.map((child, n) => {
              let _msg = window.btoa(menu.index + '&' + i + '&' + n + '&' + msg)
              let _msg = window.btoa(menu.MenuID + '&' + i + '&' + n + '&' + msg)
              child.src = '#/main/' + _msg
              return child
            })
@@ -96,6 +96,30 @@
    }
  }
  // componentDidMount () {
  //   this.props.modifyTabview([{
  //     Action: "Index",
  //     Deleted: "0",
  //     IsButton: "0",
  //     LinkUrl: "Main/Index?MenuNo=SRMPurchaseOrderM",
  //     MenuID: "MM02130020118001000170",
  //     MenuName: "采购单管理",
  //     MenuNo: "SRMPurchaseOrderM",
  //     Ot: "",
  //     ParentID: "MM021300201180010",
  //     Remark: "",
  //     Sort: "100",
  //     icon: "Content/Upload/2018-07-02/2018070216084721656911_199046432321408044.png",
  //     id: "MM02130020118001000170",
  //     pid: "MM021300201180010",
  //     sIcon: "Content/Upload/2018-07-02/2018070216084721656911_199046432321408044.png",
  //     selected: true,
  //     src: "#/main/MCYwJjAmVTAwMDAwMDAwMSZudWxs",
  //     text: "采购单管理",
  //     url: null
  //   }])
  // }
  onOpenChange = openKeys => {
    const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1)
    if (this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
src/locales/en-US/login.js
@@ -1,4 +1,7 @@
export default {
  'login.auth.tip': 'The system is not authorized, please contact the administrator.',
  'login.auth.ok': 'OK',
  'login.auth.cancel': 'Cancel',
  'login.username': 'Username',
  'login.username.empty': 'Please input your username!',
  'login.password': 'Password',
src/locales/en-US/main.js
@@ -4,5 +4,7 @@
  'main.copy.success': 'Copy success',
  'main.pagination.of': 'of',
  'main.pagination.items': 'items',
  'main.action.confirm.tip': 'Do you want to execute?'
  'main.action.confirm.tip': 'Do you want to execute?',
  'main.action.confirm.success': 'Execute successfully!',
  'main.action.confirm.selectline': 'Please select a line!'
}
src/locales/zh-CN/login.js
@@ -1,4 +1,7 @@
export default {
  'login.auth.tip': '系统未授权,请联系管理员。',
  'login.auth.ok': '确定',
  'login.auth.cancel': '取消',
  'login.username': '用户名',
  'login.username.empty': '请输入用户名!',
  'login.password': '密码',
src/locales/zh-CN/main.js
@@ -4,5 +4,7 @@
  'main.copy.success': '复制成功',
  'main.pagination.of': '共',
  'main.pagination.items': '条',
  'main.action.confirm.tip': '确定要执行吗?'
  'main.action.confirm.tip': '确定要执行吗?',
  'main.action.confirm.success': '执行成功!',
  'main.action.confirm.selectline': '请选择行!'
}
src/router/index.js
@@ -1,5 +1,7 @@
import React, {Component} from 'react'
import {HashRouter, Switch, Route, Redirect} from 'react-router-dom'
import moment from 'moment'
import md5 from 'md5'
import asyncComponent from '@/utils/asyncComponent'
const main = asyncComponent(() => import('@/views/main'))
const login = asyncComponent(() => import('@/views/login'))
@@ -23,15 +25,19 @@
      return (<Redirect to={{ pathname: '/main'}}/>)
    }
    
    let userId = sessionStorage.getItem('UserID')
    if (userId) {
    let userId = sessionStorage.getItem('UserID') // 判断是否存在userid
    let authCode = localStorage.getItem('AuthCode') // 判断系统是否在授权期限内
    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
    let isauth = authCode && authCode.includes(_s)
    if (userId && isauth) {
      return (<item.component {...props}/>)
    } else {
      let param = sessionStorage.getItem('view_param')
      if (param) {
        param = param.split('&')
        sessionStorage.setItem('UserID', param[3])
        sessionStorage.setItem('lang', param[4])
        return (<item.component {...props}/>)
      } else {
        return (<Redirect to={{ pathname: '/login', state: {from: props.location}}}/>)
src/store/options.js
New file
@@ -0,0 +1,4 @@
// 系统配置
export default {
  AppId: '2019092321511819778303670F4A640128471'
}
src/tabviews/commontable/index.jsx
@@ -31,7 +31,8 @@
      orderColumn: '',
      orderType: '',
      search: ''
    }
    },
    fixed: {}
  }
  async loadconfig () {
@@ -54,7 +55,11 @@
        newconfig.columns = result.columns.map(column => {
          return column
        })
        newconfig.columns.length = 4
        newconfig.columns.length = 5
      }
      newconfig.fixed = {
        fixaction: true,
        fixtable: true
      }
      newconfig.select = result.select
      this.setState(newconfig)
@@ -78,6 +83,7 @@
  }
  refreshbysearch = (searches) => {
    // 搜索条件变化
    this.loadmaindata(this.state.param.pageIndex, this.state.param.pageSize, this.state.param.orderColumn, this.state.param.orderType, searches)
    let param = Object.assign({}, this.state.param, {
      search: searches
@@ -89,6 +95,7 @@
  }
  refreshbytable = (pagination, filters, sorter) => {
    // 表格查询条件修改
    console.log(filters)
    if (sorter.order) {
      let _chg = {
@@ -108,6 +115,24 @@
      loading: true,
      param: param
    })
  }
  refreshbyaction = () => {
    // 按钮操作后刷新表格,重置页码及选择项
    this.refs.mainTable.resetTable()
    this.loadmaindata(1, this.state.param.pageSize, this.state.param.orderColumn, this.state.param.orderType, this.state.param.search)
    this.setState({
      loading: true
    })
  }
  gettableselected = () => {
    // 获取表格选择项
    let data = []
    this.refs.mainTable.state.selectedRowKeys.forEach(item => {
      data.push(this.refs.mainTable.props.data[item])
    })
    return data
  }
  copyMenuNo = (e) => {
@@ -136,9 +161,37 @@
    return (
      <div className="commontable">
        {!this.state.searchlist && <Loading />}
        {this.state.searchlist && <MainSearch refreshdata={this.refreshbysearch} searchlist={this.state.searchlist} dict={this.state.dict} />}
        {this.state.actions && <MainAction fixed={true} actions={this.state.actions} dict={this.state.dict} />}
        {this.state.columns && <MainTable refreshdata={this.refreshbytable} columns={this.state.columns} data={this.state.data} select={this.state.select} total={this.state.total} loading={this.state.loading} dict={this.state.dict} />}
        {this.state.searchlist &&
          <MainSearch
            refreshdata={this.refreshbysearch}
            searchlist={this.state.searchlist}
            dict={this.state.dict}
          />
        }
        {this.state.actions &&
          <MainAction
            MenuNo={this.props.MenuNo}
            fixed={this.state.fixed.fixaction}
            refreshdata={this.refreshbyaction}
            gettableselected={this.gettableselected}
            actions={this.state.actions}
            dict={this.state.dict}
          />
        }
        {this.state.columns &&
          <MainTable
            ref="mainTable"
            MenuNo={this.props.MenuNo}
            fixed={this.state.fixed}
            refreshdata={this.refreshbytable}
            columns={this.state.columns}
            data={this.state.data}
            select={this.state.select}
            total={this.state.total}
            loading={this.state.loading}
            dict={this.state.dict}
          />
        }
        <Button className="main-copy" icon="copy" onClick={this.copyMenuNo} shape="circle" />
        <BackTop>
          <div className="ant-back-top">
src/views/login/index.jsx
@@ -1,27 +1,43 @@
import React, {Component} from 'react'
import { Form, Icon, Input, Button, Checkbox, Dropdown, Menu, message } from 'antd'
import { Form, Icon, Input, Button, Checkbox, Dropdown, Menu, message, Modal } from 'antd'
import md5 from 'md5'
import moment from 'moment'
import Api from '@/api'
import zhCN from '@/locales/zh-CN/login.js'
import enUS from '@/locales/en-US/login.js'
import options from '@/store/options.js'
import logourl from '../../assets/img/login-logo.png'
import './index.scss'
const { confirm } = Modal
class Login extends Component {
  state = {
    langs: [{
      name: '中文简体',
      value: 'zh-CN'
    }, {
      name: 'English',
      value: 'en-US'
    }],
    selectedlang: {
      name: '中文简体',
      value: 'zh-CN'
    },
    dict: zhCN,
    isDisabled: false
  constructor (props) {
    super(props)
    const iszhCN = !localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN'
    this.state = {
      langs: [{
        name: '中文简体',
        value: 'zh-CN'
      }, {
        name: 'English',
        value: 'en-US'
      }],
      selectedlang: iszhCN ?
        {
          name: '中文简体',
          value: 'zh-CN'
        } :
        {
          name: 'English',
          value: 'en-US'
        },
      dict: iszhCN ? zhCN : enUS,
      isDisabled: false,
      auth: false
    }
  }
  changelang (item) {
@@ -36,11 +52,22 @@
    // md5密码加密
    const salt = 'minkesoft'
    return md5(md5(pwd + salt))
    // return pwd
  }
  handleSubmit = e => {
    // 登录参数检验
    e.preventDefault()
    if (!this.state.auth) {
      confirm({
        title: this.state.dict['login.auth.tip'],
        okText: this.state.dict['login.auth.ok'],
        cancelText: this.state.dict['login.auth.cancel'],
        onOk() {},
        onCancel() {}
      })
      return
    }
    this.props.form.validateFields((err, values) => {
      if (err) return
      this.setState({
@@ -55,8 +82,9 @@
    let password = this.md5Password(param.password)
    let result = await Api.loginsystem(param.username, password)
    if (result.status) {
    // if (!result.IsError) {
      sessionStorage.setItem('UserID', result.userid)
      sessionStorage.setItem('lang', this.state.selectedlang.value)
      localStorage.setItem('lang', this.state.selectedlang.value)
      if (param.remember) { // 记住密码时账号密码存入localStorage
        localStorage.setItem('username', param.username)
@@ -74,12 +102,47 @@
      }
    } else {
      message.warning(result.message)
      // message.warning(result.Message)
      this.setState({
        isDisabled: false
      })
    }
  }
  UNSAFE_componentWillMount () {
    let timeStamp = new Date().getTime()
    // let str = md5('MK19' + options.AppId + timeStamp)
    Api.systemauth(options.AppId, timeStamp).then(res => {
      if (res.status) {
        let box = []
        for (let i = 0; i < 15; i++) {
          let s = 'mksoft' + moment().add(i, 'days').format('YYYYMMDD')
          box.push(md5(s))
        }
        box = box.join(',')
        localStorage.setItem('AuthCode', box)
        this.setState({
          auth: true
        })
      } else {
        localStorage.removeItem('AuthCode')
        this.setState({
          auth: false
        })
      }
      // console.log(str)
    })
    let authCode = localStorage.getItem('AuthCode')
    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
    if (authCode && authCode.includes(_s)) {
      this.setState({
        auth: true
      })
    }
  }
  render () {
    const { getFieldDecorator } = this.props.form
    const menu = (