diff --git a/.env.development b/.env.development index 334ec3f..5af98fb 100644 --- a/.env.development +++ b/.env.development @@ -9,7 +9,7 @@ VUE_APP_OA_URL_TYPE = '{"采购入库":51,"请示入库":54,"调拨入库":55," #正式 -VUE_APP_BASE_API = http://192.168.60.99:9004/ +VUE_APP_BASE_API = http://192.168.60.99:8004/ #VUE_APP_UPLOAD_API = http://192.168.60.99:9004/api/admin/upload-file # 正式oa diff --git a/src/views/inventorys/stocktaking.vue b/src/views/inventorys/stocktaking.vue index aec0dfe..fb4f7e2 100644 --- a/src/views/inventorys/stocktaking.vue +++ b/src/views/inventorys/stocktaking.vue @@ -758,6 +758,17 @@ - +
+ +
@@ -1455,7 +1466,10 @@ export default { data: null, type: 1, // 默认为日常检查 inventoryList: [], - loading: false + loading: false, + pageIndex: 1, + pageSize: 10, + total: 0 }, summarySignaturePadCtx: null, summarySignaturePadCanvas: null @@ -2346,6 +2360,8 @@ export default { planCount: planData.chart_total || '-', actualCount: planData.chart_done || '-' } + this.summaryModal.pageIndex = 1 + this.summaryModal.pageSize = 10 this.summaryModal.visible = true this.loadSummaryInventoryList() this.$nextTick(() => { @@ -2357,8 +2373,8 @@ export default { this.summaryModal.loading = true try { const params = { - page: 1, - page_size: 9999, // 获取所有数据 + page: this.summaryModal.pageIndex, + page_size: this.summaryModal.pageSize, sort_name: 'status', sort_type: 'DESC', 'filter[0][key]': 'material_infos_plan_id', @@ -2387,6 +2403,7 @@ export default { return 0 }) this.summaryModal.inventoryList = list + this.summaryModal.total = res.list.total || list.length } } catch (e) { this.$Message.error('获取盘点物资列表失败') @@ -2395,6 +2412,15 @@ export default { this.summaryModal.loading = false } }, + handleSummaryPageChange(page) { + this.summaryModal.pageIndex = page + this.loadSummaryInventoryList() + }, + handleSummaryPageSizeChange(size) { + this.summaryModal.pageSize = size + this.summaryModal.pageIndex = 1 + this.loadSummaryInventoryList() + }, async exportExcel(sheetName, planId) { // 如果没有传入 planId,则使用 summaryModal.data.id(向后兼容) const targetPlanId = planId || (this.summaryModal.data && this.summaryModal.data.id) @@ -3187,6 +3213,20 @@ export default { width: 160px; } +.inventory-detail-section { + max-width: 100%; +} + +.inventory-table-wrapper { + max-width: 100%; + overflow-x: auto; + overflow-y: hidden; +} + +.inventory-table-wrapper .ivu-table { + min-width: 1200px; +} + .selector-item { margin-right: 10px; margin-bottom: 5px; diff --git a/src/views/maintenance/maintenance_records.vue b/src/views/maintenance/maintenance_records.vue index b0fd5d1..de8690a 100644 --- a/src/views/maintenance/maintenance_records.vue +++ b/src/views/maintenance/maintenance_records.vue @@ -429,15 +429,14 @@
- +
- @@ -476,66 +475,183 @@ -
-
- +
+ +
+
- -
- - @@ -554,20 +670,15 @@ import { Modal, Table } from 'view-design' -import { getOperationList, saveOperation, getOperationDetail,deleteOperation } from '@/api/maintenance/maintenance' -import { getStorehouseTypeList } from '@/api/system/storehouseType' -import { getparameteritem } from '@/api/system/dictionary.js' -import { index } from '@/api/system/baseForm.js' +import { getOperationList, saveOperation, getOperationDetail, deleteOperation } from '@/api/maintenance/maintenance' +import { getparameteritem, getparameteritemMore } from '@/api/system/dictionary.js' +import { index } from '@/api/inventory.js' import { index as getFenleilist } from '@/api/fenlei.js' -import request from '@/utils/request' +import { index as baseFormIndex } from '@/api/system/baseForm.js' import { download } from '@/utils/downloadRequest' -import qs from 'qs' -import * as XLSX from 'xlsx' -import { saveAs } from 'file-saver' -import Cookies from 'js-cookie' import { - getInfo - } from '@/api/user.js' + getInfo +} from '@/api/user.js' export default { components: { Button, @@ -579,8 +690,7 @@ export default { FormItem, Upload, Icon, - Modal, - Table + Modal }, data() { return { @@ -617,20 +727,19 @@ export default { photos: [] }, createForm: { - material_id: '', - material_name: '', + selectedInventoryIds: [], planned_maintenance_date: '', end_date: '', content: '' }, createFormRules: { - material_id: [ + selectedInventoryIds: [ { required: true, message: '请选择维护物资', trigger: 'change', validator: (rule, value, callback) => { - if (!value) { + if (!value || value.length === 0) { callback(new Error('请选择维护物资')) } else { callback() @@ -727,108 +836,132 @@ export default { total: 0, tableHeight: 550, previewUrl: '', - showMaterialModal: false, - materialSearch: '', - materialWarehouseName: '', - materialPageSize: 30, - materialPageIndex: 1, - materialTotal: 0, - materialColumns: [ - { - title: '物资名称', - key: 'zichanmingcheng', - minWidth: 180 - }, - { - title: '一级分类', - key: 'first_level_category.name', - minWidth: 120, - render: (h, params) => { - const relation = params.row.first_level_category.name - return h('span', relation ? relation : '-') - } - }, - { - title: '二级分类', - key: 'second_level_category.name', - minWidth: 120, - render: (h, params) => { - const relation = params.row.second_level_category.name - return h('span', relation ? relation : '-') - } - }, - { - title: '所属种类', - key: 'category_type.name', - minWidth: 180, - render: (h, params) => { - const relation = params.row.category_type.name - return h('span', relation ? relation : '-') - } - }, - { - title: '物资类型', - key: 'wuzileixing', - minWidth: 120 - }, - { - title: '物资型号', - key: 'guigexinghao', - minWidth: 120 - }, - { - title: '物资规格', - key: 'wuziguige', - minWidth: 120 - }, - { - title: '单位', - key: 'jiliangdanwei', - minWidth: 80 - }, - { - title: '储备年限', - key: 'chubeinianxian', - minWidth: 80 - }, - { - title: '存放要求', - key: 'cunfangyaoqiu', - minWidth: 120 - }, - { - title: '维护要求', - key: 'weihuyaoqiu', - minWidth: 120 - }, + materialList: [], + fenleiList: [], + cangkuList: [], + paraOptions: { + materials_status: [], + material_reserve: [], + materials_property: [], + materials_level: [] + }, + materialModal: { + visible: false, + loading: false, + keyword: '', + fenlei: '', + wuzizhuangtai: '', + chanquanxinxi: '', + chubeifangshi: '', + suozaicangku: '', + rukuriqi: '', + shengchanriqi: '', + dengjifenlei: '', + pageIndex: 1, + pageSize: 40, + total: 0, + selectedMaterialIds: new Set(), + selectedMaterialData: new Map(), + isInitialLoad: true, + isUpdatingSelection: false, + tableKey: 0 + }, + materialTable: [ { - title: '保养频次', - key: 'equipment_maintain_config_id_equipment_maintain_configs_id_relation', - minWidth: 120, - render: (h, params) => { - const relation = - params.row.equipment_maintain_config_id_equipment_maintain_configs_id_relation - return h('span', relation && relation.name ? relation.name : '-') - } + type: 'selection', + fixed: 'left', + selectable: (row, index) => { + return true + }, + reserveSelection: true }, { - title: '备注', - key: 'beizhu', - minWidth: 240 + label: '物资信息', + align: 'left', + prop: 'wuzibianma_material_infos_wuzibianma_relation', + multiHd: [ + { + label: '一级分类', + width: 120, + prop: 'wuzibianma_material_infos_wuzibianma_relation.first_level_category.name', + align: 'center' + }, + { + label: '二级分类', + width: 120, + prop: 'wuzibianma_material_infos_wuzibianma_relation.second_level_category.name', + align: 'center' + }, + { + label: '所属种类', + width: 120, + prop: 'wuzibianma_material_infos_wuzibianma_relation.category_type.name', + align: 'center' + }, + { + label: '物资名称', + prop: 'zichanmingcheng', + align: 'center', + width: 180, + fixed: 'left' + }, + { + label: '物资类型', + width: 120, + prop: 'wuzileixing', + align: 'center' + }, + { + label: '物资型号', + prop: 'wuzibianma_material_infos_wuzibianma_relation.guigexinghao', + align: 'center', + width: 180 + }, + { + label: '物资规格', + prop: 'wuzibianma_material_infos_wuzibianma_relation.wuziguige', + align: 'center', + width: 180 + }, + { + label: '单位', + width: 120, + prop: 'wuzibianma_material_infos_wuzibianma_relation.jiliangdanwei', + align: 'center' + } + ] }, { - title: '操作', - slot: 'action', - width: 100, - fixed: 'right', - align: 'center', - headerAlign: 'center', - className: 'table-col-action' + label: '库存信息', + prop: 'kucun', + align: 'left', + multiHd: [ + { + label: '入库批次', + width: 120, + prop: 'rukupici' + }, + { + label: '在库数量', + width: 120, + prop: 'zaikushuliang', + customFn: row => { + return ( + + {row.row.zaikushuliang} + {row.row.jiliangdanwei ? row.row.jiliangdanwei : ''} + + ) + } + }, + { + label: '顺序号', + width: 120, + prop: 'shunxuhao' + } + ] } - ], - materialList: [], - associateFenlei: '', - fenleiList: [] + ] } }, watch: { @@ -844,6 +977,8 @@ export default { this.getUserName() this.getList() this.getFenlei() + this.getCangkuList() + this.getParaOptions() }, mounted() { this.calcTableHeight() @@ -964,8 +1099,7 @@ export default { closeCreateModal() { this.showCreateModal = false this.createForm = { - material_id: '', - material_name: '', + selectedInventoryIds: [], planned_maintenance_date: '', end_date: '', content: '' @@ -1022,7 +1156,7 @@ export default { if (res) { this.$Message.success('删除成功') this.getList() - } + } }, completeMaintenance(item) { this.showModal = true @@ -1237,8 +1371,10 @@ export default { if (!valid) { return } + // 将选中的物资ID以逗号分隔 + const inventorysId = this.createForm.selectedInventoryIds.join(',') const data = { - material_info_id: this.createForm.material_id, + inventorys_id: inventorysId, planned_maintenance_date: this.formatDate(this.createForm.planned_maintenance_date), end_date: this.formatDate(this.createForm.end_date), content: this.createForm.content @@ -1254,78 +1390,264 @@ export default { } }, openMaterialModal() { - this.showMaterialModal = true + this.materialModal.visible = true + this.materialModal.pageIndex = 1 + // 如果已有选中的物资,恢复选中状态 + if (this.createForm.selectedInventoryIds && this.createForm.selectedInventoryIds.length > 0) { + this.materialModal.selectedMaterialIds = new Set( + this.createForm.selectedInventoryIds.map(id => String(id)) + ) + // 恢复选中物资的详细数据 + this.createForm.selectedInventoryIds.forEach(id => { + if (!this.materialModal.selectedMaterialData.has(String(id))) { + this.materialModal.selectedMaterialData.set(String(id), { + id: null, + inventorys_id: id + }) + } + }) + } else { + this.materialModal.selectedMaterialIds = new Set() + this.materialModal.selectedMaterialData = new Map() + } this.getFenlei() this.searchMaterials() }, async searchMaterials() { + this.materialModal.loading = true + this.materialModal.isInitialLoad = true try { - const data = { - page_size: this.materialPageSize, - page: this.materialPageIndex, - 'show_relation[0]': 'equipmentMaintainConfig', - 'show_relation[1]': 'materialInfo.materialstorage', - - 'filter[0][key]': 'zichanmingcheng', - 'filter[0][op]': 'like', - 'filter[0][value]': this.materialSearch ? this.materialSearch : '' - - // 'filter[1][key]': 'wuzileixing', - // 'filter[1][op]': 'eq', - // 'filter[1][value]': '一物一码' - } - // 如果选择了分类,添加分类筛选 - if (this.associateFenlei) { - data['filter[2][key]'] = 'fenlei' - data['filter[2][op]'] = 'eq' - data['filter[2][value]'] = this.associateFenlei - } - const res = await request({ - url: '/api/admin/material-infos/index', - method: 'post', - data: qs.stringify(data), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - } + const res = await index({ + page_size: this.materialModal.pageSize, + page: this.materialModal.pageIndex, + table_name: 'inventorys', + sort_type: 'DESC', + sort_name: 'wuzibianma', + fenlei: this.materialModal.fenlei, + wuzizhuangtai: this.materialModal.wuzizhuangtai, + chanquanxinxi: this.materialModal.chanquanxinxi, + chubeifangshi: this.materialModal.chubeifangshi, + suozaicangku: this.materialModal.suozaicangku, + start_rukuriqi: this.materialModal.rukuriqi ? this.materialModal.rukuriqi[0] : '', + end_rukuriqi: this.materialModal.rukuriqi ? this.materialModal.rukuriqi[1] : '', + start_shengchanriqi: this.materialModal.shengchanriqi + ? this.materialModal.shengchanriqi[0] + : '', + end_shengchanriqi: this.materialModal.shengchanriqi + ? this.materialModal.shengchanriqi[1] + : '', + dengjifenlei: this.materialModal.dengjifenlei, + filter: [ + { + key: 'zichanmingcheng', + op: 'like', + value: this.materialModal.keyword + } + ] }) - if (res && res.data) { - this.materialList = res.data.map(material => ({ - ...material, - selected: false - })) - this.materialTotal = res.total + + if (res && res.list) { + this.materialList = res.list.data.map(item => { + const itemId = String(item.id) + const isSelected = this.materialModal.selectedMaterialIds.has(itemId) + return { + ...item, + selected: isSelected, + _checked: isSelected, + checked: isSelected + } + }) + this.materialModal.total = res.list.total + + // 强制重新渲染表格 + this.materialModal.tableKey++ + + // 手动设置表格的选中状态 + this.$nextTick(() => { + setTimeout(() => { + this.updateTableSelection() + }, 100) + }) } } catch (e) { console.error('获取物资列表失败:', e) this.$Message.error('获取物资列表失败') + } finally { + this.materialModal.loading = false } }, - selectMaterial(row) { - this.createForm.material_id = row.id - this.createForm.material_name = row.zichanmingcheng - this.showMaterialModal = false + selectMaterial() { + // 获取选中的物资ID + const selectedIds = Array.from(this.materialModal.selectedMaterialIds) + if (selectedIds.length === 0) { + this.$Message.warning('请至少选择一个物资') + return + } + // 保存选中的物资ID列表(转换为数字数组) + this.createForm.selectedInventoryIds = selectedIds.map(id => parseInt(id, 10)) + this.handleMaterialModalClose() }, - handleMaterialSubmit() { - this.showMaterialModal = false + isSelected(item) { + const itemId = String(item.id) + return this.materialModal.selectedMaterialIds.has(itemId) + }, + async toggleMaterialSelection(item, index) { + const itemId = String(item.id) + + if (!this.isSelected(item)) { + this.materialModal.selectedMaterialIds.add(itemId) + this.materialModal.selectedMaterialData.set(itemId, { + id: null, + inventorys_id: item.id + }) + item.selected = true + } else { + this.materialModal.selectedMaterialIds.delete(itemId) + this.materialModal.selectedMaterialData.delete(itemId) + item.selected = false + } + + this.$nextTick(() => { + this.updateTableSelection() + }) }, - handleMaterialCancel() { - this.showMaterialModal = false + selectionChange(e) { + if (this.materialModal.isUpdatingSelection) { + return + } + + const currentPageIds = this.materialList.map(item => String(item.id)) + + // 从选中集合中移除当前页面的所有ID + currentPageIds.forEach(id => { + this.materialModal.selectedMaterialIds.delete(id) + }) + + // 添加新选中的项(来自当前页面) + e.forEach(item => { + const itemId = String(item.id) + this.materialModal.selectedMaterialIds.add(itemId) + if (!this.materialModal.selectedMaterialData.has(itemId)) { + this.materialModal.selectedMaterialData.set(itemId, { + id: null, + inventorys_id: item.id + }) + } + }) + + // 更新当前页面数据的selected状态 + this.materialList.forEach(item => { + const itemId = String(item.id) + item.selected = this.materialModal.selectedMaterialIds.has(itemId) + }) + }, + getSelectedRows() { + return this.materialList.filter(item => + this.materialModal.selectedMaterialIds.has(String(item.id)) + ) + }, + getSelectedMaterialsText() { + const count = this.createForm.selectedInventoryIds ? this.createForm.selectedInventoryIds.length : 0 + if (count === 0) { + return '' + } + return `已选择 ${count} 个物资` + }, + updateTableSelection(retryCount = 0) { + let table = null + + if (this.$refs.materialTable) { + if (this.$refs.materialTable.$refs && this.$refs.materialTable.$refs.table) { + table = this.$refs.materialTable.$refs.table + } else if (this.$refs.materialTable.$children && this.$refs.materialTable.$children.length > 0) { + for (const child of this.$refs.materialTable.$children) { + if (child.$refs && child.$refs.table) { + table = child.$refs.table + break + } + if (child.$children && child.$children.length > 0) { + for (const grandChild of child.$children) { + if (grandChild.$refs && grandChild.$refs.table) { + table = grandChild.$refs.table + break + } + } + if (table) break + } + } + } + } + + if (table && typeof table.clearSelection === 'function') { + this.materialModal.isUpdatingSelection = true + table.clearSelection() + + this.materialList.forEach(row => { + const rowId = String(row.id) + if (this.materialModal.selectedMaterialIds.has(rowId)) { + table.toggleRowSelection(row, true) + } + }) + + setTimeout(() => { + this.materialModal.isUpdatingSelection = false + }, 200) + } else { + if (retryCount < 3) { + setTimeout(() => { + this.updateTableSelection(retryCount + 1) + }, 500) + } + } }, handleMaterialPageChange(page) { - this.materialPageIndex = page + this.materialModal.pageIndex = page this.searchMaterials() }, handleMaterialPageSizeChange(size) { - this.materialPageSize = size - this.materialPageIndex = 1 + this.materialModal.pageSize = size + this.materialModal.pageIndex = 1 this.searchMaterials() }, resetMaterialSearch() { - this.materialSearch = '' - this.associateFenlei = '' - this.materialPageIndex = 1 + this.materialModal.keyword = '' + this.materialModal.fenlei = '' + this.materialModal.wuzizhuangtai = '' + this.materialModal.chanquanxinxi = '' + this.materialModal.chubeifangshi = '' + this.materialModal.suozaicangku = '' + this.materialModal.rukuriqi = '' + this.materialModal.shengchanriqi = '' + this.materialModal.dengjifenlei = '' + this.materialModal.pageIndex = 1 this.searchMaterials() }, + handleMaterialModalClose() { + this.materialModal.visible = false + this.materialModal.selectedMaterialIds = new Set() + this.materialModal.selectedMaterialData = new Map() + this.materialModal.pageIndex = 1 + this.materialModal.keyword = '' + this.materialModal.fenlei = '' + this.materialModal.wuzizhuangtai = '' + this.materialModal.chanquanxinxi = '' + this.materialModal.chubeifangshi = '' + this.materialModal.suozaicangku = '' + this.materialModal.rukuriqi = '' + this.materialModal.shengchanriqi = '' + this.materialModal.dengjifenlei = '' + this.materialModal.isUpdatingSelection = false + this.materialModal.tableKey = 0 + this.materialList = [] + this.materialModal.total = 0 + }, + changeFenlei(e) { + if (e) { + this.materialModal.fenlei = e[e.length - 1] + } else { + this.materialModal.fenlei = '' + } + }, async getWarehouseAreas() { try { @@ -1389,11 +1711,41 @@ export default { this.$Message.error('获取分类列表失败') } }, - changeAssociateFenlei(e) { - if (e) { - this.associateFenlei = e[e.length - 1] - } else { - this.associateFenlei = '' + async getCangkuList() { + try { + const res = await baseFormIndex({ + table_name: 'materialstorages', + page_size: 9999 + }) + if (res && res.data) { + this.cangkuList = res.data + } + } catch (e) { + console.error('获取仓库列表失败:', e) + } + }, + async getParaOptions() { + try { + const [statusRes, reserveRes, propertyRes, levelRes] = await Promise.all([ + getparameteritemMore('materials_status'), + getparameteritemMore('material_reserve'), + getparameteritemMore('materials_property'), + getparameteritemMore('materials_level') + ]) + if (statusRes && statusRes.detail) { + this.paraOptions.materials_status = statusRes.detail + } + if (reserveRes && reserveRes.detail) { + this.paraOptions.material_reserve = reserveRes.detail + } + if (propertyRes && propertyRes.detail) { + this.paraOptions.materials_property = propertyRes.detail + } + if (levelRes && levelRes.detail) { + this.paraOptions.materials_level = levelRes.detail + } + } catch (e) { + console.error('获取参数选项失败:', e) } }, removeEmptyChildren(node) { @@ -1455,8 +1807,8 @@ export default { 'filter[2][key]': 'end_date', 'filter[2][op]': 'range', 'filter[2][value]': this.select.end_date_start - ? this.formatDate(this.select.end_date_start) + - ',' + + ? this.formatDate(this.select.end_date_start) + + ',' + this.formatDate(this.select.end_date_end) : '', 'filter[3][key]': 'maintenance_date', 'filter[3][op]': 'range', @@ -1922,4 +2274,66 @@ hr { border-top: 1px solid #eaeaea; text-align: center; } + +.selector-item { + margin-right: 10px; + margin-bottom: 10px; + flex: 0 0 auto; +} + +/* 打印样式 */ +@media print { + /* 确保打印时保持两列布局 - #printmodal 本身就是 modal-body */ + #printmodal { + display: grid !important; + grid-template-columns: 1fr 1fr !important; + gap: 16px 32px !important; + padding: 0 !important; + width: 100% !important; + height: auto !important; + overflow: visible !important; + } + + /* 确保表单组在打印时正常显示 */ + #printmodal .form-group { + display: flex !important; + flex-direction: column !important; + page-break-inside: avoid; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + background: #fff !important; + border: 1px solid #333 !important; + } + + /* 隐藏不需要打印的元素 */ + .ivu-modal-header, + .ivu-modal-footer, + .ivu-modal-mask, + .ivu-modal-wrap::before { + display: none !important; + } + + /* 确保图片在打印时正常显示 */ + #printmodal .photo-preview, + #printmodal .sign-preview { + max-width: 100% !important; + height: auto !important; + } + + /* 确保打印时所有内容可见 */ + body * { + visibility: hidden; + } + + #printmodal, + #printmodal * { + visibility: visible; + } + + #printmodal { + position: absolute; + left: 0; + top: 0; + } +}