@zhouhaiyang0326/invoicetemplateform

A Vue 2 invoice template form component.
954
Install
npm install @zhouhaiyang0326/invoicetemplateform
Latest Version:0.1.28
Vue:2
License:MIT
Last Updated:Oct 24, 2026
Links: npm
Maintainer: zhouhaiyang0326

invoicetemplateform

基于 Vue 2.7、JavaScript 和 Vite 构建的发票模板表单组件。

功能特性

  • 发票类型下拉选择
  • 左上角信息通过 top-info-fields 的 field、label、value 配置展示,提交时合并进表单
  • 开票明细操作按钮上方提供独占整行的“开票要求”多行文本框,内容保存在 form.invoiceRequirement
  • “选择订单”“选择转账单”按钮,分别触发 select-order、select-transfer-order 事件
  • 顶部按钮支持通过 actions 配置名称、父组件方法和样式类型
  • 购方名称按钮通过 buyer-actions 配置;销方名称按钮通过 seller-actions 配置
  • 购销互换会同步交换购方和销方的名称、纳税人识别号、地址、电话、开户银行和银行账号
  • 每个字段的权限通过 field-permissions 配置,支持 edit、readonly、required
  • 默认必填:购方名称、购方纳税人识别号、销方名称、销方纳税人识别号,以及明细项目类型、项目名称、单价、金额、税率、税额;其余字段默认可修改
  • invoiceType 使用两位字符串编码:'01' 表示增值税专用发票,'02' 表示普通发票
  • 税率仅提供 13% 和 1%:专票默认 13%,普票默认 1%,切换类型和新增明细时自动选择
  • 买方、卖方信息展示与统一展开/收起;收起时保留名称、纳税人识别号两行
  • 明细行新增、删除、全选与清空确认
  • 所有明细列表统一提供新增、删除事件,并暴露对应新增、删除和清空方法
  • 数量、单价、金额三者联动,任意修改一个会自动推算另一个关联值
  • 单价和金额至少显示两位小数
  • 含税/不含税切换,标题和值同步转换
  • 税额、不含税合计、价税合计自动汇总
  • 价税合计自动生成人民币大写
  • 订单信息和收款信息表格通过 detail-tables 配置列、表头按钮、行内按钮和字段权限
  • “添加到备注”实时同步到备注信息区
  • 备注 textarea 手动输入与字数统计
  • 图标字体本地化,不依赖外部 CDN

环境要求

  • Node.js >= 14.18.0
  • Vue ^2.7.0
  • npm

Vue 2 已停止维护,安装时可能出现 EOL 提示,不影响当前项目运行。

安装

npm install @zhouhaiyang0326/invoicetemplateform

如果宿主项目还没有 Vue 2.7:

npm install vue@^2.7.16

Vue CLI 4 / Webpack 4 不支持 npm exports 子路径解析。此类项目请使用:

import '@zhouhaiyang0326/invoicetemplateform/dist/style.css'

Webpack 5、Vite 等项目可继续使用 @zhouhaiyang0326/invoicetemplateform/style.css。

快速开始

全局注册

import Vue from 'vue'
import InvoiceTemplateForm from '@zhouhaiyang0326/invoicetemplateform'
import '@zhouhaiyang0326/invoicetemplateform/style.css'

Vue.use(InvoiceTemplateForm)

new Vue({
  render: (h) => h(App),
}).$mount('#app')
<template>
  <InvoiceTemplateForm />
</template>

按需引入

<script>
import { InvoiceTemplateForm } from '@zhouhaiyang0326/invoicetemplateform'
import '@zhouhaiyang0326/invoicetemplateform/style.css'

export default {
  components: {
    InvoiceTemplateForm,
  },
}
</script>

<template>
  <InvoiceTemplateForm />
</template>

组件没有必填参数,挂载后即可使用完整表单界面。

表单数据与顶部按钮配置

通过 v-model 传入表单数据,通过 actions 配置顶部按钮:

<template>
  <InvoiceTemplateForm
    ref="invoiceForm"
    v-model="invoiceForm"
    :actions="invoiceActions"
    :detail-tables="detailTables"
    :buyer-actions="buyerActions"
    :seller-actions="sellerActions"
    :top-info-fields="topInfoFields"
    :field-permissions="fieldPermissions"
    @button-click="handleButtonClick"
  />
</template>

<script>
import { InvoiceTemplateForm } from '@zhouhaiyang0326/invoicetemplateform'

