From 8f78c97ffcde201e2a4d1ffa7ccb97a13f0f045d Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期四, 18 四月 2024 15:34:15 +0800 Subject: [PATCH] 2024-04-18 --- src/menu/datasource/verifycard/utils.jsx | 4 src/menu/components/timeline/normal-timeline/index.scss | 2 src/menu/components/carousel/prop-card/index.scss | 2 src/tabviews/custom/components/tree/antd-tree/index.jsx | 6 src/menu/components/card/prop-card/index.scss | 2 src/menu/components/card/cardcellcomponent/elementform/index.jsx | 14 src/tabviews/custom/components/module/invoice/invoiceTable/index.scss | 127 +++ src/menu/components/card/balcony/index.scss | 2 src/menu/components/card/data-card/index.scss | 2 src/tabviews/custom/components/module/invoice/index.jsx | 377 +++++++++ src/menu/menushell/card.jsx | 3 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx | 35 src/menu/datasource/verifycard/index.jsx | 31 src/menu/modulesource/option.jsx | 2 src/tabviews/custom/components/module/invoice/subTable/index.scss | 0 src/menu/components/module/invoice/options.jsx | 81 ++ src/menu/components/module/invoice/index.jsx | 419 ++++++++++ src/menu/datasource/verifycard/settingform/index.jsx | 12 src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx | 394 ++++++++++ src/tabviews/custom/components/module/invoice/index.scss | 260 ++++++ src/tabviews/custom/components/module/invoice/subTable/index.jsx | 245 ++++++ src/tabviews/custom/index.jsx | 7 src/menu/debug/index.jsx | 2 src/menu/components/carousel/data-card/index.scss | 2 src/menu/components/module/invoice/index.scss | 258 ++++++ src/assets/img/invoice.png | 0 src/menu/components/card/double-data-card/index.scss | 2 27 files changed, 2,243 insertions(+), 48 deletions(-) diff --git a/src/assets/img/invoice.png b/src/assets/img/invoice.png new file mode 100644 index 0000000..3a5185d --- /dev/null +++ b/src/assets/img/invoice.png Binary files differ diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss index 418b226..efe4ce6 100644 --- a/src/menu/components/card/balcony/index.scss +++ b/src/menu/components/card/balcony/index.scss @@ -32,7 +32,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-color: #ffffff; background-position: center center; diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.jsx b/src/menu/components/card/cardcellcomponent/elementform/index.jsx index ae23509..efc66b8 100644 --- a/src/menu/components/card/cardcellcomponent/elementform/index.jsx +++ b/src/menu/components/card/cardcellcomponent/elementform/index.jsx @@ -118,12 +118,14 @@ } else if (item.key === 'formula') { item.fields = [] - config.columns.forEach(col => { - item.fields.push(col.field) - }) - - if (config.subColumns) { - config.subColumns.forEach(col => { + if (side === 'sub') { + if (config.subColumns) { + config.subColumns.forEach(col => { + item.fields.push(col.field) + }) + } + } else { + config.columns.forEach(col => { item.fields.push(col.field) }) } diff --git a/src/menu/components/card/data-card/index.scss b/src/menu/components/card/data-card/index.scss index 8c298e3..43ac9dc 100644 --- a/src/menu/components/card/data-card/index.scss +++ b/src/menu/components/card/data-card/index.scss @@ -20,7 +20,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-color: #ffffff; background-position: center center; diff --git a/src/menu/components/card/double-data-card/index.scss b/src/menu/components/card/double-data-card/index.scss index 40ea29c..722a29f 100644 --- a/src/menu/components/card/double-data-card/index.scss +++ b/src/menu/components/card/double-data-card/index.scss @@ -20,7 +20,7 @@ } .card-item, .card-item-wrap { - overflow: hidden; + // overflow: hidden; position: relative; background-color: #ffffff; background-position: center center; diff --git a/src/menu/components/card/prop-card/index.scss b/src/menu/components/card/prop-card/index.scss index 5e0c1e5..21c1ad6 100644 --- a/src/menu/components/card/prop-card/index.scss +++ b/src/menu/components/card/prop-card/index.scss @@ -19,7 +19,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-color: #ffffff; background-position: center center; diff --git a/src/menu/components/carousel/data-card/index.scss b/src/menu/components/carousel/data-card/index.scss index 7d9fda3..7bbacd7 100644 --- a/src/menu/components/carousel/data-card/index.scss +++ b/src/menu/components/carousel/data-card/index.scss @@ -19,7 +19,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-position: center center; background-repeat: no-repeat; diff --git a/src/menu/components/carousel/prop-card/index.scss b/src/menu/components/carousel/prop-card/index.scss index 07e359f..6c50965 100644 --- a/src/menu/components/carousel/prop-card/index.scss +++ b/src/menu/components/carousel/prop-card/index.scss @@ -19,7 +19,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-position: center center; background-repeat: no-repeat; diff --git a/src/menu/components/module/invoice/index.jsx b/src/menu/components/module/invoice/index.jsx new file mode 100644 index 0000000..0885bec --- /dev/null +++ b/src/menu/components/module/invoice/index.jsx @@ -0,0 +1,419 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Popover, Button } from 'antd' +import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons' +import moment from 'moment' + +import Utils from '@/utils/utils.js' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { getTables, checkComponent } from '@/utils/utils-custom.js' +import MKEmitter from '@/utils/events.js' +import getWrapForm from './options' + +import './index.scss' + +const NormalForm = asyncIconComponent(() => import('@/components/normalform')) +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) + +class Invoice extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + card: null, + date: moment().format('YYYY骞碝M鏈�') + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + format: 'object', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + width: card.width || 24, + name: '鍙戠エ', + subtype: card.subtype, + wrap: { name: '鍙戠エ', width: card.width || 24, datatype: 'static' }, + style: { paddingLeft: '20px', paddingRight: '20px', paddingTop: '10px', paddingBottom: '10px' }, + setting: { interType: 'system' }, + columns: [], + scripts: [], + buyer: { + pageable: true, + format: 'array', + subtype: 'invTable', + setting: { interType: 'system' }, + columns: [], + scripts: [], + search: [ + {field: 'from_to_name', label: '浼佷笟鍚嶇О', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()}, + {field: 'from_to_tax_no', label: '浼佷笟绋庡彿', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()}, + ], + }, + detail: { + pageable: true, + format: 'array', + subtype: 'invTable', + setting: { interType: 'system' }, + columns: [], + scripts: [], + search: [ + {field: 'productname', label: '鍟嗗搧鍚嶇О', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()}, + {field: 'productcode', label: '鍟嗗搧缂栫爜', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()}, + ], + } + } + + let buys = [ + ['浼佷笟鍚嶇О', 'from_to_name'], + ['浼佷笟绋庡彿', 'from_to_tax_no'], + ['鍦板潃', 'from_to_addr', 'Nvarchar(100)'], + ['鐢佃瘽', 'from_to_tel'], + ['寮�鎴疯', 'from_to_bank_name'], + ['閾惰璐﹀彿', 'from_to_account_no'], + ['鎵嬫満鍙�', 'from_to_mob'], + ['閭', 'from_to_email'], + ['浼佷笟缂栫爜', 'from_to_code'] + ] + + buys.forEach((cell, index) => { + _card.buyer.columns.push({$index: index + 1, datatype: 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()}) + }) + + let details = [ + ['id', 'id'], + ['鍟嗗搧缂栫爜', 'productcode'], + ['鍟嗗搧鍚嶇О', 'productname'], + ['瑙勬牸鍨嬪彿', 'spec'], + ['鎻忚堪', 'Description'], + ['璁¢噺鍗曚綅', 'unit'], + ['鍗曚环', 'unitprice', 'Decimal(18,10)'], + ['绋庡姟鍒嗙被缂栫爜', 'tax_classify_code'], + ['绋庡姟鍒嗙被鍚嶇О', 'tax_classify_name'], + ['绋庣巼', 'tax_rate'], + ] + + details.forEach((cell, index) => { + _card.detail.columns.push({$index: index + 1, datatype: cell[2] || 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()}) + }) + + let cols = [ + ['鍙戠エ绉嶇被', 'invoice_type'], + ['璐拱鏂瑰悕绉�', 'from_to_name'], + ['璐拱鏂圭◣鍙�', 'from_to_tax_no'], + ['璐拱鏂瑰湴鍧�', 'from_to_addr', 'Nvarchar(100)'], + ['璐拱鏂圭數璇�', 'from_to_tel'], + ['璐拱鏂瑰紑鎴疯', 'from_to_bank_name'], + ['璐拱鏂归摱琛岃处鍙�', 'from_to_account_no'], + ['璐拱鏂规墜鏈哄彿', 'from_to_mob'], + ['璐拱鏂归偖绠�', 'from_to_email'], + ['璐拱鏂圭紪鐮�', 'from_to_code'], + ['閿�鍞柟鍚嶇О', 'orgname'], + ['閿�鍞柟绋庡彿', 'tax_no'], + ['閿�鍞柟鍦板潃', 'addr', 'Nvarchar(100)'], + ['閿�鍞柟鐢佃瘽', 'tel'], + ['閿�鍞柟寮�鎴疯', 'bank_name'], + ['閿�鍞柟閾惰璐﹀彿', 'account_no'], + ['澶囨敞', 'remark', 'Nvarchar(512)'], + ['鏀舵浜�', 'payee'], + ['澶嶆牳浜�', 'reviewer'], + ['寮�绁ㄤ汉', 'drawer'], + ['鍟嗗搧缂栫爜', 'productcode'], + ['鍟嗗搧鍚嶇О', 'productname'], + ['瑙勬牸鍨嬪彿', 'spec'], + ['璁¢噺鍗曚綅', 'unit'], + ['鏁伴噺', 'bill_count', 'Decimal(18,10)'], + ['鍗曚环', 'unitprice', 'Decimal(18,10)'], + ['閲戦', 'amount_line', 'Decimal(18,2)'], + ['绋庡姟鍒嗙被缂栫爜', 'tax_classify_code'], + ['绋庡姟鍒嗙被鍚嶇О', 'tax_classify_name'], + ['绋庣巼', 'tax_rate', 'Decimal(18,2)'], + ['绋庨', 'tax_amount', 'Decimal(18,2)'], + ] + + cols.forEach((cell, index) => { + _card.columns.push({$index: index + 1, datatype: cell[2] || 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()}) + }) + + this.updateComponent(_card) + } else { + let _card = fromJS(card).toJS() + + // _card.buyer.format = 'array' + // _card.detail.format = 'array' + + this.setState({ + card: _card + }) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (card) => { + card.width = card.wrap.width + card.name = card.wrap.name + + if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌� + this.setState({ + card: card + }) + + this.props.updateConfig(card) + return + } + + card.$c_ds = card.wrap.datatype === 'dynamic' + card.errors = checkComponent(card) + + if (card.errors.length === 0) { + if (card.buyer.setting.interType === 'system' && card.buyer.setting.execute !== 'false' && !card.buyer.setting.dataresource) { + card.errors.push({ level: 0, detail: '-璐拱鏂� 鏈缃暟鎹簮锛�'}) + } else if (card.buyer.setting.interType === 'system' && card.buyer.setting.execute === 'false' && card.buyer.scripts.filter(script => script.status !== 'false').length === 0) { + card.errors.push({ level: 0, detail: '-璐拱鏂� 鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'}) + } + } + if (card.errors.length === 0) { + if (card.detail.setting.interType === 'system' && card.detail.setting.execute !== 'false' && !card.detail.setting.dataresource) { + card.errors.push({ level: 0, detail: '-鏄庣粏 鏈缃暟鎹簮锛�'}) + } else if (card.detail.setting.interType === 'system' && card.detail.setting.execute === 'false' && card.detail.scripts.filter(script => script.status !== 'false').length === 0) { + card.errors.push({ level: 0, detail: '-鏄庣粏 鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'}) + } + } + + if (card.errors.length === 0) { + card.$tables = getTables(card) + card.$tables = [...card.$tables, ...getTables(card.buyer)] + card.$tables = [...card.$tables, ...getTables(card.detail)] + } + + this.setState({ + card: card + }) + + this.props.updateConfig(card) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle) + } + + getStyle = (style) => { + let _card = {...this.state.card, style} + + this.updateComponent(_card) + } + + getWrapForms = () => { + const { card } = this.state + + return getWrapForm(card.wrap) + } + + updateWrap = (res) => { + this.updateComponent({...this.state.card, wrap: res}) + } + + render() { + const { card, date } = this.state + + let style = {...card.style} + if (card.wrap.invColor) { + style['--inv-color'] = card.wrap.invColor + } + + return ( + <div className="menu-invoice-box" style={style} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <NormalForm title="鍩烘湰璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}> + <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/> + </NormalForm> + <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/> + <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} /> + {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>} + </div> + } trigger="hover"> + <ToolOutlined /> + </Popover> + <div className="inv-action"> + <Button className="mk-bill">淇濆瓨鍗曟嵁</Button> + <Button className="mk-submit">鎻愪氦寮�绁�</Button> + </div> + <div className="inv-header"> + <div className="mk-select">璇烽�夋嫨鍙戠エ绉嶇被</div> + <div className="date">寮�绁ㄦ棩鏈燂細{date}</div> + </div> + <div className="inv-body"> + <div className="inv-main-content"> + <div className="inv-buyer"> + <div className="inv-label">璐拱鏂�</div> + <div className="inv-content"> + <div className="mk-input"> + <label>鍚嶇О锛�</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟鍚嶇О</span> + <span className="extra"> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <SettingComponent config={card.buyer} updateConfig={(res) => this.updateComponent({...card, buyer: res})} /> + </div> + } trigger="hover"> + <EllipsisOutlined /> + </Popover> + </span> + </div> + <div className="mk-input"> + <label>绾崇◣浜鸿瘑鍒彿锛�</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟绾崇◣浜鸿瘑鍒彿</span> + </div> + <div className="mk-input"> + <label>鍦板潃銆佺數璇濓細</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟鍦板潃</span> + <span className="content">璇疯緭鍏ヨ喘涔版柟鐢佃瘽</span> + </div> + <div className="mk-input"> + <label>寮�鎴疯鍙婅处鍙凤細</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟寮�鎴疯</span> + <span className="content">璇疯緭鍏ヨ喘涔版柟璐﹀彿</span> + </div> + </div> + </div> + <div className="inv-notice"> + <div className="inv-label">閫氱煡鍒�</div> + <div className="inv-content"> + <div className="mk-input"> + <label>鎵嬫満鍙凤細</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟鎵嬫満鍙�</span> + </div> + <div className="mk-input"> + <label>閭锛�</label> + <span className="content">璇疯緭鍏ヨ喘涔版柟閭</span> + </div> + </div> + </div> + </div> + <div className="inv-details"> + <div className="detail-wrap"> + <div className="mk-th"> + <div className="mk-td">璐х墿鎴栧簲绋庡姵鍔°�佹湇鍔″悕绉�</div> + <div className="mk-td">瑙勬牸鍨嬪彿</div> + <div className="mk-td">鍗曚綅</div> + <div className="mk-td">鏁伴噺</div> + <div className="mk-td">鍗曚环锛堝惈绋庯級</div> + <div className="mk-td">閲戦锛堝惈绋庯級</div> + <div className="mk-td">绋庣巼</div> + <div className="mk-td">绋庨</div> + </div> + <div className="mk-tr"> + <div className="mk-td mk-left"> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <SettingComponent config={card.detail} updateConfig={(res) => this.updateComponent({...card, detail: res})} /> + </div> + } trigger="hover"> + <EllipsisOutlined /> + </Popover> + </div> + <div className="mk-td mk-left"></div> + <div className="mk-td mk-left"></div> + <div className="mk-td mk-right"></div> + <div className="mk-td mk-right"></div> + <div className="mk-td mk-right"></div> + <div className="mk-td mk-right"></div> + <div className="mk-td mk-right"></div> + </div> + <div className="mk-total"> + <div className="mk-td">鍚堣</div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td">锟�12</div> + <div className="mk-td"></div> + <div className="mk-td">锟�1</div> + </div> + <div className="mk-upcase"> + <div className="mk-td">浠风◣鍚堣锛堝ぇ鍐欙級</div> + <div className="mk-td"></div> + <div className="mk-td">锛堝皬鍐欙級锟�12</div> + </div> + </div> + </div> + <div className="inv-main-content"> + <div className="inv-buyer"> + <div className="inv-label">閿�鍞柟</div> + <div className="inv-content"> + <div className="mk-input"> + <label>鍚嶇О锛�</label> + <span className="content">璇疯緭鍏ラ攢鍞柟鍚嶇О</span> + </div> + <div className="mk-input"> + <label>绾崇◣浜鸿瘑鍒彿锛�</label> + <span className="content">璇疯緭鍏ラ攢鍞柟绾崇◣浜鸿瘑鍒彿</span> + </div> + <div className="mk-input"> + <label>鍦板潃銆佺數璇濓細</label> + <span className="content">璇疯緭鍏ラ攢鍞柟鍦板潃</span> + <span className="content">璇疯緭鍏ラ攢鍞柟鐢佃瘽</span> + </div> + <div className="mk-input"> + <label>寮�鎴疯鍙婅处鍙凤細</label> + <span className="content">璇疯緭鍏ラ攢鍞柟寮�鎴疯</span> + <span className="content">璇疯緭鍏ラ攢鍞柟璐﹀彿</span> + </div> + </div> + </div> + <div className="inv-notice"> + <div className="inv-label">澶囨敞</div> + <div className="inv-content" style={{paddingTop: '30px'}}> + <div className="mk-input"> + <span className="content" style={{height: '80px'}}>璇疯緭鍏ュ娉�</span> + </div> + </div> + </div> + </div> + </div> + <div className="inv-tail"> + <div className="mk-input"> + <label>鏀舵浜猴細</label> + <span className="content">鏀舵浜�</span> + </div> + <div className="mk-input"> + <label>澶嶆牳浜猴細</label> + <span className="content">澶嶆牳浜�</span> + </div> + <div className="mk-input"> + <label>寮�绁ㄤ汉锛�</label> + <span className="content">寮�绁ㄤ汉</span> + </div> + </div> + </div> + ) + } +} + +export default Invoice \ No newline at end of file diff --git a/src/menu/components/module/invoice/index.scss b/src/menu/components/module/invoice/index.scss new file mode 100644 index 0000000..13e4eb7 --- /dev/null +++ b/src/menu/components/module/invoice/index.scss @@ -0,0 +1,258 @@ +.menu-invoice-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + color: #000000; + --inv-color: #13509c; + + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .inv-action { + text-align: right; + margin-right: 30px; + .ant-btn { + margin-left: 15px; + margin-bottom: 5px; + height: 30px; + } + .mk-bill:hover, .mk-bill:active, .mk-bill:focus { + color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + } + .mk-submit, .mk-submit:hover, .mk-submit:active, .mk-submit:focus { + color: #fff; + background-color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + } + } + .inv-header { + text-align: center; + position: relative; + height: 70px; + margin-right: 30px; + .mk-select { + position: relative; + display: inline-block; + width: 390px; + font-size: 25px; + text-align: center; + font-family: kaiti; + color: var(--inv-color, #13509c); + } + .mk-select::before, .mk-select::after { + content: ''; + display: block; + width: 100%; + position: absolute; + border-top: var(--inv-color, #13509c) 1px solid; + border-bottom: var(--inv-color, #13509c) 1px solid; + height: 1px; + } + .mk-select::before { + bottom: -10px; + } + .mk-select::after { + bottom: -15px; + } + .date { + position: absolute; + right: 100px; + top: 5px; + color: var(--inv-color, #13509c); + } + } + + .mk-input { + position: relative; + height: 28px; + font-size: 13px; + background: transparent; + display: flex; + padding: 0 5px 0 15px; + margin-bottom: 5px; + label { + display: inline-block; + height: 28px; + line-height: 28px; + text-align: right; + color: var(--inv-color, #13509c); + } + span { + display: inline-block; + height: 28px; + line-height: 28px; + } + .extra { + position: absolute; + right: 0px; + .anticon-ellipsis { + padding: 0 15px; + } + } + .content { + flex: 1; + border-bottom: 1px solid #d9d9d9; + color: #b8b8b8; + transition: all 0.3s; + padding: 0px 10px; + } + } + .mk-input:hover .content { + border-color: var(--inv-color, #13509c); + } + + .inv-body { + border: var(--inv-color, #13509c) 1px solid; + font-size: 13px; + margin-right: 30px; + + .inv-main-content { + display: flex; + + .inv-buyer, .inv-notice { + width: 50%; + display: flex; + .inv-label { + color: var(--inv-color, #13509c); + width: 6.25%; + display: flex; + flex-direction: column; + writing-mode: vertical-rl; + justify-content: center; + align-items: center; + letter-spacing: 5px; + border-right: var(--inv-color, #13509c) 1px solid; + } + .inv-content { + flex: 1; + padding: 8px 0; + } + } + .inv-buyer { + border-right: var(--inv-color, #13509c) 1px solid; + label { + width: 95px; + min-width: 95px; + } + } + .inv-notice { + .inv-content { + padding-top: 45px; + } + label { + width: 75px; + min-width: 75px; + } + } + } + + .inv-details { + border-top: var(--inv-color, #13509c) 1px solid; + border-bottom: var(--inv-color, #13509c) 1px solid; + } + } + .inv-tail { + display: flex; + padding-top: 10px; + margin-right: 30px; + .mk-input { + display: flex; + flex: 1; + label { + width: 40%; + color: rgba(0, 0, 0, 0.85); + } + span { + width: 40%; + flex: none; + } + } + } + + .detail-wrap { + position: relative; + + .mk-th, .mk-tr, .mk-total { + position: relative; + display: flex; + border-bottom: var(--inv-color, #13509c) 1px solid; + + .mk-td { + width: 10%; + height: 40px; + display: flex; + justify-content: center; + align-items: center; + padding: 0 3px; + position: relative; + } + .mk-td:not(:last-child) { + border-right: var(--inv-color, #13509c) 1px solid; + } + .mk-td:first-child { + width: 20%; + } + .mk-td:nth-child(2), .mk-td:nth-child(6) { + width: 15%; + } + + .mk-left { + justify-content: start; + } + .mk-right { + justify-content: end; + } + .anticon-ellipsis { + padding: 0 10px; + position: absolute; + right: 0; + } + } + .mk-tr.active, .mk-tr:hover { + background: var(--mk-sys-color1); + } + .mk-upcase { + display: flex; + + .mk-td { + width: 40%; + height: 40px; + display: flex; + align-items: center; + padding: 0 20px; + } + .mk-td:first-child { + width: 20%; + padding: 0; + border-right: var(--inv-color, #13509c) 1px solid; + justify-content: center; + } + .mk-td:last-child { + justify-content: end; + } + } + } +} +.menu-invoice-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-invoice-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} + + diff --git a/src/menu/components/module/invoice/options.jsx b/src/menu/components/module/invoice/options.jsx new file mode 100644 index 0000000..29284b3 --- /dev/null +++ b/src/menu/components/module/invoice/options.jsx @@ -0,0 +1,81 @@ +/** + * @description Wrap琛ㄥ崟閰嶇疆淇℃伅 + */ +export default function (wrap) { + let menu = window.GLOB.customMenu + let books = [] + let bookids = [] + menu.components.forEach(item => { + if (item.subtype === 'account') { + books.push({ + value: item.uuid, + label: item.name + }) + bookids.push(item.uuid) + } + }) + + const wrapForm = [ + { + type: 'radio', + field: 'datatype', + label: '绫诲瀷', + initval: wrap.datatype || 'static', + required: true, + options: [ + {value: 'static', label: '鏂板鍙戠エ'}, + {value: 'dynamic', label: '鏌ョ湅鍗曟嵁'}, + ] + }, + { + type: 'text', + field: 'name', + label: '缁勪欢鍚嶇О', + initval: wrap.name || '', + tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�', + required: true + }, + { + type: 'number', + field: 'width', + label: '瀹藉害', + initval: wrap.width || 24, + tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', + min: 1, + max: 24, + precision: 0, + required: true + }, + { + type: 'select', + field: 'supBook', + label: '璐﹀', + initval: wrap.supBook || '', + required: true, + options: books, + allowClear: true + }, + { + type: 'radio', + field: 'business_type', + label: '鍙戠エ绫诲瀷', + initval: wrap.business_type || 'sell', + required: true, + options: [ + {value: 'sell', label: '閿�椤瑰彂绁�'}, + {value: 'buy', label: '杩涢」鍙戠エ'}, + ] + }, + { + type: 'color', + field: 'invColor', + label: '鏍峰紡', + initval: wrap.invColor || '', + tooltip: '鍙戠エ缁勪欢涓竟妗嗕互鍙婃枃瀛楃殑棰滆壊銆�', + allowClear: true, + required: false + }, + ] + + return wrapForm +} \ No newline at end of file diff --git a/src/menu/components/timeline/normal-timeline/index.scss b/src/menu/components/timeline/normal-timeline/index.scss index 2f88860..51b98ae 100644 --- a/src/menu/components/timeline/normal-timeline/index.scss +++ b/src/menu/components/timeline/normal-timeline/index.scss @@ -23,7 +23,7 @@ } .card-item { - overflow: hidden; + // overflow: hidden; position: relative; background-color: #ffffff; background-position: center center; diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx index a8300a1..d083aa3 100644 --- a/src/menu/datasource/verifycard/index.jsx +++ b/src/menu/datasource/verifycard/index.jsx @@ -678,7 +678,8 @@ if (config.subtype === 'dualdatacard') { _columns = [...columns, ...subColumns] } - let r = SettingUtils.getDebugSql(setting, _scripts, _columns, searches, config.type) + + let r = SettingUtils.getDebugSql(setting, _scripts, _columns, searches, config.subtype) let _debugId = md5(r.sql) @@ -958,7 +959,8 @@ } copyColumns = () => { - const { columns } = this.state + const { columns, setting } = this.state + let m = [] let n = [] let s = [] @@ -982,8 +984,27 @@ } let oInput = document.createElement('input') - oInput.value = `/*${m.join(',')}*/ - ${n.join(',')}` + oInput.value = `create table #${setting.tableName || 'tb'} + (${m.join(',')},sort_id INT IDENTITY(1,1)) + insert into #${setting.tableName || 'tb'} + (${n.join(',')}) + select ${n.join(',')} + from ${setting.dataresource ? `(${setting.dataresource}) tb` : setting.tableName || 'tb'} + order by @orderBy@ + + declare @mk_total int + set @mk_total = 0 + + select @mk_total = count(1) from #${setting.tableName || 'tb'} + declare @pageIndex_top int + set @pageIndex_top=(@pageIndex@-1)*@pageSize@ + + if @mk_total > @pageIndex@*@pageSize@ + delete #${setting.tableName || 'tb'} where sort_id > @pageIndex@*@pageSize@ + + if @pageIndex_top > 0 + delete #${setting.tableName || 'tb'} where sort_id <= @pageIndex_top` + document.body.appendChild(oInput) oInput.select() document.execCommand('Copy') @@ -1134,7 +1155,7 @@ wrappedComponentRef={(inst) => this.settingForm = inst} /> : null} </TabPane> - {config.subtype !== 'basetable' ? <TabPane tab={ + {!['basetable', 'invoice', 'invTable'].includes(config.subtype) ? <TabPane tab={ <span> 瀛楁闆� {columns.length ? <span className="count-tip">{columns.length}</span> : null} diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx index 8433cc5..560e5d9 100644 --- a/src/menu/datasource/verifycard/settingform/index.jsx +++ b/src/menu/datasource/verifycard/settingform/index.jsx @@ -375,7 +375,7 @@ </Form.Item> </Col> : null} {setting.interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}> - {window.GLOB.process ? <span className="process-btn" onClick={this.addProcess}>宸ヤ綔娴�</span> : null} + {window.GLOB.process && !['invoice', 'invTable'].includes(config.subtype) ? <span className="process-btn" onClick={this.addProcess}>宸ヤ綔娴�</span> : null} <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={ <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''銆俙}> <QuestionCircleOutlined className="mk-form-tip" /> @@ -409,7 +409,7 @@ </Radio.Group>)} </Form.Item> </Col> : null} - <Col span={8}> + {!['invTable'].includes(config.subtype) ? <Col span={8}> <Form.Item label="涓婚敭"> {getFieldDecorator('primaryKey', { initialValue: setting.primaryKey || '' @@ -423,7 +423,7 @@ </Select> )} </Form.Item> - </Col> + </Col> : null} {/* 鏁扮粍鏁版嵁锛岄渶璁剧疆鎺掑簭瑙勫垯 */} {config.format === 'array' ? <Col span={8}> <Form.Item label={ @@ -454,7 +454,7 @@ </Radio.Group>)} </Form.Item> </Col> : null} - {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') && MenuType !== 'billPrint' ? <Col span={8}> + {!['balcony', 'menubar', 'commonbar', 'tabbar', 'invTable'].includes(config.subtype) && (!config.wrap || config.wrap.supType !== 'multi') && MenuType !== 'billPrint' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}> <QuestionCircleOutlined className="mk-form-tip" /> @@ -516,7 +516,7 @@ </Form.Item> </Col> : null} {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */} - {!['navbar', 'interface', 'calendar'].includes(config.type) && !['editable', 'basetable', 'dualdatacard'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}> + {!['navbar', 'interface', 'calendar'].includes(config.type) && !['editable', 'basetable', 'dualdatacard', 'invoice', 'invTable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細濡傝彍鍗曟湭浣跨敤鍚庣缂撳瓨锛屽垯鏌ヨ璇彞澶т簬8000瀛楃鏃舵棤鏁堛��'}> <QuestionCircleOutlined className="mk-form-tip" /> @@ -533,7 +533,7 @@ )} </Form.Item> </Col> : null} - {!['navbar', 'balcony', 'menubar'].includes(config.type) && !['basetable'].includes(config.subtype) ? <Col span={8}> + {!['navbar', 'balcony', 'menubar'].includes(config.type) && !['basetable', 'invoice', 'invTable'].includes(config.subtype) ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={config.type === 'interface' ? '鍗曠嫭鎼滅储缁勪欢鍙綔涓哄叕鍏辨暟鎹簮鐨勬悳绱㈡潯浠躲��' : '浼樺厛浣跨敤鍚岀骇鐨勬悳绱㈡潯浠剁粍浠讹紝鍚岀骇鎼滅储涓嶅瓨鍦ㄦ椂锛屼緷娆″悜涓婇�夊彇锛屼笌褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵竴鍚岀敤浣滄暟鎹繃婊わ紙褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵紭鍏堬級銆�'}> <QuestionCircleOutlined className="mk-form-tip" /> diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx index b443500..291ef35 100644 --- a/src/menu/datasource/verifycard/utils.jsx +++ b/src/menu/datasource/verifycard/utils.jsx @@ -75,7 +75,7 @@ {reg: /@sum\$|\$sum@/ig, value: ''}, ] - if (window.GLOB.process) { + if (window.GLOB.process && type !== 'invoice') { regs.push({reg: /@works_flow_code@/ig, value: `'${getuuid()}'`}) } @@ -101,7 +101,7 @@ ` } - if (window.GLOB.urlFields) { + if (window.GLOB.urlFields && type !== 'invoice') { window.GLOB.urlFields.forEach(field => { let reg = new RegExp('@' + field + '@', 'ig') _dataresource = _dataresource.replace(reg, `'0'`) diff --git a/src/menu/debug/index.jsx b/src/menu/debug/index.jsx index 62a02cb..7d77de4 100644 --- a/src/menu/debug/index.jsx +++ b/src/menu/debug/index.jsx @@ -1521,7 +1521,7 @@ ` } - sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) ) + sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50)) Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512) Select @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}' diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx index b56942a..47269bf 100644 --- a/src/menu/menushell/card.jsx +++ b/src/menu/menushell/card.jsx @@ -30,6 +30,7 @@ const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline')) const Voucher = asyncComponent(() => import('@/menu/components/module/voucher')) const Account = asyncComponent(() => import('@/menu/components/module/account')) +const Invoice = asyncComponent(() => import('@/menu/components/module/invoice')) const Iframe = asyncComponent(() => import('@/menu/components/iframe')) const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6')) const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6')) @@ -135,6 +136,8 @@ return (<Voucher card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'module' && card.subtype === 'account') { return (<Account card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'module' && card.subtype === 'invoice') { + return (<Invoice card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx index 1607a5a..9013a15 100644 --- a/src/menu/modulesource/option.jsx +++ b/src/menu/modulesource/option.jsx @@ -32,6 +32,7 @@ import Voucher from '@/assets/mobimg/voucher.png' import Account from '@/assets/mobimg/account.png' import canlendar from '@/assets/mobimg/canlendar.png' +import Invoice from '@/assets/img/invoice.png' // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ @@ -72,4 +73,5 @@ { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: Account, component: 'module', subtype: 'account', title: '璐﹀', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: Voucher, component: 'module', subtype: 'voucher', title: '鍑瘉', width: 24, forbid: ['billPrint'] }, + { type: 'menu', url: Invoice, component: 'module', subtype: 'invoice', title: '鍙戠エ', width: 24, forbid: ['billPrint'] }, ] diff --git a/src/tabviews/custom/components/module/invoice/index.jsx b/src/tabviews/custom/components/module/invoice/index.jsx new file mode 100644 index 0000000..6307d89 --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/index.jsx @@ -0,0 +1,377 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Select, Form, Input, Button, Modal } from 'antd' +import { EllipsisOutlined } from '@ant-design/icons' +import moment from 'moment' + +// import Api from '@/api' +// import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import InvoiceTable from './invoiceTable' +import SubTable from './subTable' +import './index.scss' + +class InvoiceModule extends Component { + static propTpyes = { + config: PropTypes.object + } + + state = { + BID: '', + invTypes: [ + {value: '1', label: '鐢靛瓙鍙戠エ锛堝鍊肩◣涓撶敤鍙戠エ锛�'}, + {value: '2', label: '鐢靛瓙鍙戠エ锛堟櫘閫氬彂绁級'}, + {value: '3', label: '澧炲�肩◣绾歌川涓撶敤鍙戠エ'}, + {value: '4', label: '澧炲�肩◣绾歌川鏅�氬彂绁�'}, + {value: '5', label: '澧炲�肩◣鐢靛瓙鏅�氬彂绁�'}, + {value: '6', label: '澧炲�肩◣鐢靛瓙涓撶敤鍙戠エ'}, + ], + invoice_type: '', + date: moment().format('YYYY骞碝M鏈圖D鏃�'), + from_to_name: '', + from_to_tax_no: '', + from_to_addr: '', + from_to_tel: '', + from_to_bank_name: '', + from_to_account_no: '', + from_to_mob: '', + from_to_email: '', + from_to_code: '', + orgname: '', + tax_no: '', + addr: '', + tel: '', + bank_name: '', + account_no: '', + remark: '', + payee: '', + reviewer: '', + drawer: '', + details: [] + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + let _config = fromJS(config).toJS() + let BID = '' + let BData = '' + + if (_config.setting.supModule) { + BData = window.GLOB.CacheData.get(_config.setting.supModule) + } else { + BData = window.GLOB.CacheData.get(_config.$pageId) + } + if (BData) { + BID = BData.$BID || '' + } + + if (_config.wrap.invColor) { + _config.style['--inv-color'] = _config.wrap.invColor + } + + _config.buyer = this.formatSetting(_config.buyer, 'buyer') + _config.detail = this.formatSetting(_config.detail, 'detail') + + this.setState({ + BID: BID || '', + config: _config + }) + } + + componentDidMount () { + this.loadData() + MKEmitter.addListener('reloadData', this.reloadData) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('reloadData', this.reloadData) + } + + formatSetting = (item, type) => { + item.setting.arr_field = item.columns.map(col => col.field).join(',') + item.setting.laypage = item.setting.laypage === 'true' + + if (type === 'buyer') { + item.columns = item.columns.map(cell => { + if (['from_to_tel', 'from_to_account_no', 'from_to_code'].includes(cell.field)) { + cell.Hide = 'true' + } else if (['from_to_email', 'from_to_mob'].includes(cell.field)) { + cell.Width = 80 + } + return cell + }) + } else { + item.columns = item.columns.map(cell => { + if (['Description', 'id'].includes(cell.field)) { + cell.Hide = 'true' + } else if (['spec'].includes(cell.field)) { + cell.Width = 150 + } else if (['unit', 'unitprice', 'tax_rate'].includes(cell.field)) { + cell.Width = 80 + } + return cell + }) + } + + if (item.setting.interType !== 'system') { + item.setting.dataresource = '' + return item + } + + let regs = [ + { reg: /@userName@/ig, value: `'${sessionStorage.getItem('User_Name') || ''}'` }, + { reg: /@fullName@/ig, value: `'${sessionStorage.getItem('Full_Name') || ''}'` } + ] + + if (window.GLOB.externalDatabase !== null) { + regs.push({ + reg: /@db@/ig, + value: window.GLOB.externalDatabase + }) + } + + let _customScript = '' + let _tailScript = '' + item.scripts && item.scripts.forEach(script => { + if (script.status === 'false') return + if (script.position !== 'back') { + _customScript += ` + ${script.sql} + ` + } else { + _tailScript += ` + ${script.sql} + ` + } + }) + delete item.scripts + + item.setting.execute = item.setting.execute !== 'false' + + if (!item.setting.execute) { + item.setting.dataresource = '' + } + if (/\s/.test(item.setting.dataresource)) { + item.setting.dataresource = '(' + item.setting.dataresource + ') tb' + } + + if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 + item.setting.dataresource = item.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'') + _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'') + _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'') + } else { + item.setting.dataresource = item.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'') + _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'') + _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'') + } + + regs.forEach(cell => { + item.setting.dataresource = item.setting.dataresource.replace(cell.reg, cell.value) + _customScript = _customScript.replace(cell.reg, cell.value) + _tailScript = _tailScript.replace(cell.reg, cell.value) + }) + + item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰 + item.setting.tailScript = _tailScript // 鍚庣疆鑷畾涔夎剼鏈� + + item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript) + + return item + } + + reloadData = (menuId) => { + // const { config } = this.props + // const { activeItem } = this.state + + // if (config.uuid !== menuId) return + + // if (activeItem) { + // MKEmitter.emit('resetSelectLine', config.uuid, activeItem.id, activeItem) + // } else { + // this.loadData() + // } + } + + loadData = () => { + // let param = { + // func: 's_get_fcc_book_data', + // dataM: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '', + // mk_organization: sessionStorage.getItem('organization') || '' + // } + + // Api.genericInterface(param).then(res => { + // if (!res.status) { + // notification.warning({ + // top: 92, + // message: res.message, + // duration: 5 + // }) + // return + // } + + // let books = res.book || [] + // let activeItem = null + // let map = new Map() + // books = books.filter(item => { + // if (!item.id) return false + // if (map.has(item.id)) return false + // map.set(item.id, true) + + // if (item.selected === 'true' && !activeItem) { + // activeItem = item + // } + // if (item.months) { + // item.date = item.months.replace('-', '骞�') + '鏈�' + // } + // return true + // }) + + // this.setState({books, activeItem}) + + // if (activeItem) { + // MKEmitter.emit('resetSelectLine', this.props.config.uuid, activeItem.id, activeItem) + // } + // }) + } + + changeType = (val) => { + this.setState({invoice_type: val}) + } + + changeBuyer = (item) => { + this.setState({ + visible: false, + from_to_name: item.from_to_name || '', + from_to_tax_no: item.from_to_tax_no || '', + from_to_addr: item.from_to_addr || '', + from_to_tel: item.from_to_tel || '', + from_to_bank_name: item.from_to_bank_name || '', + from_to_account_no: item.from_to_account_no || '', + from_to_mob: item.from_to_mob || '', + from_to_email: item.from_to_email || '', + from_to_code: item.from_to_code || '', + }) + } + + render() { + const { config, invTypes, date, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee, details, visible } = this.state + + return ( + <div className="menu-invoice-wrap" style={config.style}> + <div className="inv-action"> + <Button className="mk-bill">淇濆瓨鍗曟嵁</Button> + <Button className="mk-submit">鎻愪氦寮�绁�</Button> + </div> + <div className="inv-header"> + <Select placeholder="璇烽�夋嫨鍙戠エ绉嶇被" onChange={this.changeType} dropdownClassName="inv-type-select"> + {invTypes.map(item => ( + <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option> + ))} + </Select> + <div className="date">寮�绁ㄦ棩鏈燂細{date}</div> + </div> + <div className="inv-body"> + <div className="inv-main-content"> + <div className="inv-buyer"> + <div className="inv-label">璐拱鏂�</div> + <div className="inv-content"> + <Form.Item label={<>鍚�<span></span>绉�</>} extra={<EllipsisOutlined onClick={() => this.setState({visible: true})}/>}> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟鍚嶇О" allowClear value={from_to_name} autoComplete="off" onChange={(e) => this.setState({from_to_name: e.target.value})}/> + </Form.Item> + <Form.Item label="绾崇◣浜鸿瘑鍒彿"> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟绾崇◣浜鸿瘑鍒彿" allowClear value={from_to_tax_no} autoComplete="off" onChange={(e) => this.setState({from_to_tax_no: e.target.value})}/> + </Form.Item> + <Form.Item className="mutil-input" label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟鍦板潃" allowClear value={from_to_addr} autoComplete="off" onChange={(e) => this.setState({from_to_addr: e.target.value})}/> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟鐢佃瘽" allowClear value={from_to_tel} autoComplete="off" onChange={(e) => this.setState({from_to_tel: e.target.value})}/> + </Form.Item> + <Form.Item className="mutil-input" label="寮�鎴疯鍙婅处鍙�"> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟寮�鎴疯" allowClear value={from_to_bank_name} autoComplete="off" onChange={(e) => this.setState({from_to_bank_name: e.target.value})}/> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟璐﹀彿" allowClear value={from_to_account_no} autoComplete="off" onChange={(e) => this.setState({from_to_account_no: e.target.value})}/> + </Form.Item> + </div> + </div> + <div className="inv-notice"> + <div className="inv-label">閫氱煡鍒�</div> + <div className="inv-content"> + <Form.Item label={<>鎵�<span></span>鏈�<span></span>鍙�</>}> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟鎵嬫満鍙�" allowClear value={from_to_mob} autoComplete="off" onChange={(e) => this.setState({from_to_mob: e.target.value})}/> + </Form.Item> + <Form.Item label={<>閭�<span></span>绠�</>}> + <Input placeholder="璇疯緭鍏ヨ喘涔版柟閭" allowClear value={from_to_email} autoComplete="off" onChange={(e) => this.setState({from_to_email: e.target.value})}/> + </Form.Item> + </div> + </div> + </div> + <div className="inv-details"> + <InvoiceTable data={details} config={config.detail} onChange={(details) => this.setState({details})}/> + </div> + <div className="inv-main-content"> + <div className="inv-buyer"> + <div className="inv-label">閿�鍞柟</div> + <div className="inv-content"> + <Form.Item label={<>鍚�<span></span>绉�</>}> + <Input placeholder="璇疯緭鍏ラ攢鍞柟鍚嶇О" value={orgname} autoComplete="off" onChange={(e) => this.setState({orgname: e.target.value})}/> + </Form.Item> + <Form.Item label="绾崇◣浜鸿瘑鍒彿"> + <Input placeholder="璇疯緭鍏ラ攢鍞柟绾崇◣浜鸿瘑鍒彿" disabled value={tax_no} autoComplete="off"/> + </Form.Item> + <Form.Item className="mutil-input" label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}> + <Input placeholder="璇疯緭鍏ラ攢鍞柟鍦板潃" value={addr} autoComplete="off" onChange={(e) => this.setState({addr: e.target.value})}/> + <Input placeholder="璇疯緭鍏ラ攢鍞柟鐢佃瘽" value={tel} autoComplete="off" onChange={(e) => this.setState({tel: e.target.value})}/> + </Form.Item> + <Form.Item className="mutil-input" label="寮�鎴疯鍙婅处鍙�"> + <Input placeholder="璇疯緭鍏ラ攢鍞柟寮�鎴疯" value={bank_name} autoComplete="off" onChange={(e) => this.setState({bank_name: e.target.value})}/> + <Input placeholder="璇疯緭鍏ラ攢鍞柟璐﹀彿" value={account_no} autoComplete="off" onChange={(e) => this.setState({account_no: e.target.value})}/> + </Form.Item> + </div> + </div> + <div className="inv-notice"> + <div className="inv-label">澶囨敞</div> + <div className="inv-content" style={{paddingTop: '30px'}}> + <Form.Item label=""> + <Input.TextArea placeholder="璇疯緭鍏ュ娉�" autoSize={{ minRows: 4, maxRows: 4 }} value={remark} autoComplete="off" onChange={(e) => this.setState({remark: e.target.value})}/> + </Form.Item> + </div> + </div> + </div> + </div> + <div className="inv-tail"> + <Form.Item label="鏀舵浜�"> + <Input placeholder="鏀舵浜�" value={payee} autoComplete="off" onChange={(e) => this.setState({payee: e.target.value})}/> + </Form.Item> + <Form.Item label="澶嶆牳浜�"> + <Input placeholder="澶嶆牳浜�" value={reviewer} autoComplete="off" onChange={(e) => this.setState({reviewer: e.target.value})}/> + </Form.Item> + <Form.Item label="寮�绁ㄤ汉"> + <Input placeholder="寮�绁ㄤ汉" value={drawer} autoComplete="off" onChange={(e) => this.setState({drawer: e.target.value})}/> + </Form.Item> + </div> + <Modal + title="瀹㈡埛淇℃伅" + visible={visible} + width="70vw" + maskClosable={false} + onCancel={() => { this.setState({ visible: false }) }} + footer={null} + > + <SubTable config={config.buyer} onChange={this.changeBuyer}/> + </Modal> + </div> + ) + } +} + +export default InvoiceModule \ No newline at end of file diff --git a/src/tabviews/custom/components/module/invoice/index.scss b/src/tabviews/custom/components/module/invoice/index.scss new file mode 100644 index 0000000..49e58ea --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/index.scss @@ -0,0 +1,260 @@ +.menu-invoice-wrap { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + color: #000000; + --inv-color: #13509c; + + .inv-action { + text-align: right; + margin-right: 30px; + .ant-btn { + margin-left: 15px; + margin-bottom: 5px; + height: 30px; + } + .mk-bill:hover, .mk-bill:active, .mk-bill:focus { + color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + } + .mk-submit, .mk-submit:hover, .mk-submit:active, .mk-submit:focus { + color: #fff; + background-color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + } + } + .inv-header { + text-align: center; + position: relative; + height: 70px; + margin-right: 30px; + .ant-select { + width: 390px; + border: none; + .ant-select-selection { + border: none; + box-shadow: none; + font-size: 25px; + text-align: center; + background-color: transparent; + + .ant-select-selection-selected-value { + float: none; + text-align: center; + font-family: kaiti; + color: var(--inv-color, #13509c); + } + .ant-select-selection__placeholder { + text-align: center; + font-family: kaiti; + } + } + } + .ant-select::before, .ant-select::after { + content: ''; + display: block; + width: 100%; + position: absolute; + border-top: var(--inv-color, #13509c) 1px solid; + border-bottom: var(--inv-color, #13509c) 1px solid; + height: 1px; + } + .ant-select::before { + bottom: -10px; + } + .ant-select::after { + bottom: -15px; + } + .date { + position: absolute; + right: 100px; + top: 5px; + color: var(--inv-color, #13509c); + } + } + + .ant-input { + border-top: none; + border-left: none; + border-right: none; + border-radius: 0; + box-shadow: none!important; + height: 28px; + font-size: 13px; + background: transparent; + } + .ant-input:hover, .ant-input:active, .ant-input:focus { + border-color: var(--inv-color, #13509c)!important; + } + .ant-input.ant-input-disabled { + cursor: text; + background: transparent!important; + } + + .ant-input-number { + border-top: none; + border-left: none; + border-right: none; + border-radius: 0; + box-shadow: none!important; + height: 28px; + font-size: 13px; + .ant-input-number-handler-wrap { + display: none; + } + } + .ant-input-number:hover, .ant-input-number:active, .ant-input-number:focus { + border-color: var(--inv-color, #13509c)!important; + } + + .inv-body { + border: var(--inv-color, #13509c) 1px solid; + font-size: 13px; + margin-right: 30px; + + .inv-main-content { + display: flex; + + .inv-buyer, .inv-notice { + width: 50%; + display: flex; + .inv-label { + color: var(--inv-color, #13509c); + width: 6.25%; + display: flex; + flex-direction: column; + writing-mode: vertical-rl; + justify-content: center; + align-items: center; + letter-spacing: 5px; + border-right: var(--inv-color, #13509c) 1px solid; + } + .inv-content { + flex: 1; + padding: 6px 0; + + .ant-form-item { + display: flex; + padding: 0 5px 0 15px; + font-size: 13px; + margin-bottom: 5px; + + .ant-form-item-label { + line-height: 30px; + text-align: justify; + label { + display: flex; + color: var(--inv-color, #13509c); + span { + display: inline-block; + flex: 1; + } + } + } + .ant-form-item-control-wrapper { + width: 100%; + + .ant-form-item-control { + line-height: 30px; + .ant-form-extra { + position: absolute; + top: 1px; + right: 10px; + font-size: 16px; + .anticon { + cursor: pointer; + } + } + .ant-input-affix-wrapper:not(:hover) { + .ant-input-suffix { + opacity: 0; + } + } + } + } + } + .ant-form-item.mutil-input { + .ant-form-item-children { + display: flex; + } + } + } + } + .inv-buyer { + border-right: var(--inv-color, #13509c) 1px solid; + .ant-form-item-label { + width: 95px; + min-width: 95px; + } + } + .inv-notice { + .inv-content { + padding-top: 45px; + } + .ant-form-item-label { + width: 75px; + min-width: 75px; + } + } + } + + .inv-details { + border-top: var(--inv-color, #13509c) 1px solid; + border-bottom: var(--inv-color, #13509c) 1px solid; + } + } + .inv-tail { + display: flex; + padding-top: 10px; + margin-right: 30px; + .ant-form-item { + flex: 1; + display: flex; + font-size: 13px; + .ant-form-item-label, .ant-form-item-control-wrapper { + width: 40%; + } + } + } +} +.inv-table { + .ant-table .ant-table-tbody tr:hover td { + background-color: var(--mk-sys-color1); + } +} +.tb-search-wrap { + .search-item { + display: flex; + float: left; + width: 350px; + align-items: center; + justify-content: flex-end; + + .ant-input { + width: 200px; + } + } + .ant-btn { + margin-bottom: 20px; + margin-left: 50px; + background-color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + color: #ffffff; + } + .ant-btn:hover, .ant-btn:active { + background-color: var(--mk-sys-color); + border-color: var(--mk-sys-color); + color: #ffffff; + opacity: 0.9; + } +} + +.inv-type-select { + .ant-select-dropdown-menu-item { + text-align: center; + } +} + diff --git a/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx b/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx new file mode 100644 index 0000000..791d755 --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx @@ -0,0 +1,394 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Input, InputNumber, notification, Modal } from 'antd' +import { EllipsisOutlined } from '@ant-design/icons' + +import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import SubTable from '../subTable' +import './index.scss' + +class DetailLine extends React.Component { + state = { + bill_count: 0, + unitprice: 0, + amount_line: 0, + visible: false + } + + UNSAFE_componentWillMount() { + let { line } = this.props + + this.setState({ + bill_count: line.bill_count || '', + unitprice: line.unitprice || '', + amount_line: line.amount_line || '' + }) + } + + onChange = (value, key) => { + let line = {...this.props.line} + + if (['bill_count', 'unitprice', 'amount_line'].includes(key)) { + line[key] = value || 0 + if (line[key]) { + if (key === 'bill_count') { + line[key] = Math.round(line[key] * 10000000000) / 10000000000 + if (line.unitprice) { + line.amount_line = Math.round(line.unitprice * line.bill_count * 100) / 100 + } + } else if (key === 'unitprice') { + line[key] = Math.round(line[key] * 10000000000) / 10000000000 + if (line.bill_count) { + line.amount_line = Math.round(line.unitprice * line.bill_count * 100) / 100 + } + } else if (key === 'amount_line') { + line[key] = Math.round(line[key] * 100) / 100 + if (line.bill_count) { + line.unitprice = Math.round(line.amount_line / line.bill_count * 10000000000) / 10000000000 + } else if (line.unitprice) { + line.bill_count = Math.round(line.amount_line / line.unitprice * 10000000000) / 10000000000 + } + } + } + } else { + line[key] = value + } + + this.setState({ + bill_count: line.bill_count || '', + unitprice: line.unitprice || '', + amount_line: line.amount_line || '' + }) + + this.props.changeLine(line, key) + } + + render() { + const { line, delLine, trigger } = this.props + const { bill_count, unitprice, amount_line } = this.state + + return <div className="mk-tr active"> + <div className="mk-td"> + <div className="mk-input">{line.productname || ''}<EllipsisOutlined onClick={trigger}/></div> + </div> + <div className="mk-td"> + <Input defaultValue={line.spec || ''} onChange={(e) => this.onChange(e.target.value, 'spec')}/> + </div> + <div className="mk-td"> + <Input defaultValue={line.unit || ''} onChange={(e) => this.onChange(e.target.value, 'unit')}/> + </div> + <div className="mk-td"> + <InputNumber value={bill_count} onChange={(val) => this.setState({bill_count: val})} onBlur={(e) => this.onChange(e.target.value, 'bill_count')}/> + </div> + <div className="mk-td"> + <InputNumber value={unitprice} onChange={(val) => this.setState({unitprice: val})} onBlur={(e) => this.onChange(e.target.value, 'unitprice')}/> + </div> + <div className="mk-td"> + <InputNumber value={amount_line} onChange={(val) => this.setState({amount_line: val})} onBlur={(e) => this.onChange(e.target.value, 'amount_line')}/> + </div> + <div className="mk-td">{line.tax_name}</div> + <div className="mk-td mk-right">{line.tax_amount} <span className="del-line" onClick={() => delLine(line.uuid)}></span> </div> + </div> + } +} + +class InvoiceTable extends Component { + static propTpyes = { + config: PropTypes.object, + data: PropTypes.any, + onChange: PropTypes.func + } + + state = { + data: [], + editKey: '', + total: {} + } + + UNSAFE_componentWillMount () { + const { data } = this.props + + let _data = fromJS(data).toJS() + if (!_data.length) { + _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}] + } + + this.setState({ + data: _data + }, () => { + this.getTotal(_data) + }) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('resetDetails', this.resetDetails) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('resetDetails', this.resetDetails) + } + + changeMoneyToChinese = (money) => { + let cnNums = ['闆�', '澹�', '璐�', '鍙�', '鑲�', '浼�', '闄�', '鏌�', '鎹�', '鐜�'] + let cnIntRadice = ['', '鎷�', '浣�', '浠�'] + let cnIntUnits = ['', '涓�', '浜�', '鍏�'] + let cnDecUnits = ['瑙�', '鍒�', '姣�', '鍘�'] + let cnInteger = '鏁�' + let cnIntLast = '鍏�' + let maxNum = 999999999999999.9999 // 鏈�澶у鐞嗙殑鏁板瓧 + let IntegerNum = null + let DecimalNum = null + let ChineseStr = '' + let parts = null // 鍒嗙閲戦鍚庣敤鐨勬暟缁勶紝棰勫畾涔� + let Symbol = '' // 姝h礋鍊兼爣璁� + + if (money === 0) return '' + + if (money >= maxNum) return '瓒呭嚭鏈�澶у鐞嗘暟瀛�' + + if(money < 0) { + money = -money + Symbol = '璐�' + } + money = money.toString() // 杞崲涓哄瓧绗︿覆 + if (money.indexOf('.') === -1) { + IntegerNum = money + DecimalNum = '' + } else { + parts = money.split('.') + IntegerNum = parts[0] + DecimalNum = parts[1].substr(0, 4) + } + + if (parseInt(IntegerNum, 10) > 0) { // 鑾峰彇鏁村瀷閮ㄥ垎杞崲 + let zeroCount = 0 + let IntLen = IntegerNum.length + for (let i = 0; i < IntLen; i++) { + let n = IntegerNum.substr(i, 1) + let p = IntLen - i - 1 + let q = p / 4 + let m = p % 4 + + if (n === '0') { + zeroCount++ + } else { + if (zeroCount > 0) { + ChineseStr += cnNums[0] + } + zeroCount = 0 // 褰掗浂 + ChineseStr += cnNums[parseInt(n)] + cnIntRadice[m] + } + + if (m === 0 && zeroCount < 4) { + ChineseStr += cnIntUnits[q] + } + } + ChineseStr += cnIntLast + } + + if (DecimalNum !== '') { // 灏忔暟閮ㄥ垎 + let decLen = DecimalNum.length + + for (let i = 0; i < decLen; i++) { + let n = DecimalNum.substr(i, 1) + if (n !== '0') { + ChineseStr += cnNums[Number(n)] + cnDecUnits[i] + } + } + } + if (ChineseStr === '') { + ChineseStr += cnNums[0] + cnIntLast + cnInteger + } else if (DecimalNum === '') { + ChineseStr += cnInteger + } + + ChineseStr = Symbol + ChineseStr + + return ChineseStr + } + + getTotal = (data) => { + let price = 0 + let tax = 0 + + data.forEach(item => { + if (!item.productcode) return + + price += item.amount_line + tax += item.tax_amount + }) + + this.setState({total: {price, tax, sum: price + tax, sumName: this.changeMoneyToChinese(price + tax)}}) + } + + resetDetails = (data) => { + let _data = fromJS(data).toJS() + + if (!_data.length) { + _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}] + } + + this.setState({data: _data}, () => { + this.getTotal(_data) + }) + } + + addLine = () => { + const { data } = this.state + + let line = {uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0} + + this.setState({data: [...data, line]}) + } + + delLine = () => { + const { editKey, data } = this.state + + if (data.length === 1) { + notification.warning({ + top: 92, + message: '鑷冲皯淇濈暀涓�琛屾槑缁嗭紒', + duration: 3 + }) + return + } + + let _data = data.filter(item => item.uuid !== editKey) + + this.setState({data: _data}, () => { + this.getTotal(_data) + }) + this.props.onChange(_data) + } + + changeLine = (record) => { + const { editKey, data } = this.state + + let _data = data.map(item => { + if (item.uuid === editKey) { + return record + } else { + return item + } + }) + + + this.setState({data: _data}, () => { + this.getTotal(_data) + }) + this.props.onChange(_data) + } + + checkLine = (uuid) => { + this.setState({editKey: uuid}) + } + + changeDetail = (prod) => { + const { editKey, data } = this.state + + let _data = data.map(item => { + if (item.uuid === editKey) { + item.productname = prod.productname + item.spec = prod.spec + item.unit = prod.unit + item.unitprice = prod.unitprice + item.tax_rate = prod.tax_rate + item.tax_name = prod.tax_rate + + item.productcode = prod.productcode + item.Description = prod.Description + item.tax_classify_code = prod.tax_classify_code + item.tax_classify_name = prod.tax_classify_name + + if (item.bill_count && item.unitprice) { + item.amount_line = Math.round(item.unitprice * item.bill_count * 100) / 100 + } + // item.tax_amount = prod.productname + } + + return item + }) + + this.setState({data: _data, editKey: '', visible: false}, () => { + this.setState({editKey: editKey}) + this.getTotal(_data) + }) + this.props.onChange(_data) + } + + render() { + const { config } = this.props + const { editKey, data, total, visible } = this.state + + return ( + <div className="detail-wrap"> + <span className="plus-line" onClick={this.addLine}></span> + <div className="mk-th"> + <div className="mk-td">璐х墿鎴栧簲绋庡姵鍔°�佹湇鍔″悕绉�</div> + <div className="mk-td">瑙勬牸鍨嬪彿</div> + <div className="mk-td">鍗曚綅</div> + <div className="mk-td">鏁伴噺</div> + <div className="mk-td">鍗曚环锛堝惈绋庯級</div> + <div className="mk-td">閲戦锛堝惈绋庯級</div> + <div className="mk-td">绋庣巼</div> + <div className="mk-td">绋庨</div> + </div> + {data.map(item => { + if (editKey === item.uuid) { + return <DetailLine key={item.uuid} line={item} changeLine={this.changeLine} delLine={this.delLine} trigger={() => this.setState({visible: true})}/> + } + + return <div className="mk-tr" key={item.uuid} onClick={() => this.checkLine(item.uuid)}> + <div className="mk-td mk-left">{item.productname || '**'}</div> + <div className="mk-td mk-left">{item.spec || ''}</div> + <div className="mk-td mk-left">{item.unit || ''}</div> + <div className="mk-td mk-right">{item.bill_count || ''}</div> + <div className="mk-td mk-right">{item.unitprice || ''}</div> + <div className="mk-td mk-right">{item.amount_line || ''}</div> + <div className="mk-td mk-right">{item.tax_name}</div> + <div className="mk-td mk-right">{item.tax_amount}</div> + </div> + })} + <div className="mk-total"> + <div className="mk-td">鍚堣</div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td"></div> + <div className="mk-td">锟total.price}</div> + <div className="mk-td"></div> + <div className="mk-td">锟total.tax}</div> + </div> + <div className="mk-upcase"> + <div className="mk-td">浠风◣鍚堣锛堝ぇ鍐欙級</div> + <div className="mk-td">{total.sumName}</div> + <div className="mk-td">锛堝皬鍐欙級锟total.sum}</div> + </div> + <Modal + title="鍟嗗搧淇℃伅" + visible={visible} + width="75vw" + maskClosable={false} + onCancel={() => { this.setState({ visible: false }) }} + footer={null} + > + <SubTable config={config} onChange={this.changeDetail}/> + </Modal> + </div> + ) + } +} + +export default InvoiceTable \ No newline at end of file diff --git a/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss b/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss new file mode 100644 index 0000000..fe39f35 --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss @@ -0,0 +1,127 @@ +.detail-wrap { + position: relative; + + .plus-line, .del-line { + position: absolute; + right: -40px; + top: 5px; + font-size: 26px; + border: 1px solid #d9d9d9; + border-radius: 32px; + width: 30px; + height: 30px; + transition: all 0.3s; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + } + .plus-line::before, .del-line::before { + content: ' '; + position: absolute; + top: 13px; + width: 12px; + height: 1px; + background: #b8b8b8; + transition: all 0.3s; + } + .plus-line::after { + content: ' '; + position: absolute; + top: 13px; + width: 12px; + height: 1px; + background: #b8b8b8; + transform: rotate(90deg); + transition: all 0.3s; + } + .plus-line:hover { + border-color: #26C281; + } + .plus-line:hover::before, .plus-line:hover::after { + background: #26C281; + } + .del-line:hover { + border-color: #ff4d4f; + } + .del-line:hover::before { + background: #ff4d4f; + } + + .mk-th, .mk-tr, .mk-total { + position: relative; + display: flex; + border-bottom: var(--inv-color, #13509c) 1px solid; + + .mk-td { + width: 10%; + height: 40px; + display: flex; + justify-content: center; + align-items: center; + padding: 0 3px; + } + .mk-td:not(:last-child) { + border-right: var(--inv-color, #13509c) 1px solid; + } + .mk-td:first-child { + width: 20%; + } + .mk-td:nth-child(2), .mk-td:nth-child(6) { + width: 15%; + } + + .mk-left { + justify-content: start; + } + .mk-right { + justify-content: end; + } + + .mk-input { + position: relative; + height: 28px; + width: 100%; + background: #ffffff; + border-bottom: 1px solid #d9d9d9; + transition: all 0.3s; + + .anticon-ellipsis { + position: absolute; + right: 0px; + padding: 5px 10px; + cursor: pointer; + } + } + .mk-input:hover { + border-color: var(--inv-color, #13509c); + } + + .ant-input { + background: #ffffff; + } + } + .mk-tr.active, .mk-tr:hover { + background: var(--mk-sys-color1); + } + .mk-upcase { + display: flex; + + .mk-td { + width: 40%; + height: 40px; + display: flex; + align-items: center; + padding: 0 20px; + } + .mk-td:first-child { + width: 20%; + padding: 0; + border-right: var(--inv-color, #13509c) 1px solid; + justify-content: center; + } + .mk-td:last-child { + justify-content: end; + } + } +} \ No newline at end of file diff --git a/src/tabviews/custom/components/module/invoice/subTable/index.jsx b/src/tabviews/custom/components/module/invoice/subTable/index.jsx new file mode 100644 index 0000000..04ab0e9 --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/subTable/index.jsx @@ -0,0 +1,245 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Table, Input, Button } from 'antd' + +import Api from '@/api' +import UtilsDM from '@/utils/utils-datamanage.js' +// import './index.scss' + +class SearchWrap extends Component { + static propTpyes = { + search: PropTypes.array, + onChange: PropTypes.func + } + + state = { + search: [] + } + + UNSAFE_componentWillMount () { + const { search } = this.props + + this.setState({ + search: fromJS(search).toJS() + }) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + searchChange = (val, key) => { + const { search } = this.state + + this.setState({search: search.map(item => { + if (item.field === key) { + item.value = val + } + return item + })}) + } + + trigger = () => { + const { search } = this.state + + this.props.onChange(search) + } + + render() { + const { search } = this.state + + return ( + <div className="tb-search-wrap"> + {search.map(item => ( + <div className="search-item" key={item.field}> + {item.label}锛� + <Input autoComplete="off" onChange={(e) => this.searchChange(e.target.value, item.field)}/> + </div> + ))} + <Button onClick={this.trigger}>鎼滅储</Button> + </div> + ) + } +} + +class SubTable extends Component { + static propTpyes = { + config: PropTypes.object + } + + state = { + pageIndex: 1, // 鍒濆椤甸潰绱㈠紩 + pageSize: 10, // 姣忛〉鏁版嵁鏉℃暟 + columns: null, // 鏄剧ず鍒� + pageOptions: [], + search: [] + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + let _columns = [] + + config.columns.forEach(item => { + if (item.Hide === 'true') return + _columns.push({ + align: 'center', + dataIndex: item.field, + title: item.label, + sorter: false, + width: item.Width || 120 + }) + }) + + let size = (config.setting.pageSize || 10) + '' + let pageOptions = ['10', '25', '50', '100', '500', '1000'] + + if (!pageOptions.includes(size)) { + pageOptions.push(size) + pageOptions = pageOptions.sort((a, b) => a - b) + } + + this.setState({ + pageSize: config.pageSize || 10, + pageOptions, + search: fromJS(config.search).toJS(), + columns: _columns + }) + } + + componentDidMount() { + const { config } = this.props + + if (config.setting.onload === 'true') { + this.loadData() + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + /** + * @description 鏁版嵁鍔犺浇 + */ + async loadData () { + const { config } = this.props + const { search, pageIndex, pageSize } = this.state + + this.setState({ + loading: true + }) + + let searches = search.map(item => ({ + key: item.field, + match: item.match, + type: item.type, + value: item.value || '' + })) + + let param = UtilsDM.getQueryDataParams(config.setting, searches, config.setting.order, pageIndex, pageSize, '') + + this.requestId = config.uuid + new Date().getTime() + + let result = await Api.genericInterface(param, config.setting.js_script, '', this.requestId) + + if (result.status) { + if (result.$requestId && this.requestId !== result.$requestId) return + + let start = pageSize * (pageIndex - 1) + 1 + + let data = result.data.map((item, index) => { + item.key = index + item.$Index = start + index + '' + + return item + }) + + let total = result.total || 0 + if (config.setting.custompage && data.length) { + total = data[data.length - 1].mk_total || 0 + } + + this.setState({ + data: data, + total: total, + loading: false + }) + + UtilsDM.querySuccess(result) + } else { + this.setState({ + loading: false + }) + + UtilsDM.queryFail(result) + } + } + + changeTable = (pagination) => { + this.setState({ + pageIndex: pagination.current, + pageSize: pagination.pageSize, + }, () => { + this.loadData() + }) + } + + doubleClickLine = (record) => { + this.props.onChange(record) + } + + searchChange = (search) => { + this.setState({search: search}, () => { + this.loadData() + }) + } + + render() { + const { pageIndex, pageSize, pageOptions, columns, total, loading, data, search } = this.state + + return ( + <> + <SearchWrap search={search} onChange={this.searchChange}/> + <Table + className="inv-table" + columns={columns} + dataSource={data} + bordered={true} + loading={loading} + onRow={(record) => { + return { + onDoubleClick: () => {this.doubleClickLine(record)} + } + }} + onChange={this.changeTable} + pagination={{ + current: pageIndex, + pageSize: pageSize, + pageSizeOptions: pageOptions, + showSizeChanger: true, + total: total || 0, + showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉 + }} + /> + </> + ) + } +} + +export default SubTable \ No newline at end of file diff --git a/src/tabviews/custom/components/module/invoice/subTable/index.scss b/src/tabviews/custom/components/module/invoice/subTable/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/tabviews/custom/components/module/invoice/subTable/index.scss diff --git a/src/tabviews/custom/components/tree/antd-tree/index.jsx b/src/tabviews/custom/components/tree/antd-tree/index.jsx index 6e7f7b1..1009ba9 100644 --- a/src/tabviews/custom/components/tree/antd-tree/index.jsx +++ b/src/tabviews/custom/components/tree/antd-tree/index.jsx @@ -353,9 +353,9 @@ let hasSelectKey = false data.forEach(item => { - let pval = item[config.wrap.parentField] - let val = item[config.wrap.valueField] - let uuid = item[config.setting.primaryKey] || '' + let pval = item[config.wrap.parentField] + '' + let val = item[config.wrap.valueField] + '' + let uuid = item[config.setting.primaryKey] + '' if (!val || logMap.has(val)) return diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx index c7c3bb6..b8acc23 100644 --- a/src/tabviews/custom/index.jsx +++ b/src/tabviews/custom/index.jsx @@ -41,6 +41,7 @@ const AntvX6 = asyncComponent(() => import('./components/chart/antv-X6')) const Voucher = asyncComponent(() => import('./components/module/voucher')) const Account = asyncComponent(() => import('./components/module/account')) +const Invoice = asyncComponent(() => import('./components/module/invoice')) const Iframe = asyncComponent(() => import('./components/iframe')) const Calendar = asyncComponent(() => import('./components/calendar')) const DebugTable = asyncComponent(() => import('@/tabviews/debugtable')) @@ -1698,6 +1699,12 @@ <Account config={item}/> </Col> ) + } else if (item.type === 'module' && item.subtype === 'invoice') { + return ( + <Col span={item.width} style={style} key={item.uuid}> + <Invoice config={item}/> + </Col> + ) } else if (item.type === 'iframe') { return ( <Col span={item.width} style={style} key={item.uuid}> diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx index 3bba3de..7b86cb8 100644 --- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx @@ -722,33 +722,32 @@ let cols = _verify.columns.map(col => col.Column.toLowerCase()) cols = Array.from(new Set(cols)) + let error = '' if (_verify.columns.length === 0) { - notification.warning({ - top: 92, - message: '璇疯缃瓻xcel鍒楀瓧娈�!', - duration: 5 - }) - return + error = '璇疯缃瓻xcel鍒楀瓧娈�!' } else if (_verify.columns.length > cols.length) { - notification.warning({ - top: 92, - message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!', - duration: 5 - }) - return + error = 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!' + } else if (cols.includes('bid')) { + error = 'bid瀛楁涓轰繚鐣欏瓧锛屼笉鍙娇鐢�!' + } else if (cols.includes('jskey')) { + error = 'jskey瀛楁涓轰繚鐣欏瓧锛屼笉鍙娇鐢�!' } else if (_verify.range === 1) { let tEmptys = _verify.columns.filter(op => !op.Text) if (tEmptys.length > 0) { - notification.warning({ - top: 92, - message: '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�', - duration: 5 - }) - return + error = '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�' } } + if (error) { + notification.warning({ + top: 92, + message: error, + duration: 5 + }) + return + } + _verify.columns.sort((a, b) => { if (a.import === 'init' && b.import !== 'init') { return 1 -- Gitblit v1.8.0