Jelajahi Sumber

feat(物料明细): 添加物料批量删除功能

yz 1 Minggu lalu
induk
melakukan
1e6846f9c4

+ 4 - 2
src/components/order-form/events.js

@@ -68,7 +68,9 @@ export const MATERIAL_DETAIL_EVENTS = {
   /** 物料删除事件 */
   MATERIAL_DELETE: 'material-delete',
   /** 物料更新事件 */
-  MATERIAL_UPDATE: 'material-update'
+  MATERIAL_UPDATE: 'material-update',
+  /** 物料批量删除事件 */
+  MATERIAL_BATCH_DELETE: 'material-batch-delete'
 }
 
 /**
@@ -126,7 +128,7 @@ export const ALL_EVENTS = {
 
 /**
  * 物料明细事件类型
- * @typedef {'refresh'|'material-import'|'material-delete'|'material-update'} MaterialDetailEventType
+ * @typedef {'refresh'|'material-import'|'material-delete'|'material-update'|'material-batch-delete'} MaterialDetailEventType
  */
 
 /**

+ 69 - 1
src/components/order-form/material-detail-mixin.js

@@ -174,7 +174,13 @@ export default {
        * 正在编辑的属性名 - 用于记录当前编辑的字段
        * @type {string|null}
        */
-      editingProp: null
+      editingProp: null,
+
+      /**
+       * 选中的行数据 - 用于批量操作
+       * @type {MaterialDetailRecord[]}
+       */
+      selectedRows: []
     }
   },
 
@@ -998,6 +1004,68 @@ export default {
        })
 
        return index >= 0 ? index : -1
+     },
+
+     /**
+      * 处理表格选择变化事件
+      * @description 当用户选择或取消选择表格行时触发
+      * @param {MaterialDetailRecord[]} selection - 当前选中的行数据数组
+      * @this {MaterialDetailTableComponent}
+      */
+     handleSelectionChange(selection) {
+       this.selectedRows = selection || []
+     },
+
+     /**
+      * 处理批量删除操作
+      * @description 删除当前选中的所有行,并触发批量删除事件
+      * @this {MaterialDetailTableComponent}
+      */
+     handleBatchDelete() {
+       if (!this.selectedRows || this.selectedRows.length === 0) {
+         this.$message.warning('请先选择要删除的物料')
+         return
+       }
+
+       // 检查选中的行是否都可以删除
+       const undeletableRows = this.selectedRows.filter(row => !this.isRowEditable(row))
+       if (undeletableRows.length > 0) {
+         this.$message.warning('选中的物料中包含不可删除的项目')
+         return
+       }
+
+       const count = this.selectedRows.length
+       this.$confirm(`确定要删除选中的 ${count} 个物料吗?`, '批量删除确认', {
+         confirmButtonText: '确定',
+         cancelButtonText: '取消',
+         type: 'warning'
+       }).then(() => {
+         // 触发批量删除事件
+         this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_BATCH_DELETE, {
+           rows: [...this.selectedRows],
+           count: count
+         })
+         
+         // 清空选择
+         this.resetSelection()
+         
+         this.$message.success(`成功删除 ${count} 个物料`)
+       }).catch(() => {
+         // 用户取消删除
+       })
+     },
+
+     /**
+      * 重置选择状态
+      * @description 清空当前选中的行
+      * @this {MaterialDetailTableComponent}
+      */
+     resetSelection() {
+       this.selectedRows = []
+       // 如果表格组件有 clearSelection 方法,也调用它
+       if (this.$refs.crud && typeof this.$refs.crud.clearSelection === 'function') {
+         this.$refs.crud.clearSelection()
+       }
      }
   },
 

+ 6 - 0
src/components/order-form/material-detail-option.js

