Parcourir la source

增加托盘详情修改

flower_bs il y a 1 jour
Parent
commit
0bc9b9058d

+ 6 - 0
erp/views.py

@@ -121,6 +121,12 @@ class InboundApplyCreate(APIView):
             # 保存或更新入库单
             bound_bill = self.save_or_update_inbound_bill(serializer)
 
+            materildetail_list = MaterialDetail.objects.filter(bound_billId=bound_bill).all()
+            for item in materildetail_list:
+                item.is_delete = True
+                item.save()
+                
+
             # 保存或更新物料明细
             self.save_or_update_material_detail(bound_bill, serializer)
             return WMSResponse.success( 

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
templates/dist/spa/css/8.65fea8cc.css


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
templates/dist/spa/css/8.85ce0f6b.css


+ 1 - 0
templates/dist/spa/css/chunk-common.0afca41f.css

@@ -0,0 +1 @@
+[data-v-112dd91a] .q-field__label{margin-top:8px;align-self:center}[data-v-112dd91a] .q-field__control-container{padding-left:50px;margin-top:-5px}[data-v-112dd91a] .q-table .q-editable:hover{background-color:#f0f8ff;cursor:pointer}[data-v-112dd91a] .q-field__native{padding:5px 8px}[data-v-112dd91a] .q-table tr.editing{background-color:#e8f5e9!important}

+ 0 - 1
templates/dist/spa/css/chunk-common.e1490f3e.css

@@ -1 +0,0 @@
-[data-v-0c2e412a] .q-field__label{margin-top:8px;align-self:center}[data-v-0c2e412a] .q-field__control-container{padding-left:50px;margin-top:-5px}

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 1
templates/dist/spa/index.html


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
templates/dist/spa/js/8.4c9d5326.js


BIN
templates/dist/spa/js/8.4c9d5326.js.gz


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
templates/dist/spa/js/8.b1eb79a4.js


BIN
templates/dist/spa/js/8.b1eb79a4.js.gz


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 1
templates/dist/spa/js/app.e55d498e.js


BIN
templates/dist/spa/js/app.82bf6bed.js.gz


BIN
templates/dist/spa/js/app.e55d498e.js.gz


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
templates/dist/spa/js/chunk-common.655d825e.js


BIN
templates/dist/spa/js/chunk-common.655d825e.js.gz


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
templates/dist/spa/js/chunk-common.d8a26ef6.js


BIN
templates/dist/spa/js/chunk-common.d8a26ef6.js.gz


+ 502 - 97
templates/src/components/containercard copy.vue

@@ -1,32 +1,33 @@
 <template>
   <div :style="{ backgroundColor: bgColor }">
-
     <q-dialog
       v-model="storage_dialog"
       transition-show="jump-down"
       transition-hide="jump-up"
       @show="prepareDialog()"
     >
-      <q-card style="min-width: 800px">
+      <q-card style="min-width: 1000px">
         <q-bar
           class="bg-light-blue-10 text-white rounded-borders"
           style="height: 50px"
         >
           <div>
-            {{ $t("stock.shelf.shelf_details") }}
+            {{ "托盘" }}
           </div>
           <q-space></q-space>
+          {{ containerCode }}
         </q-bar>
         <q-card-section class="q-pt-md">
           <q-tabs v-model="activeTab">
-            <q-tab name="tab2" label="批次信息" />
+            <q-tab name="tab2" label="托盘信息" />
+            <q-tab name="tab3" label="托盘详情" />
+            <q-tab name="tab1" label="操作记录" />
           </q-tabs>
         </q-card-section>
-        <!-- 选项卡内容 -->
         <q-tab-panels v-model="activeTab" animated>
-          <q-tab-panel name="tab2" style="height: 300px">
+          <q-tab-panel name="tab2" style="height: 600px">
             <template>
-              <div class="text-h6 q-mb-md">{{ "批次信息" }}</div>
+              <div class="text-h6 q-mb-md">{{ "托盘信息" }}</div>
               <q-table
                 v-if="storage_form.length > 0"
                 :data="storage_form"
@@ -52,24 +53,6 @@
                       z-index: 100;
                     "
                   >
-                    <q-btn
-                      v-if="!onlyread"
-                      @click="addInventoryDetail()"
-                      icon="add"
-                      flat
-                      dense
-                      color="primary"
-                      :label="$t('stock.add')"
-                    />
-                    <q-btn
-                      v-if="!onlyread"
-                      @click="deleteInventoryDetail()"
-                      icon="delete"
-                      flat
-                      dense
-                      color="primary"
-                      :label="$t('stock.delete')"
-                    />
                     <q-btn
                       flat
                       dense
@@ -102,26 +85,111 @@
               </div>
             </template>
           </q-tab-panel>
-          <q-tab-panel name="tab3" style="height: 300px">
-            <div class="row q-gutter-x-md">
-              <div class="col column q-gutter-y-md"></div>
-              <div class="col column q-gutter-y-md"></div>
+          <q-tab-panel name="tab3" style="height: 600px">
+            <q-table
+              :data="container_table"
+              :columns="coloums_container"
+              row-key="id"
+              flat
+              bordered
+              hide-pagination
+              class="my-sticky-table scrollable-table"
+              :style="{ 'max-height': '600px' }"
+              :container-style="{ height: 'auto' }"
+              :pagination="{ rowsPerPage: 0 }"
+            >
+              <template v-slot:body-cell-actions="props">
+                <q-td :props="props">
+                  <q-btn
+                    dense
+                    round
+                    color="primary"
+                    icon="edit"
+                    @click="handleRowEdit(props.row)"
+                  >
+                    <q-tooltip>编辑该行数据</q-tooltip>
+                  </q-btn>
+                  <q-btn
+                    dense
+                    round
+                    color="primary"
+                    icon="delete"
+                    @click="handleRowdelete(props.row)"
+                  >
+                    <q-tooltip>删除该行数据</q-tooltip>
+                  </q-btn>
+                </q-td>
+              </template>
+            </q-table>
+          </q-tab-panel>
+          <q-tab-panel name="tab1" style="height: 600px">
+            <div
+              style="
+                float: right;
+                padding: 15px 15px 50px 15px;
+                min-width: 100%;
+              "
+              flow="row wrap"
+            >
+              <q-card class="q-mb-md" bordered>
+                <q-card-section>
+                  <template>
+                    <div
+                      class="text-h6 q-mb-md"
+                      style="display: flex; justify-content: space-between"
+                    >
+                      {{ "操作记录" }}
+                    </div>
+                    <q-btn
+                      class="q-ml-sm"
+                      color="primary"
+                      icon="event"
+                      @click="sortoperatedetail"
+                      >近一个月操作记录</q-btn
+                    >
+                    <template v-if="listSize > 0">
+                      <q-list bordered class="rounded-borders">
+                        <q-expansion-item
+                          v-for="(node, index) in nodeList"
+                          v-if="node.value && node.value.length > 0"
+                          :key="index"
+                          group="op-group"
+                          :caption="`操作类型: ${formatType(
+                            node.value[0].operation_type
+                          )} ----- 操作时间:${node.value[0].timestamp}`"
+                        >
+                          <q-card>
+                            <q-card-section>
+
+                                <q-table
+
+                                  :data="node.value"
+                                  :columns="columns_operate"
+                                  row-key="id"
+                                  flat
+                                  bordered
+                                  hide-pagination
+                                  class="my-sticky-table scrollable-table"
+                                  :style="{ 'max-height': '400px' }"
+                                  :container-style="{ height: 'auto' }"
+                                  :pagination="{ rowsPerPage: 0 }"
+                                >
+                                </q-table>
+
+                            </q-card-section>
+                          </q-card>
+                        </q-expansion-item>
+                      </q-list>
+                    </template>
+                    <div v-else class="text-grey-8">暂无操作记录</div>
+                  </template>
+                </q-card-section>
+              </q-card>
             </div>
           </q-tab-panel>
         </q-tab-panels>
 
         <div style="float: right; padding: 15px 15px 15px 0">
-          <q-btn
-            color="white"
-            text-color="black"
-            style="margin-right: 25px"
-            @click="
-              shelfLocal = 'undefined';
-              handleclick();
-            "
-          >
-            {{ $t("stock.return") }}</q-btn
-          >
           <q-btn
             color="primary"
             text-color="white"
@@ -129,7 +197,7 @@
             @click="handleEdit()"
           >
             {{
-              onlyread
+              can_edit_detail
                 ? $t("stock.shelf.shelf_edit")
                 : $t("stock.shelf.shelf_confirm")
             }}</q-btn
@@ -137,119 +205,456 @@
         </div>
       </q-card>
     </q-dialog>
-  
   </div>
 </template>
 
 <script>
-import { getauth } from "boot/axios_request";
+class ListNode {
+  constructor (value) {
+    this.value = value
+    this.next = null
+  }
+}
+
+class LinkedList {
+  constructor () {
+    this.head = null
+    this.size = 0
+  }
+
+  append (value) {
+    const newNode = new ListNode(value)
+    if (!this.head) {
+      this.head = newNode
+    } else {
+      let current = this.head
+      while (current.next) {
+        current = current.next
+      }
+      current.next = newNode
+    }
+    this.size++
+  }
+
+  delete (value) {
+    if (!this.head) return
+
+    if (this.head.value === value) {
+      this.head = this.head.next
+      this.size--
+      return
+    }
+
+    let current = this.head
+    while (current.next) {
+      if (current.next.value === value) {
+        current.next = current.next.next
+        this.size--
+        return
+      }
+      current = current.next
+    }
+  }
+
+  toArray () {
+    const result = []
+    let current = this.head
+    while (current) {
+      result.push({ value: current.value })
+      current = current.next
+    }
+    return result
+  }
+
+  clear () {
+    this.head = null
+    this.size = 0
+  }
+}
+
+import { getauth, putauth, deleteauth } from 'boot/axios_request'
+import { LocalStorage } from 'quasar'
 
 export default {
   props: {
-    containerNumber: Number,
+    containerCode: Number,
+    containerNumber: Number
   },
-  data() {
+  data () {
     return {
-      pathnamecontainer: "container/locationdetail/",
+      pathnamecontainer: 'container/locationdetail/',
+      pathnamecontainer_detail: 'container/containerdetail/',
       container_id: 123456,
       results: [],
+      container_table: [],
       storage_form: [],
       showInventoryDetails: true,
       columns_batch: [
         {
-          name: "bound_number",
-          label: "批次",
+          name: 'bound_number',
+          label: '批次',
           field: (row) => row.bound_number,
-          align: "center",
+          align: 'center'
         },
         {
-          name: "plan_weight",
-          label: "当前库位容纳重量",
+          name: 'plan_weight',
+          label: '当前库位容纳重量',
           field: (row) => row.total_batch_qty,
-          align: "center",
-        },
+          align: 'center'
+        }
       ],
       columns_results: [
         {
-          label: "物料编码",
+          label: '物料编码',
           field: (row) => row.goods_code,
-          align: "center",
+          align: 'center'
         },
         {
-          label: "物料名称",
+          label: '物料名称',
           field: (row) => row.goods_desc,
-          align: "center",
+          align: 'center'
         },
         {
-          label: "每件重量",
-          field: (row) => row.goods_qty,
-          align: "center",
+          label: '物料批次',
+          field: (row) => row.bound_number,
+          align: 'center'
         },
+
         {
-          label: "件数",
+          label: '件数',
           field: (row) => row.group_qty,
-          align: "center",
+          align: 'center'
         },
         {
-          label: "批次计划重量",
+          label: '每件重量',
+          field: (row) => row.goods_qty,
+          align: 'center'
+        },
+        {
+          label: '批次计划重量',
           field: (row) => row.batch_total_qty,
-          align: "center",
+          align: 'center'
         },
         {
-          label: "在库重量",
+          label: '在库重量',
           field: (row) => row.batch_total_in_qty,
-          align: "center",
+          align: 'center'
         },
         {
-          label: "录入时间",
+          label: '录入时间',
           field: (row) => row.create_time.slice(0, 10),
-          align: "center",
+          align: 'center'
+        }
+      ],
+      coloums_container: [
+        {
+          label: '物料编码',
+          field: (row) => row.goods_code,
+          align: 'center'
+        },
+        {
+          label: '物料名称',
+          field: (row) => row.goods_desc,
+          align: 'center'
+        },
+        {
+          label: '物料批次',
+          field: (row) => row.batch,
+          align: 'center'
+        },
+        {
+          label: '入库重量',
+          field: (row) => row.goods_qty,
+          align: 'center',
+          sortable: true
+        },
+        {
+          label: '出库重量',
+          field: (row) => row.goods_out_qty,
+          align: 'center',
+          sortable: true
         },
+        {
+          label: '编辑',
+          name: 'actions', // 必须与插槽名对应
+          align: 'center',
+          field: 'actions', // 指向数据字段(可为空)
+          sortable: false, // 禁用排序
+          headerStyle: 'width: 80px' // 固定列宽
+        }
       ],
-      user_id: "",
-      auth_id: "",
-      onlyread: true,
-      clickedinput: false,
-      storage_dialog: false,
+      columns_operate: [
+        {
+          name: 'timestamp',
+          label: '操作时间',
+          field: (row) => row.timestamp,
+          align: 'center'
+        },
+        {
+          name: 'operator',
+          label: '经手人',
+          field: (row) => row.operator,
+          align: 'center'
+        },
+        {
+          name: 'batch',
+          label: '批次',
+          field: (row) => row.batch.bound_number,
+          align: 'center'
+        },
+        {
+          name: 'memo',
+          label: '备注',
+          field: (row) => row.memo,
+          align: 'center'
+        },
+        {
 
-      bgColor: "transparent",
+          label: '当前位置',
+          field: (row) => row.from_location,
 
-      error1: this.$t("stock.shelf.error1"),
-      shelfLocal: "",
-      activeTab: "tab2",
-    };
-  },
-  created() {
+          align: 'center'
+        },
+        {
 
-    this.handleclick();
+          label: '目标位置',
+          field: (row) => row.to_location,
+          align: 'center'
+        }
+      ],
+      user_id: '',
+      auth_id: '',
+      can_edit_detail: false,
+
+      storage_dialog: false,
+      bgColor: 'transparent',
+      error1: this.$t('stock.shelf.error1'),
+      shelfLocal: '',
+      activeTab: 'tab2',
+      operate_detail: [],
+      linkedList: new LinkedList()
+    }
   },
+  created () {
+    this.handleclick()
+  },
+  computed: {
+    nodeList () {
+      return this.linkedList.toArray()
+    },
 
+    listSize () {
+      return this.linkedList.size
+    }
+  },
   methods: {
-    prepareDialog() {
-      this.onlyread = true;
+    sortoperatedetail () {
+      var _this = this
+      console.log('近一个月操作记录', _this.nodeList)
+    },
+    formatType (type) {
+      switch (type) {
+        case 'container':
+          return '组盘'
+        case 'outbound':
+          return '出库'
+        case 'inbound':
+          return '入库'
+        case 'adjust':
+          return '移库'
+        case '5':
+          return '调拨'
+        case '6':
+          return '其他'
+        default:
+          return '未知'
+      }
+    },
+    getOperationRecord () {
+      var _this = this
+      _this.operate_detail = []
+      var operate_detail_container = []
+      _this.linkedList.clear()
+      getauth('container/operate/?status=1&container=' + _this.containerNumber)
+        .then((res) => {
+          _this.operate_detail = res.results
+          if (_this.operate_detail.length === 0) return
+
+          // 初始化第一个元素
+          operate_detail_container.push(_this.operate_detail[0])
+
+          for (let i = 0; i < _this.operate_detail.length - 1; i++) {
+            const current = _this.operate_detail[i]
+            const next = _this.operate_detail[i + 1]
+            if (current.operation_type === next.operation_type) {
+              operate_detail_container.push(next)
+            } else {
+              _this.linkedList.append([...operate_detail_container])
+              operate_detail_container = [next]
+            }
+          }
+
+          // 添加最后一个分组
+          if (operate_detail_container.length > 0) {
+            _this.linkedList.append([...operate_detail_container])
+          }
+        })
+        .catch((err) => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
+          })
+        })
+    },
+    handleRowdelete (rowData) {
+      if (this.can_edit_detail === true) {
+        console.log('当前行数据:', rowData)
+        this.$q
+          .dialog({
+            title: '删除物料信息',
+            message: `确定删除 ${rowData.goods_code} 吗?`,
+            ok: { label: '确定', color: 'negative' },
+            cancel: { label: '取消', color: 'primary' }
+          })
+          .onOk(() => {
+            this.deleteContainerData(rowData)
+          })
+      } else {
+        this.$q.notify({
+          message: '权限不足,请联系管理员',
+          icon: 'close',
+          color: 'negative'
+        })
+      }
     },
 
-    handleclick() {
-      this.getList();
+    async deleteContainerData (rowData) {
+      try {
+        const res = await deleteauth(`container/detail/${rowData.id}/`)
+        this.$q.notify({
+          message: '删除成功',
+          color: 'positive'
+        })
+        this.get_container_table() // 刷新数据
+      } catch (err) {
+        this.$q.notify({
+          message: '删除失败: ' + err.message,
+          color: 'negative'
+        })
+      }
+    },
+    handleRowEdit (rowData) {
+      if (this.can_edit_detail === true) {
+        console.log('当前行数据:', rowData)
+        this.$q
+          .dialog({
+            title: '编辑物料信息',
+            message: `正在编辑 ${rowData.goods_code}`,
+            prompt: {
+              model: rowData.goods_qty,
+              type: 'number',
+              label: '入库重量',
+              isValid: (val) => val >= 0 // 验证输入
+            },
+            persistent: true
+          })
+          .onOk((value) => {
+            // 调用API更新数据
+            this.updateContainerData(rowData, value)
+          })
+      } else {
+        this.$q.notify({
+          message: '权限不足,请联系管理员',
+          icon: 'close',
+          color: 'negative'
+        })
+      }
+    },
 
-      this.storage_dialog = true;
+    async updateContainerData (rowData, newValue) {
+      try {
+        const res = await putauth(`container/detail/${rowData.id}/`, {
+          goods_code: rowData.goods_code,
+          goods_desc: rowData.goods_desc,
+          goods_weight: 1,
+          goods_qty: newValue
+        })
+        this.$q.notify({
+          message: '更新成功',
+          color: 'positive'
+        })
+        this.get_container_table() // 刷新数据
+      } catch (err) {
+        this.$q.notify({
+          message: '更新失败: ' + err.message,
+          color: 'negative'
+        })
+      }
     },
+    prepareDialog () {
+      this.can_edit_detail = false
+    },
+    handleEdit () {
+      console.log('点击', this.can_edit_detail)
+      if (this.can_edit_detail === false) {
+        this.user_id = LocalStorage.getItem('login_mode')
 
-    getList() {
-      var _this = this;
-      _this.storage_form = [];
-      _this.results = [];
+        this.auth_id = LocalStorage.getItem('auth_edit')
+        console.log(this.auth_id)
 
+        if (this.auth_id === true) {
+          this.can_edit_detail = true
+        } else {
+          this.can_edit_detail = false
+        }
+        if (this.user_id === 'Admin') {
+          this.can_edit_detail = true
+        }
+      }
+      if (this.can_edit_detail === true) {
+        this.$q.notify({
+          message: '开始编辑托盘信息',
+          color: 'positive'
+        })
+      } else {
+        this.$q.notify({
+          message: '权限不足,请联系管理员',
+          icon: 'close',
+          color: 'negative'
+        })
+      }
+    },
+    handleclick () {
+      this.getList()
+      this.get_container_table()
+      this.getOperationRecord()
+      this.storage_dialog = true
+    },
+    get_container_table () {
+      var _this = this
       getauth(
-        _this.pathnamecontainer + "?container=" + _this.container_number
+        _this.pathnamecontainer_detail + '?container=' + _this.containerNumber
       ).then((res) => {
-        var data = res.data;
-        this.storage_form = data.batch_totals;
-        this.results = data.results;
-      });
+        var data = res.data
+
+        this.container_table = data
+      })
     },
-  },
-};
+    getList () {
+      var _this = this
+      _this.storage_form = []
+      _this.results = []
+      getauth(
+        _this.pathnamecontainer + '?container=' + _this.containerNumber
+      ).then((res) => {
+        var data = res.data
+        this.storage_form = data.batch_totals
+        this.results = data.results
+      })
+    }
+  }
+}
 </script>
 
 <style scoped>

+ 213 - 110
templates/src/components/containercard.vue

@@ -98,26 +98,59 @@
               :container-style="{ height: 'auto' }"
               :pagination="{ rowsPerPage: 0 }"
             >
-              <template v-slot:body-cell-actions="props">
+              <!-- 入库重量列可编辑 - 添加name属性 -->
+              <template v-slot:body-cell-goods_qty="props">
                 <q-td :props="props">
-                  <q-btn
+                  <q-input 
+                    v-if="props.row.editing && can_edit_detail"
+                    v-model.number="props.row.goods_qty" 
+                    type="number"
                     dense
-                    round
-                    color="primary"
-                    icon="edit"
-                    @click="handleRowEdit(props.row)"
-                  >
-                    <q-tooltip>编辑该行数据</q-tooltip>
-                  </q-btn>
-                  <q-btn
+                    outlined
+                    @keyup.enter="handleRowSave(props.row)"
+                  />
+                  <span v-else>
+                    {{ props.row.goods_qty }}
+                  </span>
+                </q-td>
+              </template>
+              
+              <!-- 出库重量列可编辑 - 添加name属性 -->
+              <template v-slot:body-cell-goods_out_qty="props">
+                <q-td :props="props">
+                  <q-input 
+                    v-if="props.row.editing && can_edit_detail"
+                    v-model.number="props.row.goods_out_qty" 
+                    type="number"
                     dense
-                    round
-                    color="primary"
-                    icon="delete"
-                    @click="handleRowdelete(props.row)"
-                  >
-                    <q-tooltip>删除该行数据</q-tooltip>
-                  </q-btn>
+                    outlined
+                    @keyup.enter="handleRowSave(props.row)"
+                  />
+                  <span v-else>
+                    {{ props.row.goods_out_qty }}
+                  </span>
+                </q-td>
+              </template>
+              
+              <!-- 操作列按钮 -->
+              <template v-slot:body-cell-actions="props">
+                <q-td :props="props">
+                  <template v-if="props.row.editing">
+                    <q-btn dense round color="positive" icon="save" @click="handleRowSave(props.row)">
+                      <q-tooltip>保存修改</q-tooltip>
+                    </q-btn>
+                    <q-btn dense round color="negative" icon="cancel" @click="handleRowCancel(props.row)">
+                      <q-tooltip>取消编辑</q-tooltip>
+                    </q-btn>
+                  </template>
+                  <template v-else>
+                    <q-btn dense round color="primary" icon="edit" @click="handleRowEdit(props.row)">
+                      <q-tooltip>编辑该行数据</q-tooltip>
+                    </q-btn>
+                    <q-btn dense round color="negative" icon="delete" @click="handleRowdelete(props.row)">
+                      <q-tooltip>删除该行数据</q-tooltip>
+                    </q-btn>
+                  </template>
                 </q-td>
               </template>
             </q-table>
@@ -160,9 +193,7 @@
                         >
                           <q-card>
                             <q-card-section>
-
                                 <q-table
-
                                   :data="node.value"
                                   :columns="columns_operate"
                                   row-key="id"
@@ -175,7 +206,6 @@
                                   :pagination="{ rowsPerPage: 0 }"
                                 >
                                 </q-table>
-
                             </q-card-section>
                           </q-card>
                         </q-expansion-item>
@@ -363,24 +393,26 @@ export default {
           align: 'center'
         },
         {
+          name: 'goods_qty', // 添加 name 属性
           label: '入库重量',
           field: (row) => row.goods_qty,
           align: 'center',
           sortable: true
         },
         {
+          name: 'goods_out_qty', // 添加 name 属性
           label: '出库重量',
           field: (row) => row.goods_out_qty,
           align: 'center',
           sortable: true
         },
         {
+          name: 'actions',
           label: '编辑',
-          name: 'actions', // 必须与插槽名对应
           align: 'center',
-          field: 'actions', // 指向数据字段(可为空)
-          sortable: false, // 禁用排序
-          headerStyle: 'width: 80px' // 固定列宽
+          field: 'actions',
+          sortable: false,
+          headerStyle: 'width: 80px'
         }
       ],
       columns_operate: [
@@ -409,14 +441,11 @@ export default {
           align: 'center'
         },
         {
-
           label: '当前位置',
           field: (row) => row.from_location,
-
           align: 'center'
         },
         {
-
           label: '目标位置',
           field: (row) => row.to_location,
           align: 'center'
@@ -448,9 +477,98 @@ export default {
     }
   },
   methods: {
+    // 进入编辑模式
+    handleRowEdit(row) {
+      if (this.can_edit_detail) {
+        // 保存原始数据用于取消操作时恢复
+        row.originalData = { 
+          goods_qty: row.goods_qty,
+          goods_out_qty: row.goods_out_qty
+        }
+        // 设置编辑状态
+        row.editing = true
+        
+        // 强制更新视图,确保输入框显示
+        this.$set(this.container_table, this.container_table.indexOf(row), row)
+      } else {
+        this.$q.notify({
+          message: '权限不足,请联系管理员',
+          icon: 'close',
+          color: 'negative'
+        })
+      }
+    },
+    
+    // 保存修改
+    async handleRowSave(row) {
+      try {
+        const payload = {
+          goods_code: row.goods_code,
+          goods_desc: row.goods_desc,
+          goods_qty: row.goods_qty,
+          goods_weight: 1,
+          goods_out_qty: row.goods_out_qty
+        }
+        
+        await putauth(`container/detail/${row.id}/`, payload)
+        
+        this.$q.notify({
+          message: '更新成功',
+          color: 'positive',
+          icon: 'check',
+          timeout: 1000
+        })
+        
+        // 退出编辑模式
+        row.editing = false
+        delete row.originalData
+        
+        // 强制更新视图
+        this.$set(this.container_table, this.container_table.indexOf(row), row)
+      } catch (err) {
+        console.error('更新失败:', err)
+        this.$q.notify({
+          message: `更新失败: ${err.response?.data?.detail || err.message || '服务器错误'}`,
+          color: 'negative',
+          icon: 'warning',
+          timeout: 3000
+        })
+      }
+    },
+    
+    // 取消编辑
+    handleRowCancel(row) {
+      // 恢复原始数据
+      if (row.originalData) {
+        row.goods_qty = row.originalData.goods_qty
+        row.goods_out_qty = row.originalData.goods_out_qty
+        delete row.originalData
+      }
+      // 退出编辑模式
+      row.editing = false
+      
+      // 强制更新视图
+      this.$set(this.container_table, this.container_table.indexOf(row), row)
+    },
+    
     sortoperatedetail () {
-      var _this = this
-      console.log('近一个月操作记录', _this.nodeList)
+      const oneMonthAgo = new Date()
+      oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1)
+      
+      // 过滤出近一个月的操作记录
+      const filteredList = this.linkedList.toArray().filter(node => {
+        return node.value.some(item => new Date(item.timestamp) > oneMonthAgo)
+      })
+      
+      // 使用Vue的响应式特性更新显示
+      this.$nextTick(() => {
+        this.visibleNodes = filteredList
+        this.$q.notify({
+          message: `已筛选出近一个月操作记录 (共${filteredList.length}组)`,
+          color: 'info',
+          timeout: 1500
+        })
+      })
     },
     formatType (type) {
       switch (type) {
@@ -501,34 +619,12 @@ export default {
         })
         .catch((err) => {
           _this.$q.notify({
-            message: err.detail,
+            message: err.detail || '获取操作记录失败',
             icon: 'close',
             color: 'negative'
           })
         })
     },
-    handleRowdelete (rowData) {
-      if (this.can_edit_detail === true) {
-        console.log('当前行数据:', rowData)
-        this.$q
-          .dialog({
-            title: '删除物料信息',
-            message: `确定删除 ${rowData.goods_code} 吗?`,
-            ok: { label: '确定', color: 'negative' },
-            cancel: { label: '取消', color: 'primary' }
-          })
-          .onOk(() => {
-            this.deleteContainerData(rowData)
-          })
-      } else {
-        this.$q.notify({
-          message: '权限不足,请联系管理员',
-          icon: 'close',
-          color: 'negative'
-        })
-      }
-    },
-
     async deleteContainerData (rowData) {
       try {
         const res = await deleteauth(`container/detail/${rowData.id}/`)
@@ -539,29 +635,22 @@ export default {
         this.get_container_table() // 刷新数据
       } catch (err) {
         this.$q.notify({
-          message: '删除失败: ' + err.message,
+          message: '删除失败: ' + (err.response?.data?.detail || err.message),
           color: 'negative'
         })
       }
     },
-    handleRowEdit (rowData) {
+    handleRowdelete (rowData) {
       if (this.can_edit_detail === true) {
-        console.log('当前行数据:', rowData)
         this.$q
           .dialog({
-            title: '编辑物料信息',
-            message: `正在编辑 ${rowData.goods_code}`,
-            prompt: {
-              model: rowData.goods_qty,
-              type: 'number',
-              label: '入库重量',
-              isValid: (val) => val >= 0 // 验证输入
-            },
-            persistent: true
+            title: '删除物料信息',
+            message: `确定删除物料 ${rowData.goods_code} (批次${rowData.batch}) 吗?`,
+            ok: { label: '确定', color: 'negative' },
+            cancel: { label: '取消', color: 'primary' }
           })
-          .onOk((value) => {
-            // 调用API更新数据
-            this.updateContainerData(rowData, value)
+          .onOk(() => {
+            this.deleteContainerData(rowData)
           })
       } else {
         this.$q.notify({
@@ -571,57 +660,43 @@ export default {
         })
       }
     },
-
-    async updateContainerData (rowData, newValue) {
-      try {
-        const res = await putauth(`container/detail/${rowData.id}/`, {
-          goods_code: rowData.goods_code,
-          goods_desc: rowData.goods_desc,
-          goods_weight: 1,
-          goods_qty: newValue
-        })
-        this.$q.notify({
-          message: '更新成功',
-          color: 'positive'
-        })
-        this.get_container_table() // 刷新数据
-      } catch (err) {
-        this.$q.notify({
-          message: '更新失败: ' + err.message,
-          color: 'negative'
-        })
-      }
-    },
     prepareDialog () {
       this.can_edit_detail = false
     },
     handleEdit () {
-      console.log('点击', this.can_edit_detail)
       if (this.can_edit_detail === false) {
         this.user_id = LocalStorage.getItem('login_mode')
-
         this.auth_id = LocalStorage.getItem('auth_edit')
-        console.log(this.auth_id)
-
-        if (this.auth_id === true) {
+        
+        // 检查编辑权限
+        if (this.auth_id === true || this.user_id === 'Admin') {
           this.can_edit_detail = true
+          this.$q.notify({
+            message: '已进入编辑模式',
+            color: 'positive',
+            icon: 'edit'
+          })
         } else {
           this.can_edit_detail = false
+          this.$q.notify({
+            message: '权限不足,请联系管理员',
+            icon: 'close',
+            color: 'negative'
+          })
         }
-        if (this.user_id === 'Admin') {
-          this.can_edit_detail = true
-        }
-      }
-      if (this.can_edit_detail === true) {
-        this.$q.notify({
-          message: '开始编辑托盘信息',
-          color: 'positive'
-        })
       } else {
+        // 退出编辑模式
+        this.can_edit_detail = false
+        // 退出任何正在编辑的行
+        this.container_table.forEach(row => {
+          if (row.editing) {
+            row.editing = false
+            delete row.originalData
+          }
+        })
         this.$q.notify({
-          message: '权限不足,请联系管理员',
-          icon: 'close',
-          color: 'negative'
+          message: '已退出编辑模式',
+          color: 'info'
         })
       }
     },
@@ -636,9 +711,17 @@ export default {
       getauth(
         _this.pathnamecontainer_detail + '?container=' + _this.containerNumber
       ).then((res) => {
-        var data = res.data
-
-        this.container_table = data
+        // 添加编辑状态属性
+        _this.container_table = res.data.map(item => ({
+          ...item,
+          editing: false
+        }))
+      }).catch(err => {
+        console.error('获取容器详情失败:', err)
+        _this.$q.notify({
+          message: '获取托盘详情失败:' + (err.response?.data?.detail || err.message),
+          color: 'negative'
+        })
       })
     },
     getList () {
@@ -649,8 +732,14 @@ export default {
         _this.pathnamecontainer + '?container=' + _this.containerNumber
       ).then((res) => {
         var data = res.data
-        this.storage_form = data.batch_totals
-        this.results = data.results
+        this.storage_form = data.batch_totals || []
+        this.results = data.results || []
+      }).catch(err => {
+        console.error('获取托盘信息失败:', err)
+        _this.$q.notify({
+          message: '获取托盘信息失败:' + (err.response?.data?.detail || err.message),
+          color: 'negative'
+        })
       })
     }
   }
@@ -667,4 +756,18 @@ export default {
   padding-left: 50px;
   margin-top: -5px;
 }
+
+:deep(.q-table) .q-editable:hover {
+  background-color: #f0f8ff;
+  cursor: pointer;
+}
+
+:deep(.q-field__native) {
+  padding: 5px 8px;
+}
+
+/* 高亮显示编辑状态的行 */
+:deep(.q-table tr.editing) {
+  background-color: #e8f5e9 !important;
+}
 </style>

+ 5 - 0
templates/src/pages/erp/erpasn.vue

@@ -774,6 +774,11 @@ export default {
           label: '创建时间',
           field: (row) => moment(row.create_time).format('YYYY-MM-DD'),
           align: 'center'
+        },
+        {
+          name: 'action',
+          label: '操作',
+          align: 'center'
         }
       ],