Преглед на файлове

Merge branch 'dev' of ssh://10.10.100.21/source/uas-office-integration into dev

samhoo преди 5 години
родител
ревизия
e2a94a087c
променени са 21 файла, в които са добавени 574 реда и са изтрити 231 реда
  1. 144 10
      uas-office-web/uas-mobile/src/components/common/currencyDetail/CurrencyDetail.jsx
  2. 3 14
      uas-office-web/uas-mobile/src/components/common/currencyDetail/currency-detail.less
  3. 31 15
      uas-office-web/uas-mobile/src/components/common/currencyList/CurrencyList.jsx
  4. 13 12
      uas-office-web/uas-mobile/src/components/common/formNew/FormInput.jsx
  5. 2 0
      uas-office-web/uas-mobile/src/components/common/formNew/formCommon.less
  6. 3 0
      uas-office-web/uas-mobile/src/configs/api.config.js
  7. 6 1
      uas-office-web/uas-mobile/src/configs/router.config.js
  8. 2 0
      uas-office-web/uas-mobile/src/model/common/BillModel.js
  9. 0 1
      uas-office-web/uas-mobile/src/pages/private/homePage/DocRoot.jsx
  10. 1 0
      uas-office-web/uas-mobile/src/pages/private/homePage/HomePage.jsx
  11. 99 0
      uas-office-web/uas-mobile/src/pages/private/service/ServiceAdd.jsx
  12. 33 20
      uas-office-web/uas-mobile/src/pages/private/service/ServiceDetail.jsx
  13. 15 4
      uas-office-web/uas-mobile/src/pages/private/service/ServiceList.jsx
  14. 5 0
      uas-office-web/uas-mobile/src/pages/private/service/service.less
  15. 50 0
      uas-office-web/uas-mobile/src/redux/actions/formState.js
  16. 0 1
      uas-office-web/uas-mobile/src/redux/actions/mainState.js
  17. 10 0
      uas-office-web/uas-mobile/src/redux/constants/actionTypes.js
  18. 2 0
      uas-office-web/uas-mobile/src/redux/reducers/index.js
  19. 50 0
      uas-office-web/uas-mobile/src/redux/reducers/redFormState.js
  20. 79 147
      uas-office-web/uas-mobile/src/utils/common/form.request.js
  21. 26 6
      uas-office-web/uas-mobile/src/utils/common/form.util.js

+ 144 - 10
uas-office-web/uas-mobile/src/components/common/currencyDetail/CurrencyDetail.jsx

@@ -6,41 +6,175 @@
 import React, { Component } from 'react'
 import { connect } from 'react-redux'
 import './currency-detail.less'
+import {
+  isObjEmpty,
+  isObjNull,
+  strContain,
+} from '../../../utils/common/common.util'
+import {
+  List,
+  Modal,
+  ListView,
+  SearchBar,
+} from 'antd-mobile'
 import { getFormItems } from '../../../utils/common/form.util'