export default {
  components: { InvoiceTemplateForm },
  data() {
    return {
      fieldPermissions: { // 覆盖默认字段权限,未配置字段沿用默认权限
        gmfMc: 'required', // 购方名称:可修改且必填
        gmfNsrsbh: 'readonly', // 购方纳税人识别号:只读
        xsfMc: 'required', // 销方名称:可修改且必填
        details: { // 开票明细字段权限
          name: 'required', // 项目名称:可修改且必填
          amount: 'readonly', // 金额:只读
          taxRate: 'required', // 税率:可修改且必填
        },
        bz: 'required', // 备注:可修改且必填
      },
      invoiceForm: {
        invoiceType: '01', // 发票类型:01 增值税专用发票,02 普通发票
        spfEmail: 'invoice@example.com', // 收票方邮箱
        spfPhone: '13800138000', // 收票方手机号
        gmfMc: '杭州测试科技有限公司', // 购方名称
        gmfNsrsbh: '91330106MA2XXXXXXX', // 购方纳税人识别号
        gmfDz: '浙江省杭州市西湖区文三路 100 号', // 购方地址
        gmfLxdh: '0571-88886666', // 购方电话
        gmfKhh: '', // 购方开户银行
        gmfYhzh: '', // 购方银行账号
        xsfMc: '温州测试销方有限公司', // 销方名称
        xsfNsrsbh: '91330302MA2853J12E', // 销方纳税人识别号
        xsfDz: '浙江省温州市鹿城区测试地址', // 销方地址
        xsfLxdh: '0577-88886666', // 销方电话
        xsfKhh: '中国农业银行股份有限公司温州滨江支行', // 销方开户银行
        xsfYhzh: '19211501040001739', // 销方银行账号
        details: [ // 开票明细列表
          {
            projectType: '服务类', // 项目类型
            name: '技术服务费', // 项目名称
            spec: '标准版', // 规格型号
            unit: '项', // 单位
            quantity: '1', // 数量
            unitPrice: '100', // 单价
            amount: '100', // 金额
            taxRate: 0.13, // 税率,显示为 13%
          },
        ],
        orderDetails: [ // 订单信息列表
          {
            orderCode: 'DD001', // 订单编码
            productCode: 'CP001', // 产品编码
            productName: '技术服务费', // 产品名称
            spec: '标准版', // 规格型号
            quantity: '2', // 数量
            unitPrice: '500.00', // 单价
            amount: '1000.00', // 金额
          },
        ],
        receipts: [ // 收款信息列表
          {
            receiptCode: 'SK001', // 收款单编码
            orderCode: 'DD001', // 订单编码
            receiptUnit: '测试收款单位', // 收款单位
            receiptAccount: '62220001', // 收款账户
            receiptAmount: '1234.50', // 收款金额
            receiptShop: '测试店铺', // 收款店铺
          },
        ],
        invoiceRequirement: '请按订单内容开具电子发票', // 开票要求
        bz: '测试备注', // 手动输入的备注文本
      },
    }
  },
  computed: {
    invoiceActions() {
      return [
        {
          name: '选择订单', // 按钮名称
          type: 'primary', // 按钮样式类型
          code: 'select-order', // 按钮业务编码
        },
        {
          name: '选择转账单', // 按钮名称
          type: 'primary-bordered', // 按钮样式类型
          code: 'select-transfer-order', // 按钮业务编码
        },
      ]
    },
    detailTables() {
      return {
        invoice: {
          buttons: {
            header: [
              { code: 'add' },
              { code: 'batch-edit' },
              { code: 'import' },
              { code: 'export' },
              { code: 'clear' },
            ],
            body: [
              { code: 'delete' },
              {
                name: '复制行',
                type: 'default',
                code: 'copy-row',
              },
            ],
          },
        },
        order: {
          field: 'orderDetails',
          title: '订单信息',
          buttons: {
            header: [
              { code: 'add' },
              {
                name: '关联订单',
                type: 'default',
                code: 'relate-order',
              },
              { code: 'clear' },
            ],
            body: [
              { code: 'delete' },
              {
                name: '复制行',
                type: 'default',
                code: 'copy-order-row',
              },
            ],
          },
          columns: [
            {
              field: 'orderCode',
              label: '订单编码',
              type: 'text',
              permissions: 'edit',
              required: true,
            },
            {
              field: 'productName',
              label: '产品名称',
              type: 'text',
              permissions: 'edit',
            },
            {
              field: 'amount',
              label: '金额',
              type: 'num',
              permissions: 'edit',
              required: true,
              summary: true,
            },
          ],
        },
        receipt: {
          field: 'receipts',
          title: '收款信息',
          buttons: {
            header: [
              { code: 'add' },
              { code: 'clear' },
            ],
            body: [{ code: 'delete' }],
          },
          columns: [
            {
              field: 'receiptCode',
              label: '收款单编码',
              type: 'text',
              permissions: 'edit',
              required: true,
            },
            {
              field: 'receiptAccount',
              label: '收款账户',
              type: 'text',
              permissions: 'readonly',
            },
            {
              field: 'receiptAmount',
              label: '收款金额',
              type: 'num',
              permissions: 'edit',
              required: true,
              summary: true,
            },
          ],
        },
      }
    },
    topInfoFields() {
      return [
        {
          field: 'shopName',
          label: '店铺名称',
          value: '温州测试店铺',
        },
        {
          field: 'orderTime',
          label: '下单时间',
          value: '2026-10-20 10:30:00',
        },
        {
          field: 'paymentTime',
          label: '付款时间',
          value: '2026-10-20 10:35:00',
        },
        {
          field: 'preInvoiceAmount',
          label: '预开票金额(元)',
          value: '1000.00',
        },
        {
          field: 'receivedAmount',
          label: '收款金额(元)',
          value: '1234.50',
        },
      ]
    },
    buyerActions() {
      return [
        { code: 'transfer' }, // 使用组件内置购销互换方法
        {
          name: '选择购方', // 自定义按钮名称
          type: 'primary-bordered', // 按钮颜色类型
          code: 'select-buyer', // 按钮业务编码
        },
      ]
    },
    sellerActions() {
      return [
        {
          name: '选择销方', // 按钮名称
          type: 'primary', // 按钮颜色类型
          code: 'select-seller', // 按钮业务编码
        },
      ]
    },
  },
  methods: {
    handleSelectOrder(form, code) {
      console.log('选择订单', code, form)
    },
    handleSelectTransferOrder(form, code) {
      console.log('选择转账单', code, form)
    },
    handleSellerAction(form, code) {
      console.log('销方名称按钮', code, form)
    },
    handleBuyerAction(form, code) {
      console.log('购方名称按钮', code, form)
    },
    handleDetailAction(form, type, code) {
      console.log('明细列表按钮', type, code, form)
    },
    handleDetailRowAction(form, type, code, item, index) {
      console.log('明细行按钮', type, code, item, index, form)
    },
    handleSubmit() {
      const submitData = this.$refs.invoiceForm.getSubmitData()
      console.log('合并左上角信息后的表单', submitData)
    },
  },
}
</script>

Vue 2 的 v-model 对应组件的 value prop 和 input 事件。组件内部修改会同步 回 invoiceForm,父组件替换 invoiceForm 后组件也会重新同步。

左上角信息通过 top-info-fields 配置:

topInfoFields: [
  {
    field: 'shopName',
    label: '店铺名称',
    type: 'input',
    permissions: 'required',
    value: '温州测试店铺',
  },
  {
    field: 'orderTime',
    label: '下单时间',
    type: 'text',
    permissions: 'readonly',
    value: '2026-10-20 10:30:00',
  },
  {
    field: 'paymentTime',
    label: '付款时间',
    type: 'text',
    permissions: 'readonly',
    value: '2026-10-20 10:35:00',
  },
  {
    field: 'preInvoiceAmount',
    label: '预开票金额(元)',
    type: 'text',
    permissions: 'readonly',
    value: '1000.00',
  },
  {
    field: 'receivedAmount',
    label: '收款金额(元)',
    type: 'text',
    permissions: 'readonly',
    value: '1234.50',
  },
]

这些值默认只用于展示,不会立即写入 form。左上角字段不会自动添加千分位、 补齐小数或使用其他字段替代空值,直接按配置原值展示。提交时使用:

const submitData = this.$refs.invoiceForm.getSubmitData()

submitData 会按每项的 field 把 value 合并到表单副本。调用组件的 submit() 会合并到当前表单,并触发 submit 事件。

topInfoFields 同样支持 type 和 permissions:

  • text、input、num、number、date、datetime-local
  • select,通过 options 传入 { value, label }
  • edit、readonly、required、hidden

date、datetime-local 的 value 支持 10 位秒级或 13 位毫秒级时间戳。

select 默认支持按 label 或 value 搜索;传入 searchable: false 可关闭搜索。

input、数字、日期和 select 类型会直接编辑当前表单数据,并在 getFormData()/提交时合并;required 会参与必填校验,hidden 不渲染, readonly 只展示不可修改。未传 type 时按 text 展示,未传 permissions 时默认为 edit。

不传 top-info-fields 或传入空数组时,左上角信息区域不展示。

备注信息下方自定义字段

