feat: opt printer
This commit is contained in:
@@ -52,7 +52,10 @@
|
|||||||
"Bash(identify:*)",
|
"Bash(identify:*)",
|
||||||
"WebFetch(domain:github.com)",
|
"WebFetch(domain:github.com)",
|
||||||
"Bash(file:*)",
|
"Bash(file:*)",
|
||||||
"Bash(xargs:*)"
|
"Bash(xargs:*)",
|
||||||
|
"Bash(unzip:*)",
|
||||||
|
"WebFetch(domain:gainscha.github.io)",
|
||||||
|
"WebFetch(domain:m.gainscha.com)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.lukouguoji.module_base.util
|
package com.lukouguoji.module_base.util
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.graphics.Typeface
|
|
||||||
import com.gainscha.sdk2.ConnectType
|
import com.gainscha.sdk2.ConnectType
|
||||||
import com.gainscha.sdk2.ConnectionListener
|
import com.gainscha.sdk2.ConnectionListener
|
||||||
import com.gainscha.sdk2.Printer
|
import com.gainscha.sdk2.Printer
|
||||||
@@ -334,9 +333,9 @@ object PrinterUtils {
|
|||||||
merged = CellData("集装器编号:", "ULD NO.:", bean.uld)
|
merged = CellData("集装器编号:", "ULD NO.:", bean.uld)
|
||||||
))
|
))
|
||||||
|
|
||||||
// 第4行:件数 | 重量
|
// 第4行:件数 | 重量(件数value暂不打印)
|
||||||
rows.add(GridRow(
|
rows.add(GridRow(
|
||||||
left = CellData("件数:", "PIECES:", bean.pieces.ifEmpty { "0" }),
|
left = CellData("件数:", "PIECES:", ""),
|
||||||
right = CellData("重量:", "GROSS WEIGHT:", bean.totalWeight.toInt().toString())
|
right = CellData("重量:", "GROSS WEIGHT:", bean.totalWeight.toInt().toString())
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -360,7 +359,8 @@ object PrinterUtils {
|
|||||||
addSize(100, 100)
|
addSize(100, 100)
|
||||||
addGap(3)
|
addGap(3)
|
||||||
addCls()
|
addCls()
|
||||||
addTextByBitmap(150, 80, 0, 110, "合肥新桥国际机场", Typeface.DEFAULT)
|
// 使用 addText 替代 addTextByBitmap,避免 fimage 依赖问题
|
||||||
|
addText(150, 80, Tspl.FONT_TSS24, 0, 3, 3, "合肥新桥国际机场")
|
||||||
// 表格横线
|
// 表格横线
|
||||||
for (i in 0 until 5) {
|
for (i in 0 until 5) {
|
||||||
addBar(gridStartX, gridStartY + (i * gridItemHeight), gridWidth, 2)
|
addBar(gridStartX, gridStartY + (i * gridItemHeight), gridWidth, 2)
|
||||||
@@ -403,7 +403,8 @@ object PrinterUtils {
|
|||||||
addSize(100, 100)
|
addSize(100, 100)
|
||||||
addGap(3)
|
addGap(3)
|
||||||
addCls()
|
addCls()
|
||||||
addTextByBitmap(80, 80, 0, 130, "合肥新桥国际机场", Typeface.DEFAULT)
|
// 使用 addText 替代 addTextByBitmap,避免 fimage 依赖问题
|
||||||
|
addText(80, 80, Tspl.FONT_TSS24, 0, 3, 3, "合肥新桥国际机场")
|
||||||
// 表格横线
|
// 表格横线
|
||||||
for (i in 0 until 9) {
|
for (i in 0 until 9) {
|
||||||
addBar(gridStartX, gridStartY + (i * gridItemHeight), gridWidth, 2)
|
addBar(gridStartX, gridStartY + (i * gridItemHeight), gridWidth, 2)
|
||||||
@@ -449,17 +450,18 @@ object PrinterUtils {
|
|||||||
*/
|
*/
|
||||||
private fun printMergedGrid(rows: ArrayList<GridRow>) {
|
private fun printMergedGrid(rows: ArrayList<GridRow>) {
|
||||||
val gridStartX = 30
|
val gridStartX = 30
|
||||||
val gridStartY = 250
|
val gridStartY = 200
|
||||||
val columnWidth = 570
|
val columnWidth = 570
|
||||||
val rowHeight = 240
|
val rowHeight = 180 // 减小行高,适应较小字体
|
||||||
val gridWidth = columnWidth * 2
|
val gridWidth = columnWidth * 2
|
||||||
val gridHeight = rowHeight * rows.size
|
|
||||||
|
|
||||||
val bytes = Tspl().apply {
|
val bytes = Tspl().apply {
|
||||||
addSize(100, 100)
|
addSize(100, 100)
|
||||||
addGap(3)
|
addGap(3)
|
||||||
addCls()
|
addCls()
|
||||||
addTextByBitmap(80, 80, 0, 130, "合肥新桥国际机场", Typeface.DEFAULT)
|
// 标题居中(8个字 * 72像素/字 = 576像素宽,居中X = 30 + (1140-576)/2 = 312)
|
||||||
|
val titleX = gridStartX + (gridWidth - 576) / 2
|
||||||
|
addText(titleX, 60, Tspl.FONT_TSS24, 0, 3, 3, "合肥新桥国际机场")
|
||||||
|
|
||||||
// 绘制表格横线
|
// 绘制表格横线
|
||||||
for (i in 0..rows.size) {
|
for (i in 0..rows.size) {
|
||||||
@@ -479,10 +481,8 @@ object PrinterUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 右边线(总是绘制)
|
// 右边线(总是绘制)
|
||||||
if (rowIndex == rows.size - 1) {
|
|
||||||
addBar(gridStartX + gridWidth, yTop, 2, rowHeight)
|
addBar(gridStartX + gridWidth, yTop, 2, rowHeight)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 填充单元格内容
|
// 填充单元格内容
|
||||||
rows.forEachIndexed { rowIndex, row ->
|
rows.forEachIndexed { rowIndex, row ->
|
||||||
@@ -492,17 +492,18 @@ object PrinterUtils {
|
|||||||
// 合并单元格
|
// 合并单元格
|
||||||
renderCell(
|
renderCell(
|
||||||
cell = row.merged,
|
cell = row.merged,
|
||||||
x = gridStartX + 30,
|
x = gridStartX + 20,
|
||||||
y = yBase,
|
y = yBase,
|
||||||
cellWidth = gridWidth,
|
cellWidth = gridWidth,
|
||||||
cellHeight = rowHeight
|
cellHeight = rowHeight,
|
||||||
|
isMerged = true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// 左列单元格
|
// 左列单元格
|
||||||
row.left?.let { cell ->
|
row.left?.let { cell ->
|
||||||
renderCell(
|
renderCell(
|
||||||
cell = cell,
|
cell = cell,
|
||||||
x = gridStartX + 30,
|
x = gridStartX + 20,
|
||||||
y = yBase,
|
y = yBase,
|
||||||
cellWidth = columnWidth,
|
cellWidth = columnWidth,
|
||||||
cellHeight = rowHeight
|
cellHeight = rowHeight
|
||||||
@@ -512,7 +513,7 @@ object PrinterUtils {
|
|||||||
row.right?.let { cell ->
|
row.right?.let { cell ->
|
||||||
renderCell(
|
renderCell(
|
||||||
cell = cell,
|
cell = cell,
|
||||||
x = gridStartX + columnWidth + 30,
|
x = gridStartX + columnWidth + 20,
|
||||||
y = yBase,
|
y = yBase,
|
||||||
cellWidth = columnWidth,
|
cellWidth = columnWidth,
|
||||||
cellHeight = rowHeight
|
cellHeight = rowHeight
|
||||||
@@ -532,37 +533,43 @@ object PrinterUtils {
|
|||||||
* @param cell 单元格数据
|
* @param cell 单元格数据
|
||||||
* @param x 起始X坐标
|
* @param x 起始X坐标
|
||||||
* @param y 起始Y坐标
|
* @param y 起始Y坐标
|
||||||
* @param cellWidth 单元格宽度(用于计算右侧对齐)
|
* @param cellWidth 单元格宽度
|
||||||
* @param cellHeight 单元格高度(用于计算垂直居中)
|
* @param cellHeight 单元格高度
|
||||||
|
* @param isMerged 是否为合并单元格
|
||||||
*/
|
*/
|
||||||
private fun Tspl.renderCell(
|
private fun Tspl.renderCell(
|
||||||
cell: CellData,
|
cell: CellData,
|
||||||
x: Int,
|
x: Int,
|
||||||
y: Int,
|
y: Int,
|
||||||
cellWidth: Int,
|
cellWidth: Int,
|
||||||
cellHeight: Int
|
cellHeight: Int,
|
||||||
|
isMerged: Boolean = false
|
||||||
) {
|
) {
|
||||||
// 左上角:中文标签和英文标签
|
// 字体大小配置
|
||||||
val titleY = y + 30 // 中文标签Y位置
|
val titleSize = 2 // 中文标签字体倍数
|
||||||
val subtitleY = y + 80 // 英文标签Y位置(中文下方)
|
val subtitleSize = 1 // 英文标签字体倍数
|
||||||
|
val valueSize = 2 // 值字体倍数
|
||||||
|
|
||||||
// 中文标签(大字,左上)
|
// Y坐标配置(基于24点阵字体,size=2约48像素高,size=1约24像素高)
|
||||||
addText(x, titleY, Tspl.FONT_TSS24, 0, 3, 3, cell.title)
|
val titleY = y + 15 // 中文标签Y位置
|
||||||
|
val subtitleY = titleY + 70 // 英文标签Y位置(中文下方,间距加大)
|
||||||
|
val valueY = y + (cellHeight / 2) - 24 // 值垂直居中
|
||||||
|
|
||||||
// 英文标签(小字,左上)
|
// 中文标签
|
||||||
addText(x, subtitleY, Tspl.FONT_TSS24, 0, 2, 2, cell.subtitle)
|
addText(x, titleY, Tspl.FONT_TSS24, 0, titleSize, titleSize, cell.title)
|
||||||
|
|
||||||
// 右侧:值(大字,垂直居中)
|
// 英文标签
|
||||||
// 计算垂直居中的Y坐标:y + (cellHeight / 2) - (文字高度 / 2)
|
addText(x, subtitleY, Tspl.FONT_TSS24, 0, subtitleSize, subtitleSize, cell.subtitle)
|
||||||
// 假设size=3的文字高度约为80像素
|
|
||||||
val valueY = y + (cellHeight / 2) - 40 // 垂直居中
|
|
||||||
|
|
||||||
// 计算右侧X坐标:中文标签宽度 + 间距
|
// 计算value的X坐标(根据英文标签长度动态调整)
|
||||||
// 假设"目的站:"宽度约为180像素,"DESTINATION:"宽度约为240像素
|
// 合并单元格(如集装器编号)使用更大的间距
|
||||||
val valueX = x + 280 // 右侧偏移量
|
val extraGap = if (isMerged) 80 else 50
|
||||||
|
val minOffset = if (isMerged) 280 else 220
|
||||||
|
val labelWidth = cell.subtitle.length * 12 + extraGap
|
||||||
|
val valueX = x + maxOf(labelWidth, minOffset)
|
||||||
|
|
||||||
// 值(大字,垂直居中,右侧)
|
// 值(垂直居中)
|
||||||
addText(valueX, valueY, Tspl.FONT_TSS24, 0, 3, 3, cell.value)
|
addText(valueX, valueY, Tspl.FONT_TSS24, 0, valueSize, valueSize, cell.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printTest() {
|
fun printTest() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.lukouguoji.gjc.holder
|
package com.lukouguoji.gjc.holder
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import com.lukouguoji.gjc.R
|
||||||
import com.lukouguoji.gjc.activity.GjcBoxWeighingDetailsActivity
|
import com.lukouguoji.gjc.activity.GjcBoxWeighingDetailsActivity
|
||||||
import com.lukouguoji.gjc.databinding.ItemGjcBoxWeighingBinding
|
import com.lukouguoji.gjc.databinding.ItemGjcBoxWeighingBinding
|
||||||
import com.lukouguoji.module_base.base.BaseViewHolder
|
import com.lukouguoji.module_base.base.BaseViewHolder
|
||||||
@@ -16,9 +17,24 @@ class GjcBoxWeighingViewHolder(view: View) :
|
|||||||
val bean = getItemBean(item)!!
|
val bean = getItemBean(item)!!
|
||||||
binding.bean = bean
|
binding.bean = bean
|
||||||
|
|
||||||
|
// 更新图标状态
|
||||||
|
updateIcon(bean)
|
||||||
|
|
||||||
|
// 图标点击切换选中状态
|
||||||
|
binding.ivIcon.setOnClickListener {
|
||||||
|
bean.checked.set(!bean.checked.get())
|
||||||
|
updateIcon(bean)
|
||||||
|
}
|
||||||
|
|
||||||
// 整行点击跳转到详情页
|
// 整行点击跳转到详情页
|
||||||
binding.ll.setOnClickListener {
|
binding.ll.setOnClickListener {
|
||||||
GjcBoxWeighingDetailsActivity.start(it.context, bean.useId)
|
GjcBoxWeighingDetailsActivity.start(it.context, bean.useId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateIcon(bean: GjcUldUseBean) {
|
||||||
|
binding.ivIcon.setImageResource(
|
||||||
|
if (bean.checked.get()) R.drawable.img_plane_s else R.drawable.img_plane
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.lukouguoji.gjc.R
|
import com.lukouguoji.gjc.R
|
||||||
import com.lukouguoji.gjc.holder.GjcBoxWeighingViewHolder
|
import com.lukouguoji.gjc.holder.GjcBoxWeighingViewHolder
|
||||||
import com.lukouguoji.module_base.base.BasePageViewModel
|
import com.lukouguoji.module_base.base.BasePageViewModel
|
||||||
|
import com.lukouguoji.module_base.bean.GjcUldUseBean
|
||||||
import com.lukouguoji.module_base.common.Constant
|
import com.lukouguoji.module_base.common.Constant
|
||||||
import com.lukouguoji.module_base.http.net.NetApply
|
import com.lukouguoji.module_base.http.net.NetApply
|
||||||
|
import com.lukouguoji.module_base.ktx.commonAdapter
|
||||||
import com.lukouguoji.module_base.ktx.launchCollect
|
import com.lukouguoji.module_base.ktx.launchCollect
|
||||||
import com.lukouguoji.module_base.ktx.launchLoadingCollect
|
import com.lukouguoji.module_base.ktx.launchLoadingCollect
|
||||||
|
import com.lukouguoji.module_base.ktx.showToast
|
||||||
import com.lukouguoji.module_base.ktx.toRequestBody
|
import com.lukouguoji.module_base.ktx.toRequestBody
|
||||||
|
import com.lukouguoji.module_base.model.BluetoothDialogModel
|
||||||
import com.lukouguoji.module_base.model.ScanModel
|
import com.lukouguoji.module_base.model.ScanModel
|
||||||
|
import com.lukouguoji.module_base.util.PrinterUtils
|
||||||
import dev.utils.common.DateUtils
|
import dev.utils.common.DateUtils
|
||||||
import com.lukouguoji.module_base.ktx.formatDate
|
import com.lukouguoji.module_base.ktx.formatDate
|
||||||
|
|
||||||
@@ -73,7 +78,27 @@ class GjcBoxWeighingViewModel : BasePageViewModel() {
|
|||||||
* 挂签打印按钮点击
|
* 挂签打印按钮点击
|
||||||
*/
|
*/
|
||||||
fun printClick() {
|
fun printClick() {
|
||||||
// TODO: 实现挂签打印功能
|
// 获取列表中选中的记录
|
||||||
|
val list = pageModel.rv?.commonAdapter()?.items as? List<GjcUldUseBean> ?: return
|
||||||
|
val selectedItems = list.filter { it.isSelected }
|
||||||
|
|
||||||
|
// 校验未选择
|
||||||
|
if (selectedItems.isEmpty()) {
|
||||||
|
showToast("请选择要打印的数据")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验多选
|
||||||
|
if (selectedItems.size > 1) {
|
||||||
|
showToast("只能选择一条记录进行打印")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行打印
|
||||||
|
val bean = selectedItems.first()
|
||||||
|
BluetoothDialogModel().showCallBack {
|
||||||
|
PrinterUtils.printGjcBoxWeighing(bean)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user