index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <template>
  2. <div class="page">
  3. <template-page
  4. v-if="!formDialog && isShowTab"
  5. ref="pageRef"
  6. :get-list="getList"
  7. :table-attributes="tableAttributes"
  8. :table-events="tableEvents"
  9. :operationColumnWidth="140"
  10. :options-evens-group="optionsEvensGroup"
  11. :moreParameters="moreParameters"
  12. :column-parsing="columnParsing"
  13. :operation="operation()"
  14. :exportList="exportList"
  15. >
  16. <div slot="moreSearch">
  17. <el-radio-group v-model="flag" size="mini" @change="changeType">
  18. <el-radio-button label="">全部</el-radio-button>
  19. <el-radio-button label="SAVE">保存</el-radio-button>
  20. <el-radio-button label="SUBMIT">提交</el-radio-button>
  21. <el-radio-button label="PAY_NOT_TAKE">已支付未提货</el-radio-button>
  22. <el-radio-button label="PAY_TAKE">已支付已提货</el-radio-button>
  23. <el-radio-button label="CANCEL">取消订单</el-radio-button>
  24. </el-radio-group>
  25. <br /><br />
  26. </div>
  27. </template-page>
  28. <div class="detail" v-if="formDialog">
  29. <attachmentSalesOrderDetail
  30. :id="id"
  31. @back="backList"
  32. :formType="formDialogType"
  33. :title="'配件销售订单' + formDialogTitles[formDialogType]"
  34. ></attachmentSalesOrderDetail>
  35. </div>
  36. <print-preview ref="preView" @initPrint="handleInitPrint" @refreshList="handleRefreshList" />
  37. <el-dialog title="导入结果" :visible.sync="showImportResult" width="600px">
  38. <div class="importResultList">
  39. <div class="item" v-for="(item, index) in importResultList" :key="index">{{ item }}</div>
  40. </div>
  41. <span slot="footer" class="dialog-footer">
  42. <el-button @click="showImportResult = false">关 闭</el-button>
  43. </span>
  44. </el-dialog>
  45. </div>
  46. </template>
  47. <script>
  48. import TemplatePage from '@/components/template/template-page-1.vue'
  49. import attachmentSalesOrderDetail from '../components/attachmentSalesOrderDetail.vue'
  50. import import_mixin from '@/components/template/import_mixin.js'
  51. import ImageUpload from '@/components/file-upload'
  52. import { downloadFiles } from '@/utils/util'
  53. import { required, mobileRequired, mobile, httpUrl, email } from '@/components/template/rules_verify.js'
  54. import {
  55. listPageV2,
  56. pageExport,
  57. getDetail,
  58. add,
  59. edit,
  60. submit,
  61. listImportP,
  62. queryImportResult
  63. } from '@/api/auxiliaryFittings/auxiliarySalesOrder'
  64. import { getWebsit } from '@/api/customerManagement'
  65. import printPreview from '../components/preview.vue'
  66. import { disAutoConnect, hiprint } from 'vue-plugin-hiprint'
  67. import operation_mixin from '@/components/template/operation_mixin.js'
  68. import { commonTemplateDownload } from '@/api/common.js'
  69. disAutoConnect()
  70. export default {
  71. components: { TemplatePage, ImageUpload, attachmentSalesOrderDetail, printPreview },
  72. mixins: [import_mixin, operation_mixin],
  73. data() {
  74. return {
  75. // 表格属性
  76. tableAttributes: {
  77. // 启用勾选列
  78. selectColumn: true
  79. },
  80. // 表格事件
  81. tableEvents: {
  82. 'selection-change': this.selectionChange
  83. },
  84. // 勾选选中行
  85. recordSelected: [],
  86. /** 表单变量 */
  87. formDialogType: 0,
  88. formDialogTitles: ['新增', '编辑', '详情'],
  89. formDialog: false,
  90. id: '',
  91. flag: this?.$route?.params?.pageCode || '',
  92. websitList: [],
  93. isShowTab: true,
  94. orderEnginBaseId: '',
  95. payQrcode: JSON.parse(localStorage.getItem('greemall_user')).payQrcode,
  96. billTitle: JSON.parse(localStorage.getItem('greemall_user')).billTitle, //打印名称
  97. showImportResult: false,
  98. importResultList: []
  99. }
  100. },
  101. computed: {
  102. // 事件组合
  103. optionsEvensGroup() {
  104. return [
  105. [
  106. [
  107. this.optionsEvensAuth('add', {
  108. click: this.addData
  109. })
  110. ]
  111. ],
  112. [
  113. [
  114. this.optionsEvensAuth('imp', {
  115. render: () => {
  116. return this.importButton(listImportP, '导入', null, null, res => {
  117. this.$nextTick(() => {
  118. this.checkImportResult(res.data)
  119. })
  120. })
  121. }
  122. })
  123. ],
  124. [
  125. this.optionsEvensAuth('template', {
  126. click: () => {
  127. this.handleDownload()
  128. }
  129. })
  130. ]
  131. ]
  132. ]
  133. },
  134. // 更多参数
  135. moreParameters() {
  136. return []
  137. },
  138. formItems() {},
  139. filterArr() {
  140. return function (arr, size) {
  141. //判断如果不是数组(就没有length),或者size没有传值,size小于1,就返回空数组
  142. if (!arr.length || !size || size < 1) return []
  143. let [start, end, result] = [null, null, []]
  144. for (let i = 0; i < Math.ceil(arr.length / size); i++) {
  145. start = i * size
  146. end = start + size
  147. result.push(arr.slice(start, end))
  148. }
  149. return result
  150. }
  151. }
  152. },
  153. created() {
  154. if (this.$route.query.id) {
  155. this.id = this.$route.query.id
  156. this.formDialogType = 2
  157. this.openForm()
  158. }
  159. if (this.pageCode) {
  160. this.orderEnginBaseId = this.pageCode
  161. }
  162. },
  163. watch: {
  164. flag() {
  165. this.isShowTab = false
  166. this.$nextTick(() => {
  167. this.isShowTab = true
  168. })
  169. }
  170. },
  171. methods: {
  172. // 切换状态
  173. changeType(val) {
  174. this.$refs.pageRef.refreshList()
  175. },
  176. backList() {
  177. this.id = ''
  178. this.formDialog = false
  179. this.$refs.pageRef.refreshList()
  180. },
  181. // 列表请求函数
  182. getList(p, cb) {
  183. try {
  184. var pam = JSON.parse(JSON.stringify(p))
  185. pam.params.push(
  186. { param: 'a.goods_type', compare: '=', value: 'P' },
  187. { param: 'a.flag', compare: '=', value: this.flag },
  188. { param: 'a.order_engin_base_id', compare: '=', value: this.orderEnginBaseId }
  189. )
  190. cb && cb(pam)
  191. return listPageV2(pam)
  192. } catch (error) {
  193. console.log(error)
  194. }
  195. },
  196. // 列表导出函数
  197. exportList: pageExport,
  198. // 表格列解析渲染数据更改
  199. columnParsing(item, defaultData) {
  200. if (item.jname === 'idCardImg') {
  201. defaultData.render = (h, { row, index, column }) => {
  202. return (
  203. <div style="padding:0 6px;cursor: pointer;">
  204. {row.idCardImg
  205. ? row.idCardImg
  206. .split(',')
  207. .map(url => (
  208. <el-image
  209. src={this.$showImgUrl(url)}
  210. preview-src-list={[this.$showImgUrl(url)]}
  211. fit="fit"
  212. style="width:80px;height:80px;"
  213. />
  214. ))
  215. : null}
  216. </div>
  217. )
  218. }
  219. }
  220. return defaultData
  221. },
  222. // 监听勾选变化
  223. selectionChange(data) {
  224. this.recordSelected = data
  225. },
  226. operation() {
  227. return this.operationBtn({
  228. edit: {
  229. conditions: ({ row, index, column }) => {
  230. return row.flag == 'SAVE'
  231. },
  232. click: ({ row, index, column }) => {
  233. this.id = row.salesId
  234. this.formDialogType = 1
  235. this.openForm()
  236. }
  237. },
  238. detail: {
  239. conditions: ({ row, index, column }) => {
  240. return row.flag != 'SAVE'
  241. },
  242. click: ({ row, index, column }) => {
  243. this.id = row.salesId
  244. this.formDialogType = 2
  245. this.openForm()
  246. }
  247. },
  248. verify: {
  249. conditions: ({ row, index, column }) => {
  250. return row.flag == 'PAY_NOT_TAKE'
  251. },
  252. click: ({ row, index, column }) => {
  253. this.id = row.salesId
  254. this.formDialogType = row.flag == 'SAVE' ? 1 : 2
  255. this.openForm()
  256. }
  257. },
  258. print: {
  259. click: ({ row, index, column }) => {
  260. this.toPrint(row, 2)
  261. }
  262. }
  263. })
  264. },
  265. addData() {
  266. this.formDialogType = 0
  267. this.openForm()
  268. },
  269. openForm() {
  270. this.formDialog = true
  271. },
  272. getWebsit() {
  273. getWebsit({ type: 'C' }).then(res => {
  274. this.websitList = res.data
  275. })
  276. },
  277. // 点击打印
  278. async toPrint(row, type) {
  279. this.getWebsit()
  280. let pagingData = []
  281. const { data } = await getDetail({
  282. salesId: row.salesId
  283. })
  284. pagingData = this.filterArr(data.items, 4)
  285. // 初始化模板,否则生成的模板叠加
  286. hiprint.init()
  287. this.hiprintTemplate = new hiprint.PrintTemplate()
  288. // 兼容批量打印
  289. // let params = !type ? this.filterArr() : [row.salesId]
  290. let len = pagingData.length
  291. let loadingLen = len
  292. // 使用 i-- 提升for效率
  293. this.$startLoading()
  294. for (let i = 0; i < len; i++) {
  295. try {
  296. let websitHtml = ''
  297. let html = ''
  298. let num = 0
  299. let totalAmount = 0
  300. pagingData[i].forEach(item => {
  301. totalAmount = (Number(item.saleAmount) * 100 + totalAmount * 100) / 100
  302. num += Number(item.salesQty)
  303. html += `
  304. <tr align="center">
  305. <td>${item.goodsName || ''}</td>
  306. <td>${item.goodsSpecification || ''}</td>
  307. <td>${item.goodsSalesUnit || ''}</td>
  308. <td>${item.salesQty || ''}</td>
  309. <td>${item.price || ''}</td>
  310. <td>${item.saleAmount || ''}</td>
  311. <td>${data.storageName}</td>
  312. <td></td>
  313. </tr>
  314. `
  315. })
  316. this.websitList.slice(0, 5).forEach(item => {
  317. websitHtml += `
  318. <div style="display: flex;font-size: 14px;margin-bottom: 6px;">
  319. <div style="margin-right: 10px;">${item.name}</div>
  320. <div style="margin-right: 10px;">${item.websitPhone}</div>
  321. <div>地址: ${item.address}</div>
  322. </div>
  323. `
  324. })
  325. // 模板基础配置
  326. this.panel = this.hiprintTemplate.addPrintPanel({
  327. height: 140,
  328. width: 241,
  329. fontFamily: '黑体',
  330. fontSize: 13,
  331. paperFooter: 340,
  332. paperHeader: 10,
  333. paperNumberDisabled: true
  334. })
  335. // 获取收款单模板和基础配置
  336. this.panel.addPrintHtml({
  337. options: {
  338. width: 633,
  339. top: 30,
  340. left: 20,
  341. fontFamily: '黑体',
  342. fontSize: 13,
  343. content: this.setTableDom(data, html, websitHtml, totalAmount, num, len, i)
  344. }
  345. })
  346. loadingLen--
  347. } catch (error) {
  348. console.log(999, error)
  349. this.$endLoading()
  350. return
  351. }
  352. }
  353. if (loadingLen === 0) {
  354. this.$endLoading()
  355. }
  356. console.log(333)
  357. // 预览打印内容
  358. this.$refs.preView.show(this.hiprintTemplate, this.panel)
  359. },
  360. // 打印模板
  361. setTableDom(data, html, websitHtml, totalAmount, num, length, page) {
  362. return `
  363. <div style="font-family:'黑体';font-size: 16px;">
  364. <div style="display: flex;justify-content: space-between;align-items: center;">
  365. <div style="width: 28%;"></div>
  366. <h1 style="text-align:center;margin: 10px 0;">${this.billTitle ? this.billTitle : data.websitName}销售单</h1>
  367. <div>共 ${length}页 第 ${page + 1} 页</div>
  368. </div>
  369. <div style="display: flex;justify-content: space-between;">
  370. <div style="width: 28%;"></div>
  371. <div>单据日期: ${data.createTime}</div>
  372. <div>单据编号: ${data.salesId}</div>
  373. </div>
  374. <div style="display: flex;justify-content: space-between;font-size: 16px;margin: 10px 0;">
  375. <div>客户: ${data.workerName}</div>
  376. <div>摘要: ${data.payType == 'CASH' ? '现金' : data.payType == 'WECHAT' ? '微信' : '工程支付'}</div>
  377. </div>
  378. <div style="display: flex;justify-content: space-between;font-size: 16px;margin-bottom: 10px;">
  379. <div>联系电话: ${data.workerMobile}</div>
  380. <div>收货地址: ${data.province ? data.province + data.city + data.area + data.street + data.address : ''}</div>
  381. <div style="width: 28%;"></div>
  382. </div>
  383. <div >
  384. <table border=".5" cellspacing="0" width="856"
  385. style="border-color: rgb(0,0,0);
  386. border-collapse: collapse;
  387. border-style: none;
  388. border: 1px solid rgb(0,0,0);
  389. font-weight: normal;
  390. text-decoration: none;
  391. vertical-align: middle;
  392. box-sizing: border-box;
  393. word-wrap: break-word;
  394. word-break: break-all;">
  395. <tr align="center">
  396. <td>商品名称</td>
  397. <td>规格</td>
  398. <td>单位</td>
  399. <td>数量</td>
  400. <td>单价</td>
  401. <td>金额</td>
  402. <td>仓库</td>
  403. <td>备注</td>
  404. </tr>
  405. ${html}
  406. <tr align="center" align="center">
  407. <td>小计: </td>
  408. <td colspan="2"></td>
  409. <td>${num}</td>
  410. <td></td>
  411. <td>${totalAmount}</td>
  412. <td colspan="2">金额总计: ${totalAmount}</td>
  413. </tr>
  414. </table>
  415. </div>
  416. <div style="display: flex;justify-content: space-between;font-size: 16px;margin: 10px 0;">
  417. <div>制单人: ${data.createBy || ''}</div>
  418. <div>审核人: ${data.confirmBy || ''}</div>
  419. <div>业务员: </div>
  420. <div>签收人: </div>
  421. </div>
  422. <div style="display: flex;justify-content: space-between;">
  423. <div>
  424. ${websitHtml}
  425. </div>
  426. ${
  427. data.payType == 'CASH' && this.payQrcode
  428. ? `<div style="">
  429. <img style="width: 80px;height: 80px;" src="${this.$showImgUrl(this.payQrcode)}"/>
  430. </div>`
  431. : ''
  432. }
  433. </div>
  434. <div style="margin:100px 0 0 0">
  435. <div></div>
  436. </div>
  437. </div>
  438. `
  439. },
  440. handleRefreshList() {
  441. this.recordSelected = []
  442. this.$refs.pageRef.refreshList()
  443. },
  444. handleInitPrint() {
  445. this.$nextTick(() => {
  446. this.initPrint()
  447. })
  448. },
  449. // 下载导入模版
  450. handleDownload() {
  451. commonTemplateDownload({ name: '配件销售订单导入模板.xlsx' }, `${this.$route.meta.title}`)
  452. .then(res => {
  453. this.$message({
  454. message: '下载成功',
  455. type: 'success'
  456. })
  457. })
  458. .catch(err => {
  459. this.$message.error('下载失败')
  460. })
  461. },
  462. // 查询导入结果
  463. checkImportResult(importBatchId) {
  464. const loading = this.$loading({
  465. lock: true,
  466. text: '正在查询导入结果',
  467. spinner: 'el-icon-loading',
  468. background: 'rgba(0, 0, 0, 0.7)'
  469. })
  470. queryImportResult({
  471. importBatchId
  472. })
  473. .then(result => {
  474. if (result.data.waitCount == 0) {
  475. clearInterval(this.timer)
  476. loading.close()
  477. // result.data.errList = ['测试测试1', '测试测试1']
  478. if (result.data?.errList?.length > 0) {
  479. this.importResultList = result.data.errList
  480. this.showImportResult = true
  481. } else {
  482. }
  483. } else {
  484. this.timer = setTimeout(() => {
  485. this.checkImportResult(importBatchId)
  486. }, 2000)
  487. }
  488. })
  489. .catch(err => {
  490. loading.close()
  491. clearInterval(this.timer)
  492. })
  493. }
  494. }
  495. }
  496. </script>
  497. <style lang="scss" scoped>
  498. .page {
  499. height: 100%;
  500. }
  501. .tab {
  502. padding: 20px 20px 0 20px;
  503. }
  504. .importResultList {
  505. .item {
  506. font-size: 16px;
  507. margin-bottom: 10px;
  508. }
  509. }
  510. </style>