通过 invoice-info-fields 在“备注信息”下方渲染四列表格。配置格式与 top-info-fields 相同,并增加 type 和 permissions:

<InvoiceTemplateForm
  v-model="invoiceForm"
  :invoice-info-fields="invoiceInfoFields"
/>
invoiceInfoFields: [
  {
    field: 'contractNo',
    label: '合同编号',
    type: 'input',
    permissions: 'required',
  },
  {
    field: 'settlementType',
    label: '结算方式',
    type: 'select',
    permissions: 'edit',
    value: 'MONTHLY',
    options: [
      { value: 'MONTHLY', label: '月结' },
      { value: 'CASH', label: '现结' },
    ],
  },
  {
    field: 'orderSource',
    label: '订单来源',
    type: 'text',
    permissions: 'readonly',
    value: '线上订单',
  },
]

支持的 type:

类型 展示方式
text 文本
input 文本输入框
num / number 数字输入框
date 日期输入框
datetime-local 日期时间输入框
select 下拉框,选项格式为 { value, label }

支持的 permissions:

权限 效果
edit 可修改
readonly 只读
required 可修改、显示必填标记并参与校验
hidden 隐藏

date、datetime-local 支持传入 10 位秒级或 13 位毫秒级时间戳,组件会自动转换为 日期输入框所需格式。

select 默认启用搜索,并会根据视口底部空间自动向上或向下展开。

自定义字段值会合并到 getFormData() 和提交数据中,也会触发表单字段变更事件。

字段权限统一通过 field-permissions 对象传入。配置会与默认权限合并:

fieldPermissions: {
  gmfMc: 'required', // 可修改,显示必填标记并参与校验
  gmfNsrsbh: 'readonly', // 只读,不可修改
  gmfDz: 'edit', // 可修改,非必填
  bz: 'hidden', // 隐藏备注字段
  details: {
    name: 'required', // 开票明细项目名称必填
    amount: 'readonly', // 开票明细金额只读
  },
  'details.projectType': 'required', // 也支持使用完整字段路径
}

权限值说明:

值 含义
edit 可修改,非必填;除默认必填字段外使用此值
readonly 只读,页面上不能修改
required 可修改,显示必填标记并参与 validateRequiredFields() 校验
hidden 不渲染字段,同时跳过该字段的必填校验

默认必填字段:

{
  gmfMc: 'required', // 购方名称
  gmfNsrsbh: 'required', // 购方纳税人识别号
  xsfMc: 'required', // 销方名称
  xsfNsrsbh: 'required', // 销方纳税人识别号
  details: {
    projectType: 'required', // 开票明细项目类型
    name: 'required', // 开票明细项目名称
    unitPrice: 'required', // 开票明细单价
    amount: 'required', // 开票明细金额
    taxRate: 'required', // 开票明细税率
    tax: 'required', // 开票明细税额
  },
}

如需取消某个默认必填项,可显式传 edit:

fieldPermissions: {
  gmfMc: 'edit', // 购方名称改为非必填
  details: {
    amount: 'edit', // 明细金额改为非必填
  },
}

支持的字段:

  • 收票信息:spfEmail、spfPhone
  • 发票类型:invoiceType
  • 购方:gmfMc、gmfNsrsbh、gmfDz、gmfLxdh、gmfKhh、gmfYhzh
  • 销方:xsfMc、xsfNsrsbh、xsfDz、xsfLxdh、xsfKhh、xsfYhzh
  • 开票明细:details.projectType、details.name、details.spec、details.unit、details.quantity、details.unitPrice、details.amount、details.taxRate、details.tax
  • 开票要求:invoiceRequirement
  • 备注:bz

details.tax 为自动计算字段,配置为 required 时会显示必填标记并参与校验。 字段只读只影响页面输入;父组件仍可通过 v-model 或公开方法更新数据。 字段隐藏只影响页面展示,表单中的原值仍会保留并参与提交。top-info-fields 中配置的字段同样可以使用 fieldPermissions[field] = 'hidden' 隐藏。

权限只作用于具体字段,不会控制按钮、勾选列、行内增删或列表级操作。列表级按钮 是否显示完全由 detail-tables.*.buttons 配置决定。

示例只列出了部分字段,未传字段会使用组件默认值;details 数组会 覆盖默认数组,行 id 可以省略,组件会自动生成并保证唯一。

字段 说明
name 按钮显示文字
method 可选的旧版回调;新代码通过 button-click 处理,不需要传入
type 按钮样式:primary、primary-bordered(或 bordered)、default
code 按钮业务编码,通过 button-click 的 payload.code 获取

不传 actions 时,默认显示“选择订单”和“选择转账单”,并分别触发 select-order、select-transfer-order 事件。

发票明细列表按钮配置

发票明细表头按钮通过 detail-tables.invoice.buttons.header 配置。未传 header 时默认显示 add、import、batch-edit 和 clear;传入数组后会完全 覆盖默认按钮:

<InvoiceTemplateForm
  v-model="invoiceForm"
  :detail-tables="{
    invoice: {
      field: 'details',
      title: '发票明细',
      buttons: {
        header: [
          { code: 'add' },
          { code: 'batch-edit' },
          { code: 'import' },
          { code: 'export' },
          { code: 'clear' },
        ],
      },
    },
  }"
/>

配置字段:

字段 说明
name 按钮显示文字
method 可选的旧版回调;新代码通过 button-click 处理,不需要传入
type primary、primary-bordered、default 等按钮颜色类型
code 按钮业务编码;add、import、export、batch-edit、clear 是内置功能

未配置时的默认值:

detailTables.invoice.buttons.header: [
  { code: 'add' },
  { code: 'batch-edit' },
  { code: 'import' },
  { code: 'export' },
  { code: 'clear' },
]

通过传入空数组可以完全隐藏某个列表的默认按钮:

detailTables: {
  invoice: {
    buttons: {
      header: [],
    },
  },
}

code: 'add' 不需要传 name、method、type:

detailTables.invoice.buttons.header: [{ code: 'add' }]

组件会使用对应列表的内置新增方法,并显示“新增行”或“添加行”。传 name 或 type 可以覆盖新增按钮的名称和颜色,但 method 始终使用组件内置的新增方法。

code: 'clear' 同样不需要传其他字段:

detailTables.invoice.buttons.header: [{ code: 'clear' }]

配置 { code: 'clear' } 时会调用 clearInvoiceDetails()。

code: 'import' 打开内置导入窗口。支持 .xlsx、.xls、JSON、CSV、TSV 文件, 也可以直接粘贴 Excel 数据。带匹配明细 ID 的行会更新原明细,ID 为空或未匹配的 行会新增,原有其他明细保持不变。点击“下载导入模板”会生成带表头和示例行的 Excel 文件,可直接填写后再导入。

