PrintCard.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. <template>
  2. <div>
  3. <div v-show="printing">
  4. <Navbar title="标签打印" :is-go-back="true" />
  5. <div class="printDiv">
  6. <div>
  7. <span style="color: red"> * </span>
  8. <label>导入批次:</label>
  9. <a-select
  10. v-model:value="queryParams.batchNo"
  11. show-search
  12. class="commonStyle"
  13. :options="batchNos.map((item) => ({ value: item.label }))"
  14. @change="batchNoChange"
  15. />
  16. <label>保管人员:</label>
  17. <a-select
  18. v-model:value="queryParams.depositoryUser"
  19. show-search
  20. class="commonStyle"
  21. :options="depositoryUsers.map((item) => ({ value: item.label }))"
  22. @change="searchDatas"
  23. />
  24. <label>打印状态:</label>
  25. <a-select
  26. v-model:value="queryParams.labelPrintType"
  27. show-search
  28. class="commonStyle"
  29. :options="
  30. statusOptions.map((item) => ({
  31. value: item.value,
  32. label: item.label,
  33. }))
  34. "
  35. @change="searchDatas"
  36. />
  37. </div>
  38. <div style="margin: 8px 0 0 9px">
  39. <label>公司名称:</label>
  40. <a-select
  41. v-model:value="queryParams.clientName"
  42. show-search
  43. class="commonStyle"
  44. :options="clientNames.map((item) => ({ value: item.label }))"
  45. @change="searchDatas"
  46. />
  47. <label>所属部门:</label>
  48. <a-select
  49. v-model:value="queryParams.organizationName"
  50. show-search
  51. class="commonStyle"
  52. :options="organizationNames.map((item) => ({ value: item.label }))"
  53. @change="searchDatas"
  54. />
  55. <label>成本中心:</label>
  56. <a-select
  57. v-model:value="queryParams.costCenterName"
  58. show-search
  59. class="commonStyle"
  60. :options="costCenterNames.map((item) => ({ value: item.label }))"
  61. @change="searchDatas"
  62. />
  63. <a-button type="primary" @click="searchDatas">查询</a-button>
  64. </div>
  65. <div style="margin-top: 8px">
  66. <span style="color: red"> * </span>
  67. <label>打印模板:</label>
  68. <a-select
  69. v-model:value="printTemplate"
  70. show-search
  71. class="commonStyle"
  72. :options="
  73. templateNames.map((item) => ({
  74. value: `${item.id}-${item.name}`,
  75. label: item.name,
  76. }))
  77. "
  78. @change="getTemplateInfo"
  79. />
  80. <a-button
  81. type="dashed"
  82. style="margin-right: 16px"
  83. @click="printPreview"
  84. >
  85. 效果预览
  86. </a-button>
  87. <a-button
  88. type="dashed"
  89. style="margin-right: 16px"
  90. @click="showPrintInfo"
  91. >
  92. 打印
  93. </a-button>
  94. <a-button type="dashed" style="margin-right: 16px" @click="printAll">
  95. 打印全部
  96. </a-button>
  97. <a-button type="dashed" @click="downloadImageZip">
  98. 下载全部
  99. </a-button>
  100. </div>
  101. <a-divider />
  102. <CommonTable
  103. ref="table"
  104. :total="total"
  105. :columns="columns"
  106. :is-loading="isLoading"
  107. :is-select="isSelect"
  108. :data-source="dataSource"
  109. @get-selected="selectColumn"
  110. @get-pager="getPageParams"
  111. >
  112. <template #bodyCell="{ column, record }">
  113. <template v-if="column.key === 'imageUrl'">
  114. <a-image
  115. :width="100"
  116. :height="50"
  117. :src="getImageSrc(className, record.imageUrl)"
  118. />
  119. </template>
  120. </template>
  121. </CommonTable>
  122. <a-modal
  123. v-model:visible="printVisible"
  124. title="包装信息"
  125. ok-text="确认"
  126. cancel-text="取消"
  127. @ok="
  128. all === false
  129. ? printCard(select.selectedRows)
  130. : printCard(select.allData)
  131. "
  132. >
  133. <label>包装批号:</label>
  134. <a-input
  135. id="displayName"
  136. v-model:value="packageBatchNo"
  137. :disabled="true"
  138. />
  139. <label>上次的批号:</label>
  140. <a-input v-model:value="lastPackageBatchNo" :disabled="true" />
  141. <label>包装名称:</label>
  142. <a-input
  143. id="displayName"
  144. v-model:value="packageName"
  145. :disabled="true"
  146. />
  147. <label>上次的名称:</label>
  148. <a-input v-model:value="lastPackageName" :disabled="true" />
  149. <div class="operationBtn">
  150. <a-button type="dashed" style="width: 240px" @click="lastTime">
  151. 同上一次
  152. </a-button>
  153. <a-button
  154. type="dashed"
  155. style="width: 240px; margin-left: 4px"
  156. @click="createNew"
  157. >
  158. 生成新的
  159. </a-button>
  160. </div>
  161. </a-modal>
  162. <a-modal
  163. v-model:visible="imageVisible"
  164. title="效果预览"
  165. :mask-closable="false"
  166. :body-style="bodyStyle"
  167. >
  168. <a-image :src="imageUrls[0]" />
  169. <template #footer />
  170. </a-modal>
  171. <Loading v-if="globalLoading" :text="propText" />
  172. </div>
  173. </div>
  174. <div ref="hua" style="float: left; z-index: -999" />
  175. </div>
  176. </template>
  177. <script setup>
  178. import Common from '../common/Common';
  179. import CreateJPEG from '../common/X6';
  180. import { message } from 'ant-design-vue';
  181. import { base64toFile } from '../common/X6';
  182. import CommonTable from '../common/CommonTable.vue';
  183. import { SqlApi, Notify } from 'pc-component-v3';
  184. import { getImageSrc } from '../common/image-src';
  185. import { ref, reactive, onMounted, watch } from 'vue';
  186. import {
  187. columns,
  188. dateConvert,
  189. multipleImageUpload,
  190. getTemplate,
  191. downloadZip,
  192. } from './config';
  193. const className = ref('com.leanwo.prodog.print.model.LabelPrintLine');
  194. const table = ref(null);
  195. const imageUrls = reactive([]);
  196. const printing = ref(true);
  197. const total = ref(0);
  198. const isSelect = ref(true);
  199. const isLoading = ref(false);
  200. const select = reactive({ selectedRows: [], allData: [] });
  201. const dataSource = ref([]);
  202. const printVisible = ref(false);
  203. const imageVisible = ref(false);
  204. const visible = ref(false);
  205. const globalLoading = ref(false);
  206. const all = ref(false);
  207. const propText = ref('');
  208. const bodyStyle = {
  209. display: 'flex',
  210. justifyContent: 'center',
  211. };
  212. const batchNos = ref([]);
  213. const clientNames = ref([]);
  214. const depositoryUsers = ref([]);
  215. const costCenterNames = ref([]);
  216. const organizationNames = ref([]);
  217. const statusOptions = ref([
  218. {
  219. value: '',
  220. label: '',
  221. },
  222. {
  223. value: 'To_Be_Printed',
  224. label: '待打印',
  225. },
  226. {
  227. value: 'Printing',
  228. label: '打印中',
  229. },
  230. {
  231. value: 'Printed',
  232. label: '已打印',
  233. },
  234. ]);
  235. const queryParams = reactive({
  236. batchNo: '',
  237. depositoryUser: '',
  238. labelPrintType: '',
  239. clientName: '',
  240. organizationName: '',
  241. costCenterName: '',
  242. });
  243. const pager = reactive({
  244. start: 0,
  245. length: 20,
  246. });
  247. const templateId = ref('');
  248. const allTemplate = ref([]);
  249. const templateData = ref(null);
  250. const lastBatchNo = ref('');
  251. const printTemplate = ref('');
  252. const templateNames = ref([]);
  253. const packageBatchNo = ref('');
  254. const lastPackageBatchNo = ref('');
  255. const packageName = ref('');
  256. const lastPackageName = ref('');
  257. const newPackageName = ref('');
  258. const hua = ref(null);
  259. const clientId = ref('');
  260. let getBase64;
  261. // 获取分页
  262. const getPageParams = (start, length) => {
  263. pager.start = (start - 1) * length;
  264. pager.length = length;
  265. searchPrintInfo();
  266. };
  267. // 批次号切换
  268. const batchNoChange = () => {
  269. queryParams.clientName = '';
  270. queryParams.depositoryUser = '';
  271. queryParams.costCenterName = '';
  272. queryParams.organizationName = '';
  273. queryParams.labelPrintType = '';
  274. commonSqlApi('20230613_192444', depositoryUsers); // 查询保管人
  275. commonSqlApi('20230613_193808', clientNames); // 查询公司
  276. commonSqlApi('20230613_194108', organizationNames); // 查询部门
  277. commonSqlApi('20230613_194557', costCenterNames); // 查询成本中心
  278. table.value.clear(); // 清空选择
  279. table.value.backFirstPage(); // 回到第一页
  280. };
  281. // 查询回到第一页
  282. const searchDatas = () => {
  283. table.value.backFirstPage();
  284. };
  285. // 查询信息
  286. const searchPrintInfo = () => {
  287. isLoading.value = true;
  288. clientId.value = JSON.parse(localStorage.getItem('#LoginInfo')).loginClientId;
  289. let params = { ...queryParams, ...pager, clientId: clientId.value };
  290. if (queryParams.batchNo !== '') {
  291. SqlApi.execute('20230613_140456', params).then(
  292. successData => {
  293. const { lines, errorMessage, errorCode } = successData;
  294. if (errorCode == 0) {
  295. total.value = successData.total;
  296. dataSource.value = lines;
  297. select.allData = lines;
  298. isLoading.value = false;
  299. } else {
  300. Notify.error('查询异常', errorMessage, true);
  301. }
  302. isLoading.value = false;
  303. },
  304. errorData => {
  305. Common.processException(errorData);
  306. isLoading.value = false;
  307. },
  308. );
  309. } else {
  310. isLoading.value = false;
  311. }
  312. };
  313. // 获取所选项的数据
  314. const selectColumn = selected => {
  315. select.selectedRows = selected.selectedRows;
  316. // console.log('onSelectChange', select.selectedRows);
  317. };
  318. // 展开打印框
  319. const showPrintInfo = () => {
  320. if (printTemplate.value !== '' && queryParams.batchNo !== '') {
  321. printVisible.value = true;
  322. const nameArr = [];
  323. const obj = JSON.parse(JSON.stringify(queryParams));
  324. delete obj.labelPrintType;
  325. for (let key in obj) {
  326. if (obj[key] !== '') nameArr.push(obj[key]);
  327. }
  328. packageName.value = nameArr.join('-');
  329. newPackageName.value = nameArr.join('-');
  330. packageBatchNo.value = dateConvert(new Date());
  331. } else {
  332. message.warning('请检查是否已选择导入批次或模板!');
  333. }
  334. };
  335. // 同上一次包装信息
  336. const lastTime = () => {
  337. if (lastPackageName.value == null && lastPackageBatchNo.value == null) {
  338. message.info('没有上次的包装信息');
  339. } else {
  340. packageName.value = lastPackageName.value;
  341. packageBatchNo.value = lastPackageBatchNo.value;
  342. }
  343. };
  344. // 生产新的包装信息
  345. const createNew = () => {
  346. packageBatchNo.value = dateConvert(new Date());
  347. packageName.value = newPackageName.value;
  348. };
  349. // 获取模板数据及 ID
  350. const getTemplateInfo = async () => {
  351. templateId.value = printTemplate.value.slice(
  352. 0,
  353. printTemplate.value.indexOf('-'),
  354. );
  355. allTemplate.value.forEach(item => {
  356. if (item.id == templateId.value) {
  357. templateData.value = item.contentX6;
  358. }
  359. });
  360. };
  361. // 打印预览
  362. const printPreview = async () => {
  363. if (printTemplate.value !== '' && queryParams.batchNo !== '') {
  364. imageVisible.value = true;
  365. printing.value = false;
  366. imageUrls.length = 0;
  367. let tempStr = JSON.stringify(templateData.value);
  368. const rows = JSON.parse(JSON.stringify(dataSource.value[0]));
  369. let base64 = await getBase64(rows, tempStr);
  370. imageUrls.push(base64);
  371. printing.value = true;
  372. } else {
  373. message.warning('请检查是否已选择导入批次或模板!');
  374. }
  375. };
  376. // 确认打印
  377. const printCard = async data => {
  378. if (data.length !== 0) {
  379. printVisible.value = false;
  380. globalLoading.value = true;
  381. printing.value = false;
  382. const formData = new FormData();
  383. formData.append('customerPrintTemplateId', templateId.value);
  384. formData.append('packageBatchNo', packageBatchNo.value);
  385. formData.append('packageName', packageName.value);
  386. let tempStr = JSON.stringify(templateData.value);
  387. const rows = JSON.parse(JSON.stringify(data));
  388. let amount = 0;
  389. for (let key in rows) {
  390. amount = amount + 1;
  391. let base64 = await getBase64(rows[key], tempStr, rows[key].assetNo);
  392. let file = base64toFile(base64, rows[key].id);
  393. formData.append('file', file);
  394. propText.value = `生成中,已生成${amount}张`;
  395. }
  396. multipleImageUpload(formData).then(
  397. successData => {
  398. if (successData.success === true) {
  399. message.success('资产生产图片成功');
  400. } else {
  401. message.error('资产生产图片失败');
  402. }
  403. globalLoading.value = false;
  404. printing.value = true;
  405. all.value = false;
  406. searchPrintInfo();
  407. clearSelect();
  408. },
  409. errorData => {
  410. Common.processException(errorData);
  411. globalLoading.value = false;
  412. printing.value = true;
  413. all.value = false;
  414. clearSelect();
  415. },
  416. );
  417. } else {
  418. all.value = false;
  419. printVisible.value = false;
  420. message.warning('请选择打印数据');
  421. }
  422. };
  423. // 全部生成图片
  424. const printAll = () => {
  425. all.value = true;
  426. pager.start = 0;
  427. pager.length = 10000;
  428. searchPrintInfo();
  429. showPrintInfo();
  430. };
  431. //下载全部图片(zip)
  432. const downloadImageZip = () => {
  433. if (queryParams.batchNo === '') {
  434. message.warning('请选择导入批次');
  435. } else {
  436. globalLoading.value = true;
  437. var xhr = new XMLHttpRequest();
  438. xhr.open('get', `api/LabelPrintResource/batchImageDownload?batchNo=${queryParams.batchNo}`, true);
  439. const token = localStorage.getItem('#token');
  440. xhr.setRequestHeader('token', token);
  441. xhr.setRequestHeader('Content-type', 'application/json');
  442. xhr.responseType = 'blob';
  443. xhr.onreadystatechange = function(){
  444. if(xhr.readyState === 4 && xhr.status === 200){
  445. let res = xhr.response;
  446. let blob = new Blob([res]);
  447. const blobUrl = URL.createObjectURL(blob);
  448. const link = document.createElement('a');
  449. link.download = '图片.zip';
  450. link.style.display = 'none';
  451. link.href = blobUrl;
  452. document.body.appendChild(link);
  453. link.click();
  454. URL.revokeObjectURL(blobUrl);
  455. document.body.removeChild(link);
  456. globalLoading.value = false;
  457. message.success('下载成功');
  458. }
  459. };
  460. xhr.send();
  461. }
  462. };
  463. // 打印后清除所有选择
  464. const clearSelect = () => {
  465. table.value.clear();
  466. };
  467. onMounted(() => {
  468. init();
  469. getBase64 = CreateJPEG(hua.value);
  470. clientId.value = JSON.parse(localStorage.getItem('#LoginInfo')).loginClientId;
  471. });
  472. // 封装通用sqlApi请求函数
  473. const commonSqlApi = (url, data) => {
  474. clientId.value = JSON.parse(localStorage.getItem('#LoginInfo')).loginClientId;
  475. let params = { clientId: clientId.value, batchNo: queryParams.batchNo };
  476. SqlApi.execute(url, params).then(
  477. successData => {
  478. if (successData.errorCode == 0) {
  479. if (successData.lines !== null) {
  480. data.value = successData.lines.map(item => {
  481. return (item = { label: item });
  482. });
  483. data.value.unshift({ label: '' });
  484. } else {
  485. data.value = [];
  486. }
  487. } else {
  488. Notify.error('查询信息异常', successData.errorMessage, true);
  489. }
  490. },
  491. errorData => {
  492. Common.processException(errorData);
  493. },
  494. );
  495. };
  496. // 初始化数据
  497. const init = () => {
  498. clientId.value = JSON.parse(localStorage.getItem('#LoginInfo')).loginClientId;
  499. let params = { clientId: clientId.value };
  500. getTemplate().then(res => {
  501. allTemplate.value = res.datas;
  502. });
  503. // 查询批次号
  504. SqlApi.execute('20230613_134214', params).then(
  505. successData => {
  506. if (successData.errorCode == 0) {
  507. if (successData.lines !== null) {
  508. let datas = successData.lines.map(item => {
  509. return (item = { label: item });
  510. });
  511. batchNos.value = datas.reverse();
  512. }
  513. } else {
  514. Notify.error('查询导入批次异常', successData.errorMessage, true);
  515. }
  516. },
  517. errorData => {
  518. Common.processException(errorData);
  519. },
  520. );
  521. // 查询模板
  522. SqlApi.execute('20230613_135541', params).then(
  523. successData => {
  524. if (successData.errorCode == 0) {
  525. if (successData.label !== null) {
  526. templateNames.value = successData.lines;
  527. }
  528. } else {
  529. Notify.error('查询模板信息异常', successData.errorMessage, true);
  530. }
  531. },
  532. errorData => {
  533. Common.processException(errorData);
  534. },
  535. );
  536. // 获取上一次的包装信息
  537. SqlApi.execute('20230613_194855', params).then(
  538. successData => {
  539. if (successData.errorCode == 0) {
  540. const { packageName, packageBatchNo } = successData.lines[0];
  541. lastPackageName.value = packageName;
  542. lastPackageBatchNo.value = packageBatchNo;
  543. } else {
  544. Notify.error('获取包装信息异常', successData.errorMessage, true);
  545. }
  546. },
  547. errorData => {
  548. Common.processException(errorData);
  549. },
  550. );
  551. };
  552. </script>
  553. <style scoped>
  554. .commonStyle {
  555. margin-right: 16px;
  556. width: 160px;
  557. }
  558. .search,
  559. .operationBtn {
  560. margin-top: 8px;
  561. }
  562. .operationBtn {
  563. display: flex;
  564. justify-content: space-between;
  565. }
  566. #displayName:disabled {
  567. background: white;
  568. color: black;
  569. }
  570. .full-modal .ant-modal {
  571. max-width: 100%;
  572. top: 0;
  573. padding-bottom: 0;
  574. margin: 0;
  575. }
  576. .full-modal .ant-modal-content {
  577. display: flex;
  578. flex-direction: column;
  579. height: calc(100vh);
  580. }
  581. .full-modal .ant-modal-body {
  582. flex: 1;
  583. }
  584. .ant-divider-horizontal{
  585. margin: 4px 0;
  586. }
  587. </style>