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.

903 lines
28 KiB

4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
4 months ago
4 months ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
2 weeks ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
  1. <template>
  2. <div class="mod-config">
  3. <!-- 查询表单 -->
  4. <el-form :inline="true" label-position="top" style="margin-top: 1px; margin-left: 0px;">
  5. <el-form-item label="物料编号">
  6. <el-input v-model="queryData.partNo" style="width: 120px" placeholder="物料编号" clearable></el-input>
  7. </el-form-item>
  8. <el-form-item label="批次号">
  9. <el-input v-model="queryData.lotBatchNo" style="width: 120px" placeholder="批次号" clearable></el-input>
  10. </el-form-item>
  11. <el-form-item label="接口名称">
  12. <el-select v-model="queryData.interfaceName" placeholder="请选择" style="width: 150px" clearable>
  13. <el-option label="全部" value=""></el-option>
  14. <el-option label="MoveInventoryPart" value="MoveInventoryPart"></el-option>
  15. <el-option label="IssueInventoryPart" value="IssueInventoryPart"></el-option>
  16. <el-option label="ReturnInventoryPart" value="ReturnInventoryPart"></el-option>
  17. </el-select>
  18. </el-form-item>
  19. <el-form-item label="方法类型">
  20. <el-select v-model="queryData.methodType" placeholder="请选择" style="width: 120px" clearable>
  21. <el-option label="全部" value=""></el-option>
  22. <el-option label="库存移库(栈板)" value="库存移库(栈板)"></el-option>
  23. <el-option label="发料" value="发料"></el-option>
  24. <el-option label="退料" value="退料"></el-option>
  25. </el-select>
  26. </el-form-item>
  27. <el-form-item label="处理状态">
  28. <el-select v-model="queryData.processStatus" placeholder="请选择" style="width: 120px" clearable>
  29. <el-option label="全部" value=""></el-option>
  30. <el-option
  31. v-for="item in statusOptions"
  32. :key="item.value"
  33. :label="item.label"
  34. :value="item.value">
  35. </el-option>
  36. </el-select>
  37. </el-form-item>
  38. <el-form-item label="创建时间从">
  39. <el-date-picker
  40. v-model="queryData.startDate"
  41. type="date"
  42. style="width: 120px"
  43. placeholder="开始日期"
  44. value-format="yyyy-MM-dd"
  45. clearable>
  46. </el-date-picker>
  47. </el-form-item>
  48. <el-form-item label="创建时间至">
  49. <el-date-picker
  50. v-model="queryData.endDate"
  51. type="date"
  52. style="width: 120px"
  53. placeholder="结束日期"
  54. value-format="yyyy-MM-dd"
  55. clearable>
  56. </el-date-picker>
  57. </el-form-item>
  58. <el-form-item label=" ">
  59. <el-button type="primary" @click="getDataList()">查询</el-button>
  60. <el-button @click="resetQuery()">重置</el-button>
  61. <!-- rqrq - 一键重试按钮后端批量处理 -->
  62. <el-button
  63. type="warning"
  64. :loading="batchRetrying"
  65. :disabled="batchRetrying || selectedRows.length === 0"
  66. @click="handleBatchRetry()">
  67. {{ batchRetrying ? '批量重试中...' : `一键重试(${selectedRows.length})` }}
  68. </el-button>
  69. <!-- 导出按钮 - rqrq -->
  70. <download-excel
  71. :fields="fields()"
  72. :data="exportData"
  73. type="xls"
  74. :name="exportName"
  75. :header="exportHeader"
  76. :footer="exportFooter"
  77. :fetch="createExportData"
  78. :before-generate="startDownload"
  79. :before-finish="finishDownload"
  80. worksheet="导出信息"
  81. class="el-button el-button--primary el-button--medium">
  82. {{ '导出' }}
  83. </download-excel>
  84. </el-form-item>
  85. </el-form>
  86. <!-- 数据表格 -->
  87. <el-table
  88. ref="dataTable"
  89. :data="dataList"
  90. :height="height"
  91. border
  92. highlight-current-row
  93. v-loading="dataListLoading"
  94. @selection-change="handleSelectionChange"
  95. style="width: 100%;">
  96. <!-- rqrq - 多选列只允许选择PENDING状态的记录 -->
  97. <el-table-column
  98. type="selection"
  99. width="50"
  100. :selectable="checkSelectable">
  101. </el-table-column>
  102. <el-table-column
  103. v-for="(item,index) in columnList" :key="index"
  104. :sortable="item.columnSortable"
  105. :prop="item.columnProp"
  106. :header-align="item.headerAlign"
  107. :show-overflow-tooltip="item.showOverflowTooltip"
  108. :align="item.align"
  109. :fixed="item.fixed==''?false:item.fixed"
  110. :min-width="item.columnWidth"
  111. :label="item.columnLabel">
  112. <template slot-scope="scope">
  113. <span v-if="item.columnProp === 'processStatus'">
  114. <el-tag
  115. :type="getStatusType(scope.row.processStatus)"
  116. size="small">
  117. {{ getStatusLabel(scope.row.processStatus) }}
  118. </el-tag>
  119. </span>
  120. <span v-else-if="item.columnProp === 'operate'">
  121. <el-button
  122. v-if="scope.row.processStatus === 'PENDING'"
  123. type="text"
  124. size="small"
  125. @click="showDetailDialog(scope.row)">
  126. 查看详情
  127. </el-button>
  128. <!-- rqrq - 使用全局重试状态控制按钮 -->
  129. <el-button
  130. v-if="scope.row.processStatus === 'PENDING'"
  131. type="text"
  132. size="small"
  133. style="color: #E6A23C;"
  134. :loading="retryingRowId === scope.row.id"
  135. :disabled="retryingRowId !== null"
  136. @click="handleRetry(scope.row)">
  137. {{ retryingRowId === scope.row.id ? '重试中...' : '重试' }}
  138. </el-button>
  139. <span v-else>-</span>
  140. </span>
  141. <span v-else>{{ scope.row[item.columnProp] }}</span>
  142. </template>
  143. </el-table-column>
  144. <el-table-column
  145. header-align="center"
  146. align="center"
  147. fixed="right"
  148. width="180"
  149. label="操作">
  150. <template slot-scope="scope">
  151. <a type="text" size="small" @click="showDetailDialog(scope.row)">查看详情</a>
  152. <!-- rqrq - 当前行正在重试时显示"重试中..." -->
  153. <span
  154. v-if="scope.row.processStatus === 'PENDING' && retryingRowId === scope.row.id"
  155. style="color: #E6A23C; margin-left: 10px;">重试中...</span>
  156. <!-- rqrq - 其他行有重试时显示禁用状态的重试按钮 -->
  157. <span
  158. v-else-if="scope.row.processStatus === 'PENDING' && retryingRowId !== null"
  159. style="color: #C0C4CC; margin-left: 10px; cursor: not-allowed;"
  160. @click="handleRetry(scope.row)">重试</span>
  161. <!-- rqrq - 没有重试时显示正常的重试按钮 -->
  162. <a
  163. type="text"
  164. size="small"
  165. v-else-if="scope.row.processStatus === 'PENDING'"
  166. @click="handleRetry(scope.row)">重试</a>
  167. <!-- <a type="text" size="small" v-if="scope.row.processStatus === 'PENDING'" @click="closeRetry(scope.row)">忽略</a>-->
  168. </template>
  169. </el-table-column>
  170. </el-table>
  171. <!-- 分页 -->
  172. <el-pagination
  173. @size-change="sizeChangeHandle"
  174. @current-change="currentChangeHandle"
  175. :current-page="pageIndex"
  176. :page-sizes="[20, 50, 100, 1000]"
  177. :page-size="pageSize"
  178. :total="totalPage"
  179. layout="total, sizes, prev, pager, next, jumper">
  180. </el-pagination>
  181. <!-- 详情弹窗 - rqrq -->
  182. <el-dialog
  183. title="IFS错误日志详情"
  184. :visible.sync="detailVisible"
  185. width="70%"
  186. :close-on-click-modal="false"
  187. v-drag>
  188. <el-form label-width="120px" style="padding: 10px;">
  189. <!-- 基本信息 - rqrq -->
  190. <el-row>
  191. <el-col :span="8">
  192. <el-form-item label="工厂编码:">
  193. <span>{{ currentRow.site }}</span>
  194. </el-form-item>
  195. </el-col>
  196. <el-col :span="8">
  197. <el-form-item label="物料编号:">
  198. <span>{{ currentRow.partNo }}</span>
  199. </el-form-item>
  200. </el-col>
  201. <el-col :span="8">
  202. <el-form-item label="批次号:">
  203. <span>{{ currentRow.lotBatchNo }}</span>
  204. </el-form-item>
  205. </el-col>
  206. </el-row>
  207. <el-row>
  208. <el-col :span="8">
  209. <el-form-item label="源库位:">
  210. <span>{{ currentRow.sourceLocation }}</span>
  211. </el-form-item>
  212. </el-col>
  213. <el-col :span="8">
  214. <el-form-item label="目标库位:">
  215. <span>{{ currentRow.destLocation }}</span>
  216. </el-form-item>
  217. </el-col>
  218. <el-col :span="8">
  219. <el-form-item label="数量:">
  220. <span>{{ currentRow.qty }}</span>
  221. </el-form-item>
  222. </el-col>
  223. </el-row>
  224. <el-row>
  225. <el-col :span="8">
  226. <el-form-item label="接口名称:">
  227. <span>{{ currentRow.interfaceName }}</span>
  228. </el-form-item>
  229. </el-col>
  230. <el-col :span="8">
  231. <el-form-item label="方法类型:">
  232. <span>{{ currentRow.methodType }}</span>
  233. </el-form-item>
  234. </el-col>
  235. <el-col :span="8">
  236. <el-form-item label="创建时间:">
  237. <span>{{ currentRow.createdAt }}</span>
  238. </el-form-item>
  239. </el-col>
  240. </el-row>
  241. <!-- 错误信息 - rqrq -->
  242. <el-form-item label="错误信息:">
  243. <el-input
  244. type="textarea"
  245. :rows="5"
  246. resize='none'
  247. v-model="currentRow.errorMessage"
  248. readonly>
  249. </el-input>
  250. </el-form-item>
  251. <!-- 请求数据 - rqrq -->
  252. <el-form-item label="请求数据:" style="margin-top: 90px">
  253. <el-input
  254. type="textarea"
  255. :rows="3"
  256. resize='none'
  257. v-model="currentRow.requestData"
  258. readonly>
  259. </el-input>
  260. </el-form-item>
  261. <el-form-item label="标签:" style="margin-top: 55px">
  262. <el-input
  263. type="textarea"
  264. :rows="2"
  265. resize='none'
  266. v-model="currentRow.serialNos"
  267. readonly>
  268. </el-input>
  269. </el-form-item>
  270. <!-- 响应数据 - rqrq -->
  271. <el-form-item label="响应数据:" style="margin-top: 40px">
  272. <el-input
  273. type="textarea"
  274. :rows="2"
  275. resize='none'
  276. v-model="currentRow.responseData"
  277. readonly>
  278. </el-input>
  279. </el-form-item>
  280. <!-- 处理备注 - rqrq -->
  281. <el-form-item label="处理备注:" style="margin-top: 40px">
  282. <el-input
  283. type="textarea"
  284. :rows="2"
  285. resize='none'
  286. v-model="processRemark"
  287. placeholder="请输入处理说明(标记为已处理或已忽略时必填)">
  288. </el-input>
  289. </el-form-item>
  290. </el-form>
  291. <div slot="footer" class="dialog-footer" style="margin-top: 25px">
  292. <el-button
  293. type="success"
  294. @click="markAsProcessed"
  295. :loading="markProcessedLoading"
  296. :disabled="markProcessedLoading || markIgnoredLoading">
  297. {{ markProcessedLoading ? '处理中...' : '标记为已处理' }}
  298. </el-button>
  299. <el-button
  300. type="warning"
  301. @click="markAsIgnored"
  302. :loading="markIgnoredLoading"
  303. :disabled="markProcessedLoading || markIgnoredLoading">
  304. {{ markIgnoredLoading ? '处理中...' : '标记为已忽略' }}
  305. </el-button>
  306. <el-button @click="detailVisible = false" :disabled="markProcessedLoading || markIgnoredLoading">
  307. 关闭
  308. </el-button>
  309. </div>
  310. </el-dialog>
  311. </div>
  312. </template>
  313. <script>
  314. import {
  315. getIfsErrorLogList,
  316. markErrorAsProcessed,
  317. markErrorAsIgnored,
  318. getUserAuthorizedSites,
  319. retryIfsCall,
  320. closeIfsCall,
  321. batchRetryIfsCall
  322. } from '@/api/warehouse/ifsCallErrorLog.js'
  323. export default {
  324. data() {
  325. return {
  326. // 查询条件 - rqrq
  327. queryData: {
  328. site: '',
  329. partNo: '',
  330. lotBatchNo: '',
  331. interfaceName: '',
  332. methodType: '',
  333. processStatus: '',
  334. startDate: '',
  335. endDate: '',
  336. page: 1,
  337. limit: 20
  338. },
  339. // 表格高度 - rqrq
  340. height: 450,
  341. // 状态选项 - rqrq
  342. statusOptions: [
  343. { label: '待处理', value: 'PENDING' },
  344. { label: '已处理', value: 'PROCESSED' },
  345. { label: '已忽略', value: 'IGNORED' }
  346. ],
  347. // 站点选项 - rqrq
  348. siteOptions: [],
  349. // 表格列配置 - rqrq
  350. columnList: [
  351. {
  352. columnProp: "site",
  353. headerAlign: "center",
  354. align: "center",
  355. columnLabel: "工厂",
  356. columnWidth: 60,
  357. columnSortable: false,
  358. showOverflowTooltip: true,
  359. fixed: ""
  360. },
  361. {
  362. columnProp: "partNo",
  363. headerAlign: "center",
  364. align: "center",
  365. columnLabel: "物料编号",
  366. columnWidth: 120,
  367. columnSortable: false,
  368. showOverflowTooltip: true,
  369. fixed: ""
  370. },
  371. {
  372. columnProp: "lotBatchNo",
  373. headerAlign: "center",
  374. align: "center",
  375. columnLabel: "批次号",
  376. columnWidth: 120,
  377. columnSortable: false,
  378. showOverflowTooltip: true,
  379. fixed: ""
  380. },
  381. {
  382. columnProp: "sourceLocation",
  383. headerAlign: "center",
  384. align: "center",
  385. columnLabel: "源库位",
  386. columnWidth: 100,
  387. columnSortable: false,
  388. showOverflowTooltip: true,
  389. fixed: ""
  390. },
  391. {
  392. columnProp: "destLocation",
  393. headerAlign: "center",
  394. align: "center",
  395. columnLabel: "目标库位",
  396. columnWidth: 100,
  397. columnSortable: false,
  398. showOverflowTooltip: true,
  399. fixed: ""
  400. },
  401. {
  402. columnProp: "qty",
  403. headerAlign: "center",
  404. align: "center",
  405. columnLabel: "数量",
  406. columnWidth: 80,
  407. columnSortable: false,
  408. showOverflowTooltip: true,
  409. fixed: ""
  410. },
  411. {
  412. columnProp: "serialNos",
  413. headerAlign: "center",
  414. align: "center",
  415. columnLabel: "标签",
  416. columnWidth: 260,
  417. columnSortable: false,
  418. showOverflowTooltip: true,
  419. fixed: ""
  420. },
  421. {
  422. columnProp: "processStatus",
  423. headerAlign: "center",
  424. align: "center",
  425. columnLabel: "处理状态",
  426. columnWidth: 100,
  427. columnSortable: false,
  428. showOverflowTooltip: true,
  429. fixed: ""
  430. },
  431. {
  432. columnProp: "retryCount",
  433. headerAlign: "center",
  434. align: "center",
  435. columnLabel: "重试次数",
  436. columnWidth: 80,
  437. columnSortable: false,
  438. showOverflowTooltip: true,
  439. fixed: ""
  440. },
  441. {
  442. columnProp: "errorMessage",
  443. headerAlign: "center",
  444. align: "left",
  445. columnLabel: "错误信息",
  446. columnWidth: 200,
  447. columnSortable: false,
  448. showOverflowTooltip: true,
  449. fixed: ""
  450. },
  451. {
  452. columnProp: "createdAt",
  453. headerAlign: "center",
  454. align: "center",
  455. columnLabel: "创建时间",
  456. columnWidth: 150,
  457. columnSortable: false,
  458. showOverflowTooltip: true,
  459. fixed: ""
  460. },
  461. {
  462. columnProp: "processedAt",
  463. headerAlign: "center",
  464. align: "center",
  465. columnLabel: "处理时间",
  466. columnWidth: 150,
  467. columnSortable: false,
  468. showOverflowTooltip: true,
  469. fixed: ""
  470. },
  471. {
  472. columnProp: "processedBy",
  473. headerAlign: "center",
  474. align: "center",
  475. columnLabel: "处理人",
  476. columnWidth: 100,
  477. columnSortable: false,
  478. showOverflowTooltip: true,
  479. fixed: ""
  480. },
  481. {
  482. columnProp: "remark",
  483. headerAlign: "center",
  484. align: "left",
  485. columnLabel: "备注",
  486. columnWidth: 150,
  487. columnSortable: false,
  488. showOverflowTooltip: true,
  489. fixed: ""
  490. },
  491. ],
  492. // 数据列表 - rqrq
  493. dataList: [],
  494. // 分页参数 - rqrq
  495. pageIndex: 1,
  496. pageSize: 20,
  497. totalPage: 0,
  498. dataListLoading: false,
  499. // 详情弹窗 - rqrq
  500. detailVisible: false,
  501. currentRow: {},
  502. processRemark: '',
  503. markProcessedLoading: false,
  504. markIgnoredLoading: false,
  505. retryingRowId: null, // 正在重试的行ID,全局唯一 - rqrq
  506. // 批量重试相关 - rqrq
  507. selectedRows: [], // 选中的行
  508. batchRetrying: false, // 批量重试中
  509. batchRetryProgress: 0, // 批量重试进度
  510. batchRetryTotal: 0, // 批量重试总数
  511. // 导出相关 - rqrq
  512. exportData: [],
  513. exportName: 'IFS错误日志' + this.dayjs().format('YYYYMMDDHHmmss'),
  514. exportHeader: ["IFS错误日志"],
  515. exportFooter: [],
  516. }
  517. },
  518. mounted() {
  519. this.$nextTick(() => {
  520. // 计算表格高度 - rqrq
  521. this.height = window.innerHeight - 220;
  522. })
  523. },
  524. activated() {
  525. this.getDataList()
  526. this.getSiteOptions()
  527. },
  528. methods: {
  529. // 获取数据列表 - rqrq
  530. getDataList() {
  531. this.dataListLoading = true
  532. this.queryData.page = this.pageIndex
  533. this.queryData.limit = this.pageSize
  534. getIfsErrorLogList(this.queryData).then(({data}) => {
  535. this.dataListLoading = false
  536. if (data && data.code === 0) {
  537. this.dataList = data.page.list || []
  538. this.totalPage = data.page.totalCount || 0
  539. } else {
  540. this.dataList = []
  541. this.totalPage = 0
  542. this.$alert(data.msg || '查询失败', '错误', { confirmButtonText: '确定' })
  543. }
  544. }).catch(error => {
  545. this.dataListLoading = false
  546. console.error('查询IFS错误日志失败:', error)
  547. this.$alert('查询失败', '错误', { confirmButtonText: '确定' })
  548. })
  549. },
  550. // 获取站点选项 - rqrq
  551. getSiteOptions() {
  552. const params = {
  553. userName: this.$store.state.user.name
  554. }
  555. getUserAuthorizedSites(params).then(({data}) => {
  556. if (data && data.code === 0) {
  557. this.siteOptions = data.data || []
  558. }
  559. }).catch(error => {
  560. console.error('获取站点列表失败:', error)
  561. })
  562. },
  563. // 重置查询条件 - rqrq
  564. resetQuery() {
  565. this.queryData = {
  566. site: '',
  567. partNo: '',
  568. lotBatchNo: '',
  569. interfaceName: '',
  570. methodType: '',
  571. processStatus: '',
  572. startDate: '',
  573. endDate: '',
  574. page: 1,
  575. limit: 20
  576. }
  577. this.pageIndex = 1
  578. this.getDataList()
  579. },
  580. // 每页数量变化 - rqrq
  581. sizeChangeHandle(val) {
  582. this.pageSize = val
  583. this.pageIndex = 1
  584. this.getDataList()
  585. },
  586. // 当前页变化 - rqrq
  587. currentChangeHandle(val) {
  588. this.pageIndex = val
  589. this.getDataList()
  590. },
  591. // 获取状态标签类型 - rqrq
  592. getStatusType(status) {
  593. const statusMap = {
  594. 'PENDING': 'warning',
  595. 'PROCESSED': 'success',
  596. 'IGNORED': 'info'
  597. }
  598. return statusMap[status] || 'info'
  599. },
  600. // 获取状态标签文本 - rqrq
  601. getStatusLabel(status) {
  602. const statusMap = {
  603. 'PENDING': '待处理',
  604. 'PROCESSED': '已处理',
  605. 'IGNORED': '已忽略'
  606. }
  607. return statusMap[status] || status
  608. },
  609. // 显示详情弹窗 - rqrq
  610. showDetailDialog(row) {
  611. this.currentRow = { ...row }
  612. this.processRemark = ''
  613. this.detailVisible = true
  614. },
  615. // 标记为已处理 - rqrq
  616. markAsProcessed() {
  617. if (!this.processRemark || this.processRemark.trim() === '') {
  618. this.$message.warning('请填写处理备注')
  619. return
  620. }
  621. this.markProcessedLoading = true
  622. const params = {
  623. id: this.currentRow.id,
  624. remark: this.processRemark
  625. }
  626. markErrorAsProcessed(params).then(({data}) => {
  627. if (data && data.code === 0) {
  628. this.$message.success('标记成功')
  629. this.detailVisible = false
  630. this.getDataList()
  631. } else {
  632. this.$alert(data.msg || '操作失败', '错误', { confirmButtonText: '确定' })
  633. }
  634. }).catch(error => {
  635. console.error('标记失败:', error)
  636. this.$alert('操作失败', '错误', { confirmButtonText: '确定' })
  637. }).finally(() => {
  638. this.markProcessedLoading = false
  639. })
  640. },
  641. // 标记为已忽略 - rqrq
  642. markAsIgnored() {
  643. if (!this.processRemark || this.processRemark.trim() === '') {
  644. this.$message.warning('请填写忽略原因')
  645. return
  646. }
  647. this.markIgnoredLoading = true
  648. const params = {
  649. id: this.currentRow.id,
  650. remark: this.processRemark
  651. }
  652. markErrorAsIgnored(params).then(({data}) => {
  653. if (data && data.code === 0) {
  654. this.$message.success('标记成功')
  655. this.detailVisible = false
  656. this.getDataList()
  657. } else {
  658. this.$alert(data.msg || '操作失败', '错误', { confirmButtonText: '确定' })
  659. }
  660. }).catch(error => {
  661. console.error('标记失败:', error)
  662. this.$alert('操作失败', '错误', { confirmButtonText: '确定' })
  663. }).finally(() => {
  664. this.markIgnoredLoading = false
  665. })
  666. },
  667. closeRetry(row){
  668. this.$confirm('确定要忽略此记录的IFS接口调用吗?', '确认重试', {
  669. confirmButtonText: '确定',
  670. cancelButtonText: '取消',
  671. type: 'warning'
  672. }).then(() => {
  673. const params = {
  674. id: row.id
  675. }
  676. closeIfsCall(params).then(({data}) => {
  677. if (data && data.code === 0) {
  678. this.$message.success('忽略成功')
  679. // 刷新列表 - rqrq
  680. this.getDataList()
  681. } else {
  682. this.$alert(data.msg || '忽略失败', '错误', { confirmButtonText: '确定' })
  683. // 刷新列表(更新重试次数)- rqrq
  684. this.getDataList()
  685. }
  686. })
  687. })
  688. },
  689. // 手工重试IFS接口调用 - rqrq
  690. // 多选变化处理 - rqrq
  691. handleSelectionChange(selection) {
  692. // 只保留PENDING状态的记录 - rqrq
  693. this.selectedRows = selection.filter(row => row.processStatus === 'PENDING')
  694. },
  695. // 检查行是否可选(只允许选择PENDING状态)- rqrq
  696. checkSelectable(row) {
  697. return row.processStatus === 'PENDING'
  698. },
  699. // 延时函数 - rqrq
  700. sleep(ms) {
  701. return new Promise(resolve => setTimeout(resolve, ms))
  702. },
  703. // 批量重试(调用后端接口,由后端按时间顺序执行)- rqrq
  704. handleBatchRetry() {
  705. if (this.selectedRows.length === 0) {
  706. this.$message.warning('请先选择要重试的记录')
  707. return
  708. }
  709. // 检查是否有单个重试正在进行 - rqrq
  710. if (this.retryingRowId !== null) {
  711. this.$message.warning('请等待当前重试完成后再操作')
  712. return
  713. }
  714. this.$confirm(`确定要重试选中的 ${this.selectedRows.length} 条记录吗?将按时间顺序从最早开始逐个重试。`, '批量重试确认', {
  715. confirmButtonText: '确定',
  716. cancelButtonText: '取消',
  717. type: 'warning'
  718. }).then(() => {
  719. // 获取选中行的ID列表 - rqrq
  720. const ids = this.selectedRows.map(row => row.id)
  721. // 开始批量重试 - rqrq
  722. this.batchRetrying = true
  723. this.batchRetryTotal = ids.length
  724. this.batchRetryProgress = 0
  725. // 调用后端批量重试接口 - rqrq
  726. batchRetryIfsCall({ ids }).then(({data}) => {
  727. if (data && data.code === 0) {
  728. const successCount = data.successCount || 0
  729. const failCount = data.failCount || 0
  730. // 显示结果 - rqrq
  731. this.$alert(
  732. `批量重试完成!<br/>成功:<span style="color: #67C23A; font-weight: bold;">${successCount}</span> 条<br/>失败:<span style="color: #F56C6C; font-weight: bold;">${failCount}</span> 条`,
  733. '重试结果',
  734. {
  735. dangerouslyUseHTMLString: true,
  736. confirmButtonText: '确定'
  737. }
  738. )
  739. } else {
  740. this.$alert(data.msg || '批量重试失败', '错误', { confirmButtonText: '确定' })
  741. }
  742. }).catch(error => {
  743. console.error('批量重试失败:', error)
  744. this.$alert('批量重试失败,请稍后再试', '错误', { confirmButtonText: '确定' })
  745. }).finally(() => {
  746. // 重试完成,重置状态 - rqrq
  747. this.batchRetrying = false
  748. this.batchRetryProgress = 0
  749. this.batchRetryTotal = 0
  750. this.selectedRows = []
  751. // 刷新列表 - rqrq
  752. this.getDataList()
  753. })
  754. }).catch(() => {
  755. // 用户取消操作
  756. })
  757. },
  758. handleRetry(row) {
  759. // 检查是否有批量重试正在进行 - rqrq
  760. if (this.batchRetrying) {
  761. this.$message.warning('批量重试进行中,请等待完成')
  762. return
  763. }
  764. // 检查是否有其他行正在重试 - rqrq
  765. if (this.retryingRowId !== null) {
  766. this.$message.warning('请等待当前重试完成后再操作')
  767. return
  768. }
  769. this.$confirm('确定要重试此记录的IFS接口调用吗?', '确认重试', {
  770. confirmButtonText: '确定',
  771. cancelButtonText: '取消',
  772. type: 'warning'
  773. }).then(() => {
  774. // 设置全局重试状态 - rqrq
  775. this.retryingRowId = row.id
  776. this.$set(row, '_retrying', true)
  777. const params = {
  778. id: row.id
  779. }
  780. retryIfsCall(params).then(({data}) => {
  781. if (data && data.code === 0) {
  782. this.$message.success('重试成功,IFS接口调用完成')
  783. // 刷新列表 - rqrq
  784. this.getDataList()
  785. } else {
  786. this.$alert(data.msg || '重试失败', '错误', { confirmButtonText: '确定' })
  787. // 刷新列表(更新重试次数)- rqrq
  788. this.getDataList()
  789. }
  790. }).catch(error => {
  791. console.error('重试失败:', error)
  792. this.$alert('重试失败,请稍后再试', '错误', { confirmButtonText: '确定' })
  793. // 刷新列表 - rqrq
  794. this.getDataList()
  795. }).finally(() => {
  796. // 取消loading状态 - rqrq
  797. this.$set(row, '_retrying', false)
  798. this.retryingRowId = null
  799. })
  800. }).catch(() => {
  801. // 用户取消操作
  802. })
  803. },
  804. // 导出相关方法 - rqrq
  805. async createExportData() {
  806. const queryParams = {
  807. ...this.queryData,
  808. page: 1,
  809. limit: 999999 // 设置一个很大的数字来获取全部数据 - rqrq
  810. }
  811. const {data} = await getIfsErrorLogList(queryParams)
  812. if (data && data.code === 0) {
  813. return (data.page.list || []).map(item => {
  814. return {
  815. ...item,
  816. processStatus: this.getStatusLabel(item.processStatus)
  817. }
  818. })
  819. }
  820. return []
  821. },
  822. startDownload() {
  823. // 开始导出 - rqrq
  824. },
  825. finishDownload() {
  826. // 导出完成 - rqrq
  827. },
  828. fields() {
  829. let json = "{"
  830. this.columnList.forEach((item, index) => {
  831. if (index == this.columnList.length - 1) {
  832. json += "\"" + item.columnLabel + "\"" + ":" + "\"" + item.columnProp + "\""
  833. } else {
  834. json += "\"" + item.columnLabel + "\"" + ":" + "\"" + item.columnProp + "\"" + ","
  835. }
  836. })
  837. json += "}"
  838. let s = eval("(" + json + ")")
  839. return s
  840. }
  841. }
  842. }
  843. </script>
  844. <style scoped>
  845. /* 表格样式优化 - rqrq */
  846. .mod-config {
  847. padding: 10px;
  848. }
  849. </style>