MixLabelPrinter.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <template>
  2. <div class="main-wrapper">
  3. <div class="left" :style="leftBoxStyle">
  4. <div v-for="itm in printedLabels" :key="itm.label" style="margin: 0 8px 8px 0">
  5. <div class="label-box">
  6. <div class="label-text">
  7. <div>泰和医院20人混采</div>
  8. <div>
  9. {{ itm.label }}
  10. <el-tag v-if="itm.reprint === 1" type="warning">重打</el-tag>
  11. </div>
  12. </div>
  13. <div :id="itm.label + 'qrcode'"></div>
  14. </div>
  15. </div>
  16. </div>
  17. <div class="right">
  18. <div class="reprint-box">
  19. <el-radio-group v-model="reprintWarning">
  20. <el-radio :value="1">重打时提示,让我决定是否重打</el-radio>
  21. <div style="height: 8px"></div>
  22. <el-radio :value="2">重打时不提示,直接打印</el-radio>
  23. <div style="height: 8px"></div>
  24. <el-radio :value="3">重打时跳过,不打印</el-radio>
  25. </el-radio-group>
  26. </div>
  27. <div>
  28. <span :style="{ color: textColor }">号段范围:</span>
  29. <el-select v-model="labelTableName" style="width: 200px" @change="handleLabelRangeChange">
  30. <el-option v-for="item in labelRanges" :key="item.tableName" :label="item.labelRange"
  31. :value="item.tableName">
  32. <span v-html="analyzeFinishStatus(item.finishFlag)"></span>
  33. <el-divider direction="vertical"></el-divider>
  34. <span>{{ item.labelRange }}</span>
  35. </el-option>
  36. </el-select>
  37. </div>
  38. <div>
  39. 起始标签:
  40. <el-input v-model="startLabel" placeholder="请输入起始标签号" style="width: 200px" clearable></el-input>
  41. </div>
  42. <div>
  43. 打印数量:
  44. <el-input-number v-model="printCount" :min="1" :max="100" type="number" placeholder="请输入打印数量"
  45. style="width: 200px" clearable></el-input-number>
  46. </div>
  47. <div>打印操作:
  48. <el-button type="primary" style="width: 200px" @click="begnPrint">开始打印</el-button>
  49. </div>
  50. </div>
  51. </div>
  52. </template>
  53. <script setup name="MixLabelPrinter">
  54. import {
  55. selectLabelRanges,
  56. selectBeginLabel,
  57. selectLabelPrinter,
  58. printLabel,
  59. reprintLabel,
  60. allPrinted
  61. } from '@/api/mix-label-printer'
  62. import {ElMessage, ElMessageBox} from 'element-plus'
  63. import {qrcanvas} from 'qrcanvas'
  64. import {initLodop, getLodop} from '@/utils/c-lodop'
  65. const leftBoxStyle = {
  66. height: window.innerHeight - 25 + 'px',
  67. }
  68. const labelRanges = ref([])
  69. const labelTableName = ref(null)
  70. const currentLabelRange = ref({})
  71. const startLabel = ref(null)
  72. const printCount = ref(1)
  73. const reprintWarning = ref(1)
  74. const printedLabels = ref([])
  75. const textColor = computed(() => {
  76. return currentLabelRange.value.finishFlag === 0 ? 'green' : 'red'
  77. })
  78. const analyzeFinishStatus = (val) => {
  79. return val === 0 ? '<span style="font-size:12px;color:green">未打完</span>' : '<span style="font-size:12px;color:red">已打完</span>'
  80. }
  81. const handleLabelRangeChange = (val) => {
  82. selectBeginLabel(val).then((begin) => {
  83. startLabel.value = begin
  84. })
  85. labelRanges.value.forEach((item) => {
  86. if (item.tableName === labelTableName.value) {
  87. currentLabelRange.value = item
  88. return
  89. }
  90. })
  91. }
  92. const begnPrint = async () => {
  93. if (!startLabel.value || startLabel.value.length < currentLabelRange.value.sliceIndex) {
  94. ElMessage({
  95. message: '请输入正确的起始标签!',
  96. type: 'error',
  97. duration: 2500,
  98. showClose: true,
  99. })
  100. return
  101. }
  102. printedLabels.value = []
  103. for (let i = 0; i < printCount.value; i++) {
  104. const labelIndex = Number(startLabel.value.substring(currentLabelRange.value.sliceIndex, startLabel.value.length)) + i
  105. if (labelIndex > currentLabelRange.value.endNumber) {
  106. ElMessage({
  107. message: '打印完成',
  108. type: 'success',
  109. duration: 2500,
  110. showClose: true,
  111. })
  112. return
  113. }
  114. const label = currentLabelRange.value.prefix + labelIndex
  115. await executePrint(label).then((res) => {}).catch((e) => {})
  116. }
  117. selectBeginLabel(labelTableName.value).then((begin) => {
  118. if (begin) {
  119. startLabel.value = begin
  120. }
  121. })
  122. }
  123. const executePrint = (label) => {
  124. return new Promise((resolve, reject) => {
  125. selectLabelPrinter(labelTableName.value, label).then((origin) => {
  126. if (origin.status === 0) {
  127. printLabel(labelTableName.value, label).then((firstPrint) => {
  128. printedLabels.value.push(firstPrint)
  129. setTimeout(() => {
  130. drawQrcoce(firstPrint.label)
  131. lodopPrint(firstPrint.label)
  132. if (label === currentLabelRange.value.maxLabel) {
  133. allPrinted(labelTableName.value).then((msg) => {
  134. resolve(firstPrint)
  135. })
  136. } else {
  137. resolve(firstPrint)
  138. }
  139. }, 100)
  140. })
  141. } else {
  142. if (reprintWarning.value === 3) {
  143. reject(label)
  144. } else if (reprintWarning.value === 2) {
  145. executeReprint(origin, resolve)
  146. } else if (reprintWarning.value === 1) {
  147. ElMessageBox.confirm(`标签【${label}】已打印过,确定要重新打印吗?`, '提示', {
  148. type: 'warning',
  149. confirmButtonText: '确定',
  150. cancelButtonText: '取消',
  151. }).then(() => {
  152. executeReprint(origin, resolve)
  153. }).catch(() => {
  154. reject(label)
  155. })
  156. }
  157. }
  158. })
  159. })
  160. }
  161. const executeReprint = (origin, resolve) => {
  162. origin.tableName = labelTableName.value
  163. reprintLabel(origin).then((reprint) => {
  164. let found = false
  165. printedLabels.value.forEach((ele) => {
  166. if (ele.label === origin.label) {
  167. ele.reprint = 1
  168. found = true
  169. return
  170. }
  171. })
  172. if (!found) {
  173. printedLabels.value.push(reprint)
  174. }
  175. setTimeout(() => {
  176. document.getElementById(origin.label + 'qrcode').innerHTML = ''
  177. drawQrcoce(reprint.label)
  178. lodopPrint(reprint.label)
  179. resolve(reprint)
  180. }, 100)
  181. })
  182. }
  183. const drawQrcoce = (label) => {
  184. const labelCanvas = qrcanvas({
  185. data: label,
  186. size: 50,
  187. })
  188. document.getElementById(label + 'qrcode').appendChild(labelCanvas)
  189. }
  190. const lodopPrint = (label) => {
  191. const LODOP = getLodop()
  192. LODOP.PRINT_INIT('labels')
  193. LODOP.SET_PRINT_PAGESIZE(1, '50mm', '30mm', 'CreateCustomPage')
  194. LODOP.SET_PRINT_STYLE('Bold', 1)
  195. LODOP.ADD_PRINT_TEXT('8mm', '3mm', '32mm', '5mm', '泰和医院20人混采')
  196. LODOP.ADD_PRINT_BARCODE('14mm', '3mm', '32mm', '10mm', '128Auto', label)
  197. LODOP.ADD_PRINT_BARCODE('10mm', '35mm', '17mm', '17mm', 'QRCode', label)
  198. LODOP.PRINT()
  199. }
  200. onMounted(() => {
  201. initLodop()
  202. selectLabelRanges().then((ranges) => {
  203. labelRanges.value = ranges
  204. if (ranges && ranges.length > 0) {
  205. for (let index = 0; index < ranges.length; index++) {
  206. const item = ranges[index]
  207. if (item.finishFlag === 0) {
  208. currentLabelRange.value = item
  209. labelTableName.value = item.tableName
  210. selectBeginLabel(item.tableName).then((begin) => {
  211. startLabel.value = begin
  212. })
  213. return
  214. }
  215. }
  216. }
  217. })
  218. })
  219. </script>
  220. <style lang="scss" scoped>
  221. .main-wrapper {
  222. display: flex;
  223. padding: 12px;
  224. .left {
  225. width: 70%;
  226. display: flex;
  227. flex-wrap: wrap;
  228. overflow-y: auto;
  229. .label-box {
  230. width: 50mm;
  231. height: 30mm;
  232. background: white;
  233. display: flex;
  234. align-items: center;
  235. justify-content: center;
  236. .label-text {
  237. margin-right: 2mm;
  238. font-size: 12px;
  239. font-weight: bold;
  240. > div {
  241. padding: 1mm 0 1mm 0;
  242. }
  243. }
  244. }
  245. }
  246. .right {
  247. padding: 8px 0 0 30px;
  248. width: 30%;
  249. > div {
  250. margin-bottom: 8px;
  251. }
  252. .reprint-box {
  253. margin-bottom: 12px;
  254. background: white;
  255. width: 220px;
  256. padding: 12px;
  257. border-radius: 4px;
  258. }
  259. }
  260. }
  261. </style>