code: 'batch-edit' 打开批量修改窗口,仅修改当前已勾选的明细。可修改项目类型、 项目名称、规格型号和单位;每个字段需要单独勾选后才会应用,未勾选字段不变。

其他非内置按钮会触发 button-click,通过 payload.code 区分业务。

样式规则:

  • 开票明细按钮使用按钮样式,type 控制按钮颜色
methods: {
  handleDetailAction(form, type, code) {
    // form:当前完整表单
    // type:invoice
    // code:按钮配置中的业务编码
  },
}

发票明细行操作按钮配置

发票明细行内操作通过 detail-tables.invoice.buttons.body 配置。未传时默认显示内置删除:

detailTables: {
  invoice: {
    buttons: {
      body: [{ code: 'delete' }],
    },
  },
}

传入数组后会完全覆盖该列表的默认行操作;传入空数组可以隐藏行操作:

detailTables: {
  invoice: {
    buttons: {
      body: [
        { code: 'delete' },
        {
          name: '复制行',
          type: 'default',
          code: 'copy-row',
        },
      ],
    },
  },
}

code: 'delete' 不需要传 name、method、type,组件自动调用当前行对应的:

  • invoice → removeDetail(index)

自定义行操作方法接收:

handleDetailRowAction(form, type, code, item, index) {
  // form:完整表单
  // type:invoice
  // code:按钮业务编码
  // item:当前行对象
  // index:当前行索引
}

行操作统一使用文本链接样式;删除默认显示为橙色,其他操作默认蓝色。type 传 primary、primary-bordered 时也显示为橙色。

自定义明细表配置

除固定发票明细外,其他表格全部通过 detail-tables 自定义。order、receipt 只是示例 key,没有内置数据字段、标题或列配置。未配置的表格不会渲染。

detailTables: {
  order: {
    field: 'orderDetails',
    title: '订单信息',
    buttons: {
      header: [
        { code: 'add' },
        {
          name: '关联订单',
          type: 'default',
          code: 'relate-order',
        },
        { code: 'clear' },
      ],
      body: [
        { code: 'delete' },
        {
          name: '复制行',
          type: 'default',
          code: 'copy-order-row',
        },
      ],
    },
    columns: [
      {
        field: 'orderCode',
        label: '订单编码',
        type: 'text',
        permissions: 'edit',
        required: true,
      },
      {
        field: 'productName',
        label: '产品名称',
        type: 'text',
        permissions: 'edit',
      },
      {
        field: 'amount',
        label: '金额',
        type: 'num',
        permissions: 'edit',
        required: true,
        summary: true,
      },
    ],
  },
  receipt: {
    field: 'receipts',
    title: '收款信息',
    buttons: {
      header: [{ code: 'add' }, { code: 'clear' }],
      body: [{ code: 'delete' }],
    },
    columns: [
      {
        field: 'receiptCode',
        label: '收款单编码',
        type: 'text',
        permissions: 'edit',
        required: true,
      },
      {
        field: 'receiptAccount',
        label: '收款账户',
        type: 'text',
        permissions: 'readonly',
      },
      {
        field: 'receiptAmount',
        label: '收款金额',
        type: 'num',
        permissions: 'edit',
        required: true,
        summary: true,
      },
    ],
  },
}

表格字段:

字段 说明
field 指定表格数据在 form 中的数组字段,例如 order
title 表格标题
buttons 表头按钮 header 和行内按钮 body
columns 列配置数组

例如:

detailTables: {
  order: {
    field: 'order',
    columns: [
      {
        field: 'orderCode',
        label: '订单编码',
        type: 'text',
        permissions: 'edit',
        required: true,
      },
    ],
  },
}

对应读取:

form.order[0].orderCode

表格 key 控制事件类型,field 控制数据来源,columns[].field 控制每一列读取 哪个行属性。任何表格未设置 field 时,默认读取 form[表格key]。

也可以使用任意配置 key,例如物流信息:

detailTables: {
  logistics: {
    field: 'logistics',
    title: '物流信息',
    buttons: {
      header: [{ code: 'add' }, { code: 'clear' }],
      body: [{ code: 'delete' }],
    },
    columns: [
      {
        field: 'trackingNo',
        label: '物流单号',
        type: 'text',
        permissions: 'edit',
        required: true,
      },
      {
        field: 'company',
        label: '物流公司',
        type: 'select',
        permissions: 'edit',
        options: [
          { value: 'SF', label: '顺丰' },
          { value: 'YTO', label: '圆通' },
          { value: 'ZTO', label: '中通' },
        ],
      },
      {
        field: 'freight',
        label: '运费',
        type: 'num',
        permissions: 'edit',
        summary: true,
      },
    ],
  },
}

对应数据为 form.logistics。如果省略 field,默认读取同名的 form.logistics。 自定义列表同样支持 add、clear、delete 以及 logistics-detail-added、 logistics-detail-removed 等事件。 add 和 delete 直接使用组件内置方法,不需要父级传 method。

form.logistics[0].company = 'SF' // 对应 { value: 'SF', label: '顺丰' }

列字段:

字段 说明
field 对应明细行对象中的字段名
label 表头显示名称
type text、select、num
permissions edit、readonly、required、hidden
required 是否必填并参与 validateRequiredFields()
options select 类型选项,格式为 { value, label } 数组
searchable select 是否支持搜索,默认 true;传 false 使用原生下拉框
summary 数字列是否显示合计

permissions: 'hidden' 的列不会渲染,也不会参与必填校验。

select 列默认启用搜索,可按 label 或 value 过滤选项: 下拉框会根据视口底部剩余空间自动选择向下或向上展开。

{
  field: 'company',
  label: '物流公司',
  type: 'select',
  permissions: 'edit',
  options: [
    { value: 'SF', label: '顺丰' },
    { value: 'YTO', label: '圆通' },
    { value: 'ZTO', label: '中通' },
  ],
}

关闭搜索:

{
  field: 'company',
  label: '物流公司',
  type: 'select',
  searchable: false,
  options: [],
}
columns: [
  {
    field: 'internalCode',
    label: '内部编码',
    permissions: 'hidden',
  },
]

按钮字段:

  • buttons.header:表头新增、清空及自定义按钮
  • buttons.body:行内删除及自定义按钮
  • code: 'add'、code: 'clear'、code: 'delete' 使用组件内置方法

销方名称按钮配置

seller-actions 默认为空数组,不传时销方名称右侧不显示按钮:

sellerActions: [
  {
    name: '选择销方',
    type: 'primary',
    code: 'select-seller',
  },
]

自定义销方按钮通过 button-click 交给父级处理:

handleButtonClick(payload) {
  if (payload.code === 'select-seller') {
    payload.preventDefault()
    this.selectSeller()
  }
}

购方名称按钮配置

buyer-actions 未传时默认显示 { code: 'transfer' } 购销互换按钮;传入数组后 完全覆盖默认配置,传入空数组可以隐藏所有购方名称按钮:

