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.

920 lines
33 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <div class="mod-config">
  3. <!-- 条件查询 -->
  4. <el-card :class="['search-card', { 'collapsed': !searchExpanded }]" shadow="hover">
  5. <div slot="header" class="search-header">
  6. <div class="header-left">
  7. <i class="el-icon-search"></i>
  8. <span class="header-title">Search</span>
  9. </div>
  10. <div class="header-right">
  11. <el-button
  12. type="text"
  13. size="small"
  14. @click="toggleSearchExpand"
  15. class="collapse-btn">
  16. <span>{{ searchExpanded ? '收起' : '展开' }}</span>
  17. <i :class="searchExpanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
  18. </el-button>
  19. </div>
  20. </div>
  21. <el-form
  22. :inline="true"
  23. label-position="top"
  24. :model="searchData"
  25. class="search-form"
  26. @keyup.enter.native="handleSearch">
  27. <template v-if="searchExpanded">
  28. <el-row :gutter="16">
  29. <el-col :span="2">
  30. <el-form-item label="BU">
  31. <el-select v-model="searchData.buNo" placeholder="请选择" clearable style="width: 100%">
  32. <el-option
  33. v-for="i in userBuList"
  34. :key="i.buNo"
  35. :label="i.buDesc"
  36. :value="i.buNo">
  37. </el-option>
  38. </el-select>
  39. </el-form-item>
  40. </el-col>
  41. <el-col :span="2">
  42. <el-form-item label="变动类型">
  43. <el-select v-model="searchData.documentType" placeholder="请选择" clearable style="width: 100%">
  44. <el-option
  45. v-for="item in documentTypeList"
  46. :key="item.value"
  47. :label="item.label"
  48. :value="item.value">
  49. </el-option>
  50. </el-select>
  51. </el-form-item>
  52. </el-col>
  53. <el-col :span="3">
  54. <el-form-item label="变动单号">
  55. <el-input v-model="searchData.transactionId" clearable placeholder="请输入"></el-input>
  56. </el-form-item>
  57. </el-col>
  58. <el-col :span="4">
  59. <el-form-item label="标签条码">
  60. <el-input v-model="searchData.rollNo" clearable placeholder="请输入" style="width: 120%"></el-input>
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="3">
  64. <el-form-item label="物料编码">
  65. <el-input v-model="searchData.partNo" clearable placeholder="请输入"></el-input>
  66. </el-form-item>
  67. </el-col>
  68. <el-col :span="4">
  69. <el-form-item label="物料名称">
  70. <el-input v-model="searchData.partDesc" clearable placeholder="请输入" style="width: 120%"></el-input>
  71. </el-form-item>
  72. </el-col>
  73. <el-col :span="3">
  74. <el-form-item label="规格型号">
  75. <el-input v-model="searchData.spec" clearable placeholder="请输入"></el-input>
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="2">
  79. <el-form-item label="传输状态">
  80. <el-select v-model="searchData.syncedFlag" placeholder="请选择" clearable style="width: 100%">
  81. <el-option label="已传输" value="Y"></el-option>
  82. <el-option label="待传输" value="N"></el-option>
  83. </el-select>
  84. </el-form-item>
  85. </el-col>
  86. </el-row>
  87. <el-row :gutter="16">
  88. <el-col :span="3">
  89. <el-form-item label="通知单号">
  90. <el-input v-model="searchData.documentNo" clearable placeholder="请输入"></el-input>
  91. </el-form-item>
  92. </el-col>
  93. <el-col :span="3">
  94. <el-form-item label="关联单号">
  95. <el-input v-model="searchData.orderNo" clearable placeholder="请输入"></el-input>
  96. </el-form-item>
  97. </el-col>
  98. <el-col :span="3">
  99. <el-form-item label="关联单行号">
  100. <el-input v-model="searchData.orderLineNo" clearable placeholder="请输入"></el-input>
  101. </el-form-item>
  102. </el-col>
  103. <el-col :span="3">
  104. <el-form-item label="合约号码">
  105. <el-input v-model="searchData.batchNo" clearable placeholder="请输入"></el-input>
  106. </el-form-item>
  107. </el-col>
  108. <el-col :span="4">
  109. <el-form-item label="仓库">
  110. <el-select v-model="searchData.warehouseIdList" multiple collapse-tags clearable placeholder="请选择" style="width: 120%">
  111. <el-option
  112. v-for="item in warehouseList"
  113. :key="item.warehouseId"
  114. :label="item.warehouseName"
  115. :value="item.warehouseId">
  116. </el-option>
  117. </el-select>
  118. </el-form-item>
  119. </el-col>
  120. <el-col :span="8">
  121. <el-form-item label="变动日期">
  122. <el-date-picker
  123. v-model="searchData.startDate"
  124. type="datetime"
  125. value-format="yyyy-MM-dd HH:mm"
  126. format="yyyy-MM-dd HH:mm"
  127. placeholder="开始日期"
  128. style="width: 44%">
  129. </el-date-picker>
  130. <span style="margin: 0 8px; color: #DCDFE6;">~</span>
  131. <el-date-picker
  132. v-model="searchData.endDate"
  133. type="datetime"
  134. value-format="yyyy-MM-dd HH:mm"
  135. format="yyyy-MM-dd HH:mm"
  136. placeholder="结束日期"
  137. style="width: 44%">
  138. </el-date-picker>
  139. </el-form-item>
  140. </el-col>
  141. </el-row>
  142. </template>
  143. <!-- 操作按钮区域 -->
  144. <el-row :gutter="16">
  145. <el-col :span="24">
  146. <div class="search-actions">
  147. <div class="action-left">
  148. <el-button
  149. type="primary"
  150. icon="el-icon-search"
  151. :loading="dataListLoading"
  152. @click="handleSearch">
  153. 查询
  154. </el-button>
  155. <el-button
  156. icon="el-icon-refresh-left"
  157. @click="resetSearch">
  158. 重置
  159. </el-button>
  160. </div>
  161. <div class="action-right">
  162. <el-button
  163. v-if="isAuth('105006:try')"
  164. type="warning"
  165. icon="el-icon-refresh-right"
  166. @click="batchRetryHandle">
  167. 手动重试
  168. </el-button>
  169. <el-button
  170. v-if="isAuth('105006:exceptionTry')"
  171. type="danger"
  172. icon="el-icon-warning-outline"
  173. @click="exceptionRetryHandle">
  174. 异常重试
  175. </el-button>
  176. <el-button
  177. icon="el-icon-download"
  178. @click="exportData">
  179. 导出
  180. </el-button>
  181. </div>
  182. </div>
  183. </el-col>
  184. </el-row>
  185. </el-form>
  186. </el-card>
  187. <!-- 页签列表 -->
  188. <el-tabs v-model="activeTab" @tab-click="handleTabClick">
  189. <el-tab-pane label="变动明细" name="all"></el-tab-pane>
  190. <el-tab-pane label="采购入库" name="采购入库"></el-tab-pane>
  191. <el-tab-pane label="采购退货" name="采购退货"></el-tab-pane>
  192. <el-tab-pane label="生产领料" name="生产领料"></el-tab-pane>
  193. <el-tab-pane label="生产退仓" name="生产退仓"></el-tab-pane>
  194. <el-tab-pane label="生产入库" name="生产入库"></el-tab-pane>
  195. <el-tab-pane label="销售出库" name="销售出库"></el-tab-pane>
  196. <el-tab-pane label="销售退货" name="销售退货"></el-tab-pane>
  197. <el-tab-pane label="其他入库" name="其他入库"></el-tab-pane>
  198. <el-tab-pane label="其他出库" name="其他出库"></el-tab-pane>
  199. <el-tab-pane label="移库调拨" name="移库调拨"></el-tab-pane>
  200. </el-tabs>
  201. <!-- 展示列表 -->
  202. <el-table
  203. :height="height"
  204. :data="dataList"
  205. border
  206. v-loading="dataListLoading"
  207. @selection-change="selectionChangeHandle"
  208. style="width: 100%;">
  209. <el-table-column
  210. type="selection"
  211. header-align="center"
  212. align="center"
  213. width="50">
  214. </el-table-column>
  215. <el-table-column prop="buNo" label="BU" header-align="center" align="center" width="80"></el-table-column>
  216. <el-table-column prop="transactionId" label="变动单号" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  217. <el-table-column prop="documentType" label="变动类型" header-align="center" align="center" width="100"></el-table-column>
  218. <el-table-column prop="documentNo" label="通知单号" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  219. <el-table-column prop="orderNo" label="关联单号" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  220. <el-table-column prop="orderLineNo" label="关联单行号" header-align="center" align="center" width="100"></el-table-column>
  221. <el-table-column prop="rollNo" label="标签条码" header-align="center" align="left" min-width="180" show-overflow-tooltip></el-table-column>
  222. <el-table-column prop="rollQty" label="变动数量" header-align="center" align="right" width="100"></el-table-column>
  223. <el-table-column prop="batchNo" label="合约号码" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  224. <el-table-column prop="partNo" label="物料编码" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  225. <el-table-column prop="partDesc" label="物料名称" header-align="center" align="left" min-width="180" show-overflow-tooltip></el-table-column>
  226. <el-table-column prop="spec" label="规格型号" header-align="center" align="left" min-width="120" show-overflow-tooltip></el-table-column>
  227. <el-table-column prop="warehouseId" label="仓库编码" header-align="center" align="center" width="100"></el-table-column>
  228. <el-table-column prop="warehouseName" label="仓库名称" header-align="center" align="left" min-width="120" show-overflow-tooltip></el-table-column>
  229. <el-table-column prop="locationId" label="库位编码" header-align="center" align="center" width="100"></el-table-column>
  230. <el-table-column prop="locationName" label="库位名称" header-align="center" align="left" min-width="120" show-overflow-tooltip></el-table-column>
  231. <el-table-column prop="syncedFlag" label="传输状态" header-align="center" align="center" width="90">
  232. <template slot-scope="scope">
  233. <el-tag :type="scope.row.syncedFlag === '已传输' ? 'success' : 'warning'" size="small">
  234. {{ scope.row.syncedFlag }}
  235. </el-tag>
  236. </template>
  237. </el-table-column>
  238. <el-table-column prop="syncedTime" label="传输时间" header-align="center" align="center" width="160"></el-table-column>
  239. <el-table-column prop="syncedErrorMsg" label="传输消息" header-align="center" align="left" min-width="150" show-overflow-tooltip></el-table-column>
  240. <el-table-column v-if="showBomItemNo" prop="bomItemNo" label="Bom行号" header-align="center" align="center" width="100"></el-table-column>
  241. <el-table-column prop="transactionBy" label="操作员" header-align="center" align="center" width="100"></el-table-column>
  242. <el-table-column prop="transactionDate" label="变动日期" header-align="center" align="center" width="160"></el-table-column>
  243. </el-table>
  244. <!-- 分页 -->
  245. <el-pagination
  246. style="margin-top: 10px"
  247. @size-change="sizeChangeHandle"
  248. @current-change="currentChangeHandle"
  249. :current-page="pageIndex"
  250. :page-sizes="[20, 50, 100, 200, 500]"
  251. :page-size="pageSize"
  252. :total="totalPage"
  253. layout="total, sizes, prev, pager, next, jumper">
  254. </el-pagination>
  255. </div>
  256. </template>
  257. <script>
  258. import { labelTransactionLogList, labelTransactionLogRetry } from '@/api/warehouse/labelTransactionLog.js'
  259. import { getSiteAndBuByUserName2 } from '@/api/qc/qc.js'
  260. import { getWarehouseList } from '@/api/wms/wms.js'
  261. import excel from '@/utils/excel-util.js' // 导入导出工具类
  262. export default {
  263. data() {
  264. return {
  265. height: window.innerHeight - 313,
  266. searchExpanded: true,
  267. searchData: {
  268. buNo: '',
  269. documentType: '',
  270. rollNo: '',
  271. partNo: '',
  272. partDesc: '',
  273. spec: '',
  274. startDate: '',
  275. endDate: '',
  276. transactionId: '',
  277. documentNo: '',
  278. orderNo: '',
  279. orderLineNo: '',
  280. batchNo: '',
  281. syncedFlag: '',
  282. warehouseIdList: [] // 仓库筛选条件,支持多选
  283. },
  284. // 变动类型列表(不包含"变动明细")
  285. documentTypeList: [
  286. { label: '采购入库', value: '采购入库' },
  287. { label: '采购退货', value: '采购退货' },
  288. { label: '生产领料', value: '生产领料' },
  289. { label: '生产退仓', value: '生产退仓' },
  290. { label: '生产入库', value: '生产入库' },
  291. { label: '销售出库', value: '销售出库' },
  292. { label: '销售退货', value: '销售退货' },
  293. { label: '其他入库', value: '其他入库' },
  294. { label: '其他出库', value: '其他出库' },
  295. { label: '移库调拨', value: '移库调拨' }
  296. ],
  297. activeTab: 'all',
  298. dataList: [],
  299. dataListLoading: false,
  300. dataListSelections: [],
  301. pageIndex: 1,
  302. pageSize: 20,
  303. totalPage: 0,
  304. userBuList: [],
  305. warehouseList: [], // 仓库列表
  306. // 导出列配置
  307. exportColumnList: [
  308. { columnProp: 'buNo', columnLabel: 'BU', headerAlign: 'center', align: 'center', columnWidth: 80 },
  309. { columnProp: 'transactionId', columnLabel: '变动单号', headerAlign: 'center', align: 'left', columnWidth: 150 },
  310. { columnProp: 'documentType', columnLabel: '变动类型', headerAlign: 'center', align: 'center', columnWidth: 100 },
  311. { columnProp: 'documentNo', columnLabel: '通知单号', headerAlign: 'center', align: 'left', columnWidth: 150 },
  312. { columnProp: 'orderNo', columnLabel: '关联单号', headerAlign: 'center', align: 'left', columnWidth: 150 },
  313. { columnProp: 'orderLineNo', columnLabel: '关联单行号', headerAlign: 'center', align: 'center', columnWidth: 100 },
  314. { columnProp: 'rollNo', columnLabel: '标签条码', headerAlign: 'center', align: 'left', columnWidth: 180 },
  315. { columnProp: 'rollQty', columnLabel: '变动数量', headerAlign: 'center', align: 'right', columnWidth: 100 },
  316. { columnProp: 'batchNo', columnLabel: '合约号码', headerAlign: 'center', align: 'left', columnWidth: 150 },
  317. { columnProp: 'partNo', columnLabel: '物料编码', headerAlign: 'center', align: 'left', columnWidth: 150 },
  318. { columnProp: 'partDesc', columnLabel: '物料名称', headerAlign: 'center', align: 'left', columnWidth: 180 },
  319. { columnProp: 'spec', columnLabel: '规格型号', headerAlign: 'center', align: 'left', columnWidth: 120 },
  320. { columnProp: 'warehouseId', columnLabel: '仓库编码', headerAlign: 'center', align: 'center', columnWidth: 100 },
  321. { columnProp: 'warehouseName', columnLabel: '仓库名称', headerAlign: 'center', align: 'left', columnWidth: 120 },
  322. { columnProp: 'locationId', columnLabel: '库位编码', headerAlign: 'center', align: 'center', columnWidth: 100 },
  323. { columnProp: 'locationName', columnLabel: '库位名称', headerAlign: 'center', align: 'left', columnWidth: 120 },
  324. { columnProp: 'syncedFlag', columnLabel: '传输状态', headerAlign: 'center', align: 'center', columnWidth: 90 },
  325. { columnProp: 'syncedTime', columnLabel: '传输时间', headerAlign: 'center', align: 'center', columnWidth: 160 },
  326. { columnProp: 'syncedErrorMsg', columnLabel: '传输消息', headerAlign: 'center', align: 'left', columnWidth: 150 },
  327. { columnProp: 'bomItemNo', columnLabel: 'Bom行号', headerAlign: 'center', align: 'center', columnWidth: 100 },
  328. { columnProp: 'transactionBy', columnLabel: '操作员', headerAlign: 'center', align: 'center', columnWidth: 100 },
  329. { columnProp: 'transactionDate', columnLabel: '变动日期', headerAlign: 'center', align: 'center', columnWidth: 160 }
  330. ]
  331. }
  332. },
  333. computed: {
  334. // 只有生产领料和生产退仓页签才显示Bom行号列
  335. showBomItemNo() {
  336. return this.activeTab === '生产领料' || this.activeTab === '生产退仓'
  337. }
  338. },
  339. mounted() {
  340. this.initBuList()
  341. this.initWarehouseList() // 初始化仓库列表
  342. this.initDefaultDate()
  343. this.getDataList()
  344. this.handleResize();
  345. window.addEventListener('resize', this.handleResize)
  346. },
  347. beforeDestroy() {
  348. window.removeEventListener('resize', this.handleResize)
  349. },
  350. methods: {
  351. handleResize() {
  352. this.$nextTick(() => {
  353. const windowHeight = window.innerHeight;
  354. const headerHeight = this.searchExpanded ? 340 : 220;
  355. this.height = windowHeight - headerHeight - 85;
  356. });
  357. },
  358. // 切换搜索区域展开/收起
  359. toggleSearchExpand() {
  360. this.searchExpanded = !this.searchExpanded;
  361. this.handleResize();
  362. },
  363. // 初始化BU列表
  364. initBuList() {
  365. const tempData = {
  366. username: this.$store.state.user.name
  367. }
  368. getSiteAndBuByUserName2(tempData).then(({ data }) => {
  369. if (data.code === 0) {
  370. this.userBuList = data.rows || []
  371. }
  372. })
  373. },
  374. // 初始化仓库列表
  375. initWarehouseList() {
  376. const params = {
  377. userName: this.$store.state.user.name
  378. }
  379. getWarehouseList(params).then(({ data }) => {
  380. if (data.code === 0) {
  381. this.warehouseList = data.rows || []
  382. }
  383. }).catch(error => {
  384. console.error('获取仓库列表失败:', error)
  385. })
  386. },
  387. // 初始化默认日期为今天
  388. initDefaultDate() {
  389. const today = this.formatDate(new Date())
  390. this.searchData.startDate = today + ' 00:00'
  391. this.searchData.endDate = today + ' 23:59'
  392. },
  393. // 格式化日期
  394. formatDate(date) {
  395. const year = date.getFullYear()
  396. const month = String(date.getMonth() + 1).padStart(2, '0')
  397. const day = String(date.getDate()).padStart(2, '0')
  398. return `${year}-${month}-${day}`
  399. },
  400. // 页签切换
  401. handleTabClick(tab) {
  402. this.pageIndex = 1
  403. this.getDataList()
  404. },
  405. // 点击查询按钮 - 重置到第一页
  406. handleSearch() {
  407. this.pageIndex = 1
  408. this.getDataList()
  409. },
  410. // 查询列表
  411. getDataList() {
  412. this.dataListLoading = true
  413. const params = {
  414. buNo: this.searchData.buNo,
  415. documentType: this.activeTab === 'all' ? this.searchData.documentType : this.activeTab,
  416. rollNo: this.searchData.rollNo,
  417. partNo: this.searchData.partNo,
  418. partDesc: this.searchData.partDesc,
  419. spec: this.searchData.spec,
  420. startDate: this.searchData.startDate || '',
  421. endDate: this.searchData.endDate || '',
  422. transactionId: this.searchData.transactionId,
  423. documentNo: this.searchData.documentNo,
  424. orderNo: this.searchData.orderNo,
  425. orderLineNo: this.searchData.orderLineNo,
  426. batchNo: this.searchData.batchNo,
  427. syncedFlag: this.searchData.syncedFlag,
  428. warehouseIdList: this.searchData.warehouseIdList, // 仓库筛选条件
  429. page: this.pageIndex,
  430. limit: this.pageSize
  431. }
  432. labelTransactionLogList(params).then(({ data }) => {
  433. this.dataListLoading = false
  434. if (data && data.code === 0) {
  435. this.dataList = data.page.list || []
  436. this.totalPage = data.page.totalCount || 0
  437. } else {
  438. this.dataList = []
  439. this.totalPage = 0
  440. this.$message.error(data.msg || '查询失败')
  441. }
  442. }).catch(() => {
  443. this.dataListLoading = false
  444. this.dataList = []
  445. this.totalPage = 0
  446. })
  447. },
  448. // 重置查询条件
  449. resetSearch() {
  450. this.searchData = {
  451. buNo: this.userBuList.length > 0 ? this.userBuList[0].buNo : '',
  452. documentType: '',
  453. rollNo: '',
  454. partNo: '',
  455. partDesc: '',
  456. spec: '',
  457. startDate: '',
  458. endDate: '',
  459. transactionId: '',
  460. documentNo: '',
  461. orderNo: '',
  462. orderLineNo: '',
  463. batchNo: '',
  464. syncedFlag: '',
  465. warehouseIdList: [] // 重置仓库筛选
  466. }
  467. this.initDefaultDate()
  468. this.activeTab = 'all'
  469. this.pageIndex = 1
  470. this.getDataList()
  471. },
  472. // 导出数据
  473. exportData() {
  474. if (this.dataList.length === 0) {
  475. this.$message.warning('没有数据可导出')
  476. return
  477. }
  478. // 构造导出参数(与查询一致,但不分页)
  479. const exportParams = {
  480. buNo: this.searchData.buNo,
  481. documentType: this.activeTab === 'all' ? this.searchData.documentType : this.activeTab,
  482. rollNo: this.searchData.rollNo,
  483. partNo: this.searchData.partNo,
  484. partDesc: this.searchData.partDesc,
  485. spec: this.searchData.spec,
  486. startDate: this.searchData.startDate || '',
  487. endDate: this.searchData.endDate || '',
  488. transactionId: this.searchData.transactionId,
  489. documentNo: this.searchData.documentNo,
  490. orderNo: this.searchData.orderNo,
  491. orderLineNo: this.searchData.orderLineNo,
  492. batchNo: this.searchData.batchNo,
  493. syncedFlag: this.searchData.syncedFlag,
  494. warehouseIdList: this.searchData.warehouseIdList, // 仓库筛选条件
  495. userName: this.$store.state.user.name,
  496. page: 1,
  497. limit: 999999 // 使用大数字代替-1,SQL Server的FETCH子句不支持负数
  498. }
  499. // 根据当前页签生成文件名
  500. const tabName = this.activeTab === 'all' ? '全部' : this.activeTab
  501. const fileName = `标签变动记录_${tabName}_${this.dayjs().format('YYYYMMDDHHmmss')}.xlsx`
  502. // 使用excel工具类导出
  503. excel.exportTable({
  504. url: '/warehouse/labelTransactionLog/list', // 使用list接口,传limit=999999导出所有数据
  505. columnMapping: this.exportColumnList, // 使用导出列配置
  506. mergeSetting: [], // 需要合并的列
  507. params: exportParams, // 查询参数
  508. fileName: fileName, // 文件名
  509. rowFetcher: res => res.data.page.list, // 数据提取路径
  510. columnFormatter: [], // 列格式化
  511. dropColumns: [] // 不需要剔除的列
  512. })
  513. },
  514. // 每页数量变化
  515. sizeChangeHandle(val) {
  516. this.pageSize = val
  517. this.pageIndex = 1
  518. this.getDataList()
  519. },
  520. // 页码变化
  521. currentChangeHandle(val) {
  522. this.pageIndex = val
  523. this.getDataList()
  524. },
  525. // 多选变化
  526. selectionChangeHandle(val) {
  527. this.dataListSelections = val
  528. },
  529. // 异常重试
  530. exceptionRetryHandle() {
  531. if (this.dataListSelections.length === 0) {
  532. this.$message.warning('请选择要重试的记录!')
  533. return
  534. }
  535. const count = this.dataListSelections.length
  536. this.$confirm(`确定要异常重试选中的 ${count} 条记录吗?`, '提示', {
  537. confirmButtonText: '确定',
  538. cancelButtonText: '取消',
  539. type: 'warning'
  540. }).then(() => {
  541. const loading = this.$loading({
  542. lock: true,
  543. text: `正在重试 ${count} 条记录,请稍候...`,
  544. spinner: 'el-icon-loading',
  545. background: 'rgba(0, 0, 0, 0.7)'
  546. })
  547. // 构造批量重试参数
  548. const retryList = this.dataListSelections.map(item => ({
  549. site: item.site,
  550. buNo: item.buNo,
  551. transactionId: item.transactionId
  552. }))
  553. // 调用批量重试接口
  554. labelTransactionLogRetry({ retryList, isExceptionRetry: true }).then(({ data }) => {
  555. loading.close()
  556. if (data && data.code === 0) {
  557. const result = data.result || {}
  558. const successCount = result.successCount || 0
  559. const failureCount = result.failureCount || 0
  560. let message = `重试完成!成功:${successCount},失败:${failureCount}`
  561. if (successCount === count) {
  562. this.$message.success(message)
  563. } else if (successCount > 0) {
  564. this.$message.warning(message)
  565. } else {
  566. this.$message.error(message)
  567. }
  568. // 显示详细结果对话框
  569. if (result.details && result.details.length > 0) {
  570. this.showRetryResultDialog(result.details)
  571. }
  572. // 刷新列表
  573. this.getDataList()
  574. } else {
  575. this.$message.error(data.msg || '重试失败')
  576. }
  577. }).catch(error => {
  578. loading.close()
  579. this.$message.error('重试失败:' + (error.message || '网络错误'))
  580. })
  581. }).catch(() => {})
  582. },
  583. // 批量手动重试
  584. batchRetryHandle() {
  585. if (this.dataListSelections.length === 0) {
  586. this.$message.warning('请选择要重试的记录!')
  587. return
  588. }
  589. // 校验:只能选择待传输(syncedFlag不为'已传输')且有错误消息的记录
  590. const invalidItems = this.dataListSelections.filter(item =>
  591. item.syncedFlag === '已传输'
  592. // || !item.syncedErrorMsg || item.syncedErrorMsg.trim() === ''
  593. )
  594. if (invalidItems.length > 0) {
  595. this.$message.warning('只能选择待传输的记录进行手动重试!')
  596. return
  597. }
  598. const count = this.dataListSelections.length
  599. this.$confirm(`确定要手动重试选中的 ${count} 条记录吗?`, '提示', {
  600. confirmButtonText: '确定',
  601. cancelButtonText: '取消',
  602. type: 'warning'
  603. }).then(() => {
  604. const loading = this.$loading({
  605. lock: true,
  606. text: `正在重试 ${count} 条记录,请稍候...`,
  607. spinner: 'el-icon-loading',
  608. background: 'rgba(0, 0, 0, 0.7)'
  609. })
  610. // 构造批量重试参数
  611. const retryList = this.dataListSelections.map(item => ({
  612. site: item.site,
  613. buNo: item.buNo,
  614. transactionId: item.transactionId
  615. }))
  616. // 调用批量重试接口
  617. labelTransactionLogRetry({ retryList }).then(({ data }) => {
  618. loading.close()
  619. if (data && data.code === 0) {
  620. const result = data.result || {}
  621. const successCount = result.successCount || 0
  622. const failureCount = result.failureCount || 0
  623. let message = `重试完成!成功:${successCount},失败:${failureCount}`
  624. if (successCount === count) {
  625. this.$message.success(message)
  626. } else if (successCount > 0) {
  627. this.$message.warning(message)
  628. } else {
  629. this.$message.error(message)
  630. }
  631. // 显示详细结果对话框
  632. if (result.details && result.details.length > 0) {
  633. this.showRetryResultDialog(result.details)
  634. }
  635. // 刷新列表
  636. this.getDataList()
  637. } else {
  638. this.$message.error(data.msg || '重试失败')
  639. }
  640. }).catch(error => {
  641. loading.close()
  642. this.$message.error('重试失败:' + (error.message || '网络错误'))
  643. })
  644. }).catch(() => {})
  645. },
  646. // 显示重试结果详情对话框
  647. showRetryResultDialog(details) {
  648. const successList = details.filter(d => d.status === 'success')
  649. const failureList = details.filter(d => d.status === 'failure')
  650. const errorList = details.filter(d => d.status === 'error')
  651. let messageHtml = '<div style="max-height: 400px; overflow-y: auto;">'
  652. if (successList.length > 0) {
  653. messageHtml += '<div style="margin-bottom: 15px;"><strong style="color: #67C23A;">成功 (' + successList.length + '):</strong><ul style="margin: 5px 0; padding-left: 20px;">'
  654. successList.forEach(item => {
  655. messageHtml += '<li>事务ID:' + item.transactionId + (item.u8CCode ? ' - U8单号:' + item.u8CCode : '') + '</li>'
  656. })
  657. messageHtml += '</ul></div>'
  658. }
  659. if (failureList.length > 0) {
  660. messageHtml += '<div style="margin-bottom: 15px;"><strong style="color: #E6A23C;">失败 (' + failureList.length + '):</strong><ul style="margin: 5px 0; padding-left: 20px;">'
  661. failureList.forEach(item => {
  662. messageHtml += '<li>事务ID:' + item.transactionId + ':' + (item.message || '未知错误') + '</li>'
  663. })
  664. messageHtml += '</ul></div>'
  665. }
  666. if (errorList.length > 0) {
  667. messageHtml += '<div><strong style="color: #F56C6C;">异常 (' + errorList.length + '):</strong><ul style="margin: 5px 0; padding-left: 20px;">'
  668. errorList.forEach(item => {
  669. messageHtml += '<li>事务ID:' + item.transactionId + ':' + (item.message || '未知异常') + '</li>'
  670. })
  671. messageHtml += '</ul></div>'
  672. }
  673. messageHtml += '</div>'
  674. this.$alert(messageHtml, '批量重试结果详情', {
  675. confirmButtonText: '确定',
  676. dangerouslyUseHTMLString: true
  677. })
  678. }
  679. }
  680. }
  681. </script>
  682. <style scoped>
  683. .mod-config {
  684. padding: 0px;
  685. }
  686. /* 搜索卡片样式 */
  687. .search-card {
  688. margin-bottom: 12px;
  689. border-radius: 8px;
  690. overflow: hidden;
  691. transition: all 0.3s ease;
  692. }
  693. .search-card:hover {
  694. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  695. }
  696. .search-card /deep/ .el-card__header {
  697. padding: 5px 20px;
  698. background: linear-gradient(135deg, #9ac3d0 20%, #b6c7dd 80%);
  699. border-bottom: none;
  700. }
  701. .search-header {
  702. display: flex;
  703. justify-content: space-between;
  704. align-items: center;
  705. }
  706. .header-left {
  707. display: flex;
  708. align-items: center;
  709. color: #fff;
  710. }
  711. .header-left i {
  712. font-size: 16px;
  713. margin-right: 8px;
  714. }
  715. .header-title {
  716. font-size: 14px;
  717. font-weight: 600;
  718. }
  719. .header-right {
  720. display: flex;
  721. align-items: center;
  722. }
  723. .collapse-btn {
  724. color: #fff !important;
  725. font-size: 12px;
  726. padding: 4px 8px;
  727. }
  728. .collapse-btn:hover {
  729. background: rgba(255, 255, 255, 0.1);
  730. border-radius: 4px;
  731. }
  732. .collapse-btn i {
  733. margin-left: 4px;
  734. }
  735. /* 搜索表单样式 */
  736. .search-form {
  737. padding: 6px 0;
  738. min-height: 0;
  739. }
  740. /* 卡片主体样式 */
  741. .search-card /deep/ .el-card__body {
  742. padding: 10px;
  743. transition: all 0.3s ease;
  744. }
  745. /* 收起时的样式 */
  746. .search-card.collapsed /deep/ .el-card__body {
  747. padding: 10px 20px;
  748. }
  749. .search-form /deep/ .el-form-item {
  750. margin-bottom: 12px;
  751. }
  752. .search-form /deep/ .el-form-item__label {
  753. font-weight: 500;
  754. color: #606266;
  755. padding-bottom: 4px;
  756. }
  757. .search-form /deep/ .el-input__inner,
  758. .search-form /deep/ .el-textarea__inner {
  759. border-radius: 6px;
  760. border: 1px solid #DCDFE6;
  761. transition: all 0.3s ease;
  762. }
  763. .search-form /deep/ .el-input__inner:focus,
  764. .search-form /deep/ .el-textarea__inner:focus {
  765. border-color: #9ac3d0;
  766. box-shadow: 0 0 0 2px rgba(154, 195, 208, 0.1);
  767. }
  768. .search-form /deep/ .el-select {
  769. width: 100%;
  770. }
  771. .search-form /deep/ .el-date-editor.el-input,
  772. .search-form /deep/ .el-date-editor--daterange.el-input__inner {
  773. width: 100%;
  774. }
  775. .search-form /deep/ .el-date-editor--daterange {
  776. width: 100% !important;
  777. }
  778. .search-form /deep/ .el-range-input {
  779. width: 42%;
  780. }
  781. .search-form /deep/ .el-range-separator {
  782. width: 16%;
  783. padding: 0;
  784. }
  785. /* 操作按钮区域 */
  786. .search-actions {
  787. display: flex;
  788. justify-content: space-between;
  789. align-items: center;
  790. padding: 8px 0 2px 0;
  791. }
  792. /* 展开时显示上边框 */
  793. .search-card:not(.collapsed) .search-actions {
  794. border-top: 1px solid #f0f0f0;
  795. margin-top: 6px;
  796. }
  797. /* 收起时不显示上边框和上边距 */
  798. .search-card.collapsed .search-actions {
  799. border-top: none;
  800. margin-top: 0;
  801. padding-top: 0;
  802. }
  803. .action-left,
  804. .action-right {
  805. display: flex;
  806. gap: 8px;
  807. }
  808. .search-actions .el-button {
  809. border-radius: 4px;
  810. padding: 5px 10px;
  811. font-size: 12px;
  812. font-weight: 500;
  813. transition: all 0.3s ease;
  814. }
  815. /* 页签样式 */
  816. /deep/ .el-tabs__header {
  817. margin-bottom: 10px;
  818. }
  819. /deep/ .el-tabs__nav-wrap::after {
  820. height: 1px;
  821. }
  822. /deep/ .el-tabs__item {
  823. padding: 0 15px;
  824. height: 36px;
  825. line-height: 36px;
  826. }
  827. /deep/ .el-tabs__item.is-active {
  828. color: #17B3A3;
  829. }
  830. /deep/ .el-tabs__active-bar {
  831. background-color: #17B3A3;
  832. }
  833. /* 分页样式 */
  834. /deep/ .el-pagination {
  835. margin-top: 10px;
  836. padding: 0;
  837. }
  838. </style>