+import { BILL_STATE, FILTER_STATE } from '../../../redux/constants/actionTypes'
+
+let mModalList = []
 
 class CurrencyDetail extends Component {
 
   constructor () {
     super()
 
-    this.state = {}
+    this.state = {
+      modalOpen: false,
+      modalDataSource: new ListView.DataSource({
+        rowHasChanged: (row1, row2) => row1 !== row2,
+      }),
+      selectModel: {},
+    }
   }
 
   componentDidMount () {
+
   }
 
   componentWillUnmount () {
 
   }
 
+  shouldComponentUpdate (nextProps, nextState, nextContext) {
+    this.forceUpdate()
+    return true
+  }
+
   render () {
-    const { formGroups } = this.props
-    const formItems = getFormItems(formGroups)
+    const { formState: { billGroupList, filterGroupList }, dataType } = this.props
+    let formItems = getFormItems(billGroupList)
+    if (dataType === FILTER_STATE) {
+      formItems = getFormItems(filterGroupList)
+    }
 
     return (
       <div className='currency-detail-root'>
-        <div className='currency-detail-content'>
-          {formItems}
-        </div>
-        <div className='currency-detail-operation'>
-
-        </div>
+        {formItems}
+        {this.getDbfindModal()}
       </div>
     )
   }
 
+  /**
+   * 放大镜弹框
+   * @returns {*}
+   */
+  getDbfindModal () {
+    const { modalOpen, modalDataSource, selectModel } = this.state
+    let selectType = selectModel.type
+    return <Modal visible={modalOpen}
+                  animationType={'slide-up'}
+                  onClose={() => {
+                    this.setState({
+                      modalOpen: false,
+                    })
+                  }}
+                  title={selectModel.caption}
+                  popup
+    >
+      <SearchBar
+        placeholder={'搜索'}
+        maxLength={16}
+        onChange={value => {
+          if (isObjEmpty(value)) {
+            this.setState({
+              modalDataSource: modalDataSource.cloneWithRows(
+                mModalList),
+            })
+          } else {
+            let searchList = []
+            if (!isObjEmpty(mModalList)) {
+              mModalList.forEach(item => {
+                if (!isObjNull(item)
+                  && (
+                    strContain(item.value, value)
+                    || strContain(item.display, value)
+                    || strContain(item.name, value)
+                    || strContain(item.EM_CODE, value)
+                    || strContain(item.EM_NAME, value)
+                    || strContain(item.EM_POSITION, value)
+                    || strContain(item.EM_DEFAULTORNAME, value)
+                  )) {
+                  searchList.push(item)
+                }
+              })
+            }
+            this.setState({
+              modalDataSource: modalDataSource.cloneWithRows(
+                searchList),
+            })
+          }
+        }}
+        onClear={value => {
+          this.setState({
+            modalDataSource: modalDataSource.cloneWithRows(
+              mModalList),
+          })
+        }}
+        /*onCancel={() => {
+          this.setState({
+            modalDataSource: modalDataSource.cloneWithRows(
+              mModalList),
+          })
+        }}*/
+      />
+      <ListView
+        dataSource={modalDataSource}
+        initialListSize={30}
+        renderRow={(rowData, sectionID, rowID) => {
+          switch (selectType) {
+            /* case SELECT_APPROVAL:
+               return <List.Item
+                 key={rowID}
+                 wrap
+                 onClick={this.onEmployeeSelect.bind(this,
+                   rowData)}>
+                 <EmployeeItem employee={rowData}/>
+               </List.Item>*/
+            /*case 'MF':
+              return <CheckboxItem
+                key={rowID}
+                checked={rowData.isSelected == true}
+                onChange={e => {
+                  let checked = e.target.checked
+                  rowData.isSelected = checked
+                  this.setState({
+                    modalDataSource,
+                  })
+                }}>{rowData.value}</CheckboxItem>*/
+            default:
+              return <List.Item
+                key={rowID}
+                wrap
+                onClick={this.onDbfindSelect.bind(this,
+                  selectModel,
+                  rowData)}>{rowData.value}</List.Item>
+          }
+        }}
+        style={{
+          height: '72vh',
+          overflow: 'auto',
+        }}
+        pageSize={20}
+        // onScroll={() => {}}
+        // scrollRenderAheadDistance={800}
+      />
+    </Modal>
+  }
+
 }
 
-let mapStateToProps = (state) => ({})
+let mapStateToProps = (state) => ({
+  formState: state.formState,
+})
 
 export default connect(mapStateToProps)(CurrencyDetail)

+ 3 - 14
uas-office-web/uas-mobile/src/components/common/currencyDetail/currency-detail.less

@@ -1,17 +1,6 @@
 .currency-detail-root {
-  .com-column-flex;
   width: 100%;
-  height: 100vh;
-
-  .currency-detail-content {
-    overflow: auto;
-    -webkit-overflow-scrolling: touch;
-    flex: 1;
-    width: 100%;
-  }
-
-  .currency-detail-operation {
-    .com-row-flex;
-    padding: 14px;
-  }
+  flex: 1;
+  overflow: auto;
+  -webkit-overflow-scrolling: touch;
 }

+ 31 - 15
uas-office-web/uas-mobile/src/components/common/currencyList/CurrencyList.jsx

@@ -27,6 +27,9 @@ import { saveListState } from '../../../redux/actions/listState'
 import { LIST_PAGE_SIZE } from '../../../configs/constans.config'
 import { GlobalEvent } from '../../../utils/common/eventbus/eventbus'
 import { CURRENCY_DETAIL_DATA_REFRESH } from '../../../utils/common/eventbus/events.types'