buyerActions: [
  { code: 'transfer' },
  {
    name: '选择购方',
    type: 'primary-bordered',
    code: 'select-buyer',
  },
]

code: 'transfer' 使用组件内置互换方法。其他操作通过 button-click 由父级 执行。购销互换会交换名称、纳税人识别号、地址、电话、开户银行和银行账号。

当前未提供发票提交接口,提交逻辑需要按实际业务接入。

组件方法

Vue 2 中可以通过 ref 获取组件实例后调用公开方法:

<template>
  <InvoiceTemplateForm ref="invoiceForm" />
</template>

<script>
import { InvoiceTemplateForm } from '@zhouhaiyang0326/invoicetemplateform'

export default {
  components: { InvoiceTemplateForm },
  methods: {
    addLine() {
      this.$refs.invoiceForm.addInvoiceDetail()
    },
  },
}
</script>

可用方法:

方法 说明 返回值
addInvoiceDetail(data?) 新增开票明细,可选传入初始字段;若当前只有一条未录入业务数据的初始空行,会复用该位置而不是额外保留空行 新增的明细对象
importInvoiceDetails(data) 增量导入明细;匹配现有明细 ID 时更新原行,否则新增。可传数组、JSON、CSV 或 TSV 文本 新增或更新的明细数组
importInvoiceDetailsByJson(json) 接收 { details: [...] } 对象或对应 JSON 字符串进行增量导入,内部调用 importInvoiceDetails() 新增或更新的明细数组
downloadInvoiceImportTemplate() 下载带表头和示例行的 Excel 导入模板 无
getInvoiceImportTemplateCsv() 获取导入模板 CSV 文本 CSV 字符串
exportInvoiceDetails() 导出当前全部开票明细为 Excel 导出的明细数据数组
getInvoiceExportData() 获取明细 ID、项目类型、项目名称、规格型号、单位、数量、单价、金额、税率和税额 数据数组
getInvoiceExportRows() 获取包含表头的 Excel 二维数组 二维数组
batchUpdateInvoiceDetails(data, targets?) 批量修改项目类型、项目名称、规格型号、单位;未传 targets 时修改全部已勾选明细 被修改的明细数组
removeInvoiceDetail(indexOrDetail) 删除指定索引或明细对象 成功返回 true
addDetailTableRow(type, data?) 向指定明细表新增一行 新增的明细对象
removeDetailTableRow(type, indexOrRow) 删除指定明细表的行 成功返回 true
getDetailTableRows(type) 获取指定明细表的全部行 当前行数组
getSelectedDetailTableRows(type) 获取指定明细表中勾选的行 勾选行数组
getSelectedInvoiceDetails() 获取勾选的开票明细 勾选行数组
swapBuyerSeller() 互换购方和销方的全部基础信息 无
validateRequiredFields() 按 field-permissions 校验所有配置为 required 的字段 { valid, errors }
clearInvoiceDetails() 清空所有开票明细 清空后的明细数组
clearDetailTable(type) 清空指定自定义明细表,type 为 detailTables 的 key 清空后的明细数组
clearAllDetails() 清空开票明细、所有自定义明细表及遗留明细数组 按数据字段返回已清空的数组
getFormData(options?) 获取完整表单数据,默认移除明细 id 表单数据
getFixedFields() 获取组件固定位置字段名称 字段名数组
getInvoiceSummary() 获取本次开票的税额、不含税金额和价税合计 { taxAmount, amountWithoutTax, totalAmount, taxIncluded }
getSubmitData(options?) 返回合并左上角配置值后的提交副本,默认移除明细 id 表单数据
mergeTopInfoToForm() 将左上角配置值合并到当前表单 当前表单
submit() 合并左上角信息并触发 submit 事件 提交表单数据

默认情况下,getFormData()、getSubmitData() 和 submit() 返回的所有明细数组 都会移除组件内部的 id,不会提交到后端:

const data = this.$refs.invoiceForm.getFormData()

如确实需要保留明细 id:

const data = this.$refs.invoiceForm.getFormData({
  includeDetailIds: true,
})

索引从 0 开始。删除方法也可以直接传入行对象,或传入行对象的 id 字符串; 传对象时会先按引用匹配,再按 id 匹配。删除最后一条开票明细后,details 会变为空数组。

清空开票明细后 details 为 [];如需清空其他明细,可单独 任意自定义明细表可调用 clearDetailTable(type);clearAllDetails() 会一次清空 开票明细和所有自定义明细表。

开票明细导入与批量修改

导入采用增量模式:

  • 明细 id 能匹配现有行时,覆盖该行的导入字段并保留原 ID。
  • id 为空或未匹配时新增一行,并自动生成唯一 ID。
  • 未出现在导入数据中的现有明细保持不变。
  • 只传数量与金额时,组件会反算单价;税额按当前税率自动计算。
const rows = this.$refs.invoiceForm.importInvoiceDetails([
  {
    id: 'detail-existing-id', // 可选,匹配时更新现有明细
    projectType: '金属制品', // 项目类型,可传配置项的 label 或 value
    name: '测试商品', // 项目名称
    spec: 'A-01', // 规格型号
    unit: '个', // 单位
    quantity: '2', // 数量
    unitPrice: '50.00', // 单价
    amount: '100.00', // 金额
    taxRate: 0.13, // 税率
  },
])

也可以直接传入带表头的 CSV、TSV 文本或 JSON 字符串:

导入弹窗还可以直接选择 .xlsx 或 .xls 文件,组件会读取第一个工作表,并按 表头名称匹配字段。项目类型属于下拉选择字段,只有值与 projectTypeOptions 中的 label 或 value 匹配时才会填充;未匹配或没有值时, projectType 和 sphfwssflhbbm 都保持为空。

this.$refs.invoiceForm.importInvoiceDetails(`
明细ID,项目类型,项目名称,规格型号,单位,数量,单价,金额,税率,税额
,金属制品,测试商品,A-01,个,2,50.00,100.00,0.13,11.50
`)

this.$refs.invoiceForm.importInvoiceDetails(JSON.stringify({
  details: [
    { projectType: '金属制品', name: '测试商品', quantity: 2, amount: 100 },
  ],
}))

也可以使用专用 JSON 接口。对象和 JSON 字符串都支持:

const importJson = {
  details: [
    {
      id: 'detail-existing-id',
      projectType: '金属制品', // 项目类型
      name: '测试商品', // 项目名称
      spec: 'A-01', // 规格型号
      unit: '个', // 单位
      quantity: '2', // 数量
      unitPrice: '50.00', // 单价
      amount: '100.00', // 金额
      taxRate: 0.13, // 税率
    },
  ],
}

this.$refs.invoiceForm.importInvoiceDetailsByJson(importJson)

