king
2024-05-06 f6c788403ccd2a216d6ba793ed591379c9d02dc5
2024-05-06
19个文件已修改
806 ■■■■ 已修改文件
public/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/options.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/baseform/index.jsx 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/customscript/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/account/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.jsx 510 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/manifest.json
@@ -6,5 +6,5 @@
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "mk_version": "20240401"
  "mk_version": "20240501"
}
src/menu/components/module/account/index.jsx
@@ -80,7 +80,7 @@
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear', 'position'], card.style, this.getStyle)
  }
  getStyle = (style) => {
src/menu/components/module/account/index.scss
@@ -1,5 +1,5 @@
.menu-account-box {
  position: relative;
  position: relative!important;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
src/menu/components/module/invoice/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Button, Modal } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'
import { EditOutlined, ToolOutlined, DeleteOutlined, LeftOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'
import moment from 'moment'
import Utils from '@/utils/utils.js'
@@ -37,12 +37,13 @@
      let _card = {
        uuid: card.uuid,
        type: card.type,
        format: 'object',   // 组件属性 - 数据格式
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        width: card.width || 24,
        name: '发票',
        subtype: card.subtype,
        fixedCol: true,
        wrap: { name: '发票', width: card.width || 24, datatype: 'static' },
        style: { paddingLeft: '20px', paddingRight: '20px', paddingTop: '10px', paddingBottom: '10px' },
        setting: { interType: 'system', primaryKey: 'ID' },
@@ -51,6 +52,7 @@
        buyer: {
          pageable: true,
          format: 'array',
          fixedCol: true,
          subtype: 'invTable',
          setting: { interType: 'system' },
          columns: [],
@@ -63,6 +65,7 @@
        detail: {
          pageable: true,
          format: 'array',
          fixedCol: true,
          subtype: 'invTable',
          setting: { interType: 'system' },
          columns: [],
@@ -72,8 +75,8 @@
            {field: 'productcode', label: '商品编码', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
          ],
        },
        billSaveBtn: {type: 'billsave', intertype: 'system', label: '保存单据'},
        billOutBtn: {type: 'billout', intertype: 'custom', label: '提交开票', procMode: 'system'},
        billSaveBtn: {type: 'billsave', parId: card.uuid, intertype: 'system', label: '保存单据'},
        billOutBtn: {type: 'billout', parId: card.uuid, intertype: 'custom', label: '提交开票', procMode: 'system'},
      }
      let buys = [
@@ -102,11 +105,12 @@
        ['单价', 'unitprice', 'Decimal(18,10)'],
        ['税务分类编码', 'tax_classify_code'],
        ['税务分类名称', 'tax_classify_name'],
        // ['税率', 'tax_rate', 'Decimal(18,2)'],
        ['一般纳税人税率', 'general_tax_rate', 'Decimal(18,2)'],
        ['小规模纳税人征收率', 'small_tax_rate', 'Decimal(18,2)'],
        ['是否享受优惠政策', 'free_tax_mark'],
        ['优惠政策类型', 'vat_special_management'],
        ['tax_item', 'tax_item'],
        ['tax_method', 'tax_method'],
      ]
      details.forEach((cell, index) => {
@@ -117,6 +121,7 @@
        ['ID', 'ID'],
        ['开票申请单号', 'io'],
        ['发票种类', 'invoice_type'],
        ['开票类型', 'business_type', 'Nvarchar(20)'],
        ['购买方名称', 'from_to_name'],
        ['购买方税号', 'from_to_tax_no'],
        ['购买方地址', 'from_to_addr', 'Nvarchar(100)'],
@@ -136,6 +141,7 @@
        ['收款人', 'payee'],
        ['复核人', 'reviewer'],
        ['开票人', 'drawer'],
        ['jskey', 'jskey'],
        ['行号', 'invoice_lp'],
        ['商品编码', 'productcode'],
        ['商品名称', 'productname'],
@@ -148,6 +154,10 @@
        ['税务分类名称', 'tax_classify_name'],
        ['税率', 'tax_rate', 'Decimal(18,2)'],
        ['税额', 'tax_amount', 'Decimal(18,2)'],
        ['是否享受优惠政策', 'free_tax_mark'],
        ['优惠政策类型', 'vat_special_management'],
        ['tax_item', 'tax_item'],
        ['tax_method', 'tax_method'],
      ]
      cols.forEach((cell, index) => {
@@ -289,6 +299,7 @@
          <ToolOutlined />
        </Popover>
        <div className="inv-action">
          {card.wrap.backBtn === 'show' ? <Button className="mk-back"><LeftOutlined />返回</Button> : null}
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control">
              <EditOutlined style={{color: '#1890ff'}} onClick={() => this.setState({btn: card.billSaveBtn})} title="编辑"/>
src/menu/components/module/invoice/index.scss
@@ -27,6 +27,16 @@
      margin-bottom: 5px;
      height: 30px;
    }
    .mk-back {
      border: none;
      float: left;
      margin-left: 0px;
      padding: 0px;
      box-shadow: none;
    }
    .mk-back::after {
      display: none;
    }
    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
      color: var(--mk-sys-color);
      border-color: var(--mk-sys-color);
src/menu/components/module/invoice/options.jsx
@@ -56,15 +56,11 @@
      allowClear: true
    },
    {
      type: 'radio',
      type: 'text',
      field: 'business_type',
      label: '发票类型',
      initval: wrap.business_type || 'sell',
      required: true,
      options: [
        {value: 'sell', label: '销项发票'},
        {value: 'buy', label: '进项发票'},
      ]
      label: '开票类型',
      initval: wrap.business_type || 'sell_01',
      required: true
    },
    {
      type: 'color',
@@ -75,6 +71,17 @@
      allowClear: true,
      required: false
    },
    {
      type: 'radio',
      field: 'backBtn',
      label: '返回按钮',
      initval: wrap.backBtn || 'hide',
      required: true,
      options: [
        {value: 'hide', label: '隐藏'},
        {value: 'show', label: '显示'},
      ]
    },
  ]
  return wrapForm
src/menu/components/module/invoice/verifycard/baseform/index.jsx
@@ -1,8 +1,9 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input } from 'antd'
// import { QuestionCircleOutlined } from '@ant-design/icons'
import { Form, Row, Col, Input, Tooltip, Cascader } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import MenuUtils from '@/utils/utils-custom.js'
// import './index.scss'
const { TextArea } = Input
@@ -12,7 +13,31 @@
    onChange: PropTypes.func
  }
  state = {}
  state = {
    modules: [],
    menulist: [],
    appType: sessionStorage.getItem('appType')
  }
  UNSAFE_componentWillMount() {
    const { verify } = this.props
    let menu = window.GLOB.customMenu
    let modules = MenuUtils.getSubModules(menu.components, verify.parId, '', menu.interfaces || null)
    let menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
      try {
        menulist = JSON.parse(menulist)
      } catch (e) {
        menulist = []
      }
    } else {
      menulist = []
    }
    this.setState({modules, menulist})
  }
  handleConfirm = () => {
    const { verify } = this.props
@@ -41,6 +66,7 @@
  render() {
    const { getFieldDecorator } = this.props.form
    const { verify } = this.props
    const { modules, menulist, appType } = this.state
    return (
      <Form className="base-form">
@@ -50,6 +76,34 @@
              <Input value={verify.label} disabled={true}/>
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="执行成功后需要刷新的组件。">
                <QuestionCircleOutlined className="mk-form-tip" />
                刷新组件
              </Tooltip>
            }>
              {getFieldDecorator('syncComponent', {
                initialValue: verify.syncComponent || []
              })(
                <Cascader allowClear={true} options={modules} expandTrigger="hover"/>
              )}
            </Form.Item>
          </Col>
          {!appType ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="执行成功后需要刷新的菜单。">
                <QuestionCircleOutlined className="mk-form-tip" />
                刷新菜单
              </Tooltip>
            }>
              {getFieldDecorator('refreshTab', {
                initialValue: verify.refreshTab || []
              })(
                <Cascader allowClear={true} options={menulist} expandTrigger="hover"/>
              )}
            </Form.Item>
          </Col> : null}
          {/* <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="">
@@ -101,6 +155,15 @@
              )}
            </Form.Item>
          </Col> : null}
          {verify.type === 'billout' ? <Col span={8}>
            <Form.Item label="回调表名">
              {getFieldDecorator('cbTable', {
                initialValue: verify.cbTable || ''
              })(
                <Input autoComplete="off"/>
              )}
            </Form.Item>
          </Col> : null}
        </Row>
      </Form>
    )
src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
@@ -195,7 +195,7 @@
  }
  render() {
    const { systemScripts, type } = this.props
    const { systemScripts, type, cbTable } = this.props
    const { getFieldDecorator } = this.props.form
    const { editItem, skip } = this.state
    const formItemLayout = {
@@ -213,6 +213,11 @@
      <Form {...formItemLayout} className="verify-form">
        <Row gutter={24}>
          {!type ? <Col span={8}>
            <Form.Item label="回调表名" style={{margin: 0, whiteSpace: 'nowrap'}}>
              {cbTable || ''}
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={8}>
            <Form.Item label="报错字段" style={{margin: 0, whiteSpace: 'nowrap'}}>
              errorcode(增加后缀NT表示数据不回滚,如ENT、NNT、FNT、NMNT、CNT、-2NT), retmsg
            </Form.Item>
src/menu/components/module/invoice/verifycard/customscript/index.jsx
@@ -73,16 +73,16 @@
          
          /* 发票主表字段 */
          
          Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
          Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
          
          Select @invoice_type='', @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='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0
          Select @invoice_type='', @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='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
          
          /* 发票明细临时表 */
          Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
          Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
          
          Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
          Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
          
          Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', ''
          Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
        `
@@ -209,8 +209,8 @@
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="公共值,请按照@xxx@格式使用。"><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename, datam</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="系统变量,系统会定义变量并赋值。"><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="账套字段,系统会定义变量并赋值。"><span style={{color: '#13c2c2'}}>account_id, account_year_id, account_code, account_year_code </span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="主表字段,系统会定义变量并赋值。"><span style={{color: '#8E44AD'}}>invoice_type, 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</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="子表字段(商品明细),系统会定义变量并赋值。">productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount</Tooltip>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="主表字段,系统会定义变量并赋值。"><span style={{color: '#8E44AD'}}>invoice_type, 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, io, orgcode, total_net_amount, total_tax, total_amount, business_type</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="子表字段(商品明细),系统会定义变量并赋值。">productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type</Tooltip>
            </Form.Item>
          </Col> : null}
          {/* {!_type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
src/menu/components/module/invoice/verifycard/index.jsx
@@ -537,6 +537,7 @@
            >
              <CallBackCustomScript
                type="fullscreen"
                cbTable={verify.cbTable}
                customScripts={verify.cbScripts}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.cbScriptsChange}
@@ -544,6 +545,7 @@
              />
            </FullScripts>
            <CallBackCustomScript
              cbTable={verify.cbTable}
              customScripts={verify.cbScripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.cbScriptsChange}
@@ -562,28 +564,32 @@
              </p>
              <p className="note">{`/* 发票主表字段 */`}</p>
              <p>
                Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
                Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
              </p>
              <p>
                Select @invoice_type='', @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='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0
                Select @invoice_type='', @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='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
              </p>
              <p className="note">{`/* 发票明细临时表 */`}</p>
              <p>
                Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
                Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
              </p>
              <p>
                Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
                Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
              </p>
              <p>
                Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', ''
                Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
              </p>
              <p className="note">{`/* 前置脚本 */`}</p>
              <p>
                ......
              </p>
              {card.type === 'billout' ? <p>
                aaa: if @ErrorCode!=''
                insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,''
              </p> :
              <p>
                aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
              </p>
              </p>}
            </div>
          </TabPane>
          <TabPane tab="信息提示" key="tip">
src/menu/components/table/normal-table/index.jsx
@@ -403,7 +403,7 @@
        </Popover>
        {appType !== 'mob' ? <SearchComponent config={card} updatesearch={this.updateComponent}/> : null}
        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updatecolumn}/>
        <div className="component-name">
          <div className="center">
            <div className="title" onDoubleClick={() => {
src/menu/datasource/index.jsx
@@ -173,7 +173,9 @@
          return item
        })
        res.columns.reverse()
        if (!config.fixedCol) {
          res.columns.reverse()
        }
      }
      let maxScript = 0
src/menu/datasource/verifycard/index.jsx
@@ -216,9 +216,11 @@
    let columns = config.columns ? fromJS(config.columns).toJS() : []
    let subColumns = config.subColumns ? fromJS(config.subColumns).toJS() : []
    columns.reverse()
    if (!config.fixedCol) {
      columns.reverse()
    }
    subColumns.reverse()
    columns.forEach(col => {
      if (!col.datatype) return
      if (/^nvarchar/.test(col.datatype)) {
@@ -959,6 +961,7 @@
  }
  copyColumns = () => {
    const { config } = this.props
    const { columns, setting } = this.state
    let m = []
@@ -983,6 +986,33 @@
      console.info('select ' + s.join(', '))
    }
    let extend = ''
    if (config.hasExtend) {
      extend = []
      let mapCol = (cols) => {
        cols.forEach(col => {
          if (col.type === 'extend') {
            let datatype = 'Nvarchar(50)'
            columns.forEach(c => {
              if (c.field === col.field) {
                datatype = c.datatype
              }
            })
            for (let i = 1; i < col.quota; i++) {
              extend.push(`${col.field}${i} ${datatype}`)
            }
          } else if (col.type === 'colspan' && col.subcols) {
            mapCol(col.subcols)
          }
        })
      }
      mapCol(config.cols)
      extend = `
      /* 扩展列字段 */
      /* ${extend.join(',')} */
      `
    }
    let oInput = document.createElement('input')
    oInput.value = `create table #${setting.tableName || 'tb'}
    (${m.join(',')},sort_id INT IDENTITY(1,1))
@@ -1005,7 +1035,7 @@
      if @pageIndex_top > 0
        delete #${setting.tableName || 'tb'} where sort_id <= @pageIndex_top
    drop table #${setting.tableName || 'tb'}`
    drop table #${setting.tableName || 'tb'}${extend}`
    document.body.appendChild(oInput)
    oInput.select()
src/tabviews/custom/components/module/account/index.jsx
@@ -84,6 +84,7 @@
          if (res.invoice_type) {
            item.invoice_type = res.invoice_type.map(cell => ({value: cell.invoice_type_code, label: cell.invoice_type_name}))
          }
          item.$$uuid = item.id
          activeItem = item
        }
        if (item.months) {
src/tabviews/custom/components/module/invoice/index.jsx
@@ -2,8 +2,9 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Select, Form, Input, Button, Modal, Spin, notification } from 'antd'
import { EllipsisOutlined } from '@ant-design/icons'
import { EllipsisOutlined, LeftOutlined } from '@ant-design/icons'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
@@ -13,6 +14,8 @@
import SubTable from './subTable'
import './index.scss'
const { confirm } = Modal
class InvoiceModule extends Component {
  static propTpyes = {
    config: PropTypes.object
@@ -20,17 +23,11 @@
  state = {
    BID: '',
    ID: Utils.getuuid(),
    ID: Utils.getguid(),
    io: '',
    invTypes: [
      {value: '1', label: '电子发票(增值税专用发票)'},
      {value: '2', label: '电子发票(普通发票)'},
      {value: '3', label: '增值税纸质专用发票'},
      {value: '4', label: '增值税纸质普通发票'},
      {value: '5', label: '增值税电子普通发票'},
      {value: '6', label: '增值税电子专用发票'},
    ],
    invTypes: [],
    invoice_type: '',
    business_type: '',
    date: moment().format('YYYY年MM月DD日'),
    from_to_name: '',
    from_to_tax_no: '',
@@ -58,7 +55,8 @@
    saveType: '',
    tax_type: '',
    reqfields: [],
    requireds: []
    requireds: [],
    timestamp: new Date().getTime() + ''
  }
  UNSAFE_componentWillMount () {
@@ -133,6 +131,13 @@
  formatSetting = (item, type) => {
    item.setting.arr_field = item.columns.map(col => col.field).join(',')
    item.setting.laypage = item.setting.laypage === 'true'
    if (item.refreshTab && item.refreshTab.length) {
      item.reTabId = item.refreshTab.pop()
    }
    if (item.syncComponent && item.syncComponent.length) {
      item.syncComId = item.syncComponent.pop()
    }
    if (type === 'buyer') {
      item.columns = item.columns.map(cell => {
@@ -281,9 +286,13 @@
  }
  async loadData() {
    const { config, BID } = this.state
    const { config, BID, book } = this.state
    if (config.wrap.datatype !== 'dynamic') return
    if (config.wrap.datatype !== 'dynamic' || !book) return
    if (!BID) {
      this.clearData()
      return
    }
    let param = UtilsDM.getQueryDataParams(config.setting, [], config.setting.order, 1, 1, BID)
@@ -293,14 +302,75 @@
    let result = await Api.genericInterface(param)
    if (result.status) {
      if (!result.data[0]) {
        this.clearData()
        this.setState({
          loading: false
        })
        return
      }
      let line = result.data[0]
      let details = result.data.map(item => {
        let tax_name = item.tax_rate * 100 + '%'
        if (item.vat_special_management && item.free_tax_mark === 'true') {
          tax_name = item.vat_special_management
        }
        return {
          uuid: item.jskey,
          productname: item.productname,
          productcode: item.productcode,
          spec: item.spec,
          unit: item.unit,
          bill_count: item.bill_count,
          unitprice: item.unitprice,
          tax_rate: item.tax_rate,
          free_tax_mark: item.free_tax_mark,
          vat_special_management: item.vat_special_management,
          tax_classify_code: item.tax_classify_code,
          tax_classify_name: item.tax_classify_name,
          amount_line: item.amount_line,
          tax_amount: item.tax_amount,
          invoice_lp: item.invoice_lp,
          tax_item: item.tax_item,
          tax_method: item.tax_method,
          tax_name: tax_name
        }
      })
      this.setState({
        ID: result.data[0][config.setting.primaryKey] || Utils.getuuid(),
        io: '',
        details: [],
        oriDetails: [],
        ID: line[config.setting.primaryKey] || Utils.getguid(),
        io: line.io,
        invoice_type: line.invoice_type,
        business_type: line.business_type,
        from_to_name: line.from_to_name,
        from_to_tax_no: line.from_to_tax_no,
        from_to_addr: line.from_to_addr,
        from_to_tel: line.from_to_tel,
        from_to_bank_name: line.from_to_bank_name,
        from_to_account_no: line.from_to_account_no,
        from_to_mob: line.from_to_mob,
        from_to_email: line.from_to_email,
        from_to_code: line.from_to_code,
        orgname: line.orgname,
        tax_no: line.tax_no,
        addr: line.addr,
        tel: line.tel,
        bank_name: line.bank_name,
        account_no: line.account_no,
        remark: line.remark,
        payee: line.payee,
        reviewer: line.reviewer,
        drawer: line.drawer,
        details: details,
        oriDetails: fromJS(details).toJS(),
        timestamp: new Date().getTime() + '',
        loading: false
      })
      this.getRequired(line.invoice_type)
      UtilsDM.querySuccess(result)
    } else {
@@ -313,6 +383,28 @@
    }
  }
  clearData = () => {
    const { from_to_tax_no, oriDetails, details } = this.state
    if (from_to_tax_no || oriDetails.length || details.length) {
      this.setState({
        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: '',
        business_type: '',
        details: [],
        oriDetails: [],
        timestamp: new Date().getTime() + '',
      })
    }
  }
  changeType = (val) => {
    sessionStorage.setItem('pre_invoice_type', val)
    this.setState({invoice_type: val})
@@ -320,7 +412,13 @@
  }
  getRequired = (invoice_type) => {
    if (!invoice_type) return
    if (!invoice_type) {
      this.setState({
        reqfields: [],
        requireds: []
      })
      return
    }
    let reqfields = []
    let requireds = []
@@ -364,7 +462,7 @@
  }
  saveBill = () => {
    const { config, book, saveType } = this.state
    const { config, BID, saveType } = this.state
    if (saveType) return
@@ -377,7 +475,7 @@
          LText: sql,
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: book.id
          BID: BID
        }
  
        param.secretkey = Utils.encrypt('', param.timestamp)
@@ -388,11 +486,34 @@
        })
        Api.genericInterface(param).then(res => {
          this.setState({
            saveType: ''
          })
          if (res.status) {
            notification.success({
              top: 92,
              message: '保存成功。',
              duration: 5
            const that = this
            confirm({
              title: '保存成功。',
              okText: '继续填开',
              cancelText: '关闭',
              onOk() {
                if (config.billSaveBtn.reTabId) {
                  MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId, 'table')
                }
                if (config.billSaveBtn.syncComId) {
                  MKEmitter.emit('reloadData', config.billSaveBtn.syncComId)
                }
                that.clearData()
              },
              onCancel() {
                if (config.billSaveBtn.reTabId) {
                  MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId, 'table')
                }
                if (config.billSaveBtn.syncComId) {
                  MKEmitter.emit('reloadData', config.billSaveBtn.syncComId)
                }
                MKEmitter.emit('closeTabView', config.$pageId)
              }
            })
          } else {
            notification.warning({
@@ -401,9 +522,6 @@
              duration: 5
            })
          }
          this.setState({
            saveType: ''
          })
        })
      }, (error) => {
        notification.warning({
@@ -411,13 +529,21 @@
          message: error,
          duration: 5
        })
        return
      })
    }, 20)
  }
  outBill = () => {
    const { config, book, saveType } = this.state
    const { config, BID, saveType } = this.state
    if (window.GLOB.systemType === 'production' && !config.billOutBtn.proInterface) {
      notification.warning({
        top: 92,
        message: '尚未设置正式系统接口地址!',
        duration: 5
      })
      return
    }
    if (saveType) return
@@ -428,16 +554,33 @@
        let param = {
          func: 'sPC_TableData_InUpDe',
          LText: sql,
          key_back_type: 'Y',
          script_type: 'Y',
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: book.id
          BID: BID
        }
  
        param.secretkey = Utils.encrypt('', param.timestamp)
        param.LText = Utils.formatOptions(param.LText, param.exec_type)
        console.info(sql)
        this.setState({
          saveType: 'out'
        })
        Api.genericInterface(param).then(res => {
          if (res.status) {
            this.outPutBill(res)
          } else {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            this.setState({
              saveType: ''
            })
          }
        })
      }, (error) => {
        notification.warning({
          top: 92,
@@ -449,11 +592,15 @@
    })
  }
  getPreSql = (btn) => {
    const { book, ID, io, details, oriDetails, invoice_type, 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, reviewer, drawer, payee } = this.state
  goback = () => {
    const { config } = this.state
    MKEmitter.emit('closeTabView', config.$pageId)
  }
    let BID = book.id
    let userName = sessionStorage.getItem('User_Name') || ''
  getPreSql = (btn) => {
    const { config, book, ID, BID, io, details, oriDetails, business_type, invoice_type, 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, reviewer, drawer, payee } = this.state
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
@@ -468,8 +615,11 @@
    let price = 0
    let tax = 0
    let lines = details.map(line => {
      let _sql = `Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.uuid}'`
    let lines = []
    details.forEach(line => {
      if (!line.productcode) return
      let _sql = `Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.tax_item}', '${line.tax_method}', '${line.uuid}'`
      let data_type = 'add'
      price += line.amount_line * 100
@@ -485,7 +635,7 @@
        })
      }
      return _sql + `, '${data_type}'`
      lines.push(_sql + `, '${data_type}'`)
    })
    let _total = (price - tax) / 100
@@ -494,7 +644,7 @@
    if (options.length) {
      options.forEach(line => {
        lines.push(`Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.uuid}', 'del'`)
        lines.push(`Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.tax_item}', '${line.tax_method}', '${line.uuid}', 'del'`)
      })
    }
@@ -511,25 +661,31 @@
    let sql = `/* 系统字段 */
      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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid=''
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID}'
      /* 发票主表字段 */
      Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
      Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
      Select @invoice_type='${invoice_type}', @from_to_name='${from_to_name}', @from_to_tax_no='${from_to_tax_no}', @from_to_addr='${from_to_addr}', @from_to_tel='${from_to_tel}', @from_to_bank_name='${from_to_bank_name}', @from_to_account_no='${from_to_account_no}', @from_to_mob='${from_to_mob}', @from_to_email='${from_to_email}', @from_to_code='${from_to_code}', @orgname='${orgname}', @tax_no='${tax_no}', @addr='${addr}', @tel='${tel}', @bank_name='${bank_name}', @account_no='${account_no}', @remark='${remark}', @payee='${payee}', @reviewer='${reviewer}', @drawer='${drawer}', @io='${io}', @orgcode='${book.orgcode || ''}', @total_net_amount=${_total}, @total_tax=${tax}, @total_amount=${price}
      Select @invoice_type='${invoice_type}', @from_to_name='${from_to_name}', @from_to_tax_no='${from_to_tax_no}', @from_to_addr='${from_to_addr}', @from_to_tel='${from_to_tel}', @from_to_bank_name='${from_to_bank_name}', @from_to_account_no='${from_to_account_no}', @from_to_mob='${from_to_mob}', @from_to_email='${from_to_email}', @from_to_code='${from_to_code}', @orgname='${orgname}', @tax_no='${tax_no}', @addr='${addr}', @tel='${tel}', @bank_name='${bank_name}', @account_no='${account_no}', @remark='${remark}', @payee='${payee}', @reviewer='${reviewer}', @drawer='${drawer}', @io='${io}', @orgcode='${book.orgcode || ''}', @total_net_amount=${_total}, @total_tax=${tax}, @total_amount=${price}, @business_type='${business_type || config.wrap.business_type || ''}'
      /* 发票明细临时表 */
      Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
      Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
      Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
      Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
      ${lines}
      /* 自定义脚本 */
      ${_script}
      `
      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    if (btn.type === 'billout') {
      sql += `aaa: if @ErrorCode!=''
      insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg, @UserID@`
    } else {
      sql += `aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    sql = sql.replace(/@ID@/ig, `'${ID}'`)
    sql = sql.replace(/@BID@/ig, `'${BID}'`)
@@ -585,7 +741,7 @@
      }
      if (!error) {
        if (details.length === 0) {
        if (details.length === 0 || details.filter(line => !!line.productcode).length === 0) {
          error = '请添加明细!'
        } else {
          details.forEach((line, index) => {
@@ -596,8 +752,6 @@
              } else if (!line.unitprice) {
                error = '明细第' + (index + 1) + '行,请输入单价!'
              }
            } else {
              error = '明细第' + (index + 1) + '行,请选择货物或应税劳务、服务名称!'
            }
          })
        }
@@ -609,6 +763,257 @@
        resolve()
      }
    })
  }
  outPutBill = (res) => {
    const { config } = this.state
    if (!res.data_invoice || !res.sellerName || !res.taxNo) {
      notification.warning({
        top: 92,
        message: '缺少开票参数!',
        duration: 5
      })
      this.setState({
        saveType: ''
      })
    }
    let param = {
      data: res.data_invoice,
      sellerName: res.sellerName,
      taxNo: res.taxNo
    }
    let trans = {
      e_general: '02',
      e_special: '01'
    }
    param.data.invoiceTypeCode = trans[param.data.invoiceTypeCode] || ''
    let url = ''
    if (window.GLOB.systemType === 'production') {
      url = config.billOutBtn.proInterface
    } else {
      url = config.billOutBtn.interface
    }
    let _params = {
      url: url,
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      data: param
    }
    Api.directRequest(_params).then(result => {
      result.mk_api_key = res.mk_api_key || ''
      this.callBackBill(result)
    })
  }
  callBackBill = (result) => {
    const { config, BID, ID } = this.state
    let btn = config.billOutBtn
    let lines = []
    let pre = '@'
    let getDefaultSql = (obj, tb, bid, level) => {
      let keys = []
      let vals = []
      let subObjs = []
      let id = Utils.getuuid()
      let tbName = pre + tb
      delete obj.$$key
      Object.keys(obj).forEach(key => {
        let val = obj[key]
        if (val === null || val === undefined) return
        if (typeof(val) === 'object') {
          if (Array.isArray(val)) {
            val.forEach(item => {
              if (typeof(item) !== 'object' || Array.isArray(item)) return
              if (Object.keys(item).length > 0) {
                item.$$key = tb + '_' + key
                subObjs.push(item)
              }
            })
          } else if (Object.keys(val).length > 0) {
            val.$$key = tb + '_' + key
            subObjs.push(val)
          }
        } else {
          if (typeof(val) === 'string') {
            val = val.replace(/'/ig, '"')
          }
          keys.push('[' + key + ']')
          vals.push(`'${val}'`)
        }
      })
      keys = keys.join(',')
      lines.push({
        table: md5(tb + keys),
        insert: `Insert into ${tbName} (${keys},[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${vals.join(',')},'${level}','${id}','${bid}'`
      })
      subObjs.forEach(item => {
        getDefaultSql(item, item.$$key, id, level + 1)
      })
    }
    getDefaultSql(result, btn.cbTable, '', 1)
    let lineMap = new Map()
    lines.forEach(line => {
      if (lineMap.has(line.table)) {
        let _line = lineMap.get(line.table)
        _line.selects.push(line.select)
        lineMap.set(line.table, _line)
      } else {
        lineMap.set(line.table, {
          table: line.table,
          insert: line.insert,
          selects: [line.select]
        })
      }
    })
    let param = {
      func: 'sPC_TableData_InUpDe',
      BID: BID,
      menuname: config.name + '(回调)'
    }
    let callbacksql = this.getBackSql()
    let _prevCustomScript = `${callbacksql}
    `
    let _backCustomScript = ''
    btn.verify.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (script.position === 'front') {
        _prevCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      } else {
        _backCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      }
    })
    _backCustomScript += `
      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    let sql = [...lineMap.values()].map(item => (`
      ${item.insert}
      ${item.selects.join(` union all
      `)}
    `))
    sql = sql.join('')
    sql = _prevCustomScript + sql
    sql = sql + _backCustomScript
    sql = sql.replace(/@ID@/ig, `'${ID || ''}'`)
    sql = sql.replace(/@BID@/ig, `'${BID || ''}'`)
    sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    sql = sql.replace(/@typename@/ig, `'admin'`)
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
    } else {
      sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    }
    if (window.GLOB.debugger === true) {
      console.info('%c' + config.name + '(回调)', 'color: blue')
      console.info(sql.replace(/\n\s{8}/ig, '\n'))
    }
    param.LText = sql
    param.exec_type = window.GLOB.execType || 'y' // 后台解码
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    param.LText = Utils.formatOptions(param.LText, param.exec_type)
    if (window.GLOB.probation) {
      param.s_debug_type = 'Y'
    }
    Api.genericInterface(param).then(res => {
      if (res.status) {
        const that = this
        confirm({
          title: '保存成功。',
          okText: '继续填开',
          cancelText: '关闭',
          onOk() {
            if (config.billOutBtn.reTabId) {
              MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId, 'table')
            }
            if (config.billOutBtn.syncComId) {
              MKEmitter.emit('reloadData', config.billOutBtn.syncComId)
            }
            that.clearData()
          },
          onCancel() {
            if (config.billOutBtn.reTabId) {
              MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId, 'table')
            }
            if (config.billOutBtn.syncComId) {
              MKEmitter.emit('reloadData', config.billOutBtn.syncComId)
            }
            MKEmitter.emit('closeTabView', config.$pageId)
          }
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        this.setState({
          saveType: ''
        })
      }
    })
  }
  getBackSql = () => {
    const { book, BID } = this.state
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    let nation = sessionStorage.getItem('nation') || ''
    let province = sessionStorage.getItem('province') || ''
    let city = sessionStorage.getItem('city') || ''
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    let sql = `/* 系统字段 */
      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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID || ''}'
      `
    return sql
  }
  changeBuyer = (item) => {
@@ -627,7 +1032,7 @@
  }
  render() {
    const { config, book, loading, invTypes, reqfields, saveType, date, invoice_type, 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, tax_type } = this.state
    const { config, book, loading, invTypes, reqfields, saveType, date, timestamp, invoice_type, 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, tax_type } = this.state
    if (!book || (config.wrap.datatype === 'dynamic' && !tax_no)) {
      return <div className="menu-invoice-wrap" style={config.style}>
@@ -647,11 +1052,12 @@
          </div> : null
        }
        <div className="inv-action">
          {config.wrap.backBtn === 'show' ? <Button className="mk-back" onClick={this.goback}><LeftOutlined />返回</Button> : null}
          <Button className="mk-bill" loading={saveType === 'bill'} onClick={this.saveBill}>保存单据</Button>
          <Button className="mk-submit" loading={saveType === 'out'} onClick={this.outBill}>提交开票</Button>
        </div>
        <div className="inv-header">
          {invoice_type ? <Select defaultValue={invoice_type} onChange={this.changeType} dropdownClassName="inv-type-select">
          {invoice_type ? <Select value={invoice_type} onChange={this.changeType} dropdownClassName="inv-type-select">
            {invTypes.map(item => (
              <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
            ))}
@@ -696,7 +1102,7 @@
            </div>
          </div>
          <div className="inv-details">
            <InvoiceTable data={details} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
            <InvoiceTable data={details} timestamp={timestamp} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
          </div>
          <div className="inv-main-content">
            <div className="inv-buyer">
src/tabviews/custom/components/module/invoice/index.scss
@@ -17,6 +17,19 @@
      margin-bottom: 5px;
      height: 30px;
    }
    .mk-back {
      border: none;
      float: left;
      margin-left: 0px;
      padding: 0px;
      box-shadow: none;
    }
    .mk-back::after {
      display: none;
    }
    .mk-back:hover, .mk-back:active, .mk-back:focus {
      color: var(--mk-sys-color);
    }
    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
      color: var(--mk-sys-color);
      border-color: var(--mk-sys-color);
src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx
@@ -78,7 +78,7 @@
  }
  render() {
    const { line, delLine, trigger } = this.props
    const { line, delLine, trigger, field } = this.props
    const { bill_count, unitprice, amount_line } = this.state
    
    return <div className="mk-tr active">
@@ -86,22 +86,22 @@
        <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')}/>
        <Input defaultValue={line.spec || ''} autoFocus={field === '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')}/>
        <Input defaultValue={line.unit || ''} autoFocus={field === 'unit'} onChange={(e) => this.onChange(e.target.value, 'unit')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={bill_count} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({bill_count: val})} onBlur={() => this.onChange(bill_count, 'bill_count')}/>
        <InputNumber value={bill_count} autoFocus={field === 'bill_count'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({bill_count: val})} onBlur={() => this.onChange(bill_count, 'bill_count')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={unitprice} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({unitprice: val})} onBlur={() => this.onChange(unitprice, 'unitprice')}/>
        <InputNumber value={unitprice} autoFocus={field === 'unitprice'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({unitprice: val})} onBlur={() => this.onChange(unitprice, 'unitprice')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={amount_line} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({amount_line: val})} onBlur={() => this.onChange(amount_line, 'amount_line')}/>
        <InputNumber value={amount_line} autoFocus={field === 'amount_line'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({amount_line: val})} onBlur={() => this.onChange(amount_line, 'amount_line')}/>
      </div>
      <div className="mk-td mk-right">{line.tax_name}</div>
      <div className="mk-td mk-right">{line.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} <span className="del-line" onClick={() => delLine(line.uuid)}></span> </div>
      <div className="mk-td mk-right">{line.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} <span className="del-line" onClick={(e) => delLine(line.uuid, e)}></span> </div>
    </div>
  }
}
@@ -109,6 +109,7 @@
class InvoiceTable extends Component {
  static propTpyes = {
    config: PropTypes.object,
    timestamp: PropTypes.string,
    data: PropTypes.any,
    onChange: PropTypes.func
  }
@@ -116,6 +117,7 @@
  state = {
    data: [],
    editKey: '',
    key: '',
    total: {}
  }
@@ -140,6 +142,21 @@
  componentDidMount () {
    MKEmitter.addListener('resetDetails', this.resetDetails)
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (this.props.timestamp !== nextProps.timestamp) {
      let _data = fromJS(nextProps.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)
      })
    }
  }
  /**
@@ -268,9 +285,11 @@
    this.setState({data: [...data, line]})
  }
  delLine = () => {
    const { editKey, data } = this.state
  delLine = (uuid, e) => {
    const { data } = this.state
    e.stopPropagation()
    if (data.length === 1) {
      notification.warning({
        top: 92,
@@ -280,7 +299,7 @@
      return
    }
    let _data = data.filter(item => item.uuid !== editKey)
    let _data = data.filter(item => item.uuid !== uuid)
    this.setState({data: _data}, () => {
      this.getTotal(_data)
@@ -306,8 +325,13 @@
    this.props.onChange(_data)
  }
  checkLine = (uuid) => {
    this.setState({editKey: uuid})
  checkLine = (uuid, key, e) => {
    e && e.stopPropagation()
    this.setState({editKey: uuid, key: key || ''}, () => {
      if (key === 'productname') {
        this.setState({visible: true})
      }
    })
  }
  changeDetail = (prod) => {
@@ -323,6 +347,8 @@
        item.tax_name = prod.tax_rate * 100 + '%'
        item.free_tax_mark = prod.free_tax_mark || ''
        item.vat_special_management = prod.vat_special_management || ''
        item.tax_item = prod.tax_item || ''
        item.tax_method = prod.tax_method || ''
        if (prod.vat_special_management && prod.free_tax_mark === 'true') {
          item.tax_name = prod.vat_special_management
@@ -356,7 +382,7 @@
  render() {
    const { config, tax_type } = this.props
    const { editKey, data, total, visible } = this.state
    const { editKey, key, data, total, visible } = this.state
    return (
      <div className="detail-wrap">
@@ -373,18 +399,18 @@
        </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 <DetailLine key={item.uuid} line={item} field={key} 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 || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{`${item.unitprice || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{`${item.amount_line || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, item.productname ? '' : 'productname', e)}>{item.productname || ''}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'spec', e)}>{item.spec || ''}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'unit', e)}>{item.unit || ''}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'bill_count', e)}>{`${item.bill_count || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'unitprice', e)}>{`${item.unitprice || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'amount_line', e)}>{`${item.amount_line || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{item.tax_name}</div>
            <div className="mk-td mk-right">{item.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}<span className="del-line" onClick={() => this.delLine(item.uuid)}></span></div>
            <div className="mk-td mk-right">{item.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}<span className="del-line" onClick={(e) => this.delLine(item.uuid, e)}></span></div>
          </div>
        })}
        <div className="mk-total">
src/templates/modalconfig/dragelement/card.jsx
@@ -138,7 +138,7 @@
  } else if (card.type === 'formula') {
    formItem = <div style={{marginTop: '8px', color: 'rgba(0, 0, 0, 0.85)', lineHeight: '1.5', ...card.style}}>{card.formula}{card.postfix || ''}</div>
  } else if (card.type === 'split') {
    formItem = <div className="split-line" style={card.style}>{card.label}</div>
    formItem = <div className="split-line" style={card.style}>{card.label}{showField && card.supField ? <span style={{color: '#8E44AD'}}>{`(上级${card.supField})`}</span> : null}</div>
  } else if (card.type === 'vercode') {
    formItem = <Input style={{marginTop: '4px'}} placeholder={card.placeholder || ''} value={card.initval} addonAfter={
      <Button type="link" style={{padding: 0}} size="small">
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -278,7 +278,7 @@
        <Row gutter={24}>
          {!type && btn.sheet ? <Col span={8}>
            <Form.Item label="表名" style={{whiteSpace: 'nowrap', margin: 0}}>
              {btn.sheet}(表变量请使用#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')})
              {btn.sheet}(临时表请使用#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')})
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={10}>