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.

313 lines
8.9 KiB

  1. <template>
  2. <div class="customer-css">
  3. <el-dialog
  4. title="导入IFS库存数据"
  5. :close-on-click-modal="false"
  6. :visible.sync="visible"
  7. width="450px"
  8. class="customer-dialog"
  9. @close="handleDialogClose"
  10. :show-close="!uploading">
  11. <el-form :inline="true" label-position="top" label-width="80px">
  12. <el-row>
  13. <el-form-item label=" ">
  14. <el-button
  15. type="primary"
  16. icon="el-icon-download"
  17. :disabled="uploading"
  18. @click="downloadTemplate">
  19. 下载 Excel 模板
  20. </el-button>
  21. </el-form-item>
  22. </el-row>
  23. <el-row>
  24. <el-col :span="24">
  25. <el-upload
  26. class="customer-upload"
  27. drag
  28. action="javascript:void(0);"
  29. ref="uploadFile"
  30. :limit="1"
  31. accept=".xlsx,.xls"
  32. :before-upload="beforeUploadHandle"
  33. :on-change="onChange"
  34. :auto-upload="false"
  35. :disabled="uploading"
  36. style="text-align: left;">
  37. <i class="el-icon-upload"></i>
  38. <div class="el-upload__text">
  39. {{ uploading ? '正在上传中,请稍候...' : '将文件拖到此处,或点击上传' }}
  40. </div>
  41. </el-upload>
  42. </el-col>
  43. </el-row>
  44. <el-row style="margin-top: 15px;">
  45. <el-alert
  46. title="导入说明"
  47. type="info"
  48. :closable="false"
  49. show-icon>
  50. <div style="font-size: 12px; line-height: 1.8;">
  51. 1. 请先下载模板按模板格式填写数据<br/>
  52. 2. 必填字段SitePart NoLot/Batch NoLocation NoQty On Hand<br/>
  53. 3. A-K列库存信息保存到inventory_stock_ifs表<br/>
  54. 4. L-U列料件属性信息保存到part_attribute表可选填<br/>
  55. 5. 料件属性如已存在会自动跳过不会报错<br/>
  56. 6. 日期格式YYYY/M/D YYYY-MM-DD
  57. </div>
  58. </el-alert>
  59. </el-row>
  60. </el-form>
  61. <span slot="footer" class="dialog-footer">
  62. <el-button type="primary" @click="saveUploadFile" :loading="uploading" :disabled="uploading">
  63. {{ uploading ? '上传中...' : '开始导入' }}
  64. </el-button>
  65. <el-button @click="closeDialog" :disabled="uploading">关闭</el-button>
  66. </span>
  67. </el-dialog>
  68. </div>
  69. </template>
  70. <script>
  71. import { uploadIfsInventoryExcel } from '@/api/warehouse/ifsInventoryInit.js'
  72. export default {
  73. name: 'ifsInventoryUploadExcel',
  74. data() {
  75. return {
  76. visible: false,
  77. fileList: [],
  78. uploading: false // 上传状态标志
  79. }
  80. },
  81. methods: {
  82. /**
  83. * 初始化组件
  84. */
  85. init() {
  86. this.fileList = []
  87. this.uploading = false
  88. this.visible = true
  89. },
  90. /**
  91. * 上传之前的验证
  92. */
  93. beforeUploadHandle(file) {
  94. let extName = file.name.substring(file.name.lastIndexOf('.')).toLowerCase()
  95. if (!(extName === '.xlsx' || extName === '.xls')) {
  96. this.$message.error('数据导入失败,请选择正确的xlsx或xls格式的Excel文件')
  97. return false
  98. }
  99. return true
  100. },
  101. /**
  102. * 选择上传文件时
  103. */
  104. onChange(file) {
  105. // 清空之前的文件列表,确保只有一个文件
  106. this.fileList = []
  107. this.fileList.push(file)
  108. },
  109. /**
  110. * 关闭弹窗
  111. */
  112. closeDialog() {
  113. this.deleteFile()
  114. this.visible = false
  115. },
  116. /**
  117. * 处理弹窗关闭事件包括右上角X按钮
  118. */
  119. handleDialogClose() {
  120. if (this.uploading) {
  121. this.$message.warning('正在上传中,请稍候...')
  122. return
  123. }
  124. this.deleteFile()
  125. },
  126. /**
  127. * 清除文件
  128. */
  129. deleteFile() {
  130. this.fileList = []
  131. this.uploading = false
  132. // 清空文件上传记录
  133. this.$refs.uploadFile.clearFiles()
  134. // 刷新父页面
  135. this.$emit('refreshTable')
  136. },
  137. /**
  138. * 格式化错误信息为HTML列表
  139. */
  140. formatErrorMessages(errorMessages) {
  141. if (!errorMessages || errorMessages.length === 0) {
  142. return ''
  143. }
  144. // 限制显示的错误数量(前20条)
  145. const displayMessages = errorMessages.slice(0, 20)
  146. const hasMore = errorMessages.length > 20
  147. let html = '<div style="text-align: left; max-height: 400px; overflow-y: auto;">'
  148. html += '<p style="color: #E6A23C; font-weight: bold; margin-bottom: 10px;">以下数据导入失败:</p>'
  149. html += '<ol style="padding-left: 20px; line-height: 1.8;">'
  150. displayMessages.forEach(msg => {
  151. html += `<li style="color: #F56C6C; margin-bottom: 5px;">${msg}</li>`
  152. })
  153. html += '</ol>'
  154. if (hasMore) {
  155. html += `<p style="color: #909399; margin-top: 10px;">...还有 ${errorMessages.length - 20} 条错误</p>`
  156. }
  157. html += '</div>'
  158. return html
  159. },
  160. /**
  161. * 下载Excel模板
  162. */
  163. downloadTemplate() {
  164. const loading = this.$loading({
  165. lock: true,
  166. text: '正在下载模板...',
  167. spinner: 'el-icon-loading',
  168. background: 'rgba(0, 0, 0, 0.7)'
  169. })
  170. this.$http({
  171. url: this.$http.adornUrl('/ifsInventoryInit/downloadTemplate'),
  172. method: 'get',
  173. responseType: 'blob'
  174. }).then(response => {
  175. loading.close()
  176. // 创建下载链接
  177. const blob = new Blob([response.data], {
  178. type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  179. })
  180. const url = window.URL.createObjectURL(blob)
  181. const link = document.createElement('a')
  182. link.href = url
  183. link.download = 'IFS库存导入模板.xlsx'
  184. document.body.appendChild(link)
  185. link.click()
  186. document.body.removeChild(link)
  187. window.URL.revokeObjectURL(url)
  188. this.$message.success('模板下载成功')
  189. }).catch(error => {
  190. loading.close()
  191. console.error('模板下载失败:', error)
  192. this.$message.error('模板下载失败,请联系管理员')
  193. })
  194. },
  195. /**
  196. * 保存上传文件
  197. */
  198. saveUploadFile() {
  199. // 判断文件是否上传
  200. if (null == this.fileList || 0 === this.fileList.length) {
  201. this.$message.error("请先选择要上传的Excel文件!")
  202. return false
  203. }
  204. // 再次校验文件格式
  205. const file = this.fileList[0].raw
  206. const fileName = file.name
  207. const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase()
  208. if (!('.xls' === fileExtension || '.xlsx' === fileExtension)) {
  209. this.$message.error('文件格式不正确,只支持.xls和.xlsx格式的Excel文件')
  210. return false
  211. }
  212. // 设置上传状态
  213. this.uploading = true
  214. // 创建FormData对象
  215. const formData = new FormData()
  216. formData.append("file", file)
  217. formData.append("site", localStorage.getItem('site'))
  218. formData.append("uploadBy", this.$store.state.user.name)
  219. // 调用上传接口
  220. uploadIfsInventoryExcel(formData).then(({ data }) => {
  221. if (data.code === 0) {
  222. // 检查是否有错误信息
  223. const errorMessages = data.errorMessages || []
  224. if (errorMessages.length > 0) {
  225. // 有错误信息,使用弹窗显示详细错误列表
  226. const errorHtml = this.formatErrorMessages(errorMessages)
  227. this.$alert(errorHtml, '导入完成(部分数据失败)', {
  228. confirmButtonText: '确定',
  229. dangerouslyUseHTMLString: true,
  230. customClass: 'import-error-dialog'
  231. }).then(() => {
  232. // 关闭窗口并刷新页面
  233. this.closeDialog()
  234. })
  235. } else {
  236. // 完全成功,显示成功提示
  237. this.$message({
  238. message: data.msg || 'IFS库存数据导入成功',
  239. type: 'success',
  240. duration: 2000
  241. })
  242. // 关闭窗口并刷新页面
  243. this.closeDialog()
  244. }
  245. } else {
  246. this.$alert(data.msg, '错误', {
  247. confirmButtonText: '确定'
  248. })
  249. }
  250. }).catch(error => {
  251. console.error('Excel上传异常:', error)
  252. this.$message.error('Excel文件上传异常,请检查文件格式和内容')
  253. }).finally(() => {
  254. // 无论成功还是失败,都重置上传状态
  255. this.uploading = false
  256. })
  257. }
  258. }
  259. }
  260. </script>
  261. <style scoped>
  262. .customer-css .customer-upload {
  263. width: 100%;
  264. }
  265. .customer-css .el-upload {
  266. width: 100%;
  267. }
  268. .customer-css .el-upload-dragger {
  269. width: 100%;
  270. }
  271. </style>
  272. <style>
  273. /* 导入错误弹窗样式 */
  274. .import-error-dialog {
  275. width: 600px !important;
  276. }
  277. .import-error-dialog .el-message-box__message {
  278. max-height: 500px;
  279. overflow-y: auto;
  280. }
  281. </style>