Print.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <template>
  2. <Dialog v-model="dialogVisible" title="预览" width="60%" scroll>
  3. <div class="materialsOut-print" id="printArea" v-loading="loading">
  4. <div class="title">物资出库单</div>
  5. <div class="meta-row">
  6. <div class="meta-item"><span class="label">申领科室:</span><span class="value">{{ detail.outDeptName || '' }}</span></div>
  7. <div class="meta-item"><span class="label">出库时间:</span><span class="value">{{ detail.orderDate || '' }}</span></div>
  8. <div class="meta-item"><span class="label">出库单号:</span><span class="value">{{ detail.orderNo || '' }}</span></div>
  9. </div>
  10. <div class="meta-row">
  11. <div class="meta-item"><span class="label">出库部门:</span><span class="value"></span></div>
  12. <div class="meta-item"><span class="label">摘要:</span><span class="value"></span></div>
  13. </div>
  14. <table class="items-table">
  15. <thead>
  16. <tr>
  17. <th class="col-idx">序号</th>
  18. <th class="col-no">编号</th>
  19. <th class="col-name">品名</th>
  20. <th class="col-spec">规格</th>
  21. <th class="col-unit">单位</th>
  22. <th class="col-qty">数量</th>
  23. <th class="col-price">进货价</th>
  24. <th class="col-amount">进货金额</th>
  25. <th class="col-remark">备注</th>
  26. </tr>
  27. </thead>
  28. <tbody>
  29. <tr v-for="(it, idx) in (detail.items || [])" :key="it.id ?? idx">
  30. <td class="text-center">{{ idx + 1 }}</td>
  31. <td>{{ it.materialNumber || '' }}</td>
  32. <td>{{ it.materialName || '' }}</td>
  33. <td>{{ it.specification || '' }}</td>
  34. <td class="text-center">{{ it.materialUnit || '' }}</td>
  35. <td class="text-center">{{ it.quantity ?? '' }}</td>
  36. <td class="text-right">{{ (it.inUnitPrice ?? '') }}</td>
  37. <td class="text-right">{{ (Number(it.amount ?? 0)).toFixed(2) }}</td>
  38. <td></td>
  39. </tr>
  40. <tr v-if="!(detail.items && detail.items.length)">
  41. <td colspan="9" class="empty">暂无明细</td>
  42. </tr>
  43. </tbody>
  44. <tfoot>
  45. <tr>
  46. <td colspan="7" class="text-right">合计</td>
  47. <td class="text-right">{{ totalAmount().toFixed(2) }}</td>
  48. <td></td>
  49. </tr>
  50. </tfoot>
  51. </table>
  52. <div class="sign-row">
  53. <div class="sign-item"><span class="label">会计:</span><span class="line"></span></div>
  54. <div class="sign-item"><span class="label">保管:</span><span class="line"></span></div>
  55. <div class="sign-item"><span class="label">领用人:</span><span class="line">{{ detail.outUser || '' }}</span></div>
  56. <div class="sign-item"><span class="label">审核:</span><span class="line"></span></div>
  57. <div class="sign-item"><span class="label">制表:</span><span class="value">{{ detail.creator || '' }}</span></div>
  58. </div>
  59. </div>
  60. <template #footer>
  61. <el-button @click="handleClosed">取消</el-button>
  62. <el-button type="primary" v-print="print">打印</el-button>
  63. </template>
  64. </Dialog>
  65. </template>
  66. <script setup lang="ts">
  67. import { nextTick, reactive, ref } from 'vue'
  68. import { getMaterialOutboundDetail } from '@/api/material/stockInAndOut'
  69. const dialogVisible = ref(false)
  70. const loading = ref(false)
  71. type OutboundItem = {
  72. id?: number
  73. orderId?: number
  74. materialId?: number
  75. materialNumber?: string
  76. materialName?: string
  77. materialUnit?: string
  78. refInboundItemId?: number
  79. refInOrderNo?: string
  80. quantity?: number
  81. inUnitPrice?: number
  82. saleUnitPrice?: number
  83. amount?: number
  84. produceDate?: string
  85. latestAvailableQty?: number
  86. refInStoreId?: number
  87. refInStoreName?: string
  88. specification?: string
  89. }
  90. type OutboundDetail = {
  91. id?: number
  92. orderNo?: string
  93. status?: number
  94. orderDate?: string
  95. outDeptId?: number
  96. outDeptName?: string
  97. outUser?: string
  98. outReason?: string
  99. remark?: string
  100. tenantId?: number
  101. createTime?: string
  102. updateTime?: string
  103. creator?: string
  104. updater?: string
  105. auditor?: string
  106. auditResult?: string
  107. auditTime?: string
  108. auditRemark?: string
  109. items?: OutboundItem[]
  110. }
  111. const detail = reactive<OutboundDetail>({
  112. items: []
  113. })
  114. const totalAmount = () => {
  115. const list = detail.items || []
  116. return list.reduce((sum, it) => sum + Number(it?.amount ?? 0), 0)
  117. }
  118. const handleClosed = () => {
  119. dialogVisible.value = false
  120. }
  121. const open = async (id: number | string) => {
  122. dialogVisible.value = true
  123. loading.value = true
  124. try {
  125. const res: any = await getMaterialOutboundDetail(id)
  126. const data: OutboundDetail = res?.data ?? res ?? {}
  127. Object.assign(detail, {
  128. ...data,
  129. items: Array.isArray(data?.items) ? data.items : []
  130. })
  131. await nextTick()
  132. } finally {
  133. loading.value = false
  134. }
  135. }
  136. // 打印
  137. const print = {
  138. id: 'printArea',
  139. extraCss: '',
  140. popTitle: '',
  141. extraHead: '',
  142. preview: false,
  143. previewTitle: '出库单预览',
  144. previewPrintBtnLabel: '预览结束,开始打印',
  145. zIndex: 20002,
  146. previewBeforeOpenCallback() {
  147. console.log('正在加载预览窗口!')
  148. },
  149. previewOpenCallback() {
  150. console.log('已经加载完预览窗口,预览打开了!')
  151. },
  152. beforeOpenCallback() {
  153. console.log('开始打印之前!')
  154. },
  155. openCallback() {
  156. console.log('执行打印了!')
  157. },
  158. closeCallback() {
  159. console.log('关闭了打印工具!')
  160. },
  161. clickMounted() {
  162. console.log('点击v-print绑定的按钮了!')
  163. },
  164. standard: ''
  165. }
  166. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  167. </script>
  168. <style media="print" lang="scss">
  169. @page {
  170. margin: 3mm;
  171. margin-top: 2cm;
  172. margin-bottom: 2cm;
  173. }
  174. @media print {
  175. html {
  176. background-color: #ffffff;
  177. height: auto;
  178. margin: 0;
  179. }
  180. .synthetic-ability-print {
  181. padding: 10px 15px;
  182. }
  183. }
  184. </style>
  185. <style lang="scss" scoped>
  186. .materialsOut-print {
  187. padding: 10px 15px;
  188. color: #000;
  189. }
  190. .title {
  191. text-align: center;
  192. font-size: 18px;
  193. font-weight: 600;
  194. margin-bottom: 10px;
  195. }
  196. .meta-row {
  197. display: flex;
  198. gap: 10px;
  199. margin-bottom: 6px;
  200. }
  201. .meta-item {
  202. flex: 1;
  203. display: flex;
  204. align-items: center;
  205. min-height: 22px;
  206. }
  207. .label {
  208. width: 90px;
  209. flex: 0 0 90px;
  210. }
  211. .value {
  212. flex: 1;
  213. border-bottom: 1px solid #000;
  214. padding: 0 6px;
  215. min-height: 18px;
  216. }
  217. .items-table {
  218. width: 100%;
  219. border-collapse: collapse;
  220. margin-top: 10px;
  221. }
  222. .items-table th,
  223. .items-table td {
  224. border: 1px solid #000;
  225. padding: 6px 6px;
  226. font-size: 12px;
  227. }
  228. .text-center {
  229. text-align: center;
  230. }
  231. .text-right {
  232. text-align: right;
  233. }
  234. .empty {
  235. text-align: center;
  236. height: 60px;
  237. }
  238. .sign-row {
  239. display: flex;
  240. margin-top: 18px;
  241. gap: 20px;
  242. }
  243. .sign-item {
  244. flex: 1;
  245. display: flex;
  246. align-items: center;
  247. }
  248. .line {
  249. flex: 1;
  250. border-bottom: 1px solid #000;
  251. margin-left: 6px;
  252. height: 18px;
  253. }
  254. </style>