// 后端返回 JSON 字符串时也可以直接传入
this.$refs.invoiceForm.importInvoiceDetailsByJson(JSON.stringify(importJson))

用于让其他 AI 将自由文本转换成导入 JSON 的提示词:

你是一个开票明细数据转换器。请把用户提供的文本转换成下面结构的合法 JSON。

目标格式:
{
  "details": [
    {
      "id": "原明细ID,没有则填空字符串",
      "projectType": "项目类型",
      "name": "项目名称",
      "spec": "规格型号",
      "unit": "单位",
      "quantity": "数量",
      "unitPrice": "单价",
      "amount": "金额",
      "taxRate": "税率"
    }
  ]
}

转换规则:
1. 只输出 JSON,不要输出 Markdown 代码块、解释、标题或任何额外文字。
2. 每个项目或商品明细输出为 details 数组中的一个对象,不得遗漏或合并。
3. id 对应“明细ID”,projectType 对应“项目类型”,name 对应“项目名称”,spec 对应“规格型号”,unit 对应“单位”,quantity 对应“数量”,unitPrice 对应“单价”,amount 对应“金额”,taxRate 对应“税率”。
4. quantity 和 amount 使用不带千分位逗号、货币符号和单位的数字字符串,例如 "2"、"100.00"。
5. 不要推测文本中没有的数据。缺失字段统一使用空字符串 ""。
6. 只有文本明确提供明细ID时才填写 id,否则使用空字符串;不要输出 sphfwssflhbbm、tax 或其他未列出的字段。
7. 保持文本中金额的小数精度;如果金额明确,优先保留两位小数。
8. 文本中的项目类型可以保留原始名称;组件只保留能在 projectTypeOptions 中匹配到的值。
9. 如果无法识别出任何明细,只输出 {"details":[]}。
10. 输出必须能被 JSON.parse 直接解析,不得包含注释、尾随逗号或未转义字符。

待转换文本:
"""
{{在这里粘贴需要转换的文本}}
"""

批量修改默认只处理已勾选的明细:

const rows = this.$refs.invoiceForm.batchUpdateInvoiceDetails({
  projectType: '金属制品', // 同时更新项目类型和 sphfwssflhbbm
  name: '统一项目名称',
  spec: '统一规格',
  unit: '个',
})

也可以通过第二个参数 targets 指定要修改的行、行 ID 或索引:

this.$refs.invoiceForm.batchUpdateInvoiceDetails(
  { unit: '箱' },
  ['invoice-row-id-1', 2],
)

导入完成会触发 invoice-details-imported,参数中包含 addedItems、 updatedItems 和 items。新增行仍会触发 detail-field-change 的 add; 更新行会触发对应字段的 update。批量修改完成会触发 invoice-details-batch-updated。

开票明细导出

配置 { code: 'export' } 会显示“导出”按钮,将当前全部开票明细导出为 Excel, 固定导出明细 ID、项目类型、项目名称、规格型号、单位、数量、单价、金额、税率和 税额十列。没有明细时会提示“没有可导出的开票明细”。

也可以通过组件方法导出:

const exportedRows = this.$refs.invoiceForm.exportInvoiceDetails()

导出文件名格式为 开票明细-YYYYMMDD-HHmmss.xlsx,完成后触发 invoice-details-exported 事件。

按钮点击事件

所有配置按钮点击都会触发统一的 button-click 事件。父组件通过 code 判断业务 并执行自己的方法,不再需要传入 method:

<InvoiceTemplateForm
  :actions="topActions"
  :detail-tables="detailTables"
  :buyer-actions="buyerActions"
  :seller-actions="sellerActions"
  @button-click="handleButtonClick"
/>
topActions: [
  {
    name: '选择订单',
    code: 'select-order',
    type: 'primary',
  },
]
methods: {
  handleButtonClick(payload) {
    if (payload.code === 'select-order') {
      payload.preventDefault()
      this.selectOrder()
      return
    }

    if (payload.code === 'import') {
      payload.preventDefault()
      this.importProducts(payload.form)
    }
  },
}

事件参数:

{
  source: 'detail-header', // top、detail-header、detail-row、buyer、seller
  button: {
    name: '导入',
    code: 'import',
    type: 'primary',
  },
  code: 'import',
  name: '导入',
  form: {},

  detailType: 'invoice', // 明细按钮才有
  dataKey: 'details',
  item: {}, // 行内按钮才有
  index: 0,
  list: [],

  handledByComponent: false, // 组件是否会继续执行内置逻辑
  defaultPrevented: false,

  preventDefault() {}, // 阻止组件内置行为及旧 method
}

按钮区域通过 payload.source 区分:

source 按钮区域
top 顶部按钮
detail-header 明细表头按钮
detail-row 明细行内按钮
buyer 购方名称按钮
seller 销方名称按钮

新增、导入、批量修改、清空、删除、购销互换等内置按钮仍由组件执行。父级调用 payload.preventDefault() 后,组件跳过内置行为,父级可以改为执行自己的方法。

字段变更事件

主表单和明细表字段发生变化时会向父组件发送事件。

事件 说明
field-change 主表单字段发生变化
detail-field-change 任意明细表新增、删除或字段发生变化

field-change 参数:

{
  field: 'gmfMc', // 字段名
  value: '新值',
  previousValue: '旧值',
  form: {}, // 当前完整表单
}

detail-field-change 参数:

{
  action: 'update', // update、add、remove、replace
  type: 'invoice', // invoice,或 detailTables 中配置的任意 key
  dataKey: 'details', // 对应 form 中的数组字段
  field: 'name', // 字段修改时为字段名,新增和删除时为 null
  value: '新值', // 新增时为新行对象,删除时为 null
  previousValue: '旧值', // 删除时为被删除行对象
  item: {}, // 当前明细行对象
  index: 0, // 当前行索引
  list: [], // 当前明细数组
  form: {}, // 当前完整表单
}

action 取值:

  • update:明细字段修改
  • add:新增明细行
  • remove:删除明细行
<InvoiceTemplateForm
  v-model="invoiceForm"
  @field-change="handleFieldChange"
  @detail-field-change="handleDetailFieldChange"
/>
methods: {
  handleFieldChange({ field, value, previousValue, form }) {
    console.log('表单字段变化', field, value, previousValue, form)
  },
  handleDetailFieldChange(payload) {
    if (payload.action === 'update') {
      console.log('字段修改', payload.field, payload.value)
    } else if (payload.action === 'add') {
      console.log('新增明细', payload.type, payload.item)
    } else if (payload.action === 'remove') {
      console.log('删除明细', payload.type, payload.previousValue)
    }
  },
}

复选框状态 selected 和内部 id 不触发字段变更事件。数量、单价、金额等 自动计算产生的字段变化也会分别触发事件。

沿用原有 detail-added、detail-removed 和 <type>-detail-added、<type>-detail-removed 事件的监听不需要修改。

