You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

591 lines
20 KiB

11 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
11 months ago
11 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
11 months ago
11 months ago
10 months ago
11 months ago
7 months ago
11 months ago
11 months ago
11 months ago
11 months ago
10 months ago
11 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
7 months ago
7 months ago
7 months ago
11 months ago
11 months ago
10 months ago
7 months ago
7 months ago
7 months ago
11 months ago
7 months ago
11 months ago
11 months ago
11 months ago
11 months ago
7 months ago
  1. <template>
  2. <div class="customer-css">
  3. <el-dialog :title="titleCon" :close-on-click-modal="false" :visible.sync="visible"
  4. width="600px" class="customer-dialog" @close="deleteFile">
  5. <el-form label-position="top" >
  6. <el-row :gutter="16">
  7. <el-col :span="6" >
  8. <el-form-item label=" ">
  9. <el-button type="primary" @click="downloadFile()">下载文件模板</el-button>
  10. </el-form-item> </el-col>
  11. <el-col :span="6">
  12. <el-form-item label="BU">
  13. <el-select v-model="pageData.buNo" placeholder="请选择" style="width: 100%">
  14. <el-option v-for = "i in buList" :key = "i.buNo" :label = "i.buDesc" :value = "i.buNo"></el-option>
  15. </el-select>
  16. </el-form-item>
  17. </el-col>
  18. <el-col :span="6">
  19. <el-form-item :label="'贸易国'" >
  20. <el-input v-model="pageData.salesArea"></el-input>
  21. </el-form-item>
  22. </el-col>
  23. <el-col :span="6">
  24. <el-form-item :label="'运抵国'" >
  25. <el-input v-model="pageData.cnative"></el-input>
  26. </el-form-item>
  27. </el-col>
  28. <el-col :span="12">
  29. <el-form-item :label="''" >
  30. <template #label>
  31. <span slot="label" style="" class="big-label">
  32. <a href="#" @click="customFlag=true">客户</a>
  33. </span>
  34. </template>
  35. <el-input type="textarea"
  36. :rows="2" v-model="pageData.customerName"></el-input>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="12">
  40. <el-form-item :label="''" >
  41. <template #label>
  42. <span slot="label" style="" class="big-label">
  43. <a href="#" @click="overseasShipperFlag=true">收货单位</a>
  44. </span>
  45. </template>
  46. <el-input type="textarea"
  47. :rows="2" v-model="pageData.overseasShipper"></el-input>
  48. </el-form-item>
  49. </el-col>
  50. <el-col :span="12" style="margin-top: 30px">
  51. <el-form-item :label="''" >
  52. <template #label>
  53. <span slot="label" style="" class="big-label">
  54. <a href="#" @click="localShipAddressFlag=true">客户地址</a>
  55. </span>
  56. </template>
  57. <el-input type="textarea"
  58. :rows="3" v-model="pageData.localShipAddress"></el-input>
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="12" style="margin-top: 30px">
  62. <el-form-item :label="''" >
  63. <template #label>
  64. <span slot="label" style="" class="big-label">
  65. <a href="#" @click="overseasAddressFlag=true">收货单位地址</a>
  66. </span>
  67. </template>
  68. <el-input type="textarea"
  69. :rows="3" v-model="pageData.overseasAddress"></el-input>
  70. </el-form-item>
  71. </el-col>
  72. <el-col :span="24" style="margin-top: 60px">
  73. <el-upload class="customer-upload" drag action="javascript:void(0);" ref="uploadFile" :limit="1" accept=".xlsx,.xls"
  74. :before-upload="beforeUploadHandle" :on-change="onChange" :auto-upload="false" style="text-align: left;">
  75. <i class="el-icon-upload"></i>
  76. <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
  77. </el-upload>
  78. </el-col>
  79. </el-row>
  80. </el-form>
  81. <span slot="footer" class="dialog-footer" style="margin-top: 10px">
  82. <el-button type="primary" @click="saveUploadFile">保存</el-button>
  83. <el-button type="primary" @click="closeDialog">关闭</el-button>
  84. </span>
  85. </el-dialog>
  86. <el-dialog title="客户" @close="closeCustomDialog" :visible.sync="customFlag" width="500px" v-drag>
  87. <el-form inline="inline" label-position="top" :model="customSearchData" style="margin-left: 7px;margin-top: -5px;">
  88. <el-form-item label="客户名称">
  89. <el-input v-model="customSearchData.ccusname" clearable style="width: 150px"></el-input>
  90. </el-form-item>
  91. <el-form-item label=" ">
  92. <el-button type="primary" style="padding: 3px 12px" @click="getCustomerList()">查询</el-button>
  93. </el-form-item>
  94. </el-form>
  95. <el-table
  96. :height="400"
  97. :data="customerList"
  98. stripe
  99. highlight-current-row
  100. border
  101. @row-dblclick="rowDblclick"
  102. style="width: 100%;">
  103. <el-table-column
  104. prop="ccusname"
  105. header-align="center"
  106. align="left"
  107. width="350"
  108. label="客户名称">
  109. </el-table-column>
  110. <el-table-column
  111. prop="country"
  112. header-align="center"
  113. align="left"
  114. label="贸易国">
  115. </el-table-column>
  116. </el-table>
  117. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  118. <el-button @click="customFlag = false">关闭</el-button>
  119. </el-footer>
  120. </el-dialog>
  121. <el-dialog title="客户地址" @close="localShipAddressFlag = false" :visible.sync="localShipAddressFlag" width="500px" v-drag>
  122. <el-table
  123. :height="400"
  124. :data="customerAddrs"
  125. stripe
  126. highlight-current-row
  127. border
  128. @row-dblclick="rowDblclick2"
  129. style="width: 100%;">
  130. <el-table-column
  131. prop="cDeliverAdd"
  132. header-align="center"
  133. align="left"
  134. label="客户地址">
  135. </el-table-column>
  136. </el-table>
  137. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  138. <el-button @click="localShipAddressFlag = false">关闭</el-button>
  139. </el-footer>
  140. </el-dialog>
  141. <el-dialog title="收货单位地址" @close="overseasAddressFlag = false" :visible.sync="overseasAddressFlag" width="500px" v-drag>
  142. <el-table
  143. :height="400"
  144. :data="customerAddrs"
  145. stripe
  146. highlight-current-row
  147. border
  148. @row-dblclick="rowDblclick3"
  149. style="width: 100%;">
  150. <el-table-column
  151. prop="cDeliverAdd"
  152. header-align="center"
  153. align="left"
  154. label="收货单位地址">
  155. </el-table-column>
  156. </el-table>
  157. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  158. <el-button @click="overseasAddressFlag = false">关闭</el-button>
  159. </el-footer>
  160. </el-dialog>
  161. <el-dialog title="收货单位" @close="overseasShipperFlag = false" :visible.sync="overseasShipperFlag" width="500px" v-drag>
  162. <el-table
  163. :height="400"
  164. :data="customerAddrs"
  165. stripe
  166. highlight-current-row
  167. border
  168. @row-dblclick="rowDblclick4"
  169. style="width: 100%;">
  170. <el-table-column
  171. prop="cDeliverUnit"
  172. header-align="left"
  173. align="left"
  174. width="350"
  175. label="收货单位">
  176. </el-table-column>
  177. <el-table-column
  178. prop="deliverycountry"
  179. header-align="center"
  180. align="left"
  181. label="运抵国">
  182. </el-table-column>
  183. </el-table>
  184. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  185. <el-button @click="overseasShipperFlag = false">关闭</el-button>
  186. </el-footer>
  187. </el-dialog>
  188. </div>
  189. </template>
  190. <script>
  191. import {queryFileId} from "@/api/qc/qc.js"
  192. import {saveEcssCoDelNotifyByExcel,getCustomerList,getCustomers,getCustomerAdd} from '@/api/ecss/ecss.js'
  193. import {downLoadObjectFile} from '@/api/eam/eam_object_list.js'
  194. import {getBuList}from '@/api/factory/site.js'
  195. export default {
  196. name: 'bomComponentUpload',
  197. data() {
  198. return {
  199. buList: [],
  200. titleCon: '文件导入',
  201. visible: false,
  202. fileList: [],
  203. pageData: {
  204. site: '',
  205. buNo: '',
  206. createBy: this.$store.state.user.name,
  207. customerName:'',
  208. localShipAddress:'',
  209. overseasShipper:'',
  210. overseasAddress:'',
  211. cnative:'',
  212. salesArea:'',
  213. },
  214. customSearchData: {},
  215. customerList : [],//所有客户
  216. customerAddrs : [],//地址
  217. customerPersons : [],//联系人
  218. customerMap:new Map,
  219. customFlag:false,
  220. localShipAddressFlag:false,
  221. overseasShipperFlag:false,
  222. overseasAddressFlag:false,
  223. cacheKey: '', // 缓存键
  224. cacheTimer: null, // 缓存定时器
  225. }
  226. },
  227. watch: {
  228. // 深度监听pageData的变化,自动保存到缓存
  229. pageData: {
  230. handler: function(newVal, oldVal) {
  231. // 只有在组件已初始化且对话框可见时才保存缓存
  232. if (this.visible && this.cacheKey) {
  233. this.saveToCache();
  234. }
  235. },
  236. deep: true
  237. }
  238. },
  239. beforeDestroy() {
  240. // 组件销毁前清理定时器
  241. if (this.cacheTimer) {
  242. clearTimeout(this.cacheTimer);
  243. }
  244. },
  245. methods: {
  246. // 生成缓存键
  247. generateCacheKey() {
  248. const userId = this.$store.state.user.id || this.$store.state.user.name;
  249. return `ecss_del_upload_cache_${userId}`;
  250. },
  251. // 保存数据到缓存(防抖处理)
  252. saveToCache() {
  253. // 清除之前的定时器
  254. if (this.cacheTimer) {
  255. clearTimeout(this.cacheTimer);
  256. }
  257. // 设置新的定时器,500ms后执行保存
  258. this.cacheTimer = setTimeout(() => {
  259. try {
  260. const cacheData = {
  261. pageData: {
  262. buNo: this.pageData.buNo,
  263. customerName: this.pageData.customerName,
  264. localShipAddress: this.pageData.localShipAddress,
  265. overseasShipper: this.pageData.overseasShipper,
  266. overseasAddress: this.pageData.overseasAddress,
  267. cnative: this.pageData.cnative,
  268. salesArea: this.pageData.salesArea,
  269. }
  270. };
  271. localStorage.setItem(this.cacheKey, JSON.stringify(cacheData));
  272. } catch (error) {
  273. console.warn('保存缓存失败:', error);
  274. }
  275. }, 500);
  276. },
  277. // 从缓存加载数据
  278. loadFromCache() {
  279. try {
  280. const cachedData = localStorage.getItem(this.cacheKey);
  281. if (cachedData) {
  282. const parsedData = JSON.parse(cachedData);
  283. if (parsedData.pageData) {
  284. // 恢复缓存的数据(不包括文件)
  285. Object.assign(this.pageData, parsedData.pageData);
  286. return true;
  287. }
  288. }
  289. } catch (error) {
  290. console.warn('加载缓存失败:', error);
  291. }
  292. return false;
  293. },
  294. // 清除缓存
  295. clearCache() {
  296. try {
  297. localStorage.removeItem(this.cacheKey);
  298. } catch (error) {
  299. console.warn('清除缓存失败:', error);
  300. }
  301. },
  302. // 初始化组件的参数
  303. init () {
  304. this.fileList = []
  305. this.cacheKey = this.generateCacheKey();
  306. let tempData = {
  307. username: this.$store.state.user.name,
  308. }
  309. getBuList(tempData).then(({data}) => {
  310. if (data.code === 0) {
  311. this.buList = data.row2
  312. if(data.row2.length===1){
  313. this.pageData.buNo=data.row2[0].buNo
  314. }
  315. }
  316. // 在获取BU列表后尝试加载缓存
  317. this.loadFromCache();
  318. })
  319. getCustomerList({}).then(({data}) => {
  320. //区分请求成功和失败的状况
  321. if (data && data.code === 0) {
  322. this.customerList=data.rows
  323. }
  324. });
  325. // 如果没有缓存数据,则初始化为空
  326. if (!this.loadFromCache()) {
  327. this.pageData.customerName=''
  328. this.pageData.cnative=''
  329. this.pageData.localShipAddress='',
  330. this.pageData.overseasShipper='',
  331. this.pageData.overseasAddress='',
  332. this.pageData.salesArea=''
  333. }
  334. this.customerPersons=[]
  335. this.customerAddrs=[]
  336. // 打开页面
  337. this.visible = true
  338. },
  339. getCustomerList(){
  340. getCustomerList(this.customSearchData).then(({data}) => {
  341. //区分请求成功和失败的状况
  342. if (data && data.code === 0) {
  343. this.customerList=data.rows
  344. }
  345. });
  346. },
  347. getCusPersons(){
  348. let cusData = {ccusname: this.pageData.customerName}
  349. getCustomers(cusData).then(({data}) => {
  350. //区分请求成功和失败的状况
  351. if (data && data.code === 0) {
  352. this.customerPersons=data.rows
  353. this.customerPersons.forEach(o => {
  354. if (!this.customerMap.has(o.ccontactname)) {
  355. this.customerMap.set(o.ccontactname, o.cnative);
  356. }
  357. });
  358. }
  359. });
  360. getCustomerAdd(cusData).then(({data}) => {
  361. //区分请求成功和失败的状况
  362. if (data && data.code === 0) {
  363. this.customerAddrs=data.rows
  364. }
  365. });
  366. },
  367. setCnative(){
  368. this.pageData.cnative=this.customerMap.get(this.pageData.overseasShipper)
  369. },
  370. closeCustomDialog () {
  371. this.customFlag = false
  372. },
  373. rowDblclick (row) {
  374. this.pageData.customerName=row.ccusname
  375. this.pageData.cnative='',
  376. this.pageData.localShipAddress='',
  377. this.pageData.overseasShipper='',
  378. this.pageData.overseasAddress='',
  379. this.pageData.salesArea = row.country
  380. this.getCusPersons()
  381. this.customFlag = false
  382. },
  383. rowDblclick2 (row) {
  384. this.pageData.localShipAddress=row.cDeliverAdd
  385. this.localShipAddressFlag = false
  386. },
  387. rowDblclick3 (row) {
  388. this.pageData.overseasAddress=row.cDeliverAdd
  389. this.overseasAddressFlag = false
  390. },
  391. rowDblclick4 (row) {
  392. this.pageData.overseasShipper=row.cDeliverUnit
  393. this.pageData.cnative=row.deliverycountry
  394. this.overseasShipperFlag = false
  395. },
  396. // 上传之前
  397. beforeUploadHandle (file) {
  398. let extName = file[0].name.substring(file[0].name.lastIndexOf('.')).toLowerCase()
  399. if (!(extName === '.xlsx' || extName === '.xls')) {
  400. this.$message.error('数据导入失败,请选择正确的xlsx模板文件')
  401. return false
  402. }
  403. },
  404. // 选择上传文件时
  405. onChange (file) {
  406. this.fileList.push(file)
  407. },
  408. // 关闭modal
  409. closeDialog () {
  410. this.deleteFile()
  411. // 关闭当前的页面
  412. this.visible = false
  413. // 注意:这里不清除缓存,让数据保留到下次打开
  414. },
  415. deleteFile(){
  416. this.fileList = []
  417. // 清空文件上传记录
  418. this.$refs.uploadFile.clearFiles()
  419. // 刷新报工的页面
  420. this.$emit('refreshTable')
  421. },
  422. // 保修当前的数据
  423. saveUploadFile () {
  424. if (null == this.pageData.buNo || this.pageData.buNo=='') {
  425. this.$message.error("请先选择BU!")
  426. return false
  427. }
  428. if (null == this.pageData.customerName || this.pageData.customerName=='') {
  429. this.$message.error("请先选择客户!")
  430. return false
  431. }
  432. if (null == this.pageData.localShipAddress || this.pageData.localShipAddress=='') {
  433. this.$message.error("请先填写客户发货地址!")
  434. return false
  435. }
  436. if (null == this.pageData.overseasShipper || this.pageData.overseasShipper=='') {
  437. this.$message.error("请先填写收货单位!")
  438. return false
  439. }
  440. if (null == this.pageData.overseasAddress || this.pageData.overseasAddress=='') {
  441. this.$message.error("请先填写收货单位地址!")
  442. return false
  443. }
  444. if (null == this.pageData.cnative || this.pageData.cnative=='') {
  445. this.$message.error("请先填写收货单位运抵国!")
  446. return false
  447. }
  448. // 判断文件是否上传
  449. if (null == this.fileList || 0 === this.fileList.length) {
  450. this.$message.error("请先上传文件!")
  451. return false
  452. }
  453. const formData = new FormData()
  454. formData.append("buNo",this.pageData.buNo)
  455. formData.append("username",this.$store.state.user.name)
  456. formData.append("file", this.fileList[0].raw)
  457. formData.append("customerName", this.pageData.customerName)
  458. formData.append("localShipAddress", this.pageData.localShipAddress)
  459. formData.append("overseasShipper", this.pageData.overseasShipper)
  460. formData.append("overseasAddress", this.pageData.overseasAddress)
  461. formData.append("cnative", this.pageData.cnative)
  462. formData.append("salesArea", this.pageData.salesArea)
  463. saveEcssCoDelNotifyByExcel(formData).then(({ data }) => {
  464. if (data.code === 0) {
  465. const { resultMap } = data;
  466. const successList = resultMap.success || [];
  467. const failList = resultMap.fail || [];
  468. // 紧凑样式
  469. let html = `
  470. <div style="max-height:380px;overflow:auto;font-size:12px;line-height:1.4;">
  471. `;
  472. if (successList.length > 0) {
  473. html += `<div style="margin-bottom:6px;">
  474. <div style="color:green;font-weight:bold;margin-bottom:3px;">
  475. 成功${successList.length}
  476. </div>
  477. <table border="1" cellspacing="0" cellpadding="2"
  478. style="border-collapse:collapse;width:100%;">
  479. `;
  480. successList.forEach(item => {
  481. html += `<tr><td style="color:green;padding:2px 4px;">${item}</td></tr>`;
  482. });
  483. html += `</table></div>`;
  484. }
  485. if (failList.length > 0) {
  486. html += `<div>
  487. <div style="color:red;font-weight:bold;margin-bottom:3px;">
  488. 失败${failList.length}
  489. </div>
  490. <table border="1" cellspacing="0" cellpadding="2"
  491. style="border-collapse:collapse;width:100%;">
  492. `;
  493. failList.forEach(item => {
  494. html += `<tr><td style="color:red;padding:2px 4px;">${item}</td></tr>`;
  495. });
  496. html += `</table></div>`;
  497. }
  498. html += `</div>`;
  499. this.$alert(html, '导入结果', {
  500. confirmButtonText: '确定',
  501. dangerouslyUseHTMLString: true,
  502. callback: () => {
  503. this.clearCache();
  504. this.closeDialog();
  505. }
  506. });
  507. } else {
  508. this.$alert(data.msg, '错误', {
  509. confirmButtonText: '确定'
  510. });
  511. }
  512. });
  513. },
  514. // 下载
  515. async downloadFile () {
  516. let file = {
  517. id: 0,
  518. fileName: ''
  519. }
  520. let tempData = {
  521. orderRef1: 'ecss',
  522. orderRef2: 'upLoadDel'
  523. }
  524. await queryFileId(tempData).then(({data}) => {
  525. if (data && data.code === 0) {
  526. file.id = data.data.id
  527. file.fileName = data.data.fileName
  528. } else {
  529. this.$alert(data.msg, '错误', {
  530. confirmButtonText: '确定'
  531. })
  532. }
  533. })
  534. await downLoadObjectFile(file).then(({data}) => {
  535. // 不限制文件下载类型
  536. const blob = new Blob([data], {type: "application/octet-stream"})
  537. // 下载文件名称
  538. const fileName = file.fileName
  539. // a标签下载
  540. const linkNode = document.createElement('a')
  541. // a标签的download属性规定下载文件的名称
  542. linkNode.download = fileName
  543. linkNode.style.display = 'none'
  544. // 生成一个Blob URL
  545. linkNode.href = URL.createObjectURL(blob)
  546. document.body.appendChild(linkNode)
  547. // 模拟在按钮上的一次鼠标单击
  548. linkNode.click()
  549. // 释放URL 对象
  550. URL.revokeObjectURL(linkNode.href)
  551. document.body.removeChild(linkNode)
  552. })
  553. },
  554. }
  555. }
  556. </script>
  557. <style scoped>
  558. /deep/ .customer-upload .el-upload .el-upload-dragger {
  559. width: 580px;
  560. }
  561. </style>