@@ -55,6 +55,12 @@ export function getMaterialDetailOption(isEditMode = false) {
     page: DEFAULT_PAGINATION_CONFIG,
     menuWidth: 120,
     rowKey: 'id',
+    // 启用多选功能
+    selection: isEditMode,
+    selectable: isEditMode ? (row, index) => {
+      // 只有可删除的物料才能被选中
+      return row.isDeletable === true
+    } : undefined,
     column: [
       {
         label: '物料编码',

+ 10 - 0
src/components/order-form/material-detail-table.vue

@@ -48,6 +48,15 @@
           >
             增加
           </el-button>
+          <el-button
+            v-if="editMode && selectedRows.length > 0"
+            type="danger"
+            icon="el-icon-delete"
+            size="small"
+            @click="handleBatchDelete"
+          >
+            批量删除 ({{ selectedRows.length }})
+          </el-button>
         </div>
       </div>
     </div>
@@ -62,6 +71,7 @@
         @refresh-change="handleRefresh"
         @current-change="handleCurrentChange"
         @size-change="handleSizeChange"
+        @selection-change="handleSelectionChange"
         @row-del="handleRowDelete"
         @row-update="handleRowUpdate"
       >

+ 59 - 0
src/components/order-form/order-form-mixin.js

@@ -1428,6 +1428,65 @@ export default {
      },
 
     /**
+     * 处理物料批量删除事件
+     * @description 批量删除选中的物料记录,仅允许删除可删除的物料
+     * @param {import('./types').MaterialBatchDeleteEventData} data - 批量删除事件数据
+     * @returns {void}
+     * @public
+     * @this {import('./types').OrderFormMixinComponent}
+     */
+    handleMaterialBatchDelete({ rows, count }) {
+      if (!Array.isArray(rows) || rows.length === 0) {
+        this.$message.warning('请选择要删除的物料')
+        return
+      }
+
+      // 检查是否有不可删除的物料
+      const undeletableItems = rows.filter(row => !row.isDeletable)
+      if (undeletableItems.length > 0) {
+        const itemNames = undeletableItems.map(item => item.itemName).join('、')
+        this.$message.warning(`以下物料不允许删除:${itemNames}`)
+        return
+      }
+
+      // 确认删除操作
+      this.$confirm(`确定要删除选中的 ${count} 条物料记录吗?`, '批量删除确认', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        try {
+          // 批量删除物料
+          const deletedItems = []
+          rows.forEach(row => {
+            const materialIndex = this.materialDetails.findIndex(item =>
+              item.itemCode === row.itemCode &&
+              item.dataSource === row.dataSource
+            )
+            
+            if (materialIndex !== -1) {
+              const deletedItem = this.materialDetails.splice(materialIndex, 1)[0]
+              deletedItems.push(deletedItem.itemName)
+            }
+          })
+
+          if (deletedItems.length > 0) {
+            this.$message.success(`成功删除 ${deletedItems.length} 条物料记录`)
+            // 触发选择重置,清空已删除的选中项
+            this.$refs.materialDetailTable?.resetSelection()
+          } else {
+            this.$message.warning('未找到要删除的物料记录')
+          }
+        } catch (error) {
+          this.$message.error('批量删除物料失败,请重试')
+          console.error('批量删除物料失败:', error)
+        }
+      }).catch(() => {
+        // 用户取消删除操作
+      })
+    },
+
+    /**
      * 处理物料导入事件
      * @description 将导入的物料数据添加到物料明细列表中,格式化数字字段并标记为可删除
      * @param {MaterialDetailRecord[]} importedMaterials - 导入的物料数据数组

+ 1 - 0
src/components/order-form/order-form.vue

@@ -62,6 +62,7 @@
           @refresh="handleMaterialChange"
           @material-import="handleMaterialImport"
           @material-delete="handleMaterialDelete"
+          @material-batch-delete="handleMaterialBatchDelete"
           @material-update="handleMaterialUpdate"
         />
       </div>

+ 17 - 0
src/components/order-form/types.d.ts

@@ -243,6 +243,8 @@ export interface OrderFormMixinMethods {
   prepareMaterialItemData(material: MaterialDetailRecord): any;
   /** 处理物料删除 */
   handleMaterialDelete(data: MaterialDeleteEventData): void;
+  /** 处理物料批量删除 */
+  handleMaterialBatchDelete(data: MaterialBatchDeleteEventData): void;
   /** 处理物料导入 */
   handleMaterialImport(importedMaterials: MaterialDetailRecord[]): void;
   /** 处理表单提交事件 */
@@ -648,6 +650,7 @@ export interface MaterialDetailTableComponent extends Vue {
   DIALOG_EVENTS: typeof import('./events').DIALOG_EVENTS;
   editingRow: MaterialDetailRecord | null;
   editingProp: string | null;
+  selectedRows: MaterialDetailRecord[];
 
   // computed
   tableOption: AvueCrudOption;
@@ -672,6 +675,9 @@ export interface MaterialDetailTableComponent extends Vue {
   handleSizeChange(size: number): void;
   handleRowDelete(row: MaterialDetailRecord, index: number): void;
   handleDeleteMaterial(row: MaterialDetailRecord, index: number): void;
+  handleSelectionChange(selection: MaterialDetailRecord[]): void;
+  handleBatchDelete(): void;
+  resetSelection(): void;
   handleRowUpdate(row: MaterialDetailRecord, index: number, done: (result: any) => void): void;
   handleQuantityBlur(row: MaterialDetailRecord, index: number): void;
   handleQuantityChange(row: MaterialDetailRecord, index: number): void;
@@ -719,6 +725,17 @@ export interface MaterialDeleteEventData {
   index: number;
 }
 
+/**
+ * 物料明细批量删除事件数据
+ * @description 当物料明细被批量删除时传递的事件数据
+ */
+export interface MaterialBatchDeleteEventData {
+  /** 被删除的行数据数组 */
+  rows: MaterialDetailRecord[];
+  /** 选中的行数量 */
+  count: number;
+}
+
 
 
 /**