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.

361 lines
12 KiB

1 month ago
10 months ago
1 month ago
10 months ago
1 month ago
3 weeks ago
10 months ago
1 month ago
1 month ago
10 months ago
1 month ago
1 month ago
10 months ago
1 month ago
1 month ago
1 month ago
10 months ago
1 month ago
10 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
4 weeks ago
4 weeks ago
1 month ago
3 weeks ago
10 months ago
1 month ago
10 months ago
4 weeks ago
4 weeks ago
4 weeks ago
3 weeks ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
4 weeks ago
3 weeks ago
1 month ago
1 month ago
1 month ago
1 month ago
3 weeks ago
3 weeks ago
4 weeks ago
  1. <template>
  2. <div class="mod-config">
  3. <el-form :inline="true" label-position="top">
  4. <el-form-item :label="$t('purchase.cancelReceipt.orderNo')">
  5. <el-input style="width: 120px;" v-model="queryHeaderData.orderNo" @keyup.enter.native="getDataList('Y')"></el-input>
  6. </el-form-item>
  7. <el-form-item :label="$t('purchase.cancelReceipt.partNo')">
  8. <el-input style="width: 120px;" v-model="queryHeaderData.partNo" @keyup.enter.native="getDataList('Y')"></el-input>
  9. </el-form-item>
  10. <el-form-item style="margin-top: 20px;">
  11. <el-button @click="getDataList('Y')" type="primary">{{ $t('purchase.common.search') }}</el-button>
  12. <el-button @click="resetQuery">{{ $t('purchase.common.reset') }}</el-button>
  13. </el-form-item>
  14. </el-form>
  15. <!-- 数据表格 -->
  16. <el-table
  17. :data="dataList"
  18. border :height="height"
  19. v-loading="dataListLoading || cancelLoading"
  20. @selection-change="selectionChangeHandle"
  21. style="width: 100%; margin-bottom: 20px;">
  22. <el-table-column
  23. prop="sourceRef1"
  24. header-align="center"
  25. align="center"
  26. :label="$t('purchase.cancelReceipt.receiptNo')"
  27. width="140">
  28. </el-table-column>
  29. <el-table-column
  30. prop="sourcePartNo"
  31. header-align="center"
  32. align="center"
  33. :label="$t('purchase.cancelReceipt.partNo')"
  34. width="150">
  35. </el-table-column>
  36. <el-table-column
  37. prop="lotBatchNo"
  38. header-align="center"
  39. align="center"
  40. :label="$t('purchase.cancelReceipt.batchNo')"
  41. width="120">
  42. </el-table-column>
  43. <el-table-column
  44. prop="description"
  45. header-align="center"
  46. align="center"
  47. :label="$t('purchase.cancelReceipt.partDesc')"
  48. min-width="200">
  49. </el-table-column>
  50. <el-table-column
  51. prop="qtyArrived"
  52. header-align="center"
  53. align="center"
  54. :label="$t('purchase.cancelReceipt.qtyArrived')"
  55. width="110">
  56. </el-table-column>
  57. <el-table-column
  58. prop="arrivalDate"
  59. header-align="center"
  60. align="center"
  61. :label="$t('purchase.cancelReceipt.arrivalDate')"
  62. width="110">
  63. </el-table-column>
  64. <el-table-column
  65. prop="sender"
  66. header-align="center"
  67. align="center"
  68. :label="$t('purchase.cancelReceipt.supplierId')"
  69. width="120">
  70. </el-table-column>
  71. <el-table-column
  72. prop="senderName"
  73. header-align="center"
  74. align="center"
  75. :label="$t('purchase.cancelReceipt.supplierName')"
  76. min-width="120">
  77. </el-table-column>
  78. <el-table-column
  79. prop="receiver"
  80. header-align="center"
  81. align="center"
  82. :label="$t('purchase.cancelReceipt.receiver')"
  83. width="100">
  84. </el-table-column>
  85. <el-table-column
  86. prop="state"
  87. header-align="center"
  88. align="center"
  89. :label="$t('purchase.common.status')"
  90. width="100">
  91. <template slot-scope="scope">
  92. <span v-if="scope.row.state === 'Received'" type="success">{{ $t('purchase.status.received') }}</span>
  93. <span v-else-if="scope.row.state === 'Cancelled'" type="danger">{{ $t('purchase.status.cancelled') }}</span>
  94. <span v-else-if="scope.row.state === 'Arrived'" type="warning">{{ $t('purchase.status.arrived') }}</span>
  95. <span v-else type="info">{{ scope.row.state }}</span>
  96. </template>
  97. </el-table-column>
  98. <el-table-column
  99. fixed="left"
  100. header-align="center"
  101. align="center"
  102. width="80"
  103. :label="$t('purchase.common.operation')">
  104. <template slot-scope="scope">
  105. <a @click="cancelSingleReceipt(scope.row)" type="text" size="small" :disabled="scope.row.state !== 'Received'">{{ $t('purchase.common.cancel') }}</a>
  106. </template>
  107. </el-table-column>
  108. </el-table>
  109. <!-- 分页 -->
  110. <el-pagination
  111. @size-change="sizeChangeHandle"
  112. @current-change="currentChangeHandle"
  113. :current-page="pageIndex"
  114. :page-sizes="[10, 20, 50, 100]"
  115. :page-size="pageSize"
  116. :total="totalPage"
  117. layout="total, sizes, prev, pager, next, jumper">
  118. </el-pagination>
  119. <!-- 取消接收对话框 -->
  120. <el-dialog
  121. :title="$t('purchase.cancelReceipt.dialogTitle')"
  122. :visible.sync="cancelDialogVisible"
  123. width="500px"
  124. :close-on-click-modal="false">
  125. <el-form :model="cancelForm" :rules="cancelRules" ref="cancelForm" label-width="100px">
  126. <el-form-item :label="$t('purchase.cancelReceipt.cancelReason')" prop="cancelReason">
  127. <el-input
  128. :placeholder="$t('purchase.cancelReceipt.cancelReasonPlaceholder')"
  129. v-model="cancelForm.cancelReason">
  130. </el-input>
  131. </el-form-item>
  132. </el-form>
  133. <span slot="footer" class="dialog-footer" style="margin-top: 80px">
  134. <el-button @click="cancelDialogVisible = false">{{ $t('purchase.common.cancel') }}</el-button>
  135. <el-button type="primary" @click="confirmCancel" :loading="cancelLoading">{{ $t('purchase.common.confirm') }}</el-button>
  136. </span>
  137. </el-dialog>
  138. </div>
  139. </template>
  140. <script>
  141. import { getCancelableReceiptList, cancelReceipt } from '@/api/purchase/purchaseManage'
  142. import { filterRowsByAuthorizedSubSite, getAuthorizedSubSiteCodeList } from '@/utils/subSiteAuth'
  143. const getCurrentSiteLike = () => {
  144. const site = localStorage.getItem('site') || ''
  145. return site ? `${site}%` : ''
  146. }
  147. export default {
  148. data () {
  149. return {
  150. height: 200,
  151. favorite: false,
  152. dataList: [],
  153. pageIndex: 1,
  154. pageSize: 20,
  155. totalPage: 0,
  156. dataListLoading: false,
  157. dataListSelections: [],
  158. queryHeaderData: {
  159. site: getCurrentSiteLike(),
  160. orderNo: '',
  161. partNo: '',
  162. batchNo: '',
  163. supplierId: '',
  164. startDate: '',
  165. endDate: ''
  166. },
  167. cancelDialogVisible: false,
  168. cancelLoading: false,
  169. cancelForm: {
  170. cancelReason: ''
  171. },
  172. cancelRules: {
  173. cancelReason: [
  174. { required: true, message: this.$t('purchase.cancelReceipt.cancelReasonRequired'), trigger: 'blur' }
  175. ]
  176. },
  177. currentCancelRecords: [],
  178. // 行级 loading:记录当前正在取消的收货记录key(contract + receiptSequence)
  179. cancelingRecordKeys: []
  180. }
  181. },
  182. mounted() {
  183. this.$nextTick(() => {
  184. this.height = (window.innerHeight - 350);
  185. })
  186. },
  187. activated () {
  188. this.getDataList()
  189. },
  190. methods: {
  191. favoriteFunction () {
  192. this.favorite = !this.favorite
  193. },
  194. // 获取数据列表
  195. getDataList (flag) {
  196. if (flag === 'Y') {
  197. this.pageIndex = 1
  198. }
  199. if (!this.queryHeaderData.orderNo) {
  200. this.$message.warning(this.$t('purchase.cancelReceipt.orderNoRequiredForQuery'))
  201. return
  202. }
  203. this.dataListLoading = true
  204. const siteLike = getCurrentSiteLike()
  205. const params = {
  206. page: this.pageIndex,
  207. size: this.pageSize,
  208. ...this.queryHeaderData,
  209. site: siteLike
  210. }
  211. getCancelableReceiptList(params).then(({data}) => {
  212. if (data && data.code === 0) {
  213. const sourceRows = (data.page && Array.isArray(data.page.list)) ? data.page.list : []
  214. const authorizedSubSiteCodeList = getAuthorizedSubSiteCodeList(this.$store.state.user.subSiteCodeList)
  215. // 后端当前按site前缀查询,前端按授权子site做二次过滤,避免展示未授权数据
  216. this.dataList = filterRowsByAuthorizedSubSite(sourceRows, authorizedSubSiteCodeList, ['contract'])
  217. this.totalPage = (data.page && data.page.totalCount) ? data.page.totalCount : 0
  218. } else {
  219. this.dataList = []
  220. this.totalPage = 0
  221. }
  222. this.dataListLoading = false
  223. })
  224. },
  225. // 每页数
  226. sizeChangeHandle (val) {
  227. this.pageSize = val
  228. this.pageIndex = 1
  229. this.getDataList()
  230. },
  231. // 当前页
  232. currentChangeHandle (val) {
  233. this.pageIndex = val
  234. this.getDataList()
  235. },
  236. // 多选
  237. selectionChangeHandle (val) {
  238. this.dataListSelections = val
  239. },
  240. getCancelRecordKey (record) {
  241. return `${record.contract || ''}__${record.receiptSequence || ''}`
  242. },
  243. isRecordCanceling (record) {
  244. return this.cancelingRecordKeys.includes(this.getCancelRecordKey(record))
  245. },
  246. // 取消单个接收记录
  247. cancelSingleReceipt (row) {
  248. if (this.cancelLoading) {
  249. return
  250. }
  251. const receiptNo = row.receiptNo || row.sourceRef1 || ''
  252. // 显示确认提示
  253. this.$confirm(this.$t('purchase.cancelReceipt.confirmSingle', { receiptNo }), this.$t('purchase.cancelReceipt.confirmTitle'), {
  254. confirmButtonText: this.$t('purchase.common.confirm'),
  255. cancelButtonText: this.$t('purchase.common.cancel'),
  256. type: 'warning'
  257. }).then(() => {
  258. this.currentCancelRecords = [row]
  259. this.cancelForm.cancelReason = ' '
  260. //this.cancelDialogVisible = true
  261. this.confirmCancel()
  262. }).catch(() => {
  263. // 用户取消操作
  264. })
  265. },
  266. // 批量取消接收记录
  267. cancelSelectedReceipts () {
  268. if (this.cancelLoading) {
  269. return
  270. }
  271. if (this.dataListSelections.length === 0) {
  272. this.$message.warning(this.$t('purchase.cancelReceipt.selectRecordsFirst'))
  273. return
  274. }
  275. // 显示确认提示
  276. this.$confirm(this.$t('purchase.cancelReceipt.confirmBatch', { count: this.dataListSelections.length }), this.$t('purchase.cancelReceipt.confirmTitle'), {
  277. confirmButtonText: this.$t('purchase.common.confirm'),
  278. cancelButtonText: this.$t('purchase.common.cancel'),
  279. type: 'warning'
  280. }).then(() => {
  281. this.currentCancelRecords = this.dataListSelections
  282. this.cancelForm.cancelReason = ' '
  283. //this.cancelDialogVisible = true
  284. this.confirmCancel()
  285. }).catch(() => {
  286. // 用户取消操作
  287. })
  288. },
  289. // 确认取消
  290. confirmCancel () {
  291. this.cancelLoading = true
  292. const cancelRecords = [...this.currentCancelRecords]
  293. this.cancelingRecordKeys = cancelRecords.map(record => this.getCancelRecordKey(record))
  294. const promises = cancelRecords.map(record => {
  295. return cancelReceipt({
  296. receiptSequence: record.receiptSequence,
  297. site: record.contract,
  298. cancelReason: this.cancelForm.cancelReason
  299. })
  300. })
  301. Promise.all(promises).then(results => {
  302. let successCount = 0
  303. let errorMessages = []
  304. results.forEach((result, index) => {
  305. if (result.data && result.data.code === 0) {
  306. successCount++
  307. } else {
  308. const record = cancelRecords[index]
  309. errorMessages.push(this.$t('purchase.cancelReceipt.cancelItemFailed', {
  310. receiptNo: record.receiptNo || record.sourceRef1 || '',
  311. reason: result.data.msg || this.$t('purchase.cancelReceipt.cancelFailed')
  312. }))
  313. }
  314. })
  315. if (successCount > 0) {
  316. this.$message.success(this.$t('purchase.cancelReceipt.cancelSuccessCount', { count: successCount }))
  317. this.getDataList()
  318. }
  319. if (errorMessages.length > 0) {
  320. this.$message.error(this.$t('purchase.cancelReceipt.partialCancelFailed', { details: errorMessages.join('\n') }))
  321. }
  322. this.cancelDialogVisible = false
  323. }).catch(() => {
  324. this.$message.error(this.$t('purchase.cancelReceipt.cancelOperationFailed'))
  325. }).finally(() => {
  326. this.cancelLoading = false
  327. this.cancelingRecordKeys = []
  328. })
  329. },
  330. // 重置查询
  331. resetQuery () {
  332. this.queryHeaderData = {
  333. site: getCurrentSiteLike(),
  334. orderNo: '',
  335. partNo: '',
  336. batchNo: '',
  337. supplierId: '',
  338. startDate: '',
  339. endDate: ''
  340. }
  341. this.getDataList('Y')
  342. }
  343. }
  344. }
  345. </script>
  346. <style scoped>
  347. </style>