king
2024-10-10 633e781cefd3e984872953c64f743dc9abb33163
2024-10-10
5个文件已修改
918 ■■■■ 已修改文件
src/components/header/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.jsx 687 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/home/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx
@@ -56,7 +56,9 @@
  componentDidMount () {
    // 获取系统的版本信息,延时查询
    setTimeout(() => {
      Api.getAppVersion()
      if (!window.GLOB.$error) {
        Api.getAppVersion()
      }
    }, 1000)
    // sessionStorage 跨页面共享
src/tabviews/custom/components/module/invoice/index.jsx
@@ -85,6 +85,12 @@
    _config.buyer = this.formatSetting(_config.buyer, 'buyer')
    _config.detail = this.formatSetting(_config.detail, 'detail')
    _config.detail.uuid = _config.uuid
    _config.buyer.setting.uuid = _config.uuid + 'buyer'
    _config.detail.setting.uuid = _config.uuid + 'detail'
    _config.billOutBtn.uuid = _config.uuid
    _config.billSaveBtn.uuid = _config.uuid
    _config.billOutBtn.logLabel = _config.$menuname + '-' + _config.billOutBtn.label
    _config.billSaveBtn.logLabel = _config.$menuname + '-' + _config.billSaveBtn.label
    let book = null
    let pas = {}
@@ -487,18 +493,23 @@
    setTimeout(() => {
      this.getBillMsg().then(() => {
        let sql = this.getPreSql(config.billSaveBtn)
        let param = {
          func: 'sPC_TableData_InUpDe',
          LText: sql,
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: BID
        let param = null
        if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + config.billSaveBtn.type)) {
          param = this.getBackPreParam(config.billSaveBtn)
        } else {
          let sql = this.getPreSql(config.billSaveBtn)
          param = {
            func: 'sPC_TableData_InUpDe',
            LText: sql,
            exec_type: window.GLOB.execType || 'y',
            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
            BID: BID
          }
          param.secretkey = Utils.encrypt('', param.timestamp)
          param.LText = Utils.formatOptions(param.LText, param.exec_type)
        }
        param.secretkey = Utils.encrypt('', param.timestamp)
        param.LText = Utils.formatOptions(param.LText, param.exec_type)
        this.setState({
          saveType: 'bill'
@@ -570,19 +581,24 @@
    setTimeout(() => {
      this.getBillMsg().then(() => {
        let sql = this.getPreSql(config.billOutBtn)
        let param = {
          func: 'sPC_TableData_InUpDe',
          LText: sql,
          script_type: 'Y',
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: BID
        let param = null
        if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + config.billOutBtn.type)) {
          param = this.getBackPreParam(config.billOutBtn)
        } else {
          let sql = this.getPreSql(config.billOutBtn)
          param = {
            func: 'sPC_TableData_InUpDe',
            LText: sql,
            script_type: 'Y',
            exec_type: window.GLOB.execType || 'y',
            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
            BID: BID
          }
          param.secretkey = Utils.encrypt('', param.timestamp)
          param.LText = Utils.formatOptions(param.LText, param.exec_type)
        }
        param.secretkey = Utils.encrypt('', param.timestamp)
        param.LText = Utils.formatOptions(param.LText, param.exec_type)
        this.setState({
          saveType: 'out'
@@ -734,6 +750,198 @@
    return sql
  }
  getBackPreParam = (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 ex = window.GLOB.CacheData.get('sql_' + btn.uuid + btn.type)
    let exps = []
    let values = {
      time_id: Utils.getguid(),
      roleid: sessionStorage.getItem('role_id') || '',
      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
      mk_organization: sessionStorage.getItem('organization') || '',
      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
      mk_nation: sessionStorage.getItem('nation') || '',
      mk_province: sessionStorage.getItem('province') || '',
      mk_city: sessionStorage.getItem('city') || '',
      mk_district: sessionStorage.getItem('district') || '',
      mk_address: sessionStorage.getItem('address') || '',
      id: ID || '',
      bid: BID || '',
      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
    }
    if (window.GLOB.externalDatabase !== null) {
      values.db = window.GLOB.externalDatabase
    }
    let options = fromJS(oriDetails).toJS()
    let price = 0
    let tax = 0
    let lines = []
    details.forEach(line => {
      if (!line.productcode) return
      let vals = [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
      tax += line.tax_amount * 100
      if (options.length) {
        options = options.filter(option => {
          if (option.uuid === line.uuid) {
            data_type = 'upt'
            return false
          }
          return true
        })
      }
      vals.push(data_type)
      lines.push(vals)
    })
    let _total = (price - tax) / 100
    price = price / 100
    tax = tax / 100
    if (options.length) {
      options.forEach(line => {
        let vals = [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']
        lines.push(vals)
      })
    }
    ex.reps.forEach(n => {
      let key = n.toLowerCase()
      if (values.hasOwnProperty(key)) {
        exps.push({
          key: n,
          value: values[key]
        })
      }
    })
    exps.push({
      key: 'account_id',
      value: book.account_id || ''
    }, {
      key: 'account_year_id',
      value: book.account_year_id || ''
    }, {
      key: 'account_code',
      value: book.account_code || ''
    }, {
      key: 'account_year_code',
      value: book.account_year_code || ''
    }, {
      key: 'invoice_type',
      value: invoice_type
    }, {
      key: 'from_to_name',
      value: from_to_name
    }, {
      key: 'from_to_tax_no',
      value: from_to_tax_no
    }, {
      key: 'from_to_addr',
      value: from_to_addr
    }, {
      key: 'from_to_tel',
      value: from_to_tel
    }, {
      key: 'from_to_bank_name',
      value: from_to_bank_name
    }, {
      key: 'from_to_account_no',
      value: from_to_account_no
    }, {
      key: 'from_to_mob',
      value: from_to_mob
    }, {
      key: 'from_to_email',
      value: from_to_email
    }, {
      key: 'from_to_code',
      value: from_to_code
    }, {
      key: 'orgname',
      value: orgname
    }, {
      key: 'tax_no',
      value: tax_no
    }, {
      key: 'addr',
      value: addr
    }, {
      key: 'tel',
      value: tel
    }, {
      key: 'bank_name',
      value: bank_name
    }, {
      key: 'account_no',
      value: account_no
    }, {
      key: 'remark',
      value: remark
    }, {
      key: 'payee',
      value: payee
    }, {
      key: 'reviewer',
      value: reviewer
    }, {
      key: 'drawer',
      value: drawer
    }, {
      key: 'io',
      value: io
    }, {
      key: 'orgcode',
      value: book.orgcode || ''
    }, {
      key: 'total_net_amount',
      value: _total
    }, {
      key: 'total_tax',
      value: tax
    }, {
      key: 'total_amount',
      value: price
    }, {
      key: 'business_type',
      value: business_type || config.wrap.business_type || ''
    })
    exps.push({
      key: 'mk_excel_data',
      value: lines
    })
    let md5_id = ''
    if (window.GLOB.probation) {
      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
    }
    return {
      $backend: true,
      $type: 's_TableData_InUpDe',
      data: [{
        id: ex.id,
        menuname: btn.logLabel || '',
        exps: exps,
        md5_id: md5_id
      }]
    }
  }
  getBillMsg = () => {
    const { requireds, invoice_type, details, remark, from_to_addr, addr } = this.state
@@ -844,147 +1052,153 @@
  callBackBill = (result) => {
    const { config, BID, ID } = this.state
    let btn = config.billOutBtn
    let lines = []
    let pre = '@'
    let param = null
    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) return
              Object.keys(item).forEach(k => {
                if (item[k] === null) {
                  item[k] = ''
                }
    if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + 'billback')) {
      param = this.getCallBackendParam(config.billOutBtn, result)
    } else {
      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) return
                Object.keys(item).forEach(k => {
                  if (item[k] === null) {
                    item[k] = ''
                  }
                })
                item.$$key = tb + '_' + key
                subObjs.push(item)
              })
              item.$$key = tb + '_' + key
              subObjs.push(item)
            })
          } else if (Object.keys(val).length > 0) {
            val.$$key = tb + '_' + key
            subObjs.push(val)
            } 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}'`)
          }
        } else {
          if (typeof(val) === 'string') {
            val = val.replace(/'/ig, '"')
          }
          keys.push('[' + key + ']')
          vals.push(`'${val}'`)
        }
      })
      keys = keys.join(',')
      vals = vals.join(',')
      lines.push({
        table: md5(tb + keys),
        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${keys ? vals + ',' : ''}'${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]
        })
        keys = keys.join(',')
        vals = vals.join(',')
        lines.push({
          table: md5(tb + keys),
          insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
          select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
        })
        subObjs.forEach(item => {
          getDefaultSql(item, item.$$key, id, level + 1)
        })
      }
    })
    let param = {
      func: 'sPC_TableData_InUpDe',
      BID: BID,
      menuname: config.name + '(回调)'
    }
    let callbacksql = this.getBackSql()
    let _prevCustomScript = `${callbacksql}
    `
    let _backCustomScript = ''
    btn.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (script.position === 'front') {
        _prevCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      } else {
        _backCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      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]
          })
        }
      })
      param = {
        func: 'sPC_TableData_InUpDe',
        BID: BID,
        menuname: config.name + '(回调)'
      }
    })
    _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(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
    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) {
      window.mkInfo('%c' + config.name + '(回调)', 'color: blue')
      window.mkInfo(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'
      let callbacksql = this.getBackSql()
      let _prevCustomScript = `${callbacksql}
      `
      let _backCustomScript = ''
      btn.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(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
      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) {
        window.mkInfo('%c' + config.name + '(回调)', 'color: blue')
        window.mkInfo(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 => {
@@ -1015,6 +1229,163 @@
    })
  }
  getCallBackendParam = (btn, result) => {
    const { book, BID, ID } = this.state
    let lines = []
    let tables = []
    btn.verify.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
      }
    })
    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
    if (result.$ErrCode) {
      delete result.$ErrCode
      delete result.$ErrMesg
    }
    let getDefaultSql = (obj, tb, bid, level) => {
      let vals = {}
      let subObjs = []
      let id = Utils.getuuid()
      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) return
              Object.keys(item).forEach(k => {
                if (item[k] === null) {
                  item[k] = ''
                }
              })
              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, '"')
          } else {
            val = val + ''
          }
          vals[key] = val
        }
      })
      vals.mk_level = level
      vals.mk_id = id
      vals.mk_bid = bid
      let isnew = true
      lines.forEach(line => {
        if (line.tb === tb) {
          line.values.push(vals)
          isnew = false
        }
      })
      if (isnew) {
        lines.push({
          tb: tb,
          type: tables.includes('#' + tb) ? '01' : '02',
          values: [vals]
        })
      }
      subObjs.forEach(item => {
        getDefaultSql(item, item.$$key, id, level + 1)
      })
    }
    getDefaultSql(result, btn.cbTable, '', 1)
    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid + 'billback')
    let exps = []
    let values = {
      time_id: Utils.getguid(),
      roleid: sessionStorage.getItem('role_id') || '',
      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
      mk_organization: sessionStorage.getItem('organization') || '',
      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
      mk_nation: sessionStorage.getItem('nation') || '',
      mk_province: sessionStorage.getItem('province') || '',
      mk_city: sessionStorage.getItem('city') || '',
      mk_district: sessionStorage.getItem('district') || '',
      mk_address: sessionStorage.getItem('address') || '',
      id: ID || '',
      bid: BID || '',
      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
    }
    if (window.GLOB.externalDatabase !== null) {
      values.db = window.GLOB.externalDatabase
    }
    ex.reps.forEach(n => {
      let key = n.toLowerCase()
      if (values.hasOwnProperty(key)) {
        exps.push({
          key: n,
          value: values[key]
        })
      }
    })
    exps.push({
      key: 'account_id',
      value: book.account_id || ''
    }, {
      key: 'account_year_id',
      value: book.account_year_id || ''
    }, {
      key: 'account_code',
      value: book.account_code || ''
    }, {
      key: 'account_year_code',
      value: book.account_year_code || ''
    })
    exps.push({
      key: 'mk_outer_params',  // 回调脚本的数据替换
      value: lines
    })
    let md5_id = ''
    if (window.GLOB.probation) {
      md5_id = md5('back_' + btn.uuid + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
    }
    return {
      $backend: true,
      $type: 's_TableData_InUpDe',
      data: [{
        id: ex.id,
        menuname: btn.logLabel + '(回调)',
        exps: exps,
        md5_id: md5_id
      }]
    }
  }
  getBackSql = () => {
    const { book, BID } = this.state
src/tabviews/custom/components/module/invoice/index.scss
@@ -23,6 +23,8 @@
      margin-left: 0px;
      padding: 0px;
      box-shadow: none;
      position: relative;
      z-index: 1;
    }
    .mk-back::after {
      display: none;
src/tabviews/home/index.jsx
@@ -43,7 +43,7 @@
      this.setState({
        waiting: false
      })
    } else {
    } else if (!window.GLOB.$error) {
      setTimeout(() => {
        this.check(times)
      }, 200)
src/utils/utils-custom.js
@@ -3195,6 +3195,26 @@
            resetButton(item, group.subButton)
          })
        } else if (item.type === 'module' && item.subtype === 'invoice') {
          let msg = getDataSource(item.buyer, [])
          sqls.push({uuid: item.uuid + 'buyer', type: 'datasource', ...msg})
          let _msg = getDataSource(item.detail, [])
          sqls.push({uuid: item.uuid + 'detail', type: 'datasource', ..._msg})
          let btnmsg = getInvoicePreSql(item.billSaveBtn, item.$menuname + '-' + item.billSaveBtn.label)
          sqls.push({uuid: item.uuid + item.billSaveBtn.type, type: 'button', ...btnmsg})
          let _btnmsg = getInvoicePreSql(item.billOutBtn, item.$menuname + '-'  + item.billOutBtn.label)
          sqls.push({uuid: item.uuid + item.billOutBtn.type, type: 'button', ..._btnmsg})
          let backmsg = getInvoiceSysBackSql(item.billOutBtn, item.$menuname + '-'  + item.billOutBtn.label + '(回调)')
          sqls.push({uuid: item.uuid + 'billback', type: 'btnCallBack', ...backmsg})
        }
      }
    })
