| | |
| | | // 上传前校检格式和大小 |
| | | function handleBeforeUpload(file) { |
| | | // 校检文件类型 |
| | | if (props.fileType.length) { |
| | | const fileName = file.name.split('.') |
| | | const fileExt = fileName[fileName.length - 1] |
| | | const isTypeOk = props.fileType.indexOf(fileExt) >= 0 |
| | | if (!isTypeOk) { |
| | | proxy.$modal.msgError(`文件格式不正确,请上传${props.fileType.join("/")}格式文件!`) |
| | | return false |
| | | } |
| | | } |
| | | // if (props.fileType.length) { |
| | | // const fileName = file.name.split('.') |
| | | // const fileExt = fileName[fileName.length - 1] |
| | | // const isTypeOk = props.fileType.indexOf(fileExt) >= 0 |
| | | // if (!isTypeOk) { |
| | | // proxy.$modal.msgError(`文件格式不正确,请上传${props.fileType.join("/")}格式文件!`) |
| | | // return false |
| | | // } |
| | | // } |
| | | // 校检文件名是否包含特殊字符 |
| | | if (file.name.includes(',')) { |
| | | proxy.$modal.msgError('文件名不正确,不能包含英文逗号!') |
| | |
| | | .upload-file-uploader { |
| | | margin-bottom: 5px; |
| | | } |
| | | .upload-file-list { |
| | | margin-top: 10px; |
| | | max-height: 150px; |
| | | overflow-y: auto; |
| | | } |
| | | .upload-file-list .el-upload-list__item { |
| | | border: 1px solid #e4e7ed; |
| | | line-height: 2; |
| | |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | color: inherit; |
| | | max-height: 20px; |
| | | } |
| | | .ele-upload-list__item-content-action .el-link { |
| | | margin-right: 10px; |
| | | } |
| | | .el-icon-document{ |
| | | padding-left: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <el-table v-loading="loading" :data="tableData" :border="border" :show-selection="showSelection" :max-height="maxHeight" |
| | | :header-cell-style="{ background: '#EBEEF5', color: '#3D3D3D' }" @selection-change="handleSelectionChange" |
| | | @row-click="handleRowClick" @row-dblclick="handleRowDblClick" @cell-click="handleCellClick" :max-width="maxWidth" |
| | | @export="handleExport"> |
| | | <el-table-column v-if="showSelection" type="selection" width="55" align="center" /> <el-table-column v-if="showIndex" label="序号" type="index" width="60" align="center" /> |
| | | <template> <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | :border="border" |
| | | :show-selection="showSelection" |
| | | :max-height="maxHeight" |
| | | :header-cell-style="{ background: '#EBEEF5', color: '#3D3D3D' }" |
| | | @selection-change="handleSelectionChange" |
| | | @row-click="handleRowClick" |
| | | @row-dblclick="handleRowDblClick" |
| | | @cell-click="handleCellClick" |
| | | :max-width="maxWidth" |
| | | @export="handleExport" |
| | | :default-selection="defaultSelection" |
| | | :show-overflow-tooltip="showOverflowTooltip" |
| | | ref="tableRef" |
| | | :row-key="rowKey" |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column v-if="showSelection" type="selection" width="55" align="center" /> |
| | | <el-table-column v-if="showIndex" label="序号" type="index" width="60" align="center" /> |
| | | <template v-for="col in columns" :key="col.prop"> |
| | | <el-table-column v-bind="col" :show-overflow-tooltip="shouldShowTooltip(col, tableData)" |
| | | :formatter="col.formatter || defaultFormatter" align="center"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { defineEmits } from 'vue' |
| | | import { defineEmits, ref , defineProps, onMounted ,defineExpose, watch, nextTick} from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | const props = defineProps({ |
| | | // 最大宽度 |
| | |
| | | operations: { |
| | | type: Array, |
| | | default: () => ['edit', 'delete', 'export'] |
| | | }, |
| | | // 删除确认信息 |
| | | }, // 删除确认信息 |
| | | deleteConfirmText: { |
| | | type: String, |
| | | default: '确认删除该记录?' |
| | | }, |
| | | // 默认选中的行 ID 数组 |
| | | defaultSelectedIds: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | // 行唯一标识字段名(默认为 id) |
| | | rowKey: { |
| | | type: String, |
| | | default: 'id' |
| | | }, |
| | | showOverflowTooltip: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }) |
| | | const tableRef = ref(null) |
| | | // 检查列是否需要显示tooltip |
| | | const shouldShowTooltip = (col, data) => { |
| | | // 如果列配置中明确设置了showOverflowTooltip,使用该设置 |
| | |
| | | const handleExport = (row) => { |
| | | emit('export', row) |
| | | } |
| | | |
| | | // 正确的 toggleRowSelection 方法:针对单行 |
| | | const toggleRowSelection = (row, selected) => { |
| | | if (tableRef.value && row) { |
| | | tableRef.value.toggleRowSelection(row, selected); |
| | | } |
| | | }; |
| | | |
| | | // 批量设置行选中状态的方法 |
| | | const setRowsSelection = (rows, selected = true) => { |
| | | if (tableRef.value && Array.isArray(rows)) { |
| | | rows.forEach((row) => { |
| | | tableRef.value.toggleRowSelection(row, selected); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // 复选框默认选中状态 |
| | | const defaultSelection = ref([]) |
| | | // 设置默认选中状态 |
| | | const setDefaultSelection = () => { |
| | | if (!tableRef.value || !props.defaultSelectedIds.length || !props.tableData.length) { |
| | | return; |
| | | } |
| | | |
| | | |
| | | // 延迟执行,确保表格完全渲染 |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | try { |
| | | tableRef.value.clearSelection(); |
| | | const rowsToSelect = props.tableData.filter(row => { |
| | | const rowId = row[props.rowKey]; |
| | | return props.defaultSelectedIds.includes(rowId); |
| | | }); |
| | | rowsToSelect.forEach(row => { |
| | | tableRef.value.toggleRowSelection(row, true); |
| | | }); |
| | | } catch (error) { |
| | | } |
| | | }, 100); |
| | | }); |
| | | }; |
| | | |
| | | // 监听数据变化,自动设置默认选中 |
| | | watch(() => [props.tableData, props.defaultSelectedIds], () => { |
| | | if (props.tableData.length > 0 && props.defaultSelectedIds.length > 0) { |
| | | setDefaultSelection(); |
| | | } |
| | | }, { |
| | | deep: true, |
| | | immediate: true |
| | | }); |
| | | |
| | | // 组件挂载后设置默认选中 |
| | | onMounted(() => { |
| | | if (props.defaultSelectedIds.length > 0) { |
| | | setDefaultSelection(); |
| | | } |
| | | }); |
| | | |
| | | // 暴露 el-table 的实例和常用方法 |
| | | defineExpose({ |
| | | // 单行选中/取消选中 |
| | | toggleRowSelection, |
| | | // 批量设置行选中状态 |
| | | setRowsSelection, |
| | | // 根据ID数组选中行 |
| | | setDefaultSelection, |
| | | // 清除所有选中 |
| | | clearSelection: () => tableRef.value?.clearSelection(), |
| | | // 获取选中的行 |
| | | getSelectionRows: () => tableRef.value?.getSelectionRows() || [], |
| | | // 设置当前行 |
| | | setCurrentRow: (row) => tableRef.value?.setCurrentRow(row), |
| | | // 获取表格实例(如需直接操作) |
| | | getTableRef: () => tableRef.value |
| | | }); |
| | | |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <template> |
| | | <el-table v-loading="loading" :data="tableData" :border="border" :show-selection="showSelection" :height="height" :max-height="maxHeight" |
| | | :header-cell-style="{ background: '#EBEEF5', color: '#3D3D3D' }" @selection-change="handleSelectionChange" |
| | | @row-click="handleRowClick" @row-dblclick="handleRowDblClick" :row-class-name="tableRowClassName" @cell-click="handleCellClick" :max-width="maxWidth" |
| | | @export="handleExport"> |
| | | <el-table-column v-if="showSelection" type="selection" width="55" align="center" /> |
| | | <el-table-column v-if="showIndex" label="序号" type="index" width="60" align="center" /> <template |
| | | v-for="col in columns" :key="col.prop"> |
| | | <el-table-column v-bind="col" :show-overflow-tooltip="shouldShowTooltip(col, tableData)" align="center"> <template |
| | | #default="scope"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | :border="border" |
| | | :show-selection="showSelection" |
| | | :height="height" |
| | | :max-height="maxHeight" |
| | | :header-cell-style="{ background: '#EBEEF5', color: '#3D3D3D' }" |
| | | @selection-change="handleSelectionChange" |
| | | @row-click="handleRowClick" |
| | | @row-dblclick="handleRowDblClick" |
| | | :row-class-name="tableRowClassName" |
| | | @cell-click="handleCellClick" |
| | | :max-width="maxWidth" |
| | | @export="handleExport" |
| | | :show-overflow-tooltip="showOverflowTooltip" |
| | | > |
| | | <el-table-column |
| | | v-if="showSelection" |
| | | type="selection" |
| | | width="55" |
| | | align="center" |
| | | /> |
| | | <el-table-column |
| | | v-if="showIndex" |
| | | label="序号" |
| | | type="index" |
| | | width="60" |
| | | align="center" |
| | | /> |
| | | <template v-for="col in columns" :key="col.prop"> |
| | | <el-table-column |
| | | v-bind="col" |
| | | :show-overflow-tooltip="shouldShowTooltip(col, tableData)" |
| | | align="center" |
| | | > |
| | | <template #default="scope"> |
| | | <template v-if="col.slot"> |
| | | <slot></slot> |
| | | </template> |
| | | <template v-else> |
| | | <div class="cell-edit" @dblclick="handleCellEdit(scope.row, col.prop)" |
| | | :class="{'editable': isColumnEditable(col.prop)}"> <span |
| | | v-if="!scope.row.editing || !scope.row.editing[col.prop]" class="cell-text"> |
| | | {{ scope.row[col.prop] == null || scope.row[col.prop] === '' ? '--' : scope.row[col.prop] }} |
| | | <div |
| | | class="cell-edit" |
| | | @dblclick="handleCellEdit(scope.row, col.prop)" |
| | | :class="{ editable: isColumnEditable(col.prop) }" |
| | | > |
| | | <span |
| | | v-if="!scope.row.editing || !scope.row.editing[col.prop]" |
| | | class="cell-text" |
| | | > |
| | | {{ |
| | | scope.row[col.prop] == null || scope.row[col.prop] === "" |
| | | ? "--" |
| | | : scope.row[col.prop] |
| | | }} |
| | | </span> |
| | | <el-input v-else v-model="scope.row[col.prop]" size="small" |
| | | @focus="handleCellFocus(scope.row, col.prop, $event)" @blur="handleCellSave(scope.row, col.prop)" |
| | | @keyup.enter="handleCellSave(scope.row, col.prop)" class="cell-input" /> |
| | | <el-input |
| | | v-else |
| | | v-model="scope.row[col.prop]" |
| | | size="small" |
| | | @focus="handleCellFocus(scope.row, col.prop, $event)" |
| | | @blur="handleCellSave(scope.row, col.prop)" |
| | | @keyup.enter="handleCellSave(scope.row, col.prop)" |
| | | class="cell-input" |
| | | /> |
| | | </div> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | <!-- 操作列 --> |
| | | <el-table-column v-if="showOperations" :label="operationsLabel" :width="operationsWidth" fixed="right" align="center"> |
| | | <el-table-column |
| | | v-if="showOperations" |
| | | :label="operationsLabel" |
| | | :width="operationsWidth" |
| | | fixed="right" |
| | | align="center" |
| | | > |
| | | <template #default="scope"> |
| | | <slot name="operations" :row="scope.row"> |
| | | <el-button v-if="operations.includes('edit')" link type="primary" size="small" |
| | | @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button |
| | | v-if="operations.includes('edit')" |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="handleEdit(scope.row)" |
| | | >编辑</el-button |
| | | > |
| | | <!-- <el-button--> |
| | | <!-- v-if="operations.includes('delete')"--> |
| | | <!-- link--> |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { defineEmits, nextTick } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| | | <script setup> |
| | | import { defineEmits, nextTick } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | const props = defineProps({ |
| | | // 获取行样式 |
| | | tableRowClassName: { |
| | | type: Function, |
| | | default: () => '' |
| | | default: () => "", |
| | | }, |
| | | // 获取高度 |
| | | height: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | default: "auto", |
| | | }, |
| | | // 是否允许编辑单元格 |
| | | editableCells: { |
| | | type: Boolean, |
| | | default: true |
| | | default: true, |
| | | }, |
| | | // 指定可编辑的列,如果为空数组则表示所有列都不可编辑 |
| | | editableColumns: { |
| | | type: Array, |
| | | default: () => [] |
| | | default: () => [], |
| | | }, |
| | | // 最大宽度 |
| | | maxWidth: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | default: "auto", |
| | | }, |
| | | handleCellClick: { |
| | | type: Function, |
| | | default: () => { } |
| | | default: () => {}, |
| | | }, |
| | | handleRowClick: { |
| | | type: Function, |
| | | default: () => { } |
| | | default: () => {}, |
| | | }, |
| | | handleExport: { |
| | | type: Function, |
| | | default: () => { } |
| | | default: () => {}, |
| | | }, |
| | | handleRowDblClick: { |
| | | type: Function, |
| | | default: () => { } |
| | | default: () => {}, |
| | | }, |
| | | // 高度 |
| | | maxHeight: { |
| | | type: [String, Number], |
| | | default: 'auto' |
| | | default: "auto", |
| | | }, |
| | | // 加载状态 |
| | | loading: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | // border |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | // 表格数据 |
| | | tableData: { |
| | | type: Array, |
| | | default: () => [] |
| | | default: () => [], |
| | | }, |
| | | // 是否显示选择列 |
| | | showSelection: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | // 是否显示序号列 |
| | | showIndex: { |
| | | type: Boolean, |
| | | default: true |
| | | default: true, |
| | | }, |
| | | // 列配置 |
| | | columns: { |
| | | type: Array, |
| | | default: () => [] |
| | | default: () => [], |
| | | }, |
| | | // 是否显示操作列 |
| | | showOperations: { |
| | | type: Boolean, |
| | | default: true |
| | | default: true, |
| | | }, |
| | | // 操作列标签 |
| | | operationsLabel: { |
| | | type: String, |
| | | default: '操作' |
| | | default: "操作", |
| | | }, |
| | | // 操作列宽度 |
| | | operationsWidth: { |
| | | type: [String, Number], |
| | | default: 100 |
| | | default: 100, |
| | | }, |
| | | // 显示哪些操作按钮 |
| | | operations: { |
| | | type: Array, |
| | | default: () => ['edit', 'delete', 'export'] |
| | | default: () => ["edit", "delete", "export"], |
| | | }, |
| | | // 删除确认信息 |
| | | deleteConfirmText: { |
| | | type: String, |
| | | default: '确认删除该记录?' |
| | | } |
| | | }) |
| | | default: "确认删除该记录?", |
| | | }, |
| | | showOverflowTooltip: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | }); |
| | | // 检查列是否需要显示tooltip |
| | | const shouldShowTooltip = (col, data) => { |
| | | // 如果没有prop,直接返回false |
| | | if (!col.prop) return false; |
| | | // 检查该列在所有数据中是否有非空值 |
| | | return data.some(row => row[col.prop] != null && row[col.prop] !== ''); |
| | | return data.some((row) => row[col.prop] != null && row[col.prop] !== ""); |
| | | }; |
| | | |
| | | // 处理单元格编辑 |
| | |
| | | if (!props.editableCells) return; |
| | | |
| | | // 如果指定了可编辑列,且当前列不在可编辑列中,则不允许编辑 |
| | | if (props.editableColumns.length > 0 && !props.editableColumns.includes(prop)) return; |
| | | if (props.editableColumns.length > 0 && !props.editableColumns.includes(prop)) |
| | | return; |
| | | |
| | | // 初始化editing对象 |
| | | if (!row.editing) { |
| | |
| | | |
| | | // 在下一个DOM更新周期,让输入框获得焦点并选中内容 |
| | | setTimeout(() => { |
| | | const inputElement = document.querySelector('.cell-edit .el-input__inner'); |
| | | const inputElement = document.querySelector(".cell-edit .el-input__inner"); |
| | | if (inputElement) { |
| | | inputElement.focus(); |
| | | inputElement.select(); |
| | | } |
| | | }, 10); |
| | | } |
| | | }; |
| | | |
| | | // 处理单元格保存 |
| | | const handleCellSave = (row, prop) => { |
| | | // 关闭编辑状态 |
| | | row.editing[prop] = false; |
| | | // 触发单元格编辑完成事件 |
| | | emit('cell-edit', row, prop, row[prop]); |
| | | } |
| | | emit("cell-edit", row, prop, row[prop]); |
| | | }; |
| | | // 处理单元格聚焦事件 |
| | | const handleCellFocus = (row, prop, event) => { |
| | | // 如果不允许编辑单元格,直接返回 |
| | | if (!props.editableCells) return; |
| | | |
| | | // 如果指定了可编辑列,且当前列不在可编辑列中,则不允许编辑 |
| | | if (props.editableColumns.length > 0 && !props.editableColumns.includes(prop)) return; |
| | | if (props.editableColumns.length > 0 && !props.editableColumns.includes(prop)) |
| | | return; |
| | | |
| | | // 初始化editing对象 |
| | | if (!row.editing) { |
| | |
| | | if (event && event.target) { |
| | | event.target.select(); |
| | | } |
| | | } |
| | | }; |
| | | // 判断列是否可编辑 |
| | | const isColumnEditable = (prop) => { |
| | | if (props.editableColumns.length === 0) { |
| | | return props.editableCells; |
| | | } |
| | | return props.editableColumns.includes(prop); |
| | | } |
| | | }; |
| | | |
| | | // 处理选择变化、编辑、删除和导出操作 |
| | | const emit = defineEmits(['selection-change', 'edit', 'delete', 'export', 'cell-edit']) |
| | | const emit = defineEmits([ |
| | | "selection-change", |
| | | "edit", |
| | | "delete", |
| | | "export", |
| | | "cell-edit", |
| | | ]); |
| | | const handleSelectionChange = (selection) => { |
| | | emit('selection-change', selection) |
| | | } |
| | | emit("selection-change", selection); |
| | | }; |
| | | const handleEdit = (row) => { |
| | | emit('edit', row) |
| | | } |
| | | emit("edit", row); |
| | | }; |
| | | const handleExport = (row) => { |
| | | emit('export', row) |
| | | } |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | emit("export", row); |
| | | }; |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .el-table { |
| | | margin: 20px 0 !important; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | } |
| | | |
| | | :deep(.cell-edit) { |
| | | margin: 20px 0 !important; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | } |
| | | |
| | | :deep(.cell-edit) { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | } |
| | | |
| | | :deep(.cell-edit .cell-text) { |
| | | width: 100%; |
| | | display: block; |
| | | } |
| | | |
| | | :deep(.cell-edit.editable:hover .cell-text) { |
| | | color: #409eff; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | :deep(.cell-input) { |
| | | width: 80%; |
| | | max-width: 120px; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | :deep(.cell-input .el-input__inner) { |
| | | border-radius: 4px; |
| | | text-align: center; |
| | | transition: all 0.2s; |
| | | } |
| | | |
| | | /* 响应式样式 */ |
| | | @media screen and (max-width: 768px) { |
| | | :deep(.el-table) { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | overflow-x: auto; |
| | | } |
| | | |
| | | :deep(.cell-edit .cell-text) { |
| | | width: 100%; |
| | | display: block; |
| | | } |
| | | |
| | | :deep(.cell-edit.editable:hover .cell-text) { |
| | | color: #409EFF; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | :deep(.cell-input) { |
| | | width: 80%; |
| | | max-width: 120px; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | :deep(.cell-input .el-input__inner) { |
| | | border-radius: 4px; |
| | | text-align: center; |
| | | transition: all 0.2s; |
| | | } |
| | | |
| | | |
| | | /* 响应式样式 */ |
| | | @media screen and (max-width: 768px) { |
| | | :deep(.el-table) { |
| | | width: 100%; |
| | | overflow-x: auto; |
| | | } |
| | | } |
| | | </style> |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <el-dialog v-model="centerDialogVisible" title="Warning" width="500" center> |
| | | <el-dialog v-model="centerDialogVisible" title="文档管理" width="500" center> |
| | | <el-form |
| | | ref="ruleFormRef" |
| | | style="max-width: 600px" |
| | |
| | | label-width="auto" |
| | | > |
| | | <el-form-item label="名称" prop="name"> |
| | | <el-input v-model="ruleForm.name" placeholder="请输入文档名称"/> |
| | | <el-input v-model="ruleForm.name" placeholder="请输入文档名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="请输入文档类型" prop="type"> |
| | | <el-select v-model="ruleForm.type" placeholder="请输入文档类型"> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="请输入文档状态" prop="status"> |
| | | <el-select v-model="ruleForm.status" placeholder="请输入文档状态"> |
| | | <el-option v-for="option in options" :key="option.value" :label="option.label" :value="option.value" /> |
| | | <el-option |
| | | v-for="option in options" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="centerDialogVisible = false">Cancel</el-button> |
| | | <el-button type="primary" @click="submit"> |
| | | Confirm |
| | | </el-button> |
| | | </div> |
| | | <el-row> |
| | | <el-col :span="24" style="text-align: right"> |
| | | <el-button @click="centerDialogVisible = false">取 消</el-button> |
| | | <el-button type="primary" @click="submit"> 确 定 </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </template> |
| | | <fileUpload |
| | | v-model="ruleForm.file" |
| | | :fileSize="1024" |
| | | :fileType="['pdf', 'docx', 'txt', 'xlsx', 'pptx....']" |
| | | :limit="10" |
| | | /> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, watch } from "vue"; |
| | | import { addOrEditArchive } from "@/api/archiveManagement" |
| | | import { addOrEditArchive } from "@/api/archiveManagement"; |
| | | import fileUpload from "@/components/FileUpload/index.vue"; |
| | | |
| | | const centerDialogVisible = defineModel("centerDialogVisible", { |
| | | type: Boolean, |
| | |
| | | // 初始化表单数据 |
| | | const ruleFormRef = ref(null); |
| | | const ruleForm = ref(initFormData(props.row)); |
| | | const copyForm = ref() |
| | | const copyForm = ref(); |
| | | // 监听 row 的变化,更新 ruleForm |
| | | watch(() => props.row, (newRow) => { |
| | | copyForm.value = initFormData(newRow); |
| | | ruleForm.value = JSON.parse(JSON.stringify(copyForm.value)); |
| | | }, { deep: true }); |
| | | watch( |
| | | () => props.row, |
| | | (newRow) => { |
| | | copyForm.value = initFormData(newRow); |
| | | ruleForm.value = JSON.parse(JSON.stringify(copyForm.value)); |
| | | }, |
| | | { deep: true } |
| | | ); |
| | | const rules = { |
| | | name: [ |
| | | { required: true, message: "Please input activity name", trigger: "blur" }, |
| | | ], |
| | | type: [ |
| | | { required: true, message: "Please select activity zone", trigger: "change" }, |
| | | ], |
| | | status: [ |
| | | { required: true, message: "Please select activity count", trigger: "change" }, |
| | | ], |
| | | name: [{ required: true, message: "请输入文档名称", trigger: "blur" }], |
| | | type: [{ required: true, message: "请选择文档类型", trigger: "blur" }], |
| | | status: [{ required: true, message: "请选择文档状态", trigger: "blur" }], |
| | | }; |
| | | |
| | | const options = [ |
| | |
| | | const submit = async () => { |
| | | // 验证表单 |
| | | if (!ruleFormRef.value) return; |
| | | |
| | | |
| | | try { |
| | | const valid = await ruleFormRef.value.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | |
| | | // 调用 API |
| | | let res = await addOrEditArchive(ruleForm.value); |
| | | console.log("API 响应:", res); |
| | | |
| | | |
| | | // 发送 emit 事件 |
| | | emit("submitForm", res); |
| | | console.log("emit submitForm 已发送"); |
| | | |
| | | |
| | | // 关闭对话框 |
| | | centerDialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error("表单验证失败或API调用失败:", error); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped></style> |
| | |
| | | <el-table-column label="煤种" min-width="120" > |
| | | <template #default="{ row, $index }" > |
| | | <el-input |
| | | v-model="row.coalType" |
| | | v-model="row.coal" |
| | | placeholder="请输入煤种" |
| | | @input="handleInput('coalType', $index, $event)" |
| | | @input="handleInput('coal', $index, $event)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | calculateTotalCost, |
| | | addRow: (rowData = {}) => { |
| | | const defaultRow = { |
| | | coalType: '', |
| | | coal: '', |
| | | calorificValue: '', |
| | | productionQuantity: '', |
| | | laborCost: '', |
| | |
| | | // 表格数据 |
| | | const tableData = ref([ |
| | | { |
| | | coalType: '动力煤', |
| | | coal: '动力煤', |
| | | calorificValue: '5000', |
| | | productionQuantity: '100', |
| | | laborCost: '1000', |
| | |
| | | const addRow = () => { |
| | | if (tableRef.value) { |
| | | tableRef.value.addRow({ |
| | | coalType: '新煤种', |
| | | coal: '', |
| | | calorificValue: '0', |
| | | productionQuantity: '0', |
| | | laborCost: '0', |
| | |
| | | div<template> |
| | | <template> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? '新增生产加工' : '编辑生产加工'" |
| | |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <el-button type="primary" @click="handlData">选择数据</el-button> |
| | | <ETableModify |
| | | :columns="columns" |
| | | height="200" |
| | | @cell-edit="handleCellEdit" |
| | | :showOperations="false" |
| | | :tableData="tableData" |
| | | @row-click="handleRowClick" |
| | | :editableColumns="['used']" |
| | | /> |
| | | <div class="empty-table"> |
| | | <h1>生产明细</h1> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="2"> |
| | | <el-button type="primary" @click="addNewRow"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | 新增 |
| | | </el-button> |
| | | <el-row :gutter="10" style="margin-bottom: 10px"> |
| | | <el-col :span="3"> |
| | | <el-button type="primary" @click="handlData" |
| | | ><el-icon> |
| | | <Plus /> </el-icon |
| | | >选择数据</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="2"> |
| | | <el-button type="danger" @click="clearAllRows"> |
| | | <el-col :span="4"> |
| | | <el-button |
| | | type="danger" |
| | | @click="removeSelectedData" |
| | | :disabled="tableData.length === 0" |
| | | > |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | 清空 |
| | | 清空已选 |
| | | </el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="2"> |
| | | <el-col :span="17" style="text-align: right; line-height: 32px"> |
| | | <el-text type="info" size="small"> |
| | | 已选择 {{ tableData.length }} 项数据 |
| | | <span v-if="tableData.length > 0"> |
| | | ,总使用量: {{ totalUsedQuantity.toFixed(2) }} |
| | | </span> |
| | | </el-text> |
| | | </el-col> |
| | | </el-row> |
| | | <ETableModify |
| | | :columns="columns" |
| | | :showOperations="false" |
| | | height="200" |
| | | @cell-edit="handleCellEdit" |
| | | :tableData="tableData" |
| | | :showOverflowTooltip="false" |
| | | @row-click="handleRowClick" |
| | | :editableColumns="['usedQuantity']" |
| | | @delete="handleRemoveItem" |
| | | /> |
| | | <div class="empty-table"> |
| | | <h1>生产明细</h1> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="2"> |
| | | <el-button type="primary" @click="addNewRow"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | 新增 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="2"> |
| | | <el-button type="danger" @click="clearAllRows"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | 清空 |
| | | </el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="2"> |
| | | <el-button type="warning" @click="calculateAllCosts"> |
| | | <el-icon> |
| | | <Warning /> |
| | | </el-icon> 重新计算 |
| | | </el-button> |
| | | </el-col> --> |
| | | </el-row> |
| | | <ProductionDetailsTable |
| | | v-model="detailsTableData" |
| | | :border="false" |
| | | :show-operations="true" |
| | | :auto-calculate="true" |
| | | @input-change="handleDetailsChange" |
| | | @delete-row="handleDeleteRow" |
| | | /> |
| | | |
| | | </el-row> |
| | | <ProductionDetailsTable |
| | | v-model="detailsTableData" |
| | | :border="false" |
| | | :show-operations="true" |
| | | :auto-calculate="true" |
| | | @input-change="handleDetailsChange" |
| | | @delete-row="handleDeleteRow" |
| | | /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button @click="handleClose" v-if="dialogType === 'add'" |
| | | >取 消</el-button |
| | | > |
| | | <el-button @click="handleReset" v-if="dialogType === 'edit'" |
| | | >重 置</el-button |
| | | > |
| | | <el-button type="primary" :loading="loading" @click="handleSubmit" |
| | | >确 定</el-button |
| | | > |
| | |
| | | center |
| | | append-to-body |
| | | > |
| | | <div style="margin-bottom: 10px"> |
| | | <el-alert |
| | | v-if="tableData.length > 0" |
| | | :title="`当前已选择 ${tableData.length} 条数据`" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon |
| | | /> |
| | | </div> |
| | | <ETable |
| | | @selection-change="handleSelectionChange" |
| | | :showOperations="false" |
| | | ref="etableRef" |
| | | :columns="formalDatabaseColumns" |
| | | :tableData="formalDatabaseData" |
| | | :defaultSelectedIds="selectedIds" |
| | | :rowKey="'id'" |
| | | height="400" |
| | | @cell-edit="handleCellEdit" |
| | | :show-selection="true" |
| | | /> |
| | | <el-row :gutter="24"> |
| | | <el-col :span="2" :offset="22"> |
| | | <el-button type="primary" @click="handleSelectData">确定</el-button> |
| | | <el-row :gutter="24" style="margin-top: 15px"> |
| | | <el-col :span="12"> |
| | | <el-text type="info"> |
| | | 已选择 {{ formalDatabaseSelectedData.length }} 条数据 |
| | | </el-text> |
| | | </el-col> |
| | | <el-col :span="12" style="text-align: right"> |
| | | <el-button @click="innerVisible = false">取消</el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="handleSelectData" |
| | | :disabled="formalDatabaseSelectedData.length === 0" |
| | | > |
| | | 确定添加 |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, watch } from "vue"; |
| | | import { ref, reactive, watch, onMounted, nextTick, computed } from "vue"; |
| | | import ETable from "@/components/Table/ETable.vue"; |
| | | import ETableModify from "@/components/Table/EtableModify.vue"; |
| | | import ProductionDetailsTable from "./ProductionDetailsTable.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { ElMessage, ElMessageBox, ElAlert, ElText } from "element-plus"; |
| | | import { Delete, Warning, Plus } from "@element-plus/icons-vue"; |
| | | import { getOfficialAll } from "@/api/production/index.js"; |
| | | import { getOfficialAll, addOrEditPM } from "@/api/production/index.js"; |
| | | import { getCurrentInstance } from "vue"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | |
| | | const tableData = ref([]); |
| | | const currentRow = ref(null); |
| | | const columns = [ |
| | | { label: "供应商名称", prop: "supplierName" }, |
| | | { label: "煤种", prop: "coal" }, |
| | | { label: "单价(不含税)", prop: "priceExcludingTax" }, |
| | | { label: "库存数量", prop: "inventoryQuantity" }, |
| | | { label: "煤种", prop: "coal", minwidth: 120 }, |
| | | { label: "库存数量", prop: "inventoryQuantity", minwidth: 100 }, |
| | | { |
| | | label: "使用数量", |
| | | prop: "used", |
| | | prop: "usedQuantity", |
| | | editable: true, |
| | | width: 120, |
| | | minwidth: 120, |
| | | editType: "number", |
| | | }, |
| | | |
| | | ]; |
| | | const detailsTableData = ref([ |
| | | |
| | | ]); |
| | | const etableRef = ref(null); |
| | | const selectedIds = ref([]); // 默认选中的ID数组 |
| | | // 调试函数:验证ID匹配逻辑 |
| | | const debugIdMatching = () => { |
| | | if (formalDatabaseData.value.length > 0 && selectedIds.value.length > 0) { |
| | | const matchedRows = formalDatabaseData.value.filter((row) => |
| | | selectedIds.value.includes(row.id) |
| | | ); |
| | | } |
| | | }; |
| | | const detailsTableData = ref([]); |
| | | const handleRowClick = (row) => { |
| | | currentRow.value = row; |
| | | }; |
| | |
| | | reviewer: "", |
| | | date: "", |
| | | }); |
| | | const handlData =async () => { |
| | | const handlData = async () => { |
| | | innerVisible.value = true; |
| | | let res = await getOfficialAll(); |
| | | console.log("获取配置数据", res); |
| | | if (res.code === 200) { |
| | | formalDatabaseData.value = res.data; |
| | | const existingOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = existingOfficialIds; |
| | | debugIdMatching(); |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | if (etableRef.value && existingOfficialIds.length > 0) { |
| | | etableRef.value.setDefaultSelection(); |
| | | } |
| | | }, 100); |
| | | }); |
| | | } else { |
| | | ElMessage.error("获取配置数据失败"); |
| | | } |
| | | }; |
| | | // 手动设置表格选中状态 |
| | | const setTableSelection = (ids) => { |
| | | if (!etableRef.value || !Array.isArray(ids) || ids.length === 0) { |
| | | return; |
| | | } |
| | | |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | try { |
| | | // 先清除所有选中 |
| | | etableRef.value.clearSelection(); |
| | | |
| | | // 找到需要选中的行并设置选中状态 |
| | | // 注意:ids中是officialId,需要匹配formalDatabaseData中的id字段 |
| | | const rowsToSelect = formalDatabaseData.value.filter((row) => |
| | | ids.includes(row.id) |
| | | ); |
| | | if (rowsToSelect.length > 0) { |
| | | etableRef.value.setRowsSelection(rowsToSelect, true); |
| | | console.log("选中状态设置完成"); |
| | | } else { |
| | | } |
| | | } catch (error) { |
| | | console.error("设置选中状态失败:", error); |
| | | } |
| | | }, 150); |
| | | }); |
| | | }; |
| | | |
| | | const formalDatabaseData = ref([]); |
| | | const formalDatabaseSelectedData = ref([]); |
| | | formalDatabaseData.value = [ |
| | | ]; |
| | | formalDatabaseData.value = []; |
| | | // 初始化 |
| | | const Initialization = () => { |
| | | tableData.value = []; |
| | | detailsTableData.value = []; |
| | | copyForm.value = null; |
| | | dialogType.value = "add"; |
| | | }; |
| | | const copyForm = ref(null); |
| | | const editInitialization = (data) => { |
| | | copyForm.value = { ...data }; // 深拷贝数据 |
| | | tableData.value = data.productionInventoryList || []; |
| | | detailsTableData.value = data.productionList || []; |
| | | dialogType.value = "edit"; |
| | | |
| | | // 设置默认选中的ID,使用officialId来匹配 |
| | | const existingOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = existingOfficialIds; |
| | | }; |
| | | // 监听对话框状态,在打开时设置选中状态 |
| | | watch(innerVisible, (newVal) => { |
| | | if (newVal && selectedIds.value.length > 0) { |
| | | console.log("对话框打开,设置选中状态"); |
| | | setTimeout(() => setTableSelection(selectedIds.value), 200); |
| | | } |
| | | // 对话框关闭时清空选择状态 |
| | | if (!newVal) { |
| | | formalDatabaseSelectedData.value = []; |
| | | } |
| | | }); |
| | | |
| | | defineExpose({ |
| | | Initialization |
| | | Initialization, |
| | | editInitialization, |
| | | }); |
| | | const handleSelectData = (row) => { |
| | | tableData.value = []; |
| | | if (!innerVisible.value) return; |
| | | // 获取选中的数据 |
| | | const selectedData = formalDatabaseSelectedData.value; |
| | | if (selectedData.length === 0) { |
| | | ElMessage.warning("请至少选择一条数据"); |
| | | return; |
| | | } |
| | | // 将选中的数据根据需要筛选到表格中 |
| | | let addedCount = 0; |
| | | let duplicateCount = 0; |
| | | selectedData.forEach((item) => { |
| | | const existingItem = tableData.value.find( |
| | | (row) => row.id === item.id |
| | | ); |
| | | if (!existingItem) { |
| | | tableData.value.push( |
| | | Object.assign({}, item, { |
| | | used: 0, // 初始使用数量为0 |
| | | }) |
| | | ); |
| | | } |
| | | const newItem = { |
| | | ...item, // 复制所有原始数据 |
| | | officialId: item.id, // 保存原始的id作为officialId |
| | | usedQuantity: 0, // 初始使用数量为0 |
| | | // 可以根据需要添加其他字段 |
| | | }; |
| | | tableData.value.push(newItem); |
| | | addedCount++; |
| | | }); |
| | | |
| | | // 更新selectedIds,确保包含所有当前tableData中的officialId |
| | | const allOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = allOfficialIds; |
| | | |
| | | console.log("更新后的表格数据:", tableData.value); |
| | | console.log("更新后的选中ID:", selectedIds.value); |
| | | |
| | | // 关闭选择对话框 |
| | | innerVisible.value = false; |
| | | |
| | | // 显示结果消息 |
| | | let message = ""; |
| | | if (addedCount > 0) { |
| | | message += `成功添加 ${addedCount} 条数据`; |
| | | } |
| | | if (duplicateCount > 0) { |
| | | message += (message ? "," : "") + `跳过 ${duplicateCount} 条重复数据`; |
| | | } |
| | | if (message) { |
| | | ElMessage.success(message); |
| | | } else { |
| | | ElMessage.info("没有新数据被添加"); |
| | | } |
| | | }; |
| | | const handleSelectionChange = (selection) => { |
| | | formalDatabaseSelectedData.value = selection; |
| | | }; |
| | | const reset = () => { |
| | | // formRef |
| | | formRef.value?.resetFields(); |
| | | const handleReset = () => { |
| | | console.log(copyForm.value); |
| | | tableData.value = |
| | | JSON.parse(JSON.stringify(copyForm.value.productionInventoryList)) || []; |
| | | detailsTableData.value = |
| | | JSON.parse(JSON.stringify(copyForm.value.productionList)) || []; |
| | | }; |
| | | |
| | | const selectChange = (value) => {}; |
| | | |
| | | // 提交表单 |
| | | const handleSubmit = async () => { |
| | | console.log("提交表单数据:", tableData.value); |
| | | console.log(detailsTableData.value); |
| | | let data = { |
| | | productionList: detailsTableData.value, |
| | | productionInventoryList: tableData.value, |
| | | ...copyForm.value, |
| | | }; |
| | | console.log("提交数据", data); |
| | | // dialogVisible.value = false; |
| | | let res = await addOrEditPM(data); |
| | | if (res.code === 200) { |
| | | dialogVisible.value = false; |
| | | emit("success"); |
| | | } else { |
| | | ElMessage.error("提交失败"); |
| | | } |
| | | }; |
| | | |
| | | // 关闭弹窗 |
| | |
| | | |
| | | // 添加单元格编辑处理函数 |
| | | const handleCellEdit = (row, prop, value) => { |
| | | if (prop === "used" && Number(value) > Number(row.stock)) { |
| | | ElMessage.warning("使用数量不能大于库存数量!"); |
| | | row.used = row.stock; |
| | | if (prop === "usedQuantity") { |
| | | const numValue = Number(value); |
| | | const inventory = Number(row.inventoryQuantity); |
| | | |
| | | // 验证输入值 |
| | | if (isNaN(numValue) || numValue < 0) { |
| | | ElMessage.warning("使用数量必须是非负数!"); |
| | | row.usedQuantity = 0; |
| | | return; |
| | | } |
| | | |
| | | if (numValue > inventory) { |
| | | ElMessage.warning(`使用数量不能大于库存数量(${inventory})!`); |
| | | row.usedQuantity = inventory; |
| | | return; |
| | | } |
| | | |
| | | // 更新值 |
| | | row.usedQuantity = numValue; |
| | | console.log(`更新 ${row.coal} 的使用数量为: ${numValue}`); |
| | | } |
| | | }; |
| | | |
| | | // 处理生产明细表格的操作 |
| | | const addNewRow = () => { |
| | | detailsTableData.value.push({ |
| | | coalType: "", |
| | | coal: "", |
| | | productionQuantity: "", |
| | | laborCost: "", |
| | | energyConsumptionCost: "", |
| | | equipmentDepreciation: "", |
| | | purchasePrice: "", |
| | | autoCalculate: "0.00", |
| | | producer:"", |
| | | producer: "", |
| | | }); |
| | | }; |
| | | |
| | | const clearAllRows = () => { |
| | | detailsTableData.value = []; |
| | | ElMessage.success("已清空所有数据"); |
| | | }; |
| | | |
| | | const calculateAllCosts = () => { |
| | | detailsTableData.value.forEach((row) => { |
| | | const laborCost = parseFloat(row.laborCost) || 0; |
| | | const energyCost = parseFloat(row.energyCost) || 0; |
| | | const equipmentDepreciation = parseFloat(row.equipmentDepreciation) || 0; |
| | | const purchasePrice = parseFloat(row.purchasePrice) || 0; |
| | | |
| | | row.totalCost = ( |
| | | laborCost + |
| | | energyCost + |
| | | equipmentDepreciation + |
| | | purchasePrice |
| | | ).toFixed(2); |
| | | }); |
| | | ElMessage.success("重新计算完成"); |
| | | }; |
| | | |
| | | const handleDetailsChange = (data) => { |
| | |
| | | const handleDeleteRow = (index) => { |
| | | ElMessage.success(`已删除第 ${index + 1} 行数据`); |
| | | }; |
| | | |
| | | // 删除单个已选数据项 |
| | | const handleRemoveItem = (row) => { |
| | | console.log("删除项:", row); |
| | | const index = tableData.value.findIndex( |
| | | (item) => item.officialId === row.officialId |
| | | ); |
| | | if (index > -1) { |
| | | tableData.value.splice(index, 1); |
| | | |
| | | // 更新selectedIds |
| | | const updatedOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = updatedOfficialIds; |
| | | |
| | | console.log("删除后的表格数据:", tableData.value); |
| | | console.log("更新后的选中ID:", selectedIds.value); |
| | | |
| | | ElMessage.success("已删除选中项"); |
| | | } |
| | | }; |
| | | |
| | | // 清空所有已选数据 |
| | | const removeSelectedData = () => { |
| | | if (tableData.value.length === 0) { |
| | | ElMessage.warning("没有可清空的数据"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("确认清空所有已选择的数据吗?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableData.value = []; |
| | | selectedIds.value = []; |
| | | console.log("已清空所有已选数据"); |
| | | ElMessage.success("已清空所有数据"); |
| | | }) |
| | | .catch(() => { |
| | | console.log("取消清空操作"); |
| | | }); |
| | | }; |
| | | |
| | | // 计算总使用量 |
| | | const totalUsedQuantity = computed(() => { |
| | | return tableData.value.reduce((total, item) => { |
| | | const usedQty = Number(item.usedQuantity) || 0; |
| | | return total + usedQty; |
| | | }, 0); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | .el-row > .el-col > h1 { |
| | | font-weight: bolder; |
| | | } |
| | | .empty-table > .el-row{ |
| | | .empty-table > .el-row { |
| | | margin-bottom: 12px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="production-container"> |
| | | <el-form :inline="true" :model="queryParams" class="search-form" style="width: 100%"> |
| | | <el-form-item label="搜索"> |
| | | <el-input v-model="queryParams.searchAll" placeholder="请输入关键词" clearable /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- 搜索表单 --> |
| | | <el-form :inline="true" :model="queryParams" class="search-form"> |
| | | <el-form-item label="搜索"> |
| | | <el-input |
| | | v-model="queryParams.searchAll" |
| | | placeholder="请输入关键词" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | <el-button @click="handleReset">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 主要内容区域 --> |
| | | <el-card> |
| | | <el-button type="success" :icon="Plus" @click="handleAddBatch">新增加工</el-button> |
| | | <el-button type="danger" :icon="Delete">删除</el-button> |
| | | <el-button type="info" :icon="Download">导出</el-button> |
| | | <ETable :loading="loading" :table-data="tableData" :columns="columns" @selection-change="handleSelectionChange" |
| | | @edit="handleEdit" @view-detail="handleViewDetail" :show-selection="true" :border="true" :maxHeight="480" /> |
| | | <!-- 操作按钮 --> |
| | | <div class="toolbar"> |
| | | <el-button type="success" :icon="Plus" @click="openDialog('add')"> |
| | | 新增加工 |
| | | </el-button> |
| | | <el-button type="danger" :icon="Delete" :disabled="!selectedRows.length"> |
| | | 删除 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- 数据表格 --> |
| | | <ETable |
| | | :loading="loading" |
| | | :table-data="tableData" |
| | | :columns="columns" |
| | | @selection-change="handleSelectionChange" |
| | | @edit="row => openDialog('edit', row)" |
| | | :show-selection="true" |
| | | :border="true" |
| | | :maxHeight="480" |
| | | > |
| | | <template #coal="{ row }"> |
| | | <div class="coal-tags"> |
| | | <el-tag v-for="coal in parseCoalArray(row.coal)" :key="coal" size="small"> |
| | | {{ coal }} |
| | | </el-tag> |
| | | <span v-if="!row.coal">--</span> |
| | | </div> |
| | | </template> |
| | | </ETable> |
| | | |
| | | <!-- 分页组件 --> |
| | | <Pagination |
| | | :total="total" |
| | | :page="queryParams.current" |
| | | :limit="queryParams.size" |
| | | :show-total="true" |
| | | @pagination="handlePageChange" |
| | | :layout="'total, prev, pager, next, jumper'" |
| | | ></Pagination> |
| | | /> |
| | | </el-card> |
| | | <ProductionDialog v-model:visible="dialogVisible" ref="childRef" :type="dialogType" |
| | | @success="handleDialogSuccess" /> |
| | | |
| | | <!-- 生产对话框 --> |
| | | <ProductionDialog |
| | | v-model:visible="dialogVisible" |
| | | ref="dialogRef" |
| | | :type="dialogType" |
| | | @success="handleDialogSuccess" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Delete, Download, List } from "@element-plus/icons-vue"; |
| | | import { Plus, Delete } from "@element-plus/icons-vue"; |
| | | import ProductionDialog from "./components/ProductionDialog.vue"; |
| | | import ETable from "@/components/Table/ETable.vue"; |
| | | import Pagination from "@/components/Pagination/index.vue"; |
| | | import { getProductionMasterList } from "@/api/production"; |
| | | const childRef = ref(null); |
| | | |
| | | // 表格列配置 |
| | | const columns = [ |
| | | { prop: "category", label: "煤种", minWidth: 150 }, |
| | | { prop: "unit", label: "单位", minWidth: 120 }, |
| | | { prop: "productionVolume", label: "生产数量", minWidth: 150 }, |
| | | { prop: "coal", label: "煤种", minWidth: 150, slot: 'coal' }, |
| | | { prop: "productionQuantity", label: "生产数量", minWidth: 120 }, |
| | | { prop: "laborCost", label: "人工成本", minWidth: 150 }, |
| | | { prop: "materialCost", label: "原料成本", minWidth: 120 }, |
| | | { prop: "equipmentCost", label: "设备费用", minWidth: 143 }, |
| | | { prop: "energyConsumptionCost", label: "能耗成本", minWidth: 120 }, |
| | | { prop: "equipmentDepreciation", label: "设备折旧", minWidth: 143 }, |
| | | { prop: "totalCost", label: "总成本", minWidth: 150 }, |
| | | { prop: "totalPrice", label: "总售价", minWidth: 150 }, |
| | | { prop: "profit", label: "利润", minWidth: 100 }, |
| | | { prop: "reviewer", label: "复记人", minWidth: 120 }, |
| | | { prop: "date", label: "日期", minWidth: 150 }, |
| | | { prop: "producer", label: "生产人", minWidth: 150 }, |
| | | ]; |
| | | |
| | | // 搜索表单数据 |
| | | |
| | | // 表格数据 |
| | | // 响应式数据 |
| | | const tableData = ref([]); |
| | | const loading = ref(false); |
| | | const total = ref(0); |
| | | |
| | | const queryParams = reactive({ |
| | | searchAll:"", |
| | | current: 1, |
| | | size: 10, // 固定每页10条 |
| | | }); |
| | | const handlePageChange = ({ page }) => { |
| | | console.log("分页变化:", { page }); |
| | | queryParams.current = page; |
| | | getList(); |
| | | }; |
| | | // 选中的行数据 |
| | | const selectedRows = ref([]); |
| | | |
| | | // 弹窗相关 |
| | | const dialogVisible = ref(false); |
| | | const dialogType = ref("add"); |
| | | const currentRow = ref(null); |
| | | const dialogRef = ref(null); |
| | | |
| | | // 生产明细对话框控制 |
| | | const detailDialogVisible = ref(false); |
| | | const currentDetailRow = ref(null); |
| | | // 查询参数 |
| | | const queryParams = reactive({ |
| | | searchAll: "", |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | |
| | | // 获取表格数据 |
| | | // 获取表格数据 |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const res = await getProductionMasterList({...queryParams}); |
| | | // 构建正确的分页参数 |
| | | const params = { |
| | | searchAll: queryParams.searchAll, |
| | | // 尝试多种常见的分页参数格式 |
| | | current: queryParams.current, |
| | | size: queryParams.size, |
| | | page: queryParams.current, |
| | | pageSize: queryParams.size, |
| | | pageNum: queryParams.current, |
| | | limit: queryParams.size, |
| | | offset: (queryParams.current - 1) * queryParams.size |
| | | }; |
| | | |
| | | console.log('发送分页参数:', params); |
| | | console.log(`第${queryParams.current}页应该显示第${(queryParams.current - 1) * queryParams.size + 1}-${queryParams.current * queryParams.size}条数据`); |
| | | |
| | | const res = await getProductionMasterList(params); |
| | | tableData.value = res.data.records || []; |
| | | total.value = res.data.total || 0; |
| | | |
| | | console.log('接收到的数据:', { |
| | | 当前页: queryParams.current, |
| | | 返回条数: tableData.value.length, |
| | | 总条数: total.value |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error("获取数据失败"); |
| | | console.error('API错误:', error); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 处理表格选择变化 |
| | | // 搜索和重置 |
| | | const handleSearch = () => { |
| | | queryParams.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | queryParams.searchAll = ""; |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 分页处理 |
| | | const handlePageChange = ({ page }) => { |
| | | queryParams.current = page; |
| | | getList(); |
| | | }; |
| | | |
| | | // 表格选择处理 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // 搜索方法 |
| | | const handleSearch = () => { |
| | | pagination.currentPage = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // 重置搜索 |
| | | const handleReset = () => { |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // 新增加工 |
| | | const handleAddBatch = () => { |
| | | dialogType.value = "add"; |
| | | // 打开对话框 - 统一处理新增和编辑 |
| | | const openDialog = (type, row = null) => { |
| | | dialogType.value = type; |
| | | dialogVisible.value = true; |
| | | childRef.value.Initialization(); |
| | | }; |
| | | |
| | | // 编辑 |
| | | const handleEdit = (row) => { |
| | | currentRow.value = row; |
| | | dialogType.value = "edit"; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 打开生产明细对话框 |
| | | const handleViewDetail = (row) => { |
| | | currentDetailRow.value = row; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 处理弹窗提交 |
| | | const handleDialogSuccess = async (formData) => { |
| | | try { |
| | | if (dialogType.value === "add") { |
| | | await addProduction(formData); |
| | | ElMessage.success("新增成功"); |
| | | } else { |
| | | await updateProduction({ |
| | | ...formData, |
| | | id: currentRow.value.id, |
| | | }); |
| | | ElMessage.success("更新成功"); |
| | | } |
| | | getList(); |
| | | } catch (error) { |
| | | ElMessage.error(dialogType.value === "add" ? "新增失败" : "更新失败"); |
| | | |
| | | if (type === 'add') { |
| | | dialogRef.value?.Initialization(); |
| | | } else if (type === 'edit' && row) { |
| | | dialogRef.value?.editInitialization({ ...row }); |
| | | } |
| | | }; |
| | | |
| | | // 处理生产明细弹窗提交 |
| | | const handleDetailDialogSuccess = async (formData) => { |
| | | try { |
| | | ElMessage.success("保存成功"); |
| | | getList(); |
| | | } catch (error) { |
| | | ElMessage.error("保存失败"); |
| | | } |
| | | }; |
| | | |
| | | // 删除 |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm("确认删除该记录吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(async () => { |
| | | try { |
| | | await deleteProduction(row.id); |
| | | ElMessage.success("删除成功"); |
| | | getList(); |
| | | } catch (error) { |
| | | console.error("删除失败:", error); |
| | | ElMessage.error("删除失败"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.info("已取消删除"); |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleExport = async (row) => { |
| | | try { |
| | | const res = await exportProduction({ id: row.id }); |
| | | const blob = new Blob([res], { type: "application/vnd.ms-excel" }); |
| | | const fileName = `生产加工记录_${new Date().getTime()}.xlsx`; |
| | | if ("download" in document.createElement("a")) { |
| | | const elink = document.createElement("a"); |
| | | elink.download = fileName; |
| | | elink.style.display = "none"; |
| | | elink.href = URL.createObjectURL(blob); |
| | | document.body.appendChild(elink); |
| | | elink.click(); |
| | | URL.revokeObjectURL(elink.href); |
| | | document.body.removeChild(elink); |
| | | } else { |
| | | navigator.msSaveBlob(blob, fileName); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("导出失败"); |
| | | } |
| | | }; |
| | | |
| | | // 处理每页显示数量变化 |
| | | const handleSizeChange = (val) => { |
| | | pagination.size = val; |
| | | // 对话框成功回调 |
| | | const handleDialogSuccess = () => { |
| | | getList(); |
| | | ElMessage.success("操作成功"); |
| | | }; |
| | | |
| | | // 处理页码变化 |
| | | const handleCurrentChange = (val) => { |
| | | pagination.currentPage = val; |
| | | getList(); |
| | | // 解析煤种数组 - 简化逻辑 |
| | | const parseCoalArray = (coalString) => { |
| | | if (!coalString) return []; |
| | | |
| | | if (Array.isArray(coalString)) return coalString; |
| | | |
| | | return String(coalString) |
| | | .replace(/^\[|\]$/g, '') |
| | | .split(',') |
| | | .map(item => item.trim()) |
| | | .filter(Boolean); |
| | | }; |
| | | |
| | | // 组件挂载时加载数据 |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | onMounted(getList); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | width: 20%; |
| | | } |
| | | } |
| | | .search-form{ |
| | | .search-form { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | .coal-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 4px; |
| | | |
| | | .el-tag { |
| | | margin-right: 4px; |
| | | margin-bottom: 4px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | </style> |