From 000ff61dd8a88eb875048e6a3deca8679d75df18 Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期六, 29 八月 2020 11:29:33 +0800 Subject: [PATCH] 2020-08-29 --- src/components/tabview/index.jsx | 14 src/menu/components/chart/antv-bar/chartcompile/index.jsx | 45 - src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx | 11 src/menu/components/chart/antv-bar/chartcompile/index.scss | 24 src/menu/menuform/index.jsx | 4 src/assets/mobimg/line.png | 0 src/tabviews/zshare/cardcomponent/index.scss | 12 src/menu/components/chart/antv-bar/index.scss | 4 src/menu/components/chart/antv-bar/index.jsx | 53 ++ src/menu/modelsource/option.jsx | 4 src/tabviews/custom/index.jsx | 630 +++++++++++++++++++++++++++++++++++ src/tabviews/custom/index.scss | 58 +++ src/menu/menushell/card.jsx | 2 src/components/sidemenu/index.jsx | 9 src/menu/datasourcecomponent/verifycard/settingform/index.jsx | 2 src/menu/header/index.jsx | 46 +- src/utils/option.js | 16 src/views/menudesign/index.jsx | 122 +++++- src/assets/mobimg/line1.png | 0 19 files changed, 928 insertions(+), 128 deletions(-) diff --git a/src/assets/mobimg/line.png b/src/assets/mobimg/line.png new file mode 100644 index 0000000..55a628e --- /dev/null +++ b/src/assets/mobimg/line.png Binary files differ diff --git a/src/assets/mobimg/line1.png b/src/assets/mobimg/line1.png new file mode 100644 index 0000000..b3a44b0 --- /dev/null +++ b/src/assets/mobimg/line1.png Binary files differ diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx index cb2c6a1..a463c20 100644 --- a/src/components/sidemenu/index.jsx +++ b/src/components/sidemenu/index.jsx @@ -130,7 +130,7 @@ try { _tmenu.PageParam = JSON.parse(child.PageParam) } catch (e) { - _tmenu.PageParam = {} + _tmenu.PageParam = {OpenType: 'newtab'} } _tmenu.type = _tmenu.PageParam.Template || _tmenu.type } else { @@ -142,6 +142,7 @@ _tmenu.MenuNo = child.MenuNo _tmenu.MenuName = child.MenuName _tmenu.text = child.MenuName + _tmenu.OpenType = _tmenu.PageParam ? _tmenu.PageParam.OpenType : 'newtab' return _tmenu }) } @@ -204,9 +205,11 @@ } let menu = JSON.parse(e.target.dataset.item) - if (menu.Ot === 'NewPage') { + + if (menu.OpenType === 'newpage') { + e.preventDefault() window.open(menu.src) - } else if (menu.Ot === 'blank') { + } else if (menu.OpenType === 'blank') { menu.selected = true this.props.modifyTabview([menu]) e.preventDefault() diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx index 7079a93..05c86cc 100644 --- a/src/components/tabview/index.jsx +++ b/src/components/tabview/index.jsx @@ -18,6 +18,7 @@ import './index.scss' const Home = asyncComponent(() => import('@/tabviews/home')) +const CustomPage = asyncComponent(() => import('@/tabviews/custom')) const CommonTable = asyncComponent(() => import('@/tabviews/commontable')) const CalendarPage = asyncComponent(() => import('@/tabviews/calendar')) const TreePage = asyncComponent(() => import('@/tabviews/treepage')) @@ -104,6 +105,8 @@ return (<Home MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) } else if (view.type === 'CommonTable' || view.type === 'ManageTable') { return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) + } else if (view.type === 'CustomPage') { + return (<CustomPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'TreePage') { return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'CalendarPage') { @@ -196,6 +199,15 @@ } } + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + render () { const { tabviews } = this.state let view = tabviews.filter(tab => tab.selected)[0] @@ -213,7 +225,7 @@ <Tabs.TabPane tab={ <span className="tab-control"> - {['CommonTable', 'FormTab', 'TreePage', 'CalendarPage'].includes(view.type) ? + {['CommonTable', 'FormTab', 'TreePage', 'CalendarPage', 'CustomPage'].includes(view.type) ? <Icon type="redo" onClick={(e) => {this.refreshTabview(e, view)}}/> : null } <span className="tab-name" onClick={(e) => {this.changeTab(e, view)}}> diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx index 677001d..66ed435 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx +++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx @@ -33,6 +33,9 @@ ] } + let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) + let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) + return [ { type: 'radio', @@ -52,7 +55,7 @@ label: 'X-杞�', initVal: card.Xaxis || '', required: true, - options: columns.filter(col => col.type === 'text') + options: xfields }, { type: 'select', @@ -62,7 +65,7 @@ multi: true, // 澶氶�� hidden: card.datatype === 'statistics', required: true, - options: columns.filter(col => col.type === 'number') + options: yfields }, { type: 'select', @@ -71,7 +74,7 @@ initVal: card.InfoType || '', hidden: card.datatype !== 'statistics', required: true, - options: columns.filter(col => col.type === 'text') + options: xfields }, { type: 'select', @@ -80,7 +83,7 @@ initVal: card.InfoValue || '', hidden: card.datatype !== 'statistics', required: true, - options: columns.filter(col => col.type === 'number') + options: yfields }, { type: 'select', diff --git a/src/menu/components/chart/antv-bar/chartcompile/index.jsx b/src/menu/components/chart/antv-bar/chartcompile/index.jsx index e40a2ed..315d9bd 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/index.jsx +++ b/src/menu/components/chart/antv-bar/chartcompile/index.jsx @@ -23,7 +23,6 @@ disabled: true, plot: null, formlist: null, - datatype: null, fieldName: null, colorOptions: fromJS(minkeColorSystem).toJS().map(option => { option.children = option.children.map(cell => { @@ -78,6 +77,7 @@ this.setState({ visible: true, view: 'normal', + disabled: config.plot.datatype === 'statistics', fieldName: fieldName, plot: fromJS(config.plot).toJS(), formlist: getBarOrLineChartOptionForm(config.plot, config.columns, config.setting) @@ -90,7 +90,7 @@ if (key === 'datatype') { this.setState({ - datatype: val, + disabled: val === 'statistics', formlist: formlist.map(item => { if (['Yaxis'].includes(item.key)) { item.hidden = val === 'statistics' @@ -336,6 +336,7 @@ } onSubmit = () => { + const { config } = this.props const { plot, view, datatype } = this.state if (view !== 'custom') { @@ -360,7 +361,7 @@ visible: false }) - this.props.plotchange(_plot) + this.props.plotchange({...config, plot: _plot}) } }) } else { @@ -400,12 +401,11 @@ } } - changeView = () => { + changeTab = (tab) => { const { config } = this.props - const { plot, view } = this.state - let _view = view === 'normal' ? 'custom' : 'normal' + const { plot } = this.state - if (_view === 'custom') { + if (tab === 'custom') { this.props.form.validateFieldsAndScroll((err, values) => { if (!err) { let _plot = {...plot, ...values} @@ -426,7 +426,7 @@ this.setState({ enabled: _plot.enabled || 'false', plot: _plot, - view: _view + view: tab }) } }) @@ -462,15 +462,12 @@ this.setState({ plot: _plot, - view: _view, + view: tab, formlist: getBarOrLineChartOptionForm(_plot, config.columns) }) } }) } - } - - changeTab = () => { } @@ -499,32 +496,22 @@ maskClosable={false} okText={dict['model.submit']} cancelText={dict['model.cancel']} - onOk={this.verifySubmit} + onOk={this.onSubmit} onCancel={() => { this.setState({ visible: false }) }} destroyOnClose > <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}> <TabPane tab="鍩虹璁剧疆" key="normal"> - <Form {...formItemLayout}> + {view === 'normal' ? <Form {...formItemLayout}> <Row gutter={16}>{this.getFields()}</Row> - </Form> + </Form> : null} </TabPane> - <TabPane tab="瀛楁闆�" disabled={disabled} key="custom"> - + <TabPane tab="鑷畾涔夎缃�" disabled={disabled} key="custom"> + {view === 'custom' ? <Form {...formItemLayout}> + <Row gutter={16}>{this.getCustomFields()}</Row> + </Form> : null} </TabPane> </Tabs> - {/* {view !== 'custom' ? <Form {...formItemLayout} className="base-setting"> - <Row gutter={16}>{this.getFields()}</Row> - {datatype === 'query' ? <Row gutter={16}> - <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>鑷畾涔夎缃�<Icon style={{marginLeft: 5}} type="right" /></Button> - </Row> : null} - </Form> : null} - {view === 'custom' ? <Form {...formItemLayout} id="chart-custom-drawer-form" className="mingke-table"> - <Row gutter={16} style={{minHeight: 'calc(100vh - 180px)'}}>{this.getCustomFields()}</Row> - <Row gutter={16}> - <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}><Icon style={{marginRight: 5}} type="left" />鍩烘湰璁剧疆</Button> - </Row> - </Form> : null} */} </Modal> </div> ); diff --git a/src/menu/components/chart/antv-bar/chartcompile/index.scss b/src/menu/components/chart/antv-bar/chartcompile/index.scss index 7338884..517b9a5 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/index.scss +++ b/src/menu/components/chart/antv-bar/chartcompile/index.scss @@ -10,16 +10,20 @@ } } .menu-chart-edit-modal { - .ant-modal-body { - padding-top: 10px; - .menu-chart-edit-box { - .anticon-question-circle { - color: #c49f47; - position: relative; - left: -3px; - } - .ant-input-number { - width: 100%; + .ant-modal { + top: 50px; + .ant-modal-body { + max-height: calc(100vh - 190px); + padding-top: 10px; + .menu-chart-edit-box { + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-input-number { + width: 100%; + } } } } diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx index 4d2f9fa..76cdec7 100644 --- a/src/menu/components/chart/antv-bar/index.jsx +++ b/src/menu/components/chart/antv-bar/index.jsx @@ -31,13 +31,14 @@ } UNSAFE_componentWillMount () { - const { card } = this.props + const { card, config } = this.props if (card.isNew) { let _plot = { chartType: card.type, // 鍥捐〃绫诲瀷 enabled: 'false', // 鏄惁浣跨敤鑷畾涔夎缃� datatype: 'query', // 鏁版嵁绫诲瀷鏌ヨ鎴栫粺璁� + customs: [] } if (card.subtype === 'bar') { @@ -46,13 +47,32 @@ } else if (card.subtype === 'bar1') { _plot.coordinate = 'angle' _plot.transpose = 'true' + } else if (card.subtype === 'line') { + _plot.shape = 'smooth' + } else if (card.subtype === 'line1') { + _plot.shape = 'hv' + } + + let name = '' + let names = { + bar: '鏌辩姸鍥�', + line: '鎶樼嚎鍥�', + } + let i = 1 + + while (!name) { + let _name = names[card.type] + i + if (config.components.filter(com => com.setting && com.setting.name === _name).length === 0) { + name = _name + } + i++ } let _card = { uuid: card.uuid, type: card.type, subtype: card.subtype, - setting: {span: 12, height: 400}, + setting: {span: 12, height: 400, name}, columns: [], scripts: [], search: [], @@ -76,9 +96,7 @@ UNSAFE_componentWillReceiveProps (nextProps) { if (!is(fromJS(this.props.plot), fromJS(nextProps.plot))) { - this.setState({}, () => { - this.viewrender() - }) + } } @@ -117,10 +135,11 @@ } linerender = () => { - const { plot, config } = this.props + const { card } = this.state + let plot = {...card.plot, height: card.setting.height - 70} let transfield = {} - config.columns.forEach(col => { + card.columns.forEach(col => { if (col.field) { transfield[col.field] = col.label } @@ -153,7 +172,7 @@ } const chart = new Chart({ - container: plot.uuid, + container: card.uuid, autoFit: true, height: plot.height || 400 }) @@ -509,8 +528,24 @@ } updateComponent = (component) => { + const card = fromJS(this.state.card).toJS() + let refresh = false + if (card.setting.span !== component.setting.span || card.setting.height !== component.setting.height || !is(fromJS(component.plot), fromJS(card.plot))) { + let _element = document.getElementById(card.uuid) + if (_element) { + _element.innerHTML = '' + } + refresh = true + } + this.setState({ card: component + }, () => { + if (refresh) { + setTimeout(() => { + this.viewrender() + }, 100) + } }) this.props.updateConfig(component) } @@ -520,7 +555,7 @@ const { config } = this.props return ( - <div className="line-chart-edit-box" style={{height: card.setting.height || 400}}> + <div className="menu-line-chart-edit-box" style={{height: card.setting.height || 400}}> <SettingComponent config={{...card, tables: config.tables}} MenuID={config.uuid} diff --git a/src/menu/components/chart/antv-bar/index.scss b/src/menu/components/chart/antv-bar/index.scss index c69327d..e96a3a6 100644 --- a/src/menu/components/chart/antv-bar/index.scss +++ b/src/menu/components/chart/antv-bar/index.scss @@ -1,6 +1,6 @@ -.line-chart-edit-box { +.menu-line-chart-edit-box { position: relative; - margin-bottom: 30px; + // margin-bottom: 0px; border: 1px solid #e8e8e8; .canvas { diff --git a/src/menu/datasourcecomponent/verifycard/settingform/index.jsx b/src/menu/datasourcecomponent/verifycard/settingform/index.jsx index 2cbec37..5458009 100644 --- a/src/menu/datasourcecomponent/verifycard/settingform/index.jsx +++ b/src/menu/datasourcecomponent/verifycard/settingform/index.jsx @@ -286,7 +286,7 @@ }> {getFieldDecorator('height', { initialValue: setting.height || 400 - })(<InputNumber min={100} max={1500} precision={0} />)} + })(<InputNumber min={150} max={1500} precision={0} />)} </Form.Item> </Col> {interType === 'inner' ? <Col span={8}> diff --git a/src/menu/header/index.jsx b/src/menu/header/index.jsx index 1e9ae6d..e8ab7dc 100644 --- a/src/menu/header/index.jsx +++ b/src/menu/header/index.jsx @@ -3,7 +3,7 @@ import { is, fromJS } from 'immutable' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' -import {Dropdown, Menu, Icon, Modal } from 'antd' +// import { Icon, Modal } from 'antd' import { logout } from '@/store/action' import zhCN from '@/locales/zh-CN/mob.js' @@ -11,7 +11,7 @@ import avatar from '@/assets/img/avatar.jpg' import './index.scss' -const { confirm } = Modal +// const { confirm } = Modal class MobHeader extends Component { static propTpyes = { @@ -27,22 +27,22 @@ userName: sessionStorage.getItem('CloudUserName') } - logout = () => { - // 閫�鍑虹櫥褰� - let _this = this - confirm({ - title: this.state.dict['mob.logout.hint'], - content: '', - okText: this.state.dict['mob.confirm'], - cancelText: this.state.dict['mob.cancel'], - onOk() { - sessionStorage.clear() - _this.props.logout() - _this.props.history.replace('/login') - }, - onCancel() {} - }) - } + // logout = () => { + // // 閫�鍑虹櫥褰� + // let _this = this + // confirm({ + // title: this.state.dict['mob.logout.hint'], + // content: '', + // okText: this.state.dict['mob.confirm'], + // cancelText: this.state.dict['mob.cancel'], + // onOk() { + // sessionStorage.clear() + // _this.props.logout() + // _this.props.history.replace('/login') + // }, + // onCancel() {} + // }) + // } shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) @@ -75,18 +75,18 @@ return ( <header className="menu-header-container"> <div className="header-logo"><img src={this.state.logourl} alt=""/></div> - <Dropdown className="header-setting" overlay={ + {/* <Dropdown className="header-setting" overlay={ <Menu> <Menu.Item key="2" onClick={this.logout}>{this.state.dict['mob.logout']}</Menu.Item> </Menu> - }> - <div> + }> */} + <div className="header-setting"> <img src={this.state.avatar} alt=""/> <span> - <span className="username">{this.state.userName}</span> <Icon type="down" /> + <span className="username">{this.state.userName}</span>{/* <Icon type="down" /> */} </span> </div> - </Dropdown> + {/* </Dropdown> */} </header> ) } diff --git a/src/menu/menuform/index.jsx b/src/menu/menuform/index.jsx index 16bbb7e..a08e50b 100644 --- a/src/menu/menuform/index.jsx +++ b/src/menu/menuform/index.jsx @@ -58,7 +58,7 @@ } }) - this.props.initMenuList(fromJS(menulist).toJS()) + this.props.initMenuList({fstMenuList: fromJS(menulist).toJS(), fstMenuId: result.FstIDSeleted}) this.setState({ fstMenuId: result.FstIDSeleted, @@ -105,8 +105,8 @@ }, () => { let _id = smenulist[0] ? smenulist[0].value : '' this.props.form.setFieldsValue({parentId: _id}) + this.props.updateConfig({...config, fstMenuId: value, parentId: _id}) }) - this.props.updateConfig({...config, fstMenuId: value}) } else if (key === 'parentId') { this.props.updateConfig({...config, parentId: value}) } diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx index ac08014..85eb1bb 100644 --- a/src/menu/menushell/card.jsx +++ b/src/menu/menushell/card.jsx @@ -38,7 +38,7 @@ } const getCardComponent = () => { - if (card.type === 'bar') { + if (card.type === 'bar' || card.type === 'line') { return (<AntvBar config={config} card={card} triggerEdit={editCard} editId={editId} updateConfig={updateConfig} />) } } diff --git a/src/menu/modelsource/option.jsx b/src/menu/modelsource/option.jsx index d5251e8..c796863 100644 --- a/src/menu/modelsource/option.jsx +++ b/src/menu/modelsource/option.jsx @@ -2,11 +2,15 @@ // import enUS from '@/locales/en-US/mob.js' import bar from '@/assets/mobimg/bar.png' import bar1 from '@/assets/mobimg/bar1.png' +import line from '@/assets/mobimg/line.png' +import line1 from '@/assets/mobimg/line1.png' // const _dict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ + { type: 'menu', url: line, component: 'line', subtype: 'line' }, + { type: 'menu', url: line1, component: 'line', subtype: 'line1' }, { type: 'menu', url: bar, component: 'bar', subtype: 'bar' }, { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1' }, ] diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx new file mode 100644 index 0000000..bf539b6 --- /dev/null +++ b/src/tabviews/custom/index.jsx @@ -0,0 +1,630 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' +import { is, fromJS } from 'immutable' +import { notification, Spin, Modal, Button, message, Tree, Typography } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import options from '@/store/options.js' +import zhCN from '@/locales/zh-CN/main.js' +import enUS from '@/locales/en-US/main.js' +import Utils from '@/utils/utils.js' +import asyncSpinComponent from '@/utils/asyncSpinComponent' +import { refreshTabView } from '@/store/action' + +import MainSearch from '@/tabviews/zshare/topSearch' +import NotFount from '@/components/404' +import './index.scss' + +// 閫氱敤缁勪欢 +const CalendarComponent = asyncSpinComponent(() => import('@/tabviews/zshare/calendar')) +const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable')) + +const { TreeNode } = Tree +const { Paragraph } = Typography + +class NormalTable extends Component { + static propTpyes = { + param: PropTypes.any, // 鍏朵粬椤甸潰浼犻�掔殑鍙傛暟 + MenuID: PropTypes.string, // 鑿滃崟Id + MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟 + MenuName: PropTypes.string // 鑿滃崟鍚嶇О + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id + BID: null, // 椤甸潰璺宠浆鏃舵惡甯D + loadingview: true, // 椤甸潰鍔犺浇涓� + viewlost: false, // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤 + lostmsg: '', // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅 + config: {}, // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑 + userConfig: null, // 鐢ㄦ埛鑷畾涔夎缃� + searchlist: null, // 鎼滅储鏉′欢 + arr_field: '', // 浣跨敤 sPC_Get_TableData 鏃剁殑鏌ヨ瀛楁闆� + setting: null, // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑 + data: null, // 鍒楄〃鏁版嵁闆� + loading: false, // 鍒楄〃鏁版嵁鍔犺浇涓� + search: '', // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞� + visible: false, // 鏍囩椤垫帶鍒� + triggerTime: '', // 鐐瑰嚮鏃堕棿 + treevisible: false, // 鑿滃崟缁撴瀯鏍戝脊妗嗘樉绀洪殣钘忔帶鍒� + calendarYear: moment().format('YYYY') // 鏃ュ巻骞翠唤 + } + + /** + * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅 + */ + async loadconfig () { + const { permAction, param } = this.props + + let _param = { + func: 'sPC_Get_LongParam', + MenuID: this.props.MenuID + } + let result = await Api.getCacheConfig(_param) + + if (result.status) { + let config = '' + let userConfig = null + let _curUserConfig = '' + + try { // 閰嶇疆淇℃伅瑙f瀽 + config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) + } catch (e) { + console.warn('Parse Failure') + config = '' + } + + // HS涓嶄娇鐢ㄨ嚜瀹氫箟璁剧疆 + if (result.LongParamUser && this.props.menuType !== 'HS') { + try { // 閰嶇疆淇℃伅瑙f瀽 + userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser))) + _curUserConfig = userConfig[this.props.MenuID] + } catch (e) { + console.warn('Parse Failure') + userConfig = null + } + } + + // 椤甸潰閰嶇疆瑙f瀽閿欒鏃舵彁绀� + if (!config) { + this.setState({ + loadingview: false, + viewlost: true + }) + return + } + + // 椤甸潰鏈惎鐢ㄦ椂锛屾樉绀烘湭鍚敤椤甸潰 + if (!config.enabled) { + this.setState({ + loadingview: false, + viewlost: true, + lostmsg: this.state.dict['main.view.unenabled'] + }) + return + } + + // 鏉冮檺杩囨护 + if (this.props.menuType !== 'HS') { + if (config.tab && !permAction[config.tab.linkTab]) { + config.tab = null + } + } + + if (_curUserConfig) { + config.setting = {...config.setting, ..._curUserConfig.setting} + config.easyCode = _curUserConfig.easyCode || config.easyCode || '' + } + + // 瀛楁鏉冮檺榛戝悕鍗曘�佸繀濉�佸瓧娈甸�忚 + let valid = true + config.search = config.search.map(item => { + item.oriInitval = item.initval + if (['text', 'select', 'link'].includes(item.type) && param) { + if (param.searchkey === item.field) { + item.initval = param.searchval + } else if (param.BID && item.field.toLowerCase() === 'bid') { + item.initval = param.BID + } else if (param.data && param.data[item.field]) { + item.initval = param.data[item.field] + } + } + + if (item.required === 'true' && !item.initval) { + valid = false + } + + if (!item.blacklist || item.blacklist.length === 0) return item + + let _black = item.blacklist.filter(v => { + return this.props.permRoles.indexOf(v) !== -1 + }) + + if (_black.length > 0) { + item.Hide = 'true' + } + + return item + }) + + this.setState({ + BID: param && param.BID ? param.BID : '', + loadingview: false, + config: config, + userConfig: userConfig, + setting: config.setting, + searchlist: config.search, + arr_field: config.columns.map(item => item.field).join(','), + search: Utils.initMainSearch(config.search) // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級 + }, () => { + if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇 + this.loadmaindata() + } + }) + } else { + this.setState({ + loadingview: false, + viewlost: true + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + } + + /** + * @description 涓昏〃鏁版嵁鍔犺浇 + */ + async loadmaindata () { + const { setting, search, BID } = this.state + let param = '' + let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0)) + + if (requireFields.length > 0) { + let labels = requireFields.map(item => item.label) + labels = Array.from(new Set(labels)) + + notification.warning({ + top: 92, + message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', + duration: 3 + }) + return + } + + this.setState({ + loading: true + }) + + if (setting.interType !== 'inner' || (setting.interType === 'inner' && setting.innerFunc)) { + param = this.getCustomParam() + } else { + param = this.getDefaultParam() + } + + if (BID) { + param.BID = BID + } + // 鏁版嵁绠$悊鏉冮檺 + if (this.props.dataManager) { + param.dataM = 'Y' + } + + let result = await Api.genericInterface(param) + if (result.status) { + this.setState({ + data: result.data.map((item, index) => { + item.key = index + return item + }), + loading: false + }) + } else { + this.setState({ + loading: false + }) + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + } + } + + /** + * @description 鑾峰彇鐢ㄦ埛鑷畾涔夊瓨鍌ㄨ繃绋嬩紶鍙� + */ + getCustomParam = () => { + const { search, setting, calendarYear, config } = this.state + + let _search = Utils.formatCustomMainSearch(search) + + let param = { + ..._search + } + + if (config.calendar.refresh === 'true') { + param.calendarDate = calendarYear + } + + if (setting.interType === 'inner') { + param.func = setting.innerFunc + } else { + if (this.props.menuType === 'HS') { + if (setting.sysInterface === 'true' && options.cloudServiceApi) { + param.rduri = options.cloudServiceApi + } else if (setting.sysInterface !== 'true') { + param.rduri = setting.interface + } + } else { + if (setting.sysInterface === 'true' && window.GLOB.mainSystemApi) { + param.rduri = window.GLOB.mainSystemApi + } else if (setting.sysInterface !== 'true') { + param.rduri = setting.interface + } + } + + if (setting.outerFunc) { + param.func = setting.outerFunc + } + } + + return param + } + + /** + * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� + */ + getDefaultParam = () => { + const { arr_field, search, setting, config, calendarYear } = this.state + + let _search = Utils.joinMainSearchkey(search) + + _search = _search ? 'where ' + _search : '' + + let param = { + func: 'sPC_Get_TableData', + obj_name: 'data', + arr_field: arr_field, + custom_script: setting.customScript || '', + default_sql: setting.default || 'true' + } + + let _dataresource = setting.dataresource + + if (/\s/.test(_dataresource)) { + _dataresource = '(' + _dataresource + ') tb' + } + + if (this.props.dataManager) { // 鏁版嵁鏉冮檺 + _dataresource = _dataresource.replace(/\$@/ig, '/*') + _dataresource = _dataresource.replace(/@\$/ig, '*/') + param.custom_script = param.custom_script.replace(/\$@/ig, '/*') + param.custom_script = param.custom_script.replace(/@\$/ig, '*/') + } else { + _dataresource = _dataresource.replace(/@\$|\$@/ig, '') + param.custom_script = param.custom_script.replace(/@\$|\$@/ig, '') + } + + let regoptions = null + if (setting.queryType === 'statistics' || param.custom_script) { + let allSearch = Utils.getAllSearchOptions(search) + + regoptions = allSearch.map(item => { + return { + reg: new RegExp('@' + item.key + '@', 'ig'), + value: `'${item.value}'` + } + }) + } + + if (config.calendar.refresh === 'true' && regoptions) { + regoptions.push({ + reg: new RegExp('@calendarDate@', 'ig'), + value: `${calendarYear}-01-01 00:00:00.000` + }) + regoptions.push({ + reg: new RegExp('@calendarDate1@', 'ig'), + value: `${calendarYear}-12-31 23:59:59.999` + }) + } + + if (setting.queryType === 'statistics' && setting.default !== 'false') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲 + regoptions.forEach(item => { + _dataresource = _dataresource.replace(item.reg, item.value) + }) + _search = '' + } + + let LText = '' + + if (setting.default !== 'false') { + LText = `select ${arr_field} from ${_dataresource} ${_search}` + } + + if (param.custom_script) { + regoptions.forEach(item => { + param.custom_script = param.custom_script.replace(item.reg, item.value) + }) + + if (LText) { + LText += ` + aaa: + if @ErrorCode!='' + insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ + ` + } else { + param.custom_script += ` + aaa: + if @ErrorCode!='' + insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ + ` + } + } + + // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 + if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { + param.custom_script && console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`) + LText && console.log(LText) + } + + param.custom_script = Utils.formatOptions(param.custom_script) + param.LText = Utils.formatOptions(LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + param.DateCount = '' + + if (this.props.menuType === 'HS') { // 浜戠鏁版嵁楠岃瘉 + param.open_key = Utils.encrypt(param.secretkey, param.timestamp, true) + } + + return param + } + + /** + * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁 + * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃� + */ + refreshbysearch = (searches) => { + const { setting } = this.state + + if (setting.onload === 'false') { + this.setState({ + search: searches, + setting: {...setting, onload: 'true'} + }, () => { + this.loadmaindata() + }) + } else { + this.setState({ + search: searches + }, () => { + this.loadmaindata() + }) + } + } + + + /** + * @description 椤甸潰鍒锋柊锛岄噸鏂拌幏鍙栭厤缃� + */ + reloadview = () => { + this.setState({ loadingview: true, viewlost: false, lostmsg: '', data: null, loading: false, search: '' + }, () => { + this.loadconfig() + }) + } + + handleviewconfig = (e) => { + e.stopPropagation() + + const { MenuNo } = this.props + const { config } = this.state + + if (config && config.funcs && config.funcs.length > 0) { + this.setState({ + treevisible: true + }) + } else { + let oInput = document.createElement('input') + oInput.value = MenuNo || '' + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + document.body.removeChild(oInput) + message.success(this.state.dict['main.copy.success']) + } + } + + getTreeNode = (data) => { + let _type = { + view: '椤甸潰', + btn: '鎸夐挳', + tab: '鏍囩' + } + + return data.map(item => { + let _title = _type[item.subtype] + let _others = [] + + _others.push( + (item.menuNo ? item.menuNo + '(鑿滃崟鍙傛暟)' : ''), + (item.tableName ? item.tableName + '(琛ㄥ悕) ' : ''), + (item.innerFunc ? item.innerFunc + '(鍐呴儴鍑芥暟) ' : ''), + (item.outerFunc ? item.outerFunc + '(澶栭儴鍑芥暟)' : '') + ) + _others = _others.filter(Boolean) + _others = _others.join('銆�') + + if (item.label) { + _title = _title + '(' + item.label + ')' + } + if (_others) { + _title = _title + ': ' + _others + } + + if (item.subfuncs && item.subfuncs.length > 0) { + return ( + <TreeNode title={_title} key={item.uuid} dataRef={item} selectable={false}> + {this.getTreeNode(item.subfuncs)} + </TreeNode> + ) + } + return <TreeNode key={item.uuid} title={_title} isLeaf selectable={false} /> + }) + } + + UNSAFE_componentWillMount () { + // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁 + this.loadconfig() + } + + UNSAFE_componentWillReceiveProps(nextProps) { + if (nextProps.refreshTab && nextProps.refreshTab.MenuID === this.props.MenuID) { + if (nextProps.refreshTab.position === 'grid') { + this.loadmaindata() + } else if (nextProps.refreshTab.position === 'view') { + this.reloadview() + } + this.props.refreshTabView('') + } else if (nextProps.param && !is(fromJS(this.props.param), fromJS(nextProps.param))) { + let search = this.state.search.map(item => { + if (item.type === 'text' && item.key === nextProps.param.searchkey) { + item.value = nextProps.param.searchval + } + return item + }) + this.refreshbysearch(search) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + changeDate = (value) => { + this.setState({calendarYear: value}, () => { + this.loadmaindata() + }) + } + + triggerDate = (item) => { + const { config } = this.state + + if (!config.tab) return + + this.setState({ + visible: true, + triggerTime: item.time.substr(0, 4) + '-' + item.time.substr(4, 2) + '-' + item.time.substr(6, 2) + }) + } + + closeTab = () => { + this.setState({ + visible: false, + triggerTime: '' + }) + } + + render() { + const { BID, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state + + return ( + <div className="calendar-page" id={this.state.ContainerId}> + {loadingview && <Spin size="large" />} + {searchlist && searchlist.length > 0 ? + <MainSearch + BID={BID} + dict={this.state.dict} + searchlist={searchlist} + menuType={this.props.menuType} + dataManager={this.props.dataManager} + refreshdata={this.refreshbysearch} + /> : null + } + {config && config.calendar ? <CalendarComponent calendar={config.calendar} loading={loading} data={data} triggerDate={this.triggerDate} changeDate={this.changeDate}/> : null} + {options.sysType !== 'cloud' ? <Button + icon="copy" + shape="circle" + className="common-table-copy" + onClick={this.handleviewconfig} + /> : null} + <Modal + className="menu-tree-modal" + title={'鑿滃崟缁撴瀯鏍�'} + width={'650px'} + maskClosable={false} + visible={this.state.treevisible} + onCancel={() => this.setState({treevisible: false})} + footer={[ + <Button key="close" onClick={() => this.setState({treevisible: false})}>{this.state.dict['main.close']}</Button> + ]} + destroyOnClose + > + <div className="menu-header"> + <span>鑿滃崟鍚嶇О锛歿this.props.MenuName}</span> + <span>鑿滃崟鍙傛暟锛歿<Paragraph copyable>{this.props.MenuNo}</Paragraph>}</span> + </div> + {this.state.treevisible ? <Tree defaultExpandAll showLine={true}> + {this.getTreeNode(config.funcs)} + </Tree> : null} + </Modal> + <Modal + title={config.tab ? config.tab.label : ''} + width={'80vw'} + maskClosable={false} + visible={this.state.visible} + onCancel={this.closeTab} + footer={[ + <Button key="close" onClick={this.closeTab}>{this.state.dict['main.close']}</Button> + ]} + destroyOnClose + > + {config.tab ? <SubTabTable + type="calendar" + BID={triggerTime} + Tab={config.tab} + SupMenuID={this.props.MenuID} + MenuID={config.tab.linkTab} + refreshSupView={() => this.loadmaindata()} + closeModalView={this.closeTab} + /> : null} + </Modal> + {viewlost ? <NotFount msg={this.state.lostmsg} /> : null} + </div> + ) + } +} + +const mapStateToProps = (state) => { + return { + menuType: state.editLevel, + tabviews: state.tabviews, + refreshTab: state.refreshTab, + permAction: state.permAction, + permRoles: state.permRoles, + dataManager: state.dataManager + } +} + +const mapDispatchToProps = (dispatch) => { + return { + refreshTabView: (refreshTab) => dispatch(refreshTabView(refreshTab)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(NormalTable) \ No newline at end of file diff --git a/src/tabviews/custom/index.scss b/src/tabviews/custom/index.scss new file mode 100644 index 0000000..b35d19b --- /dev/null +++ b/src/tabviews/custom/index.scss @@ -0,0 +1,58 @@ +.calendar-page { + position: relative; + min-height: calc(100vh - 94px); + padding-top: 16px; + padding-bottom: 80px; + .box404 { + padding-top: 30px; + } + + .ant-modal-mask { + position: absolute; + } + .ant-modal-wrap { + position: absolute; + } + .action-modal .ant-modal { + top: 40px; + max-width: 95%; + .ant-modal-body { + max-height: calc(100vh - 265px); + } + } + > .ant-spin { + position: absolute; + z-index: 10; + left: calc(50% - 22px); + top: calc(50vh - 70px); + } + + .common-table-copy { + position: fixed; + z-index: 2; + bottom: 65px; + right: 30px; + width: 40px; + height: 40px; + } +} + +.menu-tree-modal { + .ant-modal-body { + min-height: 300px; + .menu-header { + text-align: center; + span { + font-weight: 600; + margin-right: 20px; + } + .ant-typography { + font-weight: 600; + display: inline-block; + } + } + .ant-tree li .ant-tree-node-content-wrapper { + cursor: default; + } + } +} diff --git a/src/tabviews/zshare/cardcomponent/index.scss b/src/tabviews/zshare/cardcomponent/index.scss index 0ae1b0b..e0e90ae 100644 --- a/src/tabviews/zshare/cardcomponent/index.scss +++ b/src/tabviews/zshare/cardcomponent/index.scss @@ -23,16 +23,6 @@ color: #40a9ff; } - .chart-card-box:hover { - .ant-card.chart-card { - .ant-card-head { - .ant-card-extra { - opacity: 1; - } - } - } - } - .chart-card-box:not(.ant-col) { display: inline-block; margin-bottom: 20px; @@ -130,8 +120,6 @@ } .ant-card-extra { padding: 0px; - opacity: 0; - transition: opacity 0.3s; } } .ant-card-actions { diff --git a/src/utils/option.js b/src/utils/option.js index f4e0ec0..7804842 100644 --- a/src/utils/option.js +++ b/src/utils/option.js @@ -4,7 +4,7 @@ import mainsubtable from '@/assets/img/mainsubtable.jpg' import treepage from '@/assets/img/treepage.jpg' import calendar from '@/assets/img/calendar.jpg' -// import customImg from '@/assets/img/custom.jpg' +import customImg from '@/assets/img/custom.jpg' import rolemanage from '@/assets/img/rolemanage.jpg' const _dict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS @@ -78,13 +78,13 @@ baseconfig: '', isSystem: true }, - // { - // title: '鑷畾涔�', - // type: 'CustomPage', - // url: customImg, - // baseconfig: '', - // isSystem: true - // }, + { + title: '鑷畾涔�', + type: 'CustomPage', + url: customImg, + baseconfig: '', + isSystem: true + }, { title: '瑙掕壊鏉冮檺鍒嗛厤', type: 'RolePermission', diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx index b7569eb..f7c06e1 100644 --- a/src/views/menudesign/index.jsx +++ b/src/views/menudesign/index.jsx @@ -26,14 +26,16 @@ // const DataSource = asyncComponent(() => import('@/mob/datasource')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) +sessionStorage.setItem('isEditState', 'true') + class Mobile extends Component { state = { dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, MenuId: this.props.match.params.MenuId, tableFields: [], activeKey: 'basedata', + menuloading: false, oriConfig: null, - parentId: '', openEdition: '', config: null, editElem: null @@ -79,7 +81,20 @@ } submitConfig = () => { - const { config, openEdition, parentId } = this.state + const { config, openEdition } = this.state + + if (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId) { + notification.warning({ + top: 92, + message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒', + duration: 5 + }) + return + } + + if (config.enabled && this.verifyConfig()) { + config.enabled = false + } let _config = fromJS(config).toJS() delete _config.fstMenuList @@ -87,28 +102,36 @@ delete _config.sysRoles delete _config.tableFields + let funcs = [] + _config.components.forEach(component => { + if (component.setting && component.setting.innerFunc) { + funcs.push(`select '${_config.uuid}' as MenuID,'${component.setting.innerFunc}' as ProcName,'${component.setting.name}' as MenuName`) + } + if (component.action) { + component.action.forEach(item => { + if (!item.innerFunc) return + funcs.push(`select '${_config.uuid}' as MenuID,'${item.innerFunc}' as ProcName,'${item.label}' as MenuName`) + }) + } + }) + let param = { func: 'sPC_TrdMenu_AddUpt', - ParentID: parentId, - MenuID: config.uuid, - MenuNo: config.MenuNo, - EasyCode: '', - Template: '', - MenuName: '', - PageParam: '', + FstID: _config.fstMenuId, + SndID: _config.parentId, + ParentID: _config.parentId, + MenuID: _config.uuid, + MenuNo: _config.MenuNo, + EasyCode: _config.easyCode, + Template: 'CustomPage', + MenuName: _config.MenuName, + PageParam: JSON.stringify({Template: 'CustomPage', OpenType: 'newtab'}), LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))), - // LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`), - // LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`), - TypeCharOne: 'mob' + LText: funcs.join(' union all '), + LTexttb: '', // 琛ㄥ悕 } - let _LText = '' - // _LText = _LText.join(' union all ') - let _LTexttb = '' - // _LTexttb = _LTexttb.join(' union all ') - - param.LText = Utils.formatOptions(_LText) - param.LTexttb = Utils.formatOptions(_LTexttb) + param.LText = Utils.formatOptions(param.LText) param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' param.secretkey = Utils.encrypt(param.LText, param.timestamp) @@ -116,13 +139,27 @@ param.open_edition = openEdition } + this.setState({ + menuloading: true + }) + Api.getSystemConfig(param).then(response => { if (response.status) { this.setState({ oriConfig: fromJS(config).toJS(), - openEdition: response.open_edition || '' + openEdition: response.open_edition || '', + menuloading: false + }) + notification.success({ + top: 92, + message: '淇濆瓨鎴愬姛', + duration: 2 }) } else { + this.setState({ + openEdition: response.open_edition || '', + menuloading: false + }) notification.warning({ top: 92, message: response.message, @@ -154,6 +191,7 @@ version: 1.0, uuid: this.props.match.params.MenuId, MenuID: this.props.match.params.MenuId, + parentId: this.props.match.params.ParentId, Template: 'CustomPage', easyCode: '', enabled: false, @@ -162,7 +200,11 @@ tables: [], components: [] } + } else { + config.uuid = this.props.match.params.MenuId + config.MenuID = this.props.match.params.MenuId } + this.setState({ oriConfig: config, config: fromJS(config).toJS(), @@ -212,9 +254,9 @@ }) } - initMenuList = (list) => { + initMenuList = (msg) => { this.setState({ - config: {...this.state.config, fstMenuList: list} + config: {...this.state.config, ...msg} }) } @@ -247,9 +289,43 @@ onEnabledChange = () => { const { config } = this.state + if (!config.enabled && this.verifyConfig(true)) { + return + } + this.setState({ config: {...config, enabled: !config.enabled} }) + } + + verifyConfig = (show) => { + const { config } = this.state + let error = '' + + if (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId) { + notification.warning({ + top: 92, + message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒', + duration: 5 + }) + return 'false' + } + + config.components.forEach(item => { + if (!error && (!item.setting || !item.setting.dataresource)) { + error = `缁勪欢銆�${item.setting.name}銆嬫湭璁剧疆鏁版嵁婧恅 + } + }) + + if (show && error) { + notification.warning({ + top: 92, + message: error, + duration: 5 + }) + } + + return error } // 鏇存柊閰嶇疆淇℃伅 @@ -322,7 +398,7 @@ <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{dict['mob.save']}</Button> </div> } style={{ width: '100%' }}> - {config ? <MenuShell config={config} handleList={this.updateConfig} deleteCard={this.deleteCard} /> : null} + {config && config.components ? <MenuShell config={config} handleList={this.updateConfig} deleteCard={this.deleteCard} /> : null} </Card> </div> </div> -- Gitblit v1.8.0