@@ -6001,6 +6021,209 @@
    return {LText: sql, md5: md5(sql), reps}
  }
  let getInvoicePreSql = (btn, logLabel) => {
    let reps = []
    let sysVars = ['loginuid', 'sessionuid', 'userid', 'appkey', 'lang', 'username', 'fullname', 'menuname']
    let _script = ''
    btn.scripts.forEach(item => {
      if (item.status === 'false') return
      _script += `
      ${item.sql}
      `
    })
    _script = _script.replace(/@typename@/ig, `'admin'`)
    let regs = ['ID', 'BID', 'time_id', 'datam', ...sysVars]
    regs.forEach(s => {
      if (new RegExp('@' + s + '@', 'ig').test(_script)) {
        reps.push(s)
      }
    })
    reps.forEach(n => {
      _script = _script.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
    })
    if (/\$@/ig.test(_script)) {
      _script = _script.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
      reps.push('datam_begin', 'datam_end')
    }
    if (/@db@/ig.test(_script)) {
      reps.push('db')
    }
    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
    let decSql = []
    let secSql = []
    syses.forEach(s => {
      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(_script)) {
        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
          decSql.push(`@${s} nvarchar(512)`)
        } else if (['mk_address'].includes(s)) {
          decSql.push(`@mk_address nvarchar(100)`)
        } else {
          decSql.push(`@${s} nvarchar(50)`)
        }
        secSql.push(`@${s}='@${s}@'`)
        reps.push(s)
      }
    })
    decSql = decSql.join(',')
    secSql = secSql.join(',')
    let sql = `/* ${logLabel} */
      BEGIN TRY
      begin TRAN
      Declare @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @tbid nvarchar(50)${decSql ? ',' + decSql : ''}
      Select @ErrorCode='S', @retmsg='', @account_id='@account_id@', @account_year_id='@account_year_id@', @account_code='@account_code@', @account_year_code='@account_year_code@'${secSql ? ',' + secSql : ''}
      /* 发票主表字段 */
      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='@orgcode@', @total_net_amount=@total_net_amount@, @total_tax=@total_tax@, @total_amount=@total_amount@, @business_type='@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), 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, tax_item, tax_method, jskey, data_type)
      @mk_excel_data@
      /* 自定义脚本 */
      ${_script}
      `
    if (btn.type === 'billout') {
      sql += callback
    } else {
      sql += `
        select @ErrorCode as ErrorCode,@retmsg as retmsg
        ${callback}
        `
    }
    reps = reps.filter(n => {
      if (sysVars.includes(n.toLowerCase())) {
        return false
      }
      return true
    })
    sql = sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
    return {LText: sql, md5: md5(sql), reps}
  }
  let getInvoiceSysBackSql = (btn, logLabel) => {
    let _prev = ''
    let _back = ''
    let tables = []
    let reps = []
    btn.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
      }
      if (script.position === 'front') {
        _prev += `
        /* 自定义脚本 */
        ${script.sql}
        `
      } else {
        _back += `
        /* 自定义脚本 */
        ${script.sql}
        `
      }
    })
    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
    let decSql = []
    let secSql = []
    let testSql = _prev + _back
    _prev = _prev.replace(/@typename@/ig, `'admin'`)
    _back = _back.replace(/@typename@/ig, `'admin'`)
    let regs = ['ID', 'BID', 'time_id', 'datam', ...sysVars]
    regs.forEach(s => {
      if (new RegExp('@' + s + '@', 'ig').test(testSql)) {
        reps.push(s)
      }
    })
    reps.forEach(n => {
      _prev = _prev.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
      _back = _back.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
    })
    if (/\$@/ig.test(testSql)) {
      _prev = _prev.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
      _back = _back.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
      reps.push('datam_begin', 'datam_end')
    }
    if (/@db@/ig.test(testSql)) {
      reps.push('db')
    }
    syses.forEach(s => {
      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(testSql)) {
        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
          decSql.push(`@${s} nvarchar(512)`)
        } else if (['mk_address'].includes(s)) {
          decSql.push(`@mk_address nvarchar(100)`)
        } else {
          decSql.push(`@${s} nvarchar(50)`)
        }
        secSql.push(`@${s}='@${s}@'`)
        reps.push(s)
      }
    })
    decSql = decSql.join(',')
    secSql = secSql.join(',')
    // 需要声明的变量集
    let _sql = `/* ${logLabel} */
      BEGIN TRY
      begin TRAN
      Declare @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @tbid nvarchar(50)${decSql ? ',' + decSql : ''}
      Select @ErrorCode='S', @retmsg='', @account_id='@account_id@', @account_year_id='@account_year_id@', @account_code='@account_code@', @account_year_code='@account_year_code@'${secSql ? ',' + secSql : ''}
      ${_prev}
      /* 外部接口入参 */
      @mk_outer_params@
      ${_back}
      select @ErrorCode as ErrorCode,@retmsg as retmsg
      ${callback}
      `
    _sql = _sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
    reps = reps.filter(n => {
      if (sysVars.includes(n.toLowerCase())) {
        return false
      }
      return true
    })
    return { LText: _sql, md5: md5(_sql), reps, tbs: tables }
  }
  let _mainSearch = []
  if (appType === 'mob') {