黄陂项目
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.

599 lines
17 KiB

2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
  1. <template>
  2. <div
  3. v-loading="loading1"
  4. class="import-container"
  5. element-loading-background="rgba(0, 0, 0, 0.8)"
  6. >
  7. <ul class="import-header">
  8. <li><i class="step-img01" /><span>上传数据包</span></li>
  9. <li :class="['dot-img', {'dot-img-active':isShow02 || isShow03}]" />
  10. <li><i :class="['step-img02', {'step-img02-active':isShow02 || isShow03}]" /><span>读取数据</span></li>
  11. <li :class="['dot-img', {'dot-img-active':isShow03}]" />
  12. <li><i :class="['step-img03', {'step-img03-active':isShow03}]" /><span>导入数据</span></li>
  13. </ul>
  14. <div
  15. v-if="isShow01"
  16. class="step-content step-upload"
  17. >
  18. <div class="upload-container">
  19. <input ref="fileInput" :key="key" type="file" accept=".xlsx, .xls" @change="handleFileChange">
  20. <div class="upload-zip"><i class="el-icon-upload2" />选择文件</div>
  21. </div>
  22. <div class="el-upload__tip">上传限制文件类型xlsx, xls</div>
  23. <div v-for="item in fileList" :key="item.name" class="file-list">
  24. {{ item.name }}
  25. <i class="el-icon-close" @click="deleteFile(item)" />
  26. </div>
  27. </div>
  28. <div v-if="isShow01" class="step-bottom-btn">
  29. <el-button type="primary" @click="handleStep01">下一步</el-button>
  30. </div>
  31. <div v-if="isShow02" class="step-content">
  32. <div class="import-data-number"> <span style="color: #339cff;">{{ totalNum }}</span> 正常 <span style="color: #1AAE93;">{{ normalNum }}</span> 问题 <span style="color:rgb(246,81,99)">{{ errorNum }}</span> </div>
  33. <ListPre
  34. ref="importTableList"
  35. :hp-id="hpId"
  36. :initial-table-data="previewTableData"
  37. :initial-total="previewTotal"
  38. />
  39. </div>
  40. <div v-if="isShow02" class="step-bottom-btn">
  41. <el-button @click="handleReturn02">上一步</el-button>
  42. <el-button type="primary" @click="submitImport">导入</el-button>
  43. </div>
  44. <div v-if="isShow03" class="step-content step-content03">
  45. <!-- 导入中状态 -->
  46. <div v-if="importStatus === 'loading'" class="import-status-indicator">
  47. <i class="el-icon-loading" />
  48. <p>数据导入中,请耐心等待...</p>
  49. </div>
  50. <!-- 导入成功状态 -->
  51. <div v-else-if="importStatus === 'success'" class="import-status-indicator success">
  52. <i class="el-icon-circle-check" />
  53. <p>数据导入成功</p>
  54. <el-button type="primary" @click="handleReturn03">完成</el-button>
  55. </div>
  56. <!-- 导入失败状态 -->
  57. <div v-else-if="importStatus === 'error'" class="import-status-indicator error">
  58. <i class="el-icon-circle-close" />
  59. <p>数据导入失败请重试</p>
  60. <el-button type="primary" @click="retryImport">重试</el-button>
  61. <el-button @click="handleReturn03">取消</el-button>
  62. </div>
  63. </div>
  64. <!-- <div v-if="isShow03" class="step-content step-content03">
  65. <el-form ref="form" :model="form" label-width="160px">
  66. <el-row>
  67. <el-form-item label="案卷及文件数据">
  68. <el-checkbox v-model="form.importArchive">导入</el-checkbox>
  69. </el-form-item>
  70. <el-form-item label="遇到重复数据导入方式">
  71. <el-radio-group v-model="form.archivesImportType">
  72. <el-radio label="2">覆盖</el-radio>
  73. </el-radio-group>
  74. </el-form-item>
  75. </el-row>
  76. <el-row>
  77. <el-form-item label="资料数据">
  78. <el-checkbox v-model="form.importInformation">导入</el-checkbox>
  79. </el-form-item>
  80. <el-form-item label="遇到重复数据导入方式" pr>
  81. <el-radio-group v-model="form.informationInputType">
  82. <el-radio label="2">覆盖</el-radio>
  83. </el-radio-group>
  84. </el-form-item>
  85. </el-row>
  86. <el-form-item>
  87. <el-button type="primary" class="submit-btn" @click="submitForm('form')">导入</el-button>
  88. <el-button @click="handleReturn03">取消</el-button>
  89. </el-form-item>
  90. </el-form>
  91. </div> -->
  92. <el-dialog title="确认删除" :visible.sync="deleteVisible">
  93. <span class="dialog-right-top" />
  94. <span class="dialog-left-bottom" />
  95. <div class="setting-dialog">
  96. <p><span style="color:#fff;">此操作将清空所选数据</span></p>
  97. <div slot="footer" class="dialog-footer">
  98. <el-button type="primary" @click.native="handleDelConfirm">确定</el-button>
  99. </div>
  100. </div>
  101. </el-dialog>
  102. </div>
  103. </template>
  104. <script>
  105. import crudFileImport from '@/api/archivesManage/fileImport'
  106. import { mapGetters } from 'vuex'
  107. import ListPre from '../module/listPre.vue'
  108. export default {
  109. name: 'DataImport',
  110. components: { ListPre },
  111. data() {
  112. return {
  113. key: 0,
  114. file: null,
  115. fileList: [],
  116. totalNum: 0,
  117. errorNum: 0,
  118. normalNum: 0,
  119. deleteVisible: false,
  120. fileName: null,
  121. form: {
  122. importArchive: true,
  123. importInformation: true,
  124. archivesImportType: '2',
  125. informationInputType: '2'
  126. },
  127. isShow01: true,
  128. isShow02: false,
  129. isShow03: false,
  130. timer: null,
  131. loading1: false,
  132. previewTableData: [], // 用于存储预览表格数据
  133. previewTotal: 0, // 用于存储预览数据总数
  134. hpId: null,
  135. importStatus: 'loading'
  136. }
  137. },
  138. computed: {
  139. ...mapGetters([
  140. 'user',
  141. 'baseApi'
  142. ])
  143. },
  144. created() {
  145. },
  146. methods: {
  147. // input-upload change
  148. handleFileChange(event) {
  149. const files = event.target.files
  150. this.file = files[0]
  151. this.key++
  152. // const sizeLimit = this.file.size / 1024 / 1024 > 10
  153. // if (sizeLimit) {
  154. // this.$message.warning('上传文件大小不能超过 10MB!')
  155. // }
  156. for (let i = 0; i < files.length; i++) {
  157. this.fileList = []
  158. this.fileList.push(files[i])
  159. }
  160. },
  161. // delt file
  162. deleteFile(file) {
  163. this.$confirm('此操作将清空所选数据, 是否继续?', '提示', {
  164. confirmButtonText: '确定',
  165. cancelButtonText: '取消',
  166. type: 'warning'
  167. }).then(() => {
  168. const index = this.fileList.indexOf(file)
  169. this.fileList.splice(index, 1)
  170. this.file = null
  171. this.$message({
  172. type: 'success',
  173. message: '删除成功!'
  174. })
  175. }).catch(() => {
  176. this.$message({
  177. type: 'info',
  178. message: '已取消删除'
  179. })
  180. })
  181. },
  182. // 上传文件
  183. handleStep01() {
  184. this.loading1 = true
  185. const notifyInstance = this.$notify.info({
  186. title: '温馨提示',
  187. message: '当前批量数据导入所需的时间较长,请用户耐心等待,谢谢!',
  188. customClass: 'centered-notify',
  189. showClose: false,
  190. duration: 0
  191. })
  192. if (this.fileList.length === 0) {
  193. this.$message.warning('请上传相关文件 !')
  194. this.loading1 = false
  195. notifyInstance.close()
  196. return
  197. }
  198. this.fileName = this.file.name.split('.')[0]
  199. crudFileImport.zipUpload(this.baseApi + '/api/unzip/importArchives', this.file, this.user.username)
  200. .then(res => {
  201. if (res.data.code === 200 && res.data.data) {
  202. this.hpId = res.data.data
  203. return crudFileImport.FetchHpArchivesDetailsByHpId({
  204. page: 0,
  205. size: 10,
  206. hpId: this.hpId,
  207. isError: true
  208. })
  209. } else {
  210. throw new Error('文件上传或解析失败')
  211. }
  212. })
  213. .then(res => {
  214. console.log('预览数据 res2:', res.data.content)
  215. this.totalNum = res.total
  216. this.errorNum = res.error
  217. this.normalNum = res.normal
  218. this.previewTableData = res.data.content
  219. this.previewTotal = res.data.totalElements
  220. this.isShow01 = false
  221. this.isShow02 = true
  222. })
  223. .catch(() => {
  224. this.$message.error('数据加载失败,请重试。')
  225. this.isShow01 = false
  226. this.isShow02 = true
  227. })
  228. .finally(() => {
  229. this.loading1 = false
  230. notifyInstance.close()
  231. })
  232. },
  233. // 第二步 上一步
  234. handleReturn02() {
  235. this.fileList = []
  236. this.isShow01 = true
  237. this.isShow02 = false
  238. this.isShow03 = false
  239. },
  240. // 第二步 下一步
  241. handleStep02() {
  242. this.isShow01 = false
  243. this.isShow02 = false
  244. this.isShow03 = true
  245. },
  246. // 确认导入
  247. submitImport() {
  248. this.isShow01 = false
  249. this.isShow02 = false
  250. this.isShow03 = true
  251. this.importStatus = 'loading'
  252. const modifiedRows = this.$refs.importTableList.getModifiedRows()
  253. const params = {
  254. 'hpId': this.hpId,
  255. 'hpTempList': modifiedRows
  256. }
  257. console.log('params:', params)
  258. crudFileImport.FetchImportHp(params).then(res => {
  259. // this.$message({
  260. // type: 'success',
  261. // message: '导入成功!'
  262. // })
  263. console.log('导入成功, 结果:', res)
  264. // this.importStatus = 'success' // 导入成功,更新状态
  265. }).catch(() => {
  266. // console.error('导入失败')
  267. // this.importStatus = 'error' // 导入失败,更新状态
  268. this.timer = setTimeout(() => {
  269. this.$emit('step-end', '1')
  270. clearTimeout(this.timer)
  271. }, 1000)
  272. })
  273. this.timer = setTimeout(() => {
  274. this.$emit('step-end', '1')
  275. clearTimeout(this.timer)
  276. }, 1000)
  277. },
  278. retryImport() {
  279. this.submitImport()
  280. },
  281. handleReturn03() {
  282. this.isShow01 = true
  283. this.isShow02 = false
  284. this.isShow03 = false
  285. this.fileList = []
  286. this.file = null
  287. this.importStatus = 'loading'
  288. if (this.timer) {
  289. clearTimeout(this.timer)
  290. this.timer = null
  291. }
  292. },
  293. submitForm(formName) {
  294. // this.loading1 = true
  295. // const notifyInstance = this.$notify.info({
  296. // title: '温馨提示',
  297. // message: '当前批量数据导入所需的时间较长,请用户耐心等待,谢谢!',
  298. // customClass: 'centered-notify',
  299. // showClose: false,
  300. // duration: 0 // 设置为0表示不自动关闭
  301. // })
  302. this.$refs[formName].validate((valid) => {
  303. if (valid) {
  304. const params = {
  305. 'archivesImportType': this.form.archivesImportType,
  306. 'importArchive': this.form.importArchive,
  307. 'importInformation': this.form.importInformation,
  308. 'informationInputType': this.form.informationInputType,
  309. 'name': this.fileName
  310. }
  311. console.log('params:', params)
  312. crudFileImport.FetchImportZip(params).then(res => {
  313. console.log('resZip', res)
  314. this.$message({
  315. type: 'success',
  316. message: '导入成功!'
  317. })
  318. }).catch(() => {
  319. this.timer = setTimeout(() => {
  320. this.$emit('step-end', '1')
  321. clearTimeout(this.timer)
  322. }, 1000)
  323. })
  324. this.timer = setTimeout(() => {
  325. this.$emit('step-end', '1')
  326. clearTimeout(this.timer)
  327. }, 1000)
  328. } else {
  329. console.log('error submit!!')
  330. return false
  331. }
  332. })
  333. }
  334. }
  335. }
  336. </script>
  337. <style>
  338. .centered-notify{
  339. top: calc(50% + 80px) !important;
  340. left: calc(50% + 160px) !important;
  341. right: 0 !important;
  342. transform: translate(-50%,-50%) !important;
  343. background-color: #031435!important;
  344. border: 1px solid #339CFF!important;
  345. & h2{
  346. color: #fff!important;
  347. }
  348. & .el-notification__content{
  349. color: #fff!important;
  350. }
  351. }
  352. </style>
  353. <style lang="scss" scoped>
  354. ::v-deep .el-loading-spinner{
  355. top: 60%;
  356. }
  357. .import-container{
  358. position: relative;
  359. padding: 30px;
  360. height: calc(100vh - 234px);
  361. }
  362. .import-header{
  363. display: flex;
  364. justify-content: center;
  365. align-items: center;
  366. li{
  367. display: flex;
  368. flex-direction: column;
  369. text-align: center;
  370. align-items: center;
  371. width: 140px;
  372. font-size: 14px;
  373. color: #fff;
  374. i{
  375. width: 45px;
  376. height: 45px;
  377. margin-bottom: 20px;
  378. &.step-img01{
  379. background: url('~@/assets/images/step01.png') no-repeat;
  380. background-size: contain;
  381. }
  382. &.step-img02{
  383. background: url('~@/assets/images/step02_2.png') no-repeat;
  384. background-size: contain;
  385. &.step-img02-active{
  386. background: url('~@/assets/images/step02.png') no-repeat;
  387. background-size: contain;
  388. }
  389. }
  390. &.step-img03{
  391. background: url('~@/assets/images/step03_3.png') no-repeat;
  392. background-size: contain;
  393. &.step-img03-active{
  394. background: url('~@/assets/images/step03.png') no-repeat;
  395. background-size: contain;
  396. }
  397. }
  398. }
  399. &.dot-img{
  400. width: 55px;
  401. height: 30px;
  402. background: url('~@/assets/images/dot1.png') no-repeat;
  403. background-size: contain;
  404. &.dot-img-active{
  405. background: url('~@/assets/images/dot2.png') no-repeat;
  406. background-size: contain;
  407. }
  408. }
  409. }
  410. }
  411. .step-content{
  412. position: relative;
  413. }
  414. .step-content03 {
  415. display: flex;
  416. flex-direction: column;
  417. align-items: center;
  418. justify-content: center; // 垂直居中
  419. min-height: 200px; // 给一个最小高度,防止内容跳动
  420. color: #fff;
  421. .import-status-indicator {
  422. display: flex;
  423. flex-direction: column;
  424. align-items: center;
  425. gap: 15px; // 元素之间的间距
  426. i {
  427. font-size: 48px;
  428. }
  429. p {
  430. font-size: 16px;
  431. }
  432. .el-button {
  433. margin-top: 10px;
  434. }
  435. &.success i {
  436. color: #19be6b; // 成功颜色
  437. }
  438. &.error i {
  439. color: #fa5555; // 失败颜色
  440. }
  441. }
  442. }
  443. .step-upload{
  444. width: 40%;
  445. padding: 30px 0;
  446. margin: 40px auto;
  447. background-color: #02255f;
  448. border-radius: 3px;
  449. div:first-child{
  450. display: flex;
  451. justify-content: center;
  452. flex-direction: column;
  453. align-items: center;
  454. }
  455. }
  456. .import-title{
  457. font-size: 14px;
  458. color: #fff;
  459. padding-left: 50px;
  460. margin-bottom: 6px;
  461. height: 50px;
  462. line-height: 50px;
  463. &.step01{
  464. background: url('~@/assets/images/step01.png') no-repeat;
  465. background-size: 30px 30px;
  466. }
  467. &.step02{
  468. background: url('~@/assets/images/step02.png') no-repeat;
  469. background-size: 30px 30px;
  470. }
  471. &.step03{
  472. background: url('~@/assets/images/step03.png') no-repeat;
  473. background-size: 30px 30px;
  474. }
  475. }
  476. .upload-container{
  477. position: relative;
  478. input{
  479. position: absolute;
  480. left: 50%;
  481. top: 50%;
  482. transform:translate(-50%,-50%);
  483. opacity: 0;
  484. border: 1px solid #000;
  485. }
  486. .upload-zip{
  487. flex-direction: row !important;
  488. width: 100px;
  489. padding: 6px 10px;
  490. font-size: 14px;
  491. color: #fff;
  492. border: 1px solid #339cff;
  493. background-color: transparent;
  494. border-radius: 3px;
  495. & i{
  496. margin-right: 4px;
  497. }
  498. }
  499. }
  500. .el-upload__tip{
  501. text-align: center;
  502. }
  503. .file-list{
  504. font-size: 16px;
  505. color: #fff;
  506. text-align: center;
  507. margin-top: 20px;
  508. i{
  509. font-size: 12px;
  510. cursor: pointer;
  511. }
  512. }
  513. ::v-deep .el-upload{
  514. display: block;
  515. }
  516. ::v-deep .el-upload-list{
  517. margin-top: 20px;
  518. .el-upload-list__item{
  519. font-size: 16px;
  520. line-height: 30px;
  521. &:hover{
  522. background-color: transparent;
  523. }
  524. &:first-child{
  525. margin-top: 0;
  526. }
  527. }
  528. .el-upload-list__item-name [class^=el-icon]{
  529. color: #fff;
  530. }
  531. .el-upload-list__item-name{
  532. color: #fff;
  533. }
  534. .el-icon-close{
  535. display: block;
  536. color: #fff;
  537. top: 8px;
  538. }
  539. }
  540. .step-bottom-btn{
  541. text-align: center;
  542. .el-button.el-button--primary{
  543. color: #fff;
  544. background-color: #1890ff;
  545. border-color: #1890ff;
  546. }
  547. }
  548. .import-data-number{
  549. position: absolute;
  550. right: 10px;
  551. top: 20px;
  552. font-size: 12px;
  553. color: #fff;
  554. & span{
  555. font-weight: bold;
  556. color: rgb(246,81,99);
  557. }
  558. }
  559. ::v-deep .el-form{
  560. .el-row{
  561. display: flex;
  562. justify-content: flex-start;
  563. }
  564. .el-form-item{
  565. margin-right: 50px;
  566. .el-form-item__label,
  567. .el-checkbox__label,
  568. .el-radio__label{
  569. color: #fff;
  570. }
  571. }
  572. }
  573. .submit-btn{
  574. background-color: #3a99fd;
  575. border-color: #3a99fd;
  576. margin-top: 20px;
  577. }
  578. </style>