蓝牙标签打印
蓝牙标签打印技术结合了蓝牙通信与标签打印的功能,为用户提供了一种便捷、高效的打印解决方案。以下是对蓝牙标签打印的详细解析:
蓝牙标签打印机的特点
无线连接:蓝牙标签打印机最大的亮点在于其无线连接方式。用户可以通过蓝牙轻松地将手机、平板电脑或电脑与打印机连接,无需复杂的网络设置或线缆连接,极大地提高了使用的便捷性。
兼容性强:蓝牙标签打印机通常支持多种操作系统和设备,包括安卓、iOS以及Windows等,满足不同用户的需求。
便携小巧:许多蓝牙标签打印机设计得小巧轻便,便于携带,用户可以随时随地进行打印操作。
功能多样:除了基本的文本打印外,蓝牙标签打印机还支持打印条形码、二维码、图片等,广泛应用于物流、仓储、零售、医疗等行业。
蓝牙标签打印机的应用场景
物流管理:在快递、物流行业中,蓝牙标签打印机可以快速打印出运单、标签等,提高包裹的分拣和配送效率。
仓储管理:在仓库中,蓝牙标签打印机可以打印出货物标签、货架标签等,帮助工作人员快速识别和定位货物。
零售管理:在超市、便利店等零售场所,蓝牙标签打印机可以打印出价格标签、促销标签等,方便商品管理和顾客选购。
医疗管理:在医疗行业中,蓝牙标签打印机可以打印出药品标签、患者信息标签等,确保医疗过程的安全和准确。
蓝牙标签打印的优势
提高效率:无线连接和便携设计使得蓝牙标签打印机可以在任何需要的地方进行打印操作,大大提高了工作效率。
降低成本:相比于传统的有线打印方式,蓝牙标签打印机减少了线缆和设备的投入成本,同时降低了维护成本。
增强灵活性:蓝牙标签打印机支持多种打印格式和内容,可以根据实际需求进行灵活调整和优化。
打印核心代码
打印核心代码基于网上资源自己进行了二次开发,兼容了uniapp。
print.js核心代码
import tsc from './tsc.js'; import esc from './esc.js'; // 打印程序begin--------------------------------- /** * android 6.0以上需授权地理位置权限 */ var checkPemission = function(that) { var systemInfo = uni.getSystemInfoSync(); var platform = systemInfo.platform; if (platform == "ios") { getBluetoothDevices(that) } else if (platform == "android") { let system = systemInfo.system; let system_no = system.replace('android', ''); system_no = system.replace('Android', ''); if (Number(system_no) > 5) { uni.getSetting({ success: function(res) { if (!res.authSetting['scope.userLocation']) { uni.authorize({ scope: 'scope.userLocation', complete: function(res) { getBluetoothDevices(that) } }) } else { getBluetoothDevices(that) } } }) } } } /** * 获取蓝牙设备信息 */ var getBluetoothDevices = function(that) { console.log("start search") uni.showLoading({ title: '搜索中', }) that.setData({ isScanning: true }) uni.startBluetoothDevicesDiscovery({ success: function(res) { setTimeout(function() { uni.getBluetoothDevices({ success: function(res) { var devices = [] var num = 0 for (var i = 0; i < res.devices.length; ++i) { if (res.devices[i].name != "未知设备") { devices[num] = res.devices[i] num++ } } that.setData({ devicesList: devices, isScanning: false }) uni.hideLoading() uni.stopPullDownRefresh() }, }) }, 3000) }, }) } /** * 开始连接蓝牙设置 */ var connectBluetoothSettings = function(app, that) { let deviceId = that.deviceId; uni.stopBluetoothDevicesDiscovery({ success: function(res) { //console.log(res) }, }) that.setData({ serviceId: 0, writeCharacter: false, readCharacter: false, notifyCharacter: false }) uni.showLoading({ title: '正在连接', }) uni.createBLEConnection({ deviceId: deviceId, success: function(res) { app.globalData.bluetoothDeviceId = deviceId getBLEDeviceServices(app, that); uni.showLoading({ title: '连接好可以打印', }) }, fail: function(e) { uni.showModal({ title: '提示', content: '连接失败', }) uni.hideLoading() }, complete: function(e) { //console.log(e) } }) } /** * 获取蓝牙设备所有服务 */ var getBLEDeviceServices = function(app, that) { console.log(app.globalData.bluetoothDeviceId) uni.getBLEDeviceServices({ deviceId: app.globalData.bluetoothDeviceId, success: function(res) { that.setData({ services: res.services }) getBLEDeviceCharacteristics(app, that) }, fail: function(e) { console.log(e) }, complete: function(e) { //console.log(e) } }) } /** * 获取蓝牙设备某个服务中所有特征值 */ var getBLEDeviceCharacteristics = function(app, that) { var list = that.services var num = that.serviceId var write = that.writeCharacter var read = that.readCharacter var notify = that.notifyCharacter uni.getBLEDeviceCharacteristics({ deviceId: app.globalData.bluetoothDeviceId, serviceId: list[num].uuid, success: function(res) { for (var i = 0; i < res.characteristics.length; ++i) { var properties = res.characteristics[i].properties var item = res.characteristics[i].uuid if (!notify) { if (properties.notify) { app.globalData.notifyCharaterId = item app.globalData.notifyServiceId = list[num].uuid notify = true } } if (!write) { if (properties.write) { app.globalData.writeCharaterId = item app.globalData.writeServiceId = list[num].uuid write = true } } if (!read) { if (properties.read) { app.globalData.readCharaterId = item app.globalData.readServiceId = list[num].uuid read = true } } } if (!write || !notify || !read) { num++ that.setData({ writeCharacter: write, readCharacter: read, notifyCharacter: notify, serviceId: num }) if (num == list.length) { uni.showModal({ title: '提示', content: '找不到该读写的特征值', }) } else { getBLEDeviceCharacteristics(app, that) } } else { notifyBLECharacteristicValueChange(app) } }, fail: function(e) { console.log(e) }, complete: function(e) { //console.log("write:" + app.globalData.writeCharaterId) //console.log("read:" + app.globalData.readCharaterId) //console.log("notify:" + app.globalData.notifyCharaterId) } }) } /** * 启用低功耗蓝牙设备特征值变化时的 notify 功能 */ var notifyBLECharacteristicValueChange = function(app) { //console.log("deviceId:" + app.globalData.bluetoothDeviceId) //console.log("serviceId:" + app.globalData.notifyServiceId) //console.log("notifyCharaterId:" + app.globalData.notifyCharaterId) uni.hideLoading(); uni.notifyBLECharacteristicValueChange({ deviceId: app.globalData.bluetoothDeviceId, serviceId: app.globalData.notifyServiceId, characteristicId: app.globalData.notifyCharaterId, state: true, success: function(res) { uni.onBLECharacteristicValueChange(function(r) { //console.log('onBLECharacteristicValueChange=', r); }) }, fail: function(e) { console.log('fail', e) }, complete: function(e) { //console.log('complete', e) } }) } /** * 标签模式 */ var labelTest = function(app, that) { var command = tsc.jpPrinter.createNew() command.setSize(70, 50) //纸宽度70,高度50 command.setGap(0) command.setCls() //需要设置这个,不然内容和上一次重复 // 10起始位置,10行距,TSS24.BF2字体,1字与字之间的间距,1字体大小,最后一个打印内容 command.setText(10, 10, "TSS24.BF2", 2, 2, 'DIY可视化蓝牙打印') command.setText(10, 70, "TSS24.BF2", 1, 1, '联系人:邓志锋') command.setText(10, 110, "TSS24.BF2", 1, 1, '网址:diygw.com') command.setText(10, 150, "TSS24.BF2", 1, 1, '电话:15655555555') //command.setText(10, 40, "TSS24.BF2", 1, 2, "蓝牙热敏标签打印测试2") command.setPagePrint() prepareSend(app, that, command.getData()) } // 打印标签 var printLabel = function(app, that) { var command = tsc.jpPrinter.createNew() command.setSpeed(0) command.setSize(that.form.width, that.form.height) //纸宽度,高度 command.setGap(0) command.setCls() //需要设置这个,不然内容和上一次重复 // 10起始位置,TSS24.BF2字体,1字与字之间的间距,1字体大小,一行行增加40高度打印 // 打印位置 let y = 0; let content = that.form.content for (let i = 0; i < content.length; i++) { command.setText(10, y, "TSS24.BF2", content[i].scale, content[i].scale, content[i].text) y = y + 40 } command.setPagePrint() prepareSend(app, that, command.getData()) } /** * 准备发送数据 */ var prepareSend = function(app, that, buff) { //console.log('buff', buff) var time = that.oneTimeData var looptime = parseInt(buff.length / time); var lastData = parseInt(buff.length % time); that.setData({ looptime: looptime + 1, lastData: lastData, currentTime: 1, }) Send(app, that, buff) } /** * 查询打印机状态 */ var queryPrinterStatus = function() { var command = esc.jpPrinter.Query(); command.getRealtimeStatusTransmission(1); this.setData({ returnResult: "查询成功" }) } /** * 分包发送 */ var Send = function(app, that, buff) { var currentTime = that.currentTime; var loopTime = that.looptime; var lastData = that.lastData; var onTimeData = that.oneTimeData; var printNum = that.printNum; //打印多少份 var currentPrint = that.currentPrint; var buf var dataView if (currentTime < loopTime) { buf = new ArrayBuffer(onTimeData) dataView = new DataView(buf) for (var i = 0; i < onTimeData; ++i) { dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]) } } else { buf = new ArrayBuffer(lastData) dataView = new DataView(buf) for (var i = 0; i < lastData; ++i) { dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]) } } console.log("第" + currentTime + "次发送数据大小为:" + buf.byteLength); console.log("deviceId:" + app.globalData.bluetoothDeviceId) console.log("serviceId:" + app.globalData.writeServiceId) console.log("characteristicId:" + app.globalData.writeCharaterId) uni.writeBLECharacteristicValue({ deviceId: app.globalData.bluetoothDeviceId, serviceId: app.globalData.writeServiceId, characteristicId: app.globalData.writeCharaterId, value: buf, success: function(res) { console.log('写入成功', res) }, fail: function(e) { console.error('写入失败', e) }, complete: function() { currentTime++ if (currentTime <= loopTime) { that.setData({ currentTime: currentTime }) Send(app, that, buff) } else { if (currentPrint == printNum) { that.setData({ looptime: 0, lastData: 0, currentTime: 1, isReceiptSend: false, isLabelSend: false, currentPrint: 1 }) } else { currentPrint++ that.setData({ currentPrint: currentPrint, currentTime: 1, }) console.log("开始打印") Send(app, that, buff) } } //console.log('打印完成') } }) } /** * 蓝牙搜索 */ var searchBluetooth = function(that) { //判断蓝牙是否打开 if(uni.openBluetoothAdapter){ uni.openBluetoothAdapter({ success: function(res) { uni.getBluetoothAdapterState({ success: function(res) { if (res.available) { if (res.discovering) { uni.stopBluetoothDevicesDiscovery({ success: function(res) { //console.log(res) } }) } checkPemission(that) } else { uni.showModal({ title: '提示', content: '请开启手机蓝牙后再试', }) } }, }) }, fail: function() { uni.showModal({ title: '提示', content: '蓝牙初始化失败,请打开蓝牙', }) } }) }else{ that.showToast('只支持APP或小程序') } } // -end--------------------------------- var print = { searchBluetooth: searchBluetooth, connectBluetoothSettings: connectBluetoothSettings, labelTest: labelTest, printLabel: printLabel } export default print;
tsc.js核心代码
import encode from './encoding.js'; var jpPrinter = { createNew: function () { var jpPrinter = {}; var data = ""; var command = [] jpPrinter.name = "标签模式"; jpPrinter.init = function () { }; jpPrinter.addCommand = function (content) { //将指令转成数组装起 var code = new encode.TextEncoder( 'gb18030', { NONSTANDARD_allowLegacyEncoding: true }).encode(content) for (var i = 0; i < code.length; ++i) { command.push(code[i]) } } jpPrinter.setSize = function (pageWidght, pageHeight) { //设置页面大小 data = "SIZE " + pageWidght.toString() + " mm" + "," + pageHeight.toString() + " mm" + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setSpeed = function (printSpeed) { //设置打印机速度 data = "SPEED " + printSpeed.toString() + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setDensity = function (printDensity) { //设置打印机浓度 data = "DENSITY " + printDensity.toString() + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setGap = function (printGap) { //传感器 data = "GAP " + printGap.toString() + " mm\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setCountry = function (country) { //选择国际字符集 /* 001:USA 002:French 003:Latin America 034:Spanish 039:Italian 044:United Kingdom 046:Swedish 047:Norwegian 049:German */ data = "COUNTRY " + country + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setCodepage = function (codepage) { //选择国际代码页 /* 8-bit codepage 字符集代表 437:United States 850:Multilingual 852:Slavic 860:Portuguese 863:Canadian/French 865:Nordic Windows code page 1250:Central Europe 1252:Latin I 1253:Greek 1254:Turkish 以下代码页仅限于 12×24 dot 英数字体 WestEurope:WestEurope Greek:Greek Hebrew:Hebrew EastEurope:EastEurope Iran:Iran IranII:IranII Latvian:Latvian Arabic:Arabic Vietnam:Vietnam Uygur:Uygur Thai:Thai 1252:Latin I 1257:WPC1257 1251:WPC1251 866:Cyrillic 858:PC858 747:PC747 864:PC864 1001:PC100 */ data = "CODEPAGE " + codepage + "\r\n"; jpPrinter.addCommand(data) } jpPrinter.setCls = function () { //清除打印机缓存 data = "CLS" + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setFeed = function (feed) { //将纸向前推出n data = "FEED " + feed + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setBackFeed = function (backup) { //将纸向后回拉n data = "BACKFEED " + backup + "\r\n"; jpPrinter.addCommand(data) } jpPrinter.setDirection = function (direction) { //设置打印方向,参考编程手册 data = "DIRECTION " + direction + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setReference = function (x, y) { //设置坐标原点,与打印方向有关 data = "REFERENCE " + x + "," + y + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setFromfeed = function () { //根据Size进一张标签纸 data = "FORMFEED \r\n"; jpPrinter.addCommand(data) }; jpPrinter.setHome = function () { //根据Size找到下一张标签纸的位置 data = "HOME \r\n"; jpPrinter.addCommand(data) }; jpPrinter.setSound = function (level, interval) { //控制蜂鸣器 data = "SOUND " + level + "," + interval + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setLimitfeed = function (limit) { // 检测垂直间距 data = "LIMITFEED " + limit + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setBar = function (x, y, width, height) { //绘制线条 data = "BAR " + x + "," + y + "," + width + "," + height + "\r\n" jpPrinter.addCommand(data) }; jpPrinter.setBox = function (x_start, y_start, x_end, y_end, thickness) { //绘制方框 data = "BOX " + x_start + "," + y_start + "," + x_end + "," + y_end + "," + thickness + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setErase = function (x_start, y_start, x_width, y_height) { //清除指定区域的数据 data = "ERASE " + x_start + "," + y_start + "," + x_width + "," + y_height + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setReverse = function (x_start, y_start, x_width, y_height) { //将指定的区域反相打印 data = "REVERSE " + x_start + "," + y_start + "," + x_width + "," + y_height + "\r\n"; jpPrinter.addCommand(data) }; jpPrinter.setText = function (x, y, font, x_, y_, str) { //打印文字 data = "TEXT " + x + "," + y + ",\"" + font + "\"," + 0 + "," + x_ + "," + y_ + "," + "\"" + str + "\"\r\n" jpPrinter.addCommand(data) }; jpPrinter.setQR = function (x, y, level, width, mode, content) { //打印二维码 data = "QRCODE " + x + "," + y + "," + level + "," + width + "," + mode + "," + 0 + ",\"" + content + "\"\r\n" jpPrinter.addCommand(data) }; jpPrinter.setBar = function (x, y, codetype, height, readable, narrow, wide, content) { //打印条形码 data = "BARCODE " + x + "," + y + ",\"" + codetype + "\"," + height + "," + readable + "," + 0 + "," + narrow + "," + wide + ",\"" + content + "\"\r\n" jpPrinter.addCommand(data) }; jpPrinter.setBitmap = function (x, y, mode, res) { //添加图片,res为画布参数 console.log(res) var width = parseInt((res.width + 7) / 8 * 8 / 8) var height = res.height; var time = 1; var temp = res.data.length - width * 32; var pointList = [] console.log(width + "--" + height) data = "BITMAP " + x + "," + y + "," + width + "," + height + "," + mode + "," jpPrinter.addCommand(data) for (var i = 0; i < height; ++i) { console.log(temp) for (var j = 0; j < width; ++j) { for (var k = 0; k < 32; k += 4) { if (res.data[temp] == 0 && res.data[temp + 1] == 0 && res.data[temp + 2] == 0 && res.data[temp + 3] == 0) { pointList.push(1) } else { pointList.push(0) } temp += 4 } } time++ temp = res.data.length - width * 32 * time } for (var i = 0; i < pointList.length; i += 8) { var p = pointList[i] * 128 + pointList[i + 1] * 64 + pointList[i + 2] * 32 + pointList[i + 3] * 16 + pointList[i + 4] * 8 + pointList[i + 5] * 4 + pointList[i + 6] * 2 + pointList[i + 7] command.push(p) } } jpPrinter.setPagePrint = function () { //打印页面 data = "PRINT 1,1\r\n" jpPrinter.addCommand(data) }; //获取打印数据 jpPrinter.getData = function () { return command; }; return jpPrinter; } }; var tsc={ jpPrinter } export default tsc;
页面调用
<template> <view class="container container329843"> <button @tap="navigateTo" data-type="searchBluetoothFunction" class="diygw-col-24 btn-clz diygw-btn-default">搜索打印机</button> <text class="diygw-col-24 text-clz"> 如果是微信小程序,请前往微信官方公众平台设置隐私协议 </text> <u-form-item labelWidth="auto" class="diygw-col-24" v-if="devicesList.length > 0" label="选择打印机" labelPosition="top" prop="deviceId"> <diy-checkbox class="diygw-col-24" col="12" mode="radio" valueField="deviceId" labelField="name" v-model="deviceId" :list="devicesList" @change="changeDeviceId"> </diy-checkbox> </u-form-item> <u-form-item labelAlign="justify" class="diygw-col-24" label="打印份数" prop="printNum"> <u-input :focus="printNumFocus" placeholder="请输入打印份数" v-model="printNum" type="number"></u-input> </u-form-item> <u-form :model="form" :rules="formRules" :errorType="['message', 'toast']" ref="formRef" class="flex diygw-form diygw-col-24"> <view class="flex flex-wrap diygw-col-24"> <u-form-item labelAlign="justify" class="diygw-col-12" label="标签宽度" prop="width"> <u-input :focus="formData.widthFocus" placeholder="请输入宽度" v-model="form.width" type="number"></u-input> </u-form-item> <u-form-item labelAlign="justify" class="diygw-col-12" label="标签高度" prop="height"> <u-input :focus="formData.heightFocus" placeholder="请输入宽度" v-model="form.height" type="number"></u-input> </u-form-item> </view> <view class="flex flex-wrap diygw-col-24"> <view class="diygw-col-24" v-for="(contentItem, contentIndex) in form.content" :key="contentIndex"> <u-form class="diygw-col-24" :model="form.content[contentIndex]" :errorType="['message', 'toast']" ref="contentRef" :rules="contentItemRules"> <view class="flex flex-wrap diygw-col-24 flex1-clz"> <u-form-item labelAlign="justify" class="diygw-col-24" label="放大倍数" prop="scale"> <u-input :focus="formData.contentItemDatas[contentIndex].scaleFocus" placeholder="请输入宽度" v-model="contentItem.scale" type="number"></u-input> </u-form-item> <u-form-item labelAlign="justify" class="diygw-col-24" label="打印内容" prop="text"> <u-input :focus="formData.contentItemDatas[contentIndex].textFocus" placeholder="请输入宽度" v-model="contentItem.text"></u-input> </u-form-item> </view> </u-form> <view class="formcontenttools flex justify-end"> <button @tap="upContentItem" :data-index="contentIndex" class="diygw-btn flex-sub radius margin-xs"> <text class="button-icon diy-icon-fold"></text> </button> <button @tap="downContentItem" :data-index="contentIndex" class="diygw-btn flex-sub radius margin-xs"> <text class="button-icon diy-icon-unfold"></text> </button> <button @tap="addContentItem" :data-index="contentIndex" class="diygw-btn flex-sub radius margin-xs"> <text class="button-icon diy-icon-add"></text> </button> <button @tap="delContentItem" :data-index="contentIndex" class="diygw-btn flex-sub radius margin-xs"> <text class="button-icon diy-icon-close"></text> </button> </view> </view> </view> </u-form> <button @tap="navigateTo" data-type="printFunction" class="diygw-col-24 prt-clz diygw-btn-default">开始打印</button> <view class="clearfix"></view> </view> </template> <script> import print from '@/common/print/print.js'; export default { data() { return { //用户全局信息 userInfo: {}, //页面传参 globalOption: {}, //自定义全局变量 globalData: {}, devicesList: [], services: [], serviceId: 0, writeCharacter: false, readCharacter: false, notifyCharacter: false, isScanning: false, looptime: 0, currentTime: 1, lastData: 0, oneTimeData: 20, returnResult: 'returnResult', currentPrint: 1, isReceiptSend: false, isLabelSend: true, deviceId: '', printNumFocus: false, printNum: 1, form: { width: 40, height: 70, content: [] }, formRules: {}, contentItem: { scale: 1, text: 'DIYGW可视化蓝牙打印' }, contentItemData: { scaleFocus: false, textFocus: false }, formData: { widthFocus: false, heightFocus: false, contentItemDatas: [] }, contentItemRules: {} }; }, onShow() { this.setCurrentPage(this); }, onLoad(option) { this.setCurrentPage(this); if (option) { this.setData({ globalOption: this.getOption(option) }); } this.init(); }, onReady() { this.$refs.formRef?.setRules(this.formRules); this.initContentData(); }, methods: { async init() { await this.initResetform(); }, // 搜索打印机 自定义方法 async searchBluetoothFunction(param) { let thiz = this; print.searchBluetooth(this); }, // 打印 自定义方法 async printFunction(param) { let thiz = this; if (!this.deviceId) { this.navigateTo({ type: 'tip', tip: '请选择打印机' }); return; } print.printLabel(getApp(), this); }, // 连接打印 自定义方法 async connectFunction(param) { let thiz = this; print.connectBluetoothSettings(getApp(), this); }, changeDeviceId(evt) { this.navigateTo({ type: 'connectFunction' }); }, //初始化显示子表单数据条数 initContentData() { for (let i = 0; i < 1; i++) { this.form.content.push(JSON.parse(JSON.stringify(this.contentItem))); this.formData.contentItemDatas.push(JSON.parse(JSON.stringify(this.contentItemData))); } this.initContentValid(); }, //子表单验证 initContentValid() { this.$nextTick(() => { this.$refs['contentRef']?.forEach((subform) => { subform.setRules(this.contentItemRules); }); }); }, //上移子表单 upContentItem(evt) { let { index } = evt.currentTarget.dataset; if (index == 0) { this.navigateTo({ type: 'tip', tip: '已经是第一个' }); return false; } this.form.content[index] = this.form.content.splice(index - 1, 1, this.form.content[index])[0]; this.formData.contentItemDatas[index] = this.formData.contentItemDatas.splice(index - 1, 1, this.formData.contentItemDatas[index])[0]; this.initContentValid(); }, //下移子表单 downContentItem(evt) { let { index } = evt.currentTarget.dataset; if (index == this.form.content.length - 1) { this.navigateTo({ type: 'tip', tip: '已经是最后一个' }); return false; } this.form.content[index] = this.form.content.splice(index + 1, 1, this.form.content[index])[0]; this.formData.contentItemDatas[index] = this.formData.contentItemDatas.splice(index + 1, 1, this.formData.contentItemDatas[index])[0]; this.initContentValid(); }, //删除子表单 delContentItem(evt) { if (this.form.content.length == 1) { this.showToast('不能小于1个'); return; } let { index } = evt.currentTarget.dataset; this.form.content.splice(index, 1); this.formData.contentItemDatas.splice(index, 1); this.initContentValid(); }, //增加子表单 addContentItem() { this.form.content.push(JSON.parse(JSON.stringify(this.contentItem))); this.formData.contentItemDatas.push(JSON.parse(JSON.stringify(this.contentItemData))); this.initContentValid(); }, //验证所有的子表单 checkContentValid() { let flag = true; this.$refs['contentRef']?.forEach((subform) => { subform.validate((valid) => { if (!valid) { flag = false; return false; } }); }); return flag; }, initResetform() { this.initform = JSON.stringify(this.form); //如果想给表单默认初始值,其中row为某一行数据也可能是API返回的结果集,然后给到this.form //this.form = this.$tools.changeRowToForm(row,this.form) }, resetForm() { this.form = JSON.parse(this.initform); }, async submitForm(e) { this.$refs.formRef?.setRules(this.formRules); this.initContentValid(); this.$nextTick(async () => { let contentvalid = await this.checkContentValid(); let valid = await this.$refs.formRef.validate(); if (valid && contentvalid) { //保存数据 let param = this.form; let header = { 'Content-Type': 'application/json' }; let url = ''; if (!url) { this.showToast('请先配置表单提交地址', 'none'); return false; } let res = await this.$http.post(url, param, header, 'json'); if (res.code == 200) { this.showToast(res.msg, 'success'); } else { this.showModal(res.msg, '提示', false); } } else { console.log('验证失败'); } }); } } }; </script> <style lang="scss" scoped> .btn-clz { padding-top: 20rpx; border-bottom-left-radius: 120rpx; color: #fff; padding-left: 20rpx; padding-bottom: 20rpx; border-top-right-radius: 120rpx; margin-right: 30rpx; background-color: #07c160; margin-left: 30rpx; overflow: hidden; width: calc(100% - 30rpx - 30rpx) !important; border-top-left-radius: 120rpx; margin-top: 20rpx; border-bottom-right-radius: 120rpx; margin-bottom: 20rpx; text-align: center; padding-right: 20rpx; } .text-clz { border-bottom-left-radius: 120rpx; overflow: hidden; border-top-left-radius: 120rpx; border-top-right-radius: 120rpx; border-bottom-right-radius: 120rpx; text-align: center; } .formcontenttools { position: absolute; z-index: 1; right: 0rpx; top: 0rpx; } .formcontenttools .diygw-btn { padding: 5px; height: auto; flex: inherit; border-radius: 20px; } .flex1-clz { border: 2rpx solid #eee; padding-top: 10rpx; border-bottom-left-radius: 12rpx; padding-left: 10rpx; padding-bottom: 10rpx; border-top-right-radius: 12rpx; margin-right: 20rpx; margin-left: 20rpx; overflow: hidden; width: calc(100% - 20rpx - 20rpx) !important; border-top-left-radius: 12rpx; margin-top: 10rpx; border-bottom-right-radius: 12rpx; margin-bottom: 10rpx; padding-right: 10rpx; } .prt-clz { padding-top: 20rpx; border-bottom-left-radius: 120rpx; color: #fff; padding-left: 20rpx; padding-bottom: 20rpx; border-top-right-radius: 120rpx; margin-right: 30rpx; background-color: #07c160; margin-left: 30rpx; overflow: hidden; width: calc(100% - 30rpx - 30rpx) !important; border-top-left-radius: 120rpx; margin-top: 20rpx; border-bottom-right-radius: 120rpx; margin-bottom: 20rpx; text-align: center; padding-right: 20rpx; } .container329843 { } </style>