index.vue 13 KB

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