+import { refreshFormState } from '../../../redux/actions/formState'
+import { FILTER_STATE } from '../../../redux/constants/actionTypes'
+import CurrencyDetail from '../currencyDetail/CurrencyDetail'
 
 class CurrencyList extends Component {
 
@@ -45,6 +48,10 @@ class CurrencyList extends Component {
 
   componentDidMount () {
     const hei = this.state.height - ReactDOM.findDOMNode(this.lv).offsetTop
+    //将标识设置为FILTER_STATE,保证数据不错乱
+    refreshFormState({
+      stateType: FILTER_STATE,
+    })
     this.setState({
       height: hei,
       refreshing: false,
@@ -54,7 +61,13 @@ class CurrencyList extends Component {
       }),
     })
 
-    const { requestList, requestTab, requestSearchConfig, listState: { tabList, listData, filterList } } = this.props
+    const {
+      requestList,
+      requestTab,
+      requestSearchConfig,
+      formState: { filterGroupList },
+      listState: { tabList, listData, scrollTop },
+    } = this.props
 
     if (isObjEmpty(tabList) && !isObjNull(requestTab)) {
       requestTab()
@@ -65,17 +78,19 @@ class CurrencyList extends Component {
       requestList()
     }
 
-    if (isObjEmpty(filterList) && !isObjNull(requestSearchConfig)) {
+    if (isObjEmpty(filterGroupList) && !isObjNull(requestSearchConfig)) {
       requestSearchConfig()
     }
     GlobalEvent.on(CURRENCY_DETAIL_DATA_REFRESH, (billGroupModelList) => {
       saveListState({
-        filterList: billGroupModelList,
+        filterGroupList: billGroupModelList,
       })
       setTimeout(() => {
         this.forceUpdate()
       }, 0)
     }, this)
+
+    ReactDOM.findDOMNode(this.lv).scrollTop = scrollTop
   }
 
   componentWillUnmount () {
@@ -175,16 +190,10 @@ class CurrencyList extends Component {
   }
 
   getFilterLayout = () => {
-    const { listState: { filterList } } = this.props
-    console.log(filterList)
-    const formItems = getFormItems(filterList)
     return (
       <div
         className='currency-list-content-filter-content'>
-        <div
-          className='currency-list-content-filter-config'>
-          {formItems}
-        </div>
+        <CurrencyDetail dataType={FILTER_STATE}/>
         <div className='currency-list-content-filter-func'>
           <Button
             className='currency-list-content-filter-func-button'
@@ -197,8 +206,7 @@ class CurrencyList extends Component {
             onClick={this.onFilterOpen}
             inline>取消</Button>
         </div>
-      </div>
-    )
+      </div>)
   }
 
   onTabSelect = (tabIndex) => {
@@ -229,6 +237,9 @@ class CurrencyList extends Component {
   }
 
   onItemClick = (rowData) => {
+    saveListState({
+      scrollTop: ReactDOM.findDOMNode(this.lv).scrollTop,
+    })
     const { onItemClick } = this.props
     onItemClick && onItemClick(rowData)
   }
@@ -240,7 +251,11 @@ class CurrencyList extends Component {
   }
 
   onDocAdd = () => {
-
+    saveListState({
+      scrollTop: ReactDOM.findDOMNode(this.lv).scrollTop,
+    })
+    const { onDocAdd } = this.props
+    onDocAdd && onDocAdd()
   }
 
   handlePrompt = (location) => {
@@ -258,14 +273,15 @@ class CurrencyList extends Component {
   }
 
   onFilterCommit = () => {
-    const { listState: { filterList } } = this.props
-    let formAndGrid = getFormAndGrid(filterList)
+    const { formState: { filterGroupList } } = this.props
+    let formAndGrid = getFormAndGrid(filterGroupList)
     console.log(formAndGrid)
   }
 }
 
 let mapStateToProps = (state) => ({
   listState: state.listState,
+  formState: state.formState,
 })
 
 export default connect(mapStateToProps)(CurrencyList)

+ 13 - 12
uas-office-web/uas-mobile/src/components/common/formNew/FormInput.jsx

@@ -62,6 +62,7 @@ export default class FormInput extends Component {
           this.getDateCom(type, billModel)
         break
       case 'HTML':
+      case 'HOS':
         valueItem =
           this.getHtmlcom(billModel)
         break
@@ -129,7 +130,7 @@ export default class FormInput extends Component {
    * @returns {*}
    */
   renderTwoLines (billModel, valueItem) {
-    return <div className={'form-textarea-layout'}>
+    return <div className='form-textarea-layout'>
       <div className='form-common-layout'
            style={{ borderBottom: 'none' }}>
         <div style={{
@@ -153,11 +154,11 @@ export default class FormInput extends Component {
    */
   getTextCom (billModel) {
     return <TextareaItem className='form-input-value' autoHeight
-                         placeholder={this.isSelect(billModel)
-                           ? '请选择'
-                           : ((billModel.readOnly === 'T' ||
-                             billModel.editable === 'F')
-                             ? ''
+                         placeholder={(billModel.readOnly === 'T' ||
+                           billModel.editable === 'F')
+                           ? ''
+                           : (this.isSelect(billModel)
+                             ? '请选择'
                              : '请输入')}
                          clear={true}
                          editable={(billModel.readOnly === 'T' ||
@@ -205,7 +206,7 @@ export default class FormInput extends Component {
       }}
       mode={type === 'DT' ? 'datetime' : 'date'}
       extra={(billModel.readOnly === 'T' ||
-        billModel.editable === 'F') ? '' : type === 'DT' ? '选择时间' : '选择日期'}
+        billModel.editable === 'F') ? ' ' : type === 'DT' ? '选择时间' : '选择日期'}
       disabled={(billModel.readOnly === 'T' ||
         billModel.editable === 'F') ? true : false}
       value={!isObjEmpty(this.getValue(billModel))
@@ -230,11 +231,11 @@ export default class FormInput extends Component {
    */
   getNumCom (billModel) {
     return <InputItem className='form-input-value' clear
-                      placeholder={this.isSelect(billModel)
-                        ? '请选择'
-                        : ((billModel.readOnly === 'T' ||
-                          billModel.editable === 'F')
-                          ? ''
+                      placeholder={(billModel.readOnly === 'T' ||
+                        billModel.editable === 'F')
+                        ? ''
+                        : (this.isSelect(billModel)
+                          ? '请选择'
                           : '请输入')}
                       editable={(billModel.readOnly === 'T' ||
                         billModel.editable === 'F') ? false : (this.isSelect(

+ 2 - 0
uas-office-web/uas-mobile/src/components/common/formNew/formCommon.less

@@ -96,7 +96,9 @@
   max-height: 300px;
   padding-left: 4px;
   padding-right: 4px;
+  margin-bottom: 0px;
   overflow-y: scroll;
+  align-items: normal;
 }
 
 .form-textarea-layout .form-input-value.am-list-item.am-textarea-item::-webkit-scrollbar {

+ 3 - 0
uas-office-web/uas-mobile/src/configs/api.config.js

@@ -36,6 +36,9 @@ export const API = {
   //获取应用列表
   SETVICES_GETORDERLIST: _baseURL +
     '/mobile/appweb/services/getOrderList.action',
+  //获取应用详情
+  SETVICES_GETORDER: _baseURL +
+    '/mobile/appweb/services/getOrder.action',
 
   /*******************************报表*************************************/
   //获取报表菜单

+ 6 - 1
uas-office-web/uas-mobile/src/configs/router.config.js

@@ -57,6 +57,8 @@ const ServiceList = PageLoadable(
   import(/* webpackChunkName:'subscribe' */'@/pages/private/service/ServiceList'))
 const ServiceDetail = PageLoadable(
   import(/* webpackChunkName:'subscribe' */'@/pages/private/service/ServiceDetail'))
+const ServiceAdd = PageLoadable(
+  import(/* webpackChunkName:'subscribe' */'@/pages/private/service/ServiceAdd'))
 
 /*************************************************切换账套************************************************/
 const ChangeAccount = PageLoadable(
@@ -133,8 +135,11 @@ class Routes extends React.Component {
           {/*应用数据列表*/}
           <Route path='/serviceList/:caller/:title?' component={ServiceList}/>
           {/*应用单据详情*/}
-          <Route path='/ServiceDetail'
+          <Route path='/serviceDetail/:id/:caller/:title?'
                  component={ServiceDetail}/>
+          {/*应用单据新增*/}
+          <Route path='/serviceAdd/:id/:caller/:title?'
+                 component={ServiceAdd}/>
 
           {/*************************************切换账套*****************************************/}
           {/*切换账套列表*/}

+ 2 - 0
uas-office-web/uas-mobile/src/model/common/BillModel.js

@@ -11,6 +11,7 @@ export default function BillModel (billModel) {
     this.dbfind = ''//是否是dbfind字段判定
     this.caption = ''//字段名称
     this.type = ''//类型(标题类型为Constants.TYPE_TITLE,不触发点击事件等 )
+    this.sourcetype = ''//字段原类型
     this.logicType = ''//logic类型
     this.readOnly = ''//字段是否只读  T/F
     this.field = ''//字段
@@ -36,6 +37,7 @@ export default function BillModel (billModel) {
     this.dbfind = billModel.dbfind
     this.caption = billModel.caption
     this.type = billModel.type
+    this.sourcetype = billModel.sourcetype
     this.logicType = billModel.logicType
     this.readOnly = billModel.readOnly
     this.field = billModel.field

+ 0 - 1
uas-office-web/uas-mobile/src/pages/private/homePage/DocRoot.jsx

@@ -49,7 +49,6 @@ class DocRoot extends Component {
     return (
       <RefreshLayout
         direction={'down'}
-        height={'100%'}
         refreshing={this.state.refreshing}
         onRefresh={this.refreshFunc}
         className='doc-root'>

+ 1 - 0
uas-office-web/uas-mobile/src/pages/private/homePage/HomePage.jsx

@@ -15,6 +15,7 @@ import { clearListState } from '../../../redux/actions/listState'
 import { GlobalEvent } from '../../../utils/common/eventbus/eventbus'
 import { EVENT_DOC_FUNC_COUNT } from '../../../utils/common/eventbus/events.types'
 import { requestUserInfo } from '../../../utils/private/user.util'
+import { clearFormState } from '../../../redux/actions/formState'
 
 /**
  * Created by RaoMeng on 2020/11/9

+ 99 - 0
uas-office-web/uas-mobile/src/pages/private/service/ServiceAdd.jsx

@@ -0,0 +1,99 @@
+/**
+ * Created by RaoMeng on 2020/12/15
+ * Desc: 应用单据新增
+ */
+
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { GlobalEvent } from '../../../utils/common/eventbus/eventbus'
+import { CURRENCY_DETAIL_DATA_REFRESH } from '../../../utils/common/eventbus/events.types'
+import { Toast, Button } from 'antd-mobile'
+import { fetchPostObj } from '../../../utils/common/fetchRequest'
+import { API } from '../../../configs/api.config'
+import { analysisFormData } from '../../../utils/common/form.request'
+import { message } from 'antd'
+import CurrencyDetail
+  from '../../../components/common/currencyDetail/CurrencyDetail'
+import './service.less'
+import { getFormAndGrid } from '../../../utils/common/form.util'
+import { refreshFormState } from '../../../redux/actions/formState'
+import { BILL_STATE } from '../../../redux/constants/actionTypes'
+
+class ServiceAdd extends Component {
+
+  constructor () {
+    super()
+
+    this.state = {}
+  }
+
+  componentDidMount () {
+    this.caller = this.props.match.params.caller
+    this.id = this.props.match.params.id
+    const title = this.props.match.params.title
+    document.title = title || '单据新增'
+
+    //将标识设置为BILL_STATE,保证数据不错乱
+    refreshFormState({
+      stateType: BILL_STATE,
+    })
+    this.requestFormData()
+  }
+
+  componentWillUnmount () {
+
+  }
+
+  render () {
+    const { formState: { billGroupList } } = this.props
+    return (
+      <div className='service-add-root'>
+        <CurrencyDetail dataType={BILL_STATE}/>
+        {billGroupList.length > 0 &&
+        <Button
+          type={'primary'}
+          style={{
+            margin: '12px 26px 16px',
+            height: '36px',
+            lineHeight: '36px',
+            fontSize: '16px',
+          }}
+          onClick={this.onSubmitClick}>提交</Button>}
+      </div>
+    )
+  }
+
+  requestFormData = () => {
+    Toast.loading('单据获取中', 0)
+    fetchPostObj(API.SETVICES_GETORDER, {
+      id: this.id,
+      caller: this.caller,
+    }).then(response => {
+      Toast.hide()
+      const billGroupList = analysisFormData(response.data)
+      refreshFormState({ billGroupList })
+    }).catch(error => {
+      Toast.hide()
+      if (typeof error === 'string') {
+        message.error(error)
+      } else {
+        message.error('单据获取异常')
+      }
+    })
+  }
+
+  /**
+   * 单据提交
+   */
+  onSubmitClick = () => {
+    const { billGroupList } = this.state
+    let formAndGrid = getFormAndGrid(billGroupList)
+    console.log(formAndGrid)
+  }
+}
+
+let mapStateToProps = (state) => ({
+  formState: state.formState,
+})
+
+export default connect(mapStateToProps)(ServiceAdd)

+ 33 - 20
uas-office-web/uas-mobile/src/pages/private/service/ServiceDetail.jsx

@@ -11,27 +11,35 @@ import CurrencyDetail
   from '../../../components/common/currencyDetail/CurrencyDetail'
 import { GlobalEvent } from '../../../utils/common/eventbus/eventbus'
 import { CURRENCY_DETAIL_DATA_REFRESH } from '../../../utils/common/eventbus/events.types'
+import { fetchPostObj } from '../../../utils/common/fetchRequest'
+import { API } from '../../../configs/api.config'
+import { message } from 'antd'
+import {
+  clearBillState,
+  refreshFormState,
+} from '../../../redux/actions/formState'
+import { BILL_STATE, FILTER_STATE } from '../../../redux/constants/actionTypes'
 
 class ServiceDetail extends Component {
 
   constructor () {
     super()
 
-    this.state = {
-      billGroupList: [],
-    }
+    this.state = {}
   }
 
   componentDidMount () {
-    document.title = ''
+    this.caller = this.props.match.params.caller
+    this.id = this.props.match.params.id
+    const title = this.props.match.params.title
+    document.title = title || '单据详情'
 
-    this.requestFormData()
-
-    GlobalEvent.on(CURRENCY_DETAIL_DATA_REFRESH, (billGroupModelList) => {
-      this.setState({
-        billGroupList: billGroupModelList,
-      })
+    clearBillState()
+    //将标识设置为BILL_STATE,保证数据不错乱
+    refreshFormState({
+      stateType: BILL_STATE,
     })
+    this.requestFormData()
   }
 
   componentWillUnmount () {
@@ -39,21 +47,26 @@ class ServiceDetail extends Component {
   }
 
   render () {
-    const { billGroupList } = this.state
-    return (
-      <div>
-        <CurrencyDetail formGroups={billGroupList}/>
-      </div>
-    )
+    return (<CurrencyDetail dataType={BILL_STATE}/>)
   }
 
   requestFormData = () => {
     Toast.loading('单据获取中', 0)
-    setTimeout(() => {
+    fetchPostObj(API.SETVICES_GETORDER, {
+      id: this.id,
+      caller: this.caller,
+    }).then(response => {
       Toast.hide()
-      const billGroupList = analysisFormData()
-      this.setState({ billGroupList })
-    }, 1000)
+      const billGroupList = analysisFormData(response.data, true)
+      refreshFormState({ billGroupList })
+    }).catch(error => {
+      Toast.hide()
+      if (typeof error === 'string') {
+        message.error(error)
+      } else {
+        message.error('单据获取异常')
+      }
+    })
   }
 }
 

+ 15 - 4
uas-office-web/uas-mobile/src/pages/private/service/ServiceList.jsx

@@ -14,6 +14,7 @@ import { API } from '../../../configs/api.config'
 import { message } from 'antd'
 import { visitApplyBill } from '../../../components/common/currencyList/visitApplyBill'
 import { LIST_PAGE_SIZE } from '../../../configs/constans.config'
+import { refreshFormState } from '../../../redux/actions/formState'
 
 class ServiceList extends Component {
 
@@ -41,6 +42,7 @@ class ServiceList extends Component {
           requestTab={this.requestTab.bind(this)}
           requestSearchConfig={this.requestSearchConfig.bind(this)}
           onItemClick={this.onItemClick.bind(this)}
+          onDocAdd={this.onDocAdd.bind(this)}
           addAble
         />
       </div>
@@ -123,16 +125,25 @@ class ServiceList extends Component {
    */
   requestSearchConfig = () => {
     const filterTest = new visitApplyBill()
-    saveListState({
-      filterList: filterTest,
+    refreshFormState({
+      filterGroupList: filterTest,
     })
   }
 
   /**
    * 列表点击事件
    */
-  onItemClick = () => {
-    this.props.history.push('/ServiceDetail')
+  onItemClick = (rowData) => {
+    this.props.history.push(
+      '/serviceDetail/' + rowData.id + '/' + this.caller + '/' + this.title)
+  }
+
+  /**
+   * 单据新增
+   */
+  onDocAdd = () => {
+    this.props.history.push(
+      '/serviceAdd/' + 0 + '/' + this.caller + '/' + this.title)
   }
 }
 

+ 5 - 0
uas-office-web/uas-mobile/src/pages/private/service/service.less

@@ -0,0 +1,5 @@
+.service-add-root {
+  .com-column-flex;
+  width: 100%;
+  height: 100vh;
+}

+ 50 - 0
uas-office-web/uas-mobile/src/redux/actions/formState.js

@@ -0,0 +1,50 @@
+/**
+ * Created by RaoMeng on 2020/12/2
+ * Desc: 单据详情数据处理
+ */
+import store from '../store/store'
+import {
+  REFRESH_FORM_STATE,
+  CLEAR_FORM_STATE, CLEAR_FILTER_STATE, CLEAR_BILL_STATE,
+} from '../constants/actionTypes'
+
+/**
+ * Created by RaoMeng on 2020/11/9
+ * Desc: 刷新单据详情
+ */
+export const refreshFormState = (data) => {
+  return store.dispatch({
+    type: REFRESH_FORM_STATE,
+    ...data,
+  })
+}
+
+/**
+ * 清除单据详情
+ * @returns {Function}
+ */
+export const clearFilterState = () => {
+  return store.dispatch({
+    type: CLEAR_FILTER_STATE,
+  })
+}
+
+/**
+ * 清除单据详情
+ * @returns {Function}
+ */
+export const clearBillState = () => {
+  return store.dispatch({
+    type: CLEAR_BILL_STATE,
+  })
+}
+
+/**
+ * 清除单据详情
+ * @returns {Function}
+ */
+export const clearFormState = () => {
+  return store.dispatch({
+    type: CLEAR_FORM_STATE,
+  })
+}

+ 0 - 1
uas-office-web/uas-mobile/src/redux/actions/mainState.js

@@ -7,7 +7,6 @@ import {
   CLEAR_MAIN_STATE,
   FRESH_MAIN_STATE,
 } from '../constants/actionTypes'
-import { GlobalEvent } from '../../utils/common/eventbus/eventbus'
 
 /**
  * Created by RaoMeng on 2020/11/9

+ 10 - 0
uas-office-web/uas-mobile/src/redux/constants/actionTypes.js

@@ -26,3 +26,13 @@ export const REFRESH_DOC_COUNT = 'REFRESH_DOC_COUNT'
 /**********************************报表********************************************/
 export const REFRESH_REPORT_LIST = 'REFRESH_REPORT_LIST'
 export const CLEAR_REPORT_STATE = 'CLEAR_REPORT_STATE'
+
+/*********************************通用表单******************************************/
+export const FILTER_STATE = 'FILTER_STATE'
+export const BILL_STATE = 'BILL_STATE'
+
+export const REFRESH_FORM_STATE = 'REFRESH_FORM_STATE'
+export const CLEAR_FORM_STATE = 'CLEAR_FORM_STATE'
+export const CLEAR_FILTER_STATE = 'CLEAR_FILTER_STATE'
+export const CLEAR_BILL_STATE = 'CLEAR_BILL_STATE'
+

+ 2 - 0
uas-office-web/uas-mobile/src/redux/reducers/index.js

@@ -6,6 +6,7 @@ import redDocState from './redDocState'
 import redMineState from './redMineState'
 import redListState from './redListState'
 import redUserState from './redUserState'
+import redFormState from './redFormState'
 
 /**
  * Created by RaoMeng on 2020/11/9
@@ -19,4 +20,5 @@ export const appReducer = combineReducers({
   mineState: redMineState,
   listState: redListState,
   userState: redUserState,
+  formState: redFormState,
 })

+ 50 - 0
uas-office-web/uas-mobile/src/redux/reducers/redFormState.js

@@ -0,0 +1,50 @@
+/**
+ * Created by RaoMeng on 2020/12/9
+ * Desc: 单据详情数据缓存
+ */
+import {
+  REFRESH_FORM_STATE,
+  CLEAR_FORM_STATE,
+  CLEAR_FILTER_STATE,
+  CLEAR_BILL_STATE,
+} from '../constants/actionTypes'
+
+const initFormState = {
+  billGroupList: [],
+  filterGroupList: [],
+  stateType: '',
+}
+
+const redFormState = (state = initFormState, action) => {
+  if (action === undefined) {
+    return state
+  }
+
+  switch (action.type) {
+    case REFRESH_FORM_STATE:
+      //更新单据数据
+      return {
+        ...state,
+        ...action,
+      }
+    case CLEAR_FILTER_STATE:
+      //清空高级筛选配置
+      return {
+        ...state,
+        filterGroupList: [],
+      }
+    case CLEAR_BILL_STATE:
+      //清空单据详情数据
+      return {
+        ...state,
+        billGroupList: [],
+      }
+    case CLEAR_FORM_STATE:
+      //清空单据数据
+      return initFormState
+    default:
+      return state
+  }
+}
+
+export default redFormState

+ 79 - 147
uas-office-web/uas-mobile/src/utils/common/form.request.js

@@ -2,164 +2,96 @@
  * Created by RaoMeng on 2020/12/11
  * Desc: 通用表单接口数据处理
  */
-import { Toast } from 'antd-mobile'
 import { isObjEmpty } from './common.util'
 import BillGroupModel from '../../model/common/BillGroupModel'
 import BillModel from '../../model/common/BillModel'
 
-const testForm = [
-  {
-    'groupTitle': '基础信息',
-    'isForm': true,
-    'keyField': 'base',
-    'groupCaller': 'test',
-    'fieldList': [
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '姓名',
-        'value': '饶猛',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '性别',
-        'value': '男',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '年龄',
-        'value': '25',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '籍贯',
-        'value': '江西',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '公司',
-        'value': '深圳市优软科技有限公司',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '学校',
-        'value': '南昌大学',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-      {
-        'appwidth': 100,
-        'length': 100,
-        'isdefault': true,
-        'caption': '高中',
-        'value': '金溪一中',
-        'display': '饶猛',
-        'type': 'S',
-        'readOnly': true,
-        'field': 'name',
-        'defValue': '',
-        'allowBlank': true,
-        'localDatas': [],
-      },
-    ],
-  },
-]
-
-export function analysisFormData () {
+export function analysisFormData (formData, isDetail) {
   let billGroupList = []
-  if (!isObjEmpty(testForm)) {
-    testForm.forEach((groupItem, groupIndex) => {
-      let billGroup = new BillGroupModel()
-      billGroup.group = groupItem.groupTitle
-      billGroup.isForm = groupItem.isForm
-      billGroup.keyField = groupItem.keyField
-      billGroup.billCaller = groupItem.groupCaller
-      billGroup.groupIndex = groupIndex
+  if (!isObjEmpty(formData)) {
+    const formList = formData.formList
+    const gridList = formData.gridList
 
-      let showBillFields = [], hideBillFields = []
-      if (!isObjEmpty(groupItem.fieldList)) {
-        groupItem.fieldList.forEach((fieldItem, filedIndex) => {
-          let billModel = new BillModel()
+    /**
+     * 主表数据
+     */
+    if (!isObjEmpty(formList)) {
+      formList.forEach((formGroup, formIndex) => {
+        const billGroup = getBillGroup(formGroup, billGroupList.length,
+          isDetail)
+        billGroup.isForm = true
+        billGroupList.push(billGroup)
+      })
+    }
 
-          billModel.groupIndex = groupIndex
-          billModel.appwidth = fieldItem.appwidth
-          billModel.length = fieldItem.length
-          billModel.isdefault = fieldItem.isdefault
-          billModel.caption = fieldItem.caption
-          billModel.type = fieldItem.type
-          billModel.readOnly = fieldItem.readOnly ? 'T' : 'F'
-          billModel.field = fieldItem.field
-          billModel.value = fieldItem.value
-          billModel.display = fieldItem.display
-          billModel.defValue = fieldItem.defValue
-          billModel.logicType = fieldItem.logicType
-          billModel.allowBlank = fieldItem.allowBlank ? 'T' : 'F'
+    /**
+     * 从表数据
+     */
+    if (!isObjEmpty(gridList)) {
+      gridList.forEach((gridGroup, gridIndex) => {
+        //单个从表的明细列表
+        const gridDetailList = gridGroup.fieldList
+        if (!isObjEmpty(gridDetailList)) {
+          gridDetailList.forEach((gridDetail, gridDetailIndex) => {
+            const billGroup = getBillGroup({
+              ...gridGroup,
+              fieldList: gridDetail,
+            }, billGroupList.length, isDetail)
+            if (!isDetail && gridDetailIndex === (gridDetailList.length - 1)) {
+              billGroup.lastInType = true
+            } else {
+              billGroup.lastInType = false
+            }
+            billGroup.isForm = false
+            billGroupList.push(billGroup)
+          })
+        }
+      })
+    }
+  }
 
-          if (billModel.isdefault) {
-            showBillFields.push(billModel)
-          } else {
-            hideBillFields.push(billModel)
-          }
-        })
-      }
+  return billGroupList
+}
 
-      billGroup.showBillFields = showBillFields
-      billGroup.hideBillFields = hideBillFields
+export function getBillGroup (groupItem, groupIndex, isDetail) {
+  let billGroup = new BillGroupModel()
+  billGroup.group = groupItem.groupTitle
+  billGroup.isForm = groupItem.isForm
+  billGroup.keyField = groupItem.keyField
+  billGroup.billCaller = groupItem.groupCaller
+  billGroup.groupIndex = groupIndex
 
-      billGroupList.push(billGroup)
+  let showBillFields = [], hideBillFields = []
+  if (!isObjEmpty(groupItem.fieldList)) {
+    groupItem.fieldList.forEach((fieldItem, filedIndex) => {
+      let billModel = new BillModel()
+
+      billModel.groupIndex = groupIndex
+      billModel.appwidth = fieldItem.appwidth
+      billModel.length = fieldItem.length
+      billModel.isdefault = fieldItem.isdefault
+      billModel.caption = fieldItem.caption
+      billModel.type = fieldItem.type//前端类型
+      billModel.sourcetype = fieldItem.sourcetype//字段原类型
+      billModel.readOnly = (fieldItem.readOnly || isDetail) ? 'T' : 'F'
+      billModel.field = fieldItem.field
+      billModel.value = fieldItem.value
+      billModel.display = fieldItem.display
+      billModel.defValue = fieldItem.defValue
+      billModel.logicType = fieldItem.logicType
+      billModel.allowBlank = (fieldItem.allowBlank || isDetail) ? 'T' : 'F'
+      billModel.localDatas = fieldItem.localDatas
+
+      if (billModel.isdefault) {
+        showBillFields.push(billModel)
+      } else {
+        hideBillFields.push(billModel)
+      }
     })
   }
 
-  return billGroupList
+  billGroup.showBillFields = showBillFields
+  billGroup.hideBillFields = hideBillFields
+
+  return billGroup
 }

+ 26 - 6
uas-office-web/uas-mobile/src/utils/common/form.util.js

@@ -14,9 +14,10 @@ import BillModel, {
 import FormTitle from '../../components/common/formNew/FormTitle'
 import BillGroupModel from '../../model/common/BillGroupModel'
 import { _baseURL } from '../../configs/api.config'
-import { GlobalEvent } from './eventbus/eventbus'
-import { CURRENCY_DETAIL_DATA_REFRESH } from './eventbus/events.types'
 import { Modal } from 'antd-mobile'
+import { refreshFormState } from '../../redux/actions/formState'
+import store from '../../redux/store/store'
+import { BILL_STATE, FILTER_STATE } from '../../redux/constants/actionTypes'
 
 /**
  * Created by RaoMeng on 2020/11/6
@@ -105,7 +106,8 @@ function onAddClick (billGroupModelList, groupIndex) {
   let newBillGroup = newGridBillGroup(groupIndex,
     billGroupModelList[groupIndex])
   billGroupModelList.push(newBillGroup)
-  GlobalEvent.emit(CURRENCY_DETAIL_DATA_REFRESH, billGroupModelList)
+  //刷新缓存数据
+  refreshFromData(billGroupModelList)
 }
 
 function newGridBillGroup (groupIndex, oldBillGroup) {
@@ -202,8 +204,11 @@ function addGroupTitle (
   }
   if (!isObjEmpty(titleBillModel.caption)) {
     formItems.push(
-      <FormTitle billModel={titleBillModel} groupIndex={g}
-                 onDeleteClick={onDeleteClick.bind(this, billGroupModelList)}
+      <FormTitle
+        billModel={titleBillModel}
+        groupIndex={g}
+        onDeleteClick={onDeleteClick.bind(this, billGroupModelList)}
+        key={'formTitle' + g}
       />,
     )
   }
@@ -250,7 +255,9 @@ function deleteGroup (billGroupModelList, groupIndex) {
   } else {
     billGroupModelList.splice(groupIndex, 1)
   }
-  GlobalEvent.emit(CURRENCY_DETAIL_DATA_REFRESH, billGroupModelList)
+
+  //刷新缓存数据
+  refreshFromData(billGroupModelList)
 }
 
 function onTextChange (
@@ -393,6 +400,19 @@ function analysisGrid (gridBillMap) {
   return gridStoreList
 }
 
+function refreshFromData (billGroupModelList) {
+  const stateType = store.getState().formState.stateType
+  if (stateType === FILTER_STATE) {
+    refreshFormState({
+      filterGroupList: billGroupModelList,
+    })
+  } else if (stateType === BILL_STATE) {
+    refreshFormState({
+      billGroupList: billGroupModelList,
+    })
+  }
+}
+
 function getValue (billModel) {
   return billModel.value || billModel.defValue || ''
 }