明细新增与删除事件

所有明细列表都会在新增和删除行时触发事件,包括界面操作和公开的新增、删除方法。

事件 说明
detail-added 任意明细新增,通过 payload.type 判断类型
detail-removed 任意明细删除
invoice-detail-added / invoice-detail-removed 开票明细新增 / 删除
order-detail-added / order-detail-removed 订单信息新增 / 删除
receipt-detail-added / receipt-detail-removed 收款信息新增 / 删除
<type>-detail-added / <type>-detail-removed 任意 detailTables 配置 key 对应的事件

事件参数:

{
  type: 'invoice', // invoice,或 detailTables 中配置的任意 key
  item: {}, // 新增或删除的明细对象
  index: 0, // 对应列表中的索引
  list: [], // 事件触发后的当前列表
  form: {}, // 当前完整表单数据
}
<InvoiceTemplateForm
  v-model="invoiceForm"
  @invoice-detail-added="handleDetailAdded"
  @invoice-detail-removed="handleDetailRemoved"
  @order-detail-added="handleDetailAdded"
  @order-detail-removed="handleDetailRemoved"
  @receipt-detail-added="handleDetailAdded"
  @receipt-detail-removed="handleDetailRemoved"
/>
methods: {
  handleDetailAdded({ type, item, index, list, form }) {
    console.log('新增明细', type, item, index, list, form)
  },
  handleDetailRemoved({ type, item, index, list, form }) {
    console.log('删除明细', type, item, index, list, form)
  },
}

新增明细时可以同时传入业务数据:

const detail = this.$refs.invoiceForm.addInvoiceDetail({
  projectType: '其他类型', // 项目类型,可传配置项的 label 或 value
  name: '技术服务费', // 项目名称
  spec: '标准版', // 规格型号
  unit: '项', // 单位
  quantity: '1', // 数量
  unitPrice: '100', // 单价
  taxRate: 0.13, // 税率,显示为 13%
})

// 以下三种删除方式都支持
this.$refs.invoiceForm.removeInvoiceDetail(detail)
this.$refs.invoiceForm.removeInvoiceDetail({ id: detail.id })
this.$refs.invoiceForm.removeInvoiceDetail(detail.id)

const orderRow = this.$refs.invoiceForm.addDetailTableRow('order', {
  orderCode: 'DD001', // 订单编码
  productCode: 'CP001', // 产品编码
  productName: '技术服务费', // 产品名称
  spec: '标准版', // 规格型号
  quantity: '2', // 数量
  unitPrice: '500.00', // 单价
  amount: '1000.00', // 金额
})

const receiptRow = this.$refs.invoiceForm.addDetailTableRow('receipt', {
  receiptCode: 'SK001', // 收款单编码
  orderCode: 'DD001', // 订单编码
  receiptUnit: '测试收款单位', // 收款单位
  receiptAccount: '62220001', // 收款账户
  receiptAmount: '1234.50', // 收款金额
  receiptShop: '测试店铺', // 收款店铺
})

this.$refs.invoiceForm.removeDetailTableRow('order', orderRow)
this.$refs.invoiceForm.removeDetailTableRow('receipt', receiptRow.id)

this.$refs.invoiceForm.clearInvoiceDetails()
this.$refs.invoiceForm.clearDetailTable('order')
this.$refs.invoiceForm.clearAllDetails()

projectType 传入 projectTypeOptions 中的 label 或 value 时,组件会同时写入 details[].projectType(label)和 details[].sphfwssflhbbm(value)。 如果未匹配到配置项,则 projectType 和 sphfwssflhbbm 都不填充。

数量与单价同时传入时,金额会自动计算。新增明细和自定义明细行的 id 会自动生成: 优先使用 UUID,浏览器不支持时回退为时间戳、序号和随机串;新增时还会检查当前 列表,避免重复。传入的 id 会被忽略。

数据模型

组件内部主要使用以下状态:

  • form:发票表单数据
  • form.details:明细行数组
  • form.orderDetails:订单信息数组
  • form.receipts:收款信息数组
  • form.bz:手动备注文本
  • taxIncluded:当前单价/金额的含税口径
  • topInfoExpanded:买方、卖方信息是否展开

明细行字段

{
  id: 'detail-1', // 明细行唯一标识,新增时自动生成
  projectType: '金属制品', // 项目类型名称
  sphfwssflhbbm: '1080414010000000000', // 项目类型业务编码
  name: '', // 项目名称
  spec: '', // 规格型号
  unit: '', // 单位
  quantity: '', // 数量
  unitPrice: '', // 单价
  amount: '', // 金额
  taxRate: 0.13, // 税率,显示为 13%
  selected: false, // 是否勾选
}

收款信息字段

{
  id: 'receipt-1', // 收款行唯一标识,新增时自动生成
  receiptCode: '', // 收款单编码
  orderCode: '', // 订单编码
  receiptUnit: '', // 收款单位
  receiptAccount: '', // 收款账户
  receiptAmount: '', // 收款金额
  receiptShop: '', // 收款店铺
  selected: false, // 是否勾选
}

订单信息字段

{
  id: 'order-1', // 订单行唯一标识,新增时自动生成
  orderCode: '', // 订单编码
  productCode: '', // 产品编码
  productName: '', // 产品名称
  spec: '', // 规格型号
  quantity: '', // 数量
  unitPrice: '', // 单价
  amount: '', // 金额
  selected: false, // 是否勾选
}

表单主要字段

{
  invoiceType: '01', // 发票类型:01 增值税专用发票,02 普通发票
  shopName: '', // 店铺名称
  orderTime: '', // 下单时间
  paymentTime: '', // 付款时间
  preInvoiceAmount: '', // 预开票金额
  receivedAmount: '', // 收款金额
  spfEmail: '', // 收票方邮箱
  spfPhone: '', // 收票方手机号
  gmfMc: '', // 购方名称
  gmfNsrsbh: '', // 购方纳税人识别号
  gmfDz: '', // 购方地址
  gmfLxdh: '', // 购方电话
  gmfKhh: '', // 购方开户银行
  gmfYhzh: '', // 购方银行账号
  xsfMc: '', // 销方名称
  xsfNsrsbh: '', // 销方纳税人识别号
  xsfDz: '', // 销方地址
  xsfLxdh: '', // 销方电话
  xsfKhh: '', // 销方开户银行
  xsfYhzh: '', // 销方银行账号
  skr: '', // 收款人
  fhr: '', // 复核人
  details: [], // 开票明细数组
  orderDetails: [], // 订单信息数组
  receipts: [], // 收款信息数组
  invoiceRequirement: '', // 开票要求
  bz: '', // 手动备注文本
}

交互说明

明细行

  • 行内删除通过 detail-tables.invoice.buttons.body 的默认 { code: 'delete' } 提供
  • 列表按钮配置在 detail-tables.invoice.buttons.header
  • 列表按钮配置 { code: 'add' } 时显示“新增行”按钮
  • 列表按钮配置 { code: 'import' } 时显示“导入”按钮;ID 匹配时更新,否则新增
  • 列表按钮配置 { code: 'export' } 时显示“导出”按钮并导出当前开票明细
  • 列表按钮配置 { code: 'batch-edit' } 时显示“批量修改”按钮,作用于勾选明细
  • “清空”按钮通过 detail-tables.invoice.buttons.header 配置 { code: 'clear' } 后显示
  • 表头复选框控制全部明细的勾选状态

数量、单价、金额

  • 修改数量:优先用单价重算金额;单价为空时用金额反算单价
  • 修改单价:优先用数量重算金额;数量为空时用金额反算数量
  • 修改金额:优先用数量反算单价;数量为空时用单价反算数量
  • 数量或单价为空、除数为 0 时不会执行无效除法

税率自动选择

  • 专票(invoiceType: '01')默认税率 taxRate: 0.13,显示为 13%
  • 普票(invoiceType: '02')默认税率 taxRate: 0.01,显示为 1%
  • 可通过 tax-rate-options-by-invoice-type 为每种发票类型指定可选税点
  • 切换发票类型时,所有明细税点自动使用当前类型税点列表的第一项
  • 新增开票明细时同样默认使用第一个税点
  • 切换发票类型时,所有开票明细的税率会按新配置更新
<InvoiceTemplateForm
  v-model="invoiceForm"
  :tax-rate-options-by-invoice-type="taxRateOptionsByInvoiceType"
/>
taxRateOptionsByInvoiceType: {
  '01': [
    { value: 0.13, label: '13%' },
  ],
  '02': [
    { value: 0.01, label: '1%' },
    { value: 0.03, label: '3%' },
  ],
}

未传该配置时,默认仍为专票 13%、普票 1%。

项目类型配置

发票明细的“项目类型”使用配置化下拉,默认选项为:

[
  {
    value: '1080414010000000000',
    label: '金属制品',
  },
]

父组件可以覆盖:

<InvoiceTemplateForm
  v-model="invoiceForm"
  :project-type-options="projectTypeOptions"
/>
projectTypeOptions: [
  { value: '1080414010000000000', label: '金属制品' },
  { value: '1080414010000000001', label: '其他类型' },
]

新增明细或项目类型配置变化时,默认使用选项列表第一项。value 按字符串保存, 对应的 label 写入 details[].projectType,value 写入 details[].sphfwssflhbbm,不会把大整数转换成不精确的 JavaScript Number。 通过 addInvoiceDetail() 传入 projectType 时,可以传 label 或 value; 手动更新明细的 projectType 后,组件也会按配置自动同步 sphfwssflhbbm。

示例明细:

{
  projectType: '金属制品',
  sphfwssflhbbm: '1080414010000000000',
}

含税切换

切换右上角含税开关时:

  • “单价(含税)”与“单价(不含税)”同步切换
  • “金额(含税)”与“金额(不含税)”同步切换
  • 单价和金额会按当前税率互相换算
  • 税额和价税合计按当前口径重新计算

税额和合计

  • 含税金额的税额:金额 × 税率 ÷ (100 + 税率)
  • 不含税金额的税额:金额 × 税率 ÷ 100
  • 合计行金额显示不含税金额
  • 价税合计自动生成人民币大写

订单信息

  • 订单信息表格仅在 detail-tables.order 配置后显示
  • 列、表头按钮和行内按钮均来自 detail-tables
  • 有数据时始终展示,不提供展开/收起按钮;没有数据时不展示表格内容
  • 数据源由 detail-tables.order.field 指定,未传时读取 form.order
  • 列的 permissions 和 required 控制只读与必填

收款信息

  • 收款信息表格仅在 detail-tables.receipt 配置后显示
  • 列、表头按钮和行内按钮均来自 detail-tables
  • 有数据时始终展示,不提供展开/收起按钮;没有数据时不展示表格内容
  • 数据源由 detail-tables.receipt.field 指定,未传时读取 form.receipt
  • 数字列配置 summary: true 时显示合计

开票要求

  • 位于开票明细操作按钮上方,独占整行
  • 内容保存在 form.invoiceRequirement,通过 v-model 与父组件同步
  • 可通过 field-permissions.invoiceRequirement 设置为 edit、readonly 或 required

备注信息

  • 勾选买方地址、买方开户银行、卖方地址、卖方开户银行后的“添加到备注”
  • 勾选内容会显示在备注框上方的分栏信息区
  • 勾选状态下修改对应字段,备注内容会实时更新
  • 取消勾选只移除对应信息块
  • 勾选内容只在备注信息区实时展示,不会立即修改 form.bz
  • getFormData()、getSubmitData() 和 submit() 返回的数据会在 bz 末尾合并当前勾选的自动内容,并保留 textarea 中手写的备注
  • 取消勾选只会移除预览内容,不会修改 textarea 数据
  • 备注 textarea 上限为 200 字
  • 备注 textarea 会随内容自动增高,最小 92px,最大 428px,超过后内部滚动

本地开发

npm install
npm run dev

开发入口为根目录的 index.html,预览页面位于 playground/。

构建

npm run build

构建产物:

  • dist/index.js:ES Module
  • dist/index.umd.cjs:UMD
  • dist/style.css:组件样式

发布

发布前修改 package.json 中的版本号,并确认包名和许可协议:

npm publish

publishConfig 已指向 npm 官方源。

目录结构

.
├── playground/                     # 本地开发预览
├── src/
│   ├── assets/
│   │   ├── fonts/                  # 本地图标字体
│   │   └── images/
│   ├── components/
│   │   └── InvoiceTemplateForm.vue
│   └── index.js                    # 组件库入口
├── index.html                      # 开发服务器入口
├── vite.config.js
└── README.md

注意事项

  • 图标字体已放在 src/assets/fonts,构建后随样式一起打包
  • 当前版本没有实现历史发票和真实接口提交

Related Packages

vue-form-components

A collection of bootstrap form components for Vue 2

1,826 30
@lyracom/vue-embedded-form

Vue Lyra embedded form

1,790 0
seed-toolkit

One step generating pages from data

798
ll-form-table

基于vue2.6和element-ui封装的以数据驱动视图的表单表格组件,将表单、表格由`templat...

330 0
@baoyog/agent-vue2

宝遥智能体 Vue2 通用插件 - 支持标准化表单助手且无第三方 UI 框架依赖

0

Version History

Version Released Vue License
0.1.28 ^2.7.0 MIT
0.1.27 ^2.7.0 MIT
0.1.26 ^2.7.0 MIT
0.1.25 ^2.7.0 MIT
0.1.24 ^2.7.0 MIT
Pre-releases (1)
Version Released License
0.0.0-stage