Pārlūkot izejas kodu

增加前端监测ERp任务

flower_mr 1 mēnesi atpakaļ
vecāks
revīzija
e547d01f1a

BIN
db.sqlite3


BIN
erp/__pycache__/filter.cpython-38.pyc


BIN
erp/__pycache__/models.cpython-38.pyc


BIN
erp/__pycache__/serializers.cpython-38.pyc


BIN
erp/__pycache__/urls.cpython-38.pyc


BIN
erp/__pycache__/views.cpython-38.pyc


+ 1 - 0
erp/filter.py

@@ -18,6 +18,7 @@ class InboundBillFilter(FilterSet):
             "create_time": ['exact', 'gt', 'gte', 'lt', 'lte', 'range'],
             "update_time": ['exact', 'gt', 'gte', 'lt', 'lte', 'range'],
             "is_delete": ['exact'],
+            "bound_status" : ['exact', 'gt', 'gte', 'lt', 'lte', 'isnull', 'in', 'range']
         }
 
 class MaterialDetailFilter(FilterSet):

+ 18 - 0
erp/migrations/0002_inboundbill_bound_status.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-04-29 18:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('erp', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='inboundbill',
+            name='bound_status',
+            field=models.IntegerField(default=0, verbose_name='状态'),
+        ),
+    ]

+ 21 - 0
erp/migrations/0003_alter_inboundbill_options_and_more.py

@@ -0,0 +1,21 @@
+# Generated by Django 4.1.2 on 2025-04-29 19:35
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('erp', '0002_inboundbill_bound_status'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='inboundbill',
+            options={'ordering': ['-update_time', '-create_time'], 'verbose_name': '生产入库单', 'verbose_name_plural': '生产入库单'},
+        ),
+        migrations.AlterModelOptions(
+            name='materialdetail',
+            options={'ordering': ['-update_time', '-create_time'], 'verbose_name': '物料明细', 'verbose_name_plural': '物料明细'},
+        ),
+    ]

BIN
erp/migrations/__pycache__/0002_inboundbill_bound_status.cpython-38.pyc


BIN
erp/migrations/__pycache__/0003_alter_inboundbill_options_and_more.cpython-38.pyc


+ 9 - 0
erp/models.py

@@ -5,6 +5,12 @@ class InboundBill(models.Model):
         (1, '订单'),
         (2, '其他'),
     )
+    STATUS_CHOICES = (
+        (0, '草稿'),
+        (1, '已审批'),
+        (2, '已入库'),
+        (3, '已取消'),
+    )
     billId = models.IntegerField(primary_key=True,verbose_name='原始单据ID')
     number = models.CharField(max_length=50, unique=True, verbose_name='单据编号')
     type = models.IntegerField(choices=BOUND_TYPE, verbose_name='绑定类型')
@@ -16,11 +22,13 @@ class InboundBill(models.Model):
     totalCount = models.IntegerField(verbose_name='总条目数')
     create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
     update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
+    bound_status = models.IntegerField(default=0, verbose_name='状态')
     is_delete = models.BooleanField(default=False, verbose_name='是否删除')
 
     class Meta:
         verbose_name = '生产入库单'
         verbose_name_plural = verbose_name
+        ordering = ['-update_time', '-create_time']
 
 
 class MaterialDetail(models.Model):
@@ -49,3 +57,4 @@ class MaterialDetail(models.Model):
         verbose_name = '物料明细'
         verbose_name_plural = verbose_name
         unique_together = [('bound_billId', 'entryIds')]
+        ordering = ['-update_time', '-create_time']

+ 2 - 1
erp/serializers.py

@@ -8,7 +8,8 @@ class InboundApplySerializer(serializers.ModelSerializer):
     """
     class Meta:
         model = InboundBill
-        exclude = [ 'creater', 'note', 'totalCount']
+        fields = '__all__'
+        ordering_fields = ['update_time', 'create_time']
         read_only_fields = ['billId', 'number', 'type', 'date', 'department', 'warehouse', 'creater', 'note', 'totalCount']
 
 class boundPostSerializer(serializers.Serializer):

+ 2 - 2
erp/urls.py

@@ -8,12 +8,12 @@ urlpatterns = [
     path('updateBatchInfo', views.BatchUpdate.as_view()),
     path('productInfo', views.ProductInfo.as_view()),
 
-    path('inboundBills', views.InboundBills.as_view({"get": "list"}),name="inboundBills"),
+    path('inboundBills/', views.InboundBills.as_view({"get": "list"}),name="inboundBills"),
     re_path(r'^inboundBills/(?P<pk>\d+)/$', views.InboundBills.as_view({
         'get': 'retrieve'
     }), name="inboundBills_1"),
 
-    path('materials', views.Materials.as_view({"get": "list"}),name="Materials"),
+    path('materials/', views.Materials.as_view({"get": "list"}),name="Materials"),
     re_path(r'^materials/(?P<pk>\d+)/$', views.Materials.as_view({
         'get': 'retrieve',
 

+ 19 - 11
erp/views.py

@@ -3,9 +3,11 @@ from rest_framework.response import Response
 from rest_framework.permissions import AllowAny
 from rest_framework import status
 from rest_framework import viewsets
-from django_filters.rest_framework import DjangoFilterBackend, OrderingFilter
+from django_filters.rest_framework import DjangoFilterBackend
+from rest_framework.filters import OrderingFilter
 from django.utils import timezone
 from django.db.models import Q, F, Case, When
+
 from utils.page import MyPageNumberPagination
 from .models import *
 from .serializers import *
@@ -264,6 +266,7 @@ class InboundApplyCreate(APIView):
                     update_time=timezone.now()
                 )
         return material_detail
+
 class OutboundApplyCreate(APIView):
     """
     生产出库申请
@@ -303,15 +306,16 @@ class InboundBills(viewsets.ModelViewSet):
         list:
             Response a data list(all)
     """
-    authentication_classes = []  # 禁用所有认证类
-    permission_classes = [AllowAny]  # 允许任意访问
+    # authentication_classes = []  # 禁用所有认证类
+    # permission_classes = [AllowAny]  # 允许任意访问
     
-    pagination_class = MyPageNumberPagination   
+    pagination_class = MyPageNumberPagination
     filter_backends = [DjangoFilterBackend, OrderingFilter, ]
-    ordering_fields = ['id', "create_time", "update_time", ]
+    ordering_fields = ["update_time", "create_time"]
     filter_class = InboundBillFilter
 
     def get_project(self):
+        # 获取项目ID,如果不存在则返回None
         try:
             id = self.kwargs.get('pk')
             return id
@@ -319,20 +323,24 @@ class InboundBills(viewsets.ModelViewSet):
             return None
 
     def get_queryset(self):
+        # 根据请求用户过滤查询集
         id = self.get_project()
         if self.request.user:
             if id is None:
                 return InboundBill.objects.filter(is_delete=False)
             else:
-                return InboundBill.objects.filter(id=id)
+                return InboundBill.objects.filter(billId=id, is_delete=False)
         else:
             return InboundBill.objects.none()
-    def  get_serializer_class(self):
-        if self.action in ['retrieve', 'list']:
+
+    def get_serializer_class(self):
+        # 根据操作类型选择合适的序列化器
+        if self.action in ['list', 'retrieve', ]:
             return InboundApplySerializer
         else:
             return self.http_method_not_allowed(request=self.request)
 
+
 class Materials(viewsets.ModelViewSet):
     """
         retrieve:
@@ -340,8 +348,8 @@ class Materials(viewsets.ModelViewSet):
         list:
             Response a data list(all)
     """
-    authentication_classes = []  # 禁用所有认证类
-    permission_classes = [AllowAny]  # 允许任意访问
+    # authentication_classes = []  # 禁用所有认证类
+    # permission_classes = [AllowAny]  # 允许任意访问
     
     pagination_class = MyPageNumberPagination   
     filter_backends = [DjangoFilterBackend, OrderingFilter, ]
@@ -365,7 +373,7 @@ class Materials(viewsets.ModelViewSet):
         else:
             return MaterialDetail.objects.none()
 
-    def  get_serializer_class(self):
+    def get_serializer_class(self):
         if self.action in ['retrieve', 'list']:
             return MaterialDetailSerializer
         else:

BIN
greaterwms/__pycache__/settings.cpython-38.pyc


+ 2 - 2
greaterwms/settings.py

@@ -229,6 +229,7 @@ REST_FRAMEWORK = {
 
 SERVER_LOGS_FILE = os.path.join(BASE_DIR, "logs", "server.log")
 ERROR_LOGS_FILE = os.path.join(BASE_DIR, "logs", "error.log")
+BILL_LOGS_FILE = os.path.join(BASE_DIR, "logs", "boundBill.log")
 if not os.path.exists(os.path.join(BASE_DIR, "logs")):
     os.makedirs(os.path.join(BASE_DIR, "logs"))
 
@@ -280,13 +281,12 @@ LOGGING = {
         'boundBill': {
             'level': 'INFO',
             'class': 'logging.handlers.RotatingFileHandler',
-            'filename': 'logs/boundBill.log',
+            'filename': BILL_LOGS_FILE,
             "maxBytes": 1024 * 1024 * 100,
             "backupCount": 30,
             "formatter": "standard",
             "encoding": "utf-8",
         },
-
     },
     "loggers": {
         'wms.boundBill': {

+ 145 - 0
logs/Untitled-1.json

@@ -0,0 +1,145 @@
+
+
+{
+	"billId": 1,
+	"number": "BC01-2025-04-0001",
+	"type": "production",
+	"type_code": "BC01",
+	"date": "2025-04-27 17:51:08",
+	"business_type": "B01",
+	"department ": "D01",
+	"warehouse": "W01",
+	"creater": "洪敏",
+	"note": "生产入库备注",
+	"totalCount": 2,
+	"materials": [
+		{
+			"entryIds": 71,
+			"production_batch": "QBF03-20250401",
+			"order": 20250401,
+			"goods_code": "B000345",
+			"goods_name": "二水槲皮素颗粒(QBF03)",
+			"goods_std": "标三",
+			"goods_weight": 10,
+			"plan_qty": 10,
+			"goods_total_weight": 100,
+			"goods_unit": "kg/袋",
+			"note" :""
+		},
+		{
+			"entryIds": 72,
+			"production_batch": "QBF03-20250402",
+			"order": 20250402,
+			"goods_code": "B000345",
+			"goods_name": "二水槲皮素颗粒(QBF03)",
+			"goods_std": "标三",
+			"goods_weight": 10,
+			"plan_qty": 10,
+			"goods_total_weight": 100,
+			"goods_unit": "kg/袋",
+			"note" :""
+		}
+	]
+}
+
+{
+	"billId": 2,
+	"number": "BC01-2025-04-0002",
+	"type": "Shipping_out",
+	"type_code": "BC01",
+	"date": "2025-04-27 17:51:08",
+	"business_type": "B01",
+	"department ": "D01",
+	"warehouse": "W01",
+	"creater": "洪敏",
+	"note": "出库备注",
+	"totalCount": 2,
+	"materials": [
+		{
+			"entryIds": 52,
+			"goods_code": "B000345",
+			"goods_name": "二水槲皮素颗粒(QBF03)",
+			"production_batch": "QBF03-20250401",
+			"goods_out_qty": 5,
+			"goods_unit": "kg/袋",
+			"note": ""
+		},
+		{
+			"entryIds": 53,
+			"goods_code": "B000345",
+			"goods_name": "二水槲皮素颗粒(QBF03)",
+			"production_batch": "QBF03-20250402",
+			"goods_out_qty": 5,
+			"goods_unit": "kg/袋",
+			"note": ""
+		}
+	]
+}
+
+{
+	"status": false,
+	"errorCode": "null",
+	"message": "et id",
+	"data": {
+		"failCount": 1,
+		"totalCount":2,
+		"successCount": 1,
+		"fail_materials": [
+			{
+				"entryIds": 72,
+				"production_batch": "QBF03-20250402",
+				"order": 20250402,
+				"goods_code": "B000345",
+				"goods_name": "二水槲皮素颗粒(QBF03)",
+				"goods_std": "标三",
+				"goods_weight": 10,
+				"plan_qty": 10,
+				"goods_total_weight": 100,
+				"goods_unit": "kg/袋",
+				"note" :""
+			}
+		]
+	}
+}
+
+{
+	"production_batch": "QBF03-20250401",
+	"status": "passing",
+	"note": "合格"
+}
+
+
+{
+	"billnos" :1,
+	"billId":1,
+	"totalCount": 1,
+	"materials":[
+		{
+			"entryIds": 71,
+			"status": "passing"
+		},
+	]
+}
+
+{
+	"totalCount": 2,
+	"materials": [
+		{
+			"id": 191,
+			"product_name": "漆黄素",
+			"product_code": "FAF01",
+			"product_std": "F-STP",
+			"product_unit":"kg/袋",
+		
+		},
+		{
+			"id": 190,
+			"product_name": "圣草次苷",
+			"product_code": "LCF01",
+			"product_std": "F-STP",
+			"product_unit":"kg/袋",
+		
+		}
+		
+	]
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 8 - 0
logs/boundBill.log


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1549 - 0
logs/error.log


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1664 - 0
logs/server.log


+ 31 - 3
templates/src/layouts/MainLayout.vue

@@ -89,6 +89,22 @@
 
           <q-separator />
 
+          <q-item clickable :to="{ name: 'erpasn' }" @click="linkChange('erp')" v-ripple exact
+            :active="link === 'erp' && link !== ''" :class="{
+              'my-menu-link': link === 'erp' && link !== '',
+            }">
+            <q-item-section avatar><q-icon name="img:statics/outbound/outbound.png" /></q-item-section>
+            <q-item-section>{{ "ERP任务" }}</q-item-section>
+            <q-badge 
+              v-if="ERPTasks > 0"
+              color="red-5"
+              class="task-badge"
+              :class="{ 'high-priority': ERPTasks > 20 }"
+            >
+              {{ ERPTasks > 99 ? '99+' : ERPTasks }}
+            </q-badge>
+          </q-item>
+
           <q-item clickable :to="{ name: 'inboundAndOutbound' }" @click="linkChange('outbounddashboard')" v-ripple exact
             :active="link === 'outbounddashboard' && link !== ''" :class="{
               'my-menu-link': link === 'outbounddashboard' && link !== '',
@@ -364,8 +380,10 @@ export default {
       },
       needLogin: '',
       activeTab: '',
-      pendingTasks: 5,
-      pollInterval: null
+      ERPTasks:0,
+      pendingTasks: 0,
+      pollInterval: null,
+      timer : null,
     }
   },
   methods: {
@@ -606,7 +624,12 @@ export default {
       } else {
         this.register = true
       }
-    }
+    },
+    handleTimer() {
+      getauth('/wms/inboundBills/?bound_status=0').then((res) => {
+        this.ERPTasks = res.count
+        this.pendingTasks = res.pending_count
+      })}
   },
   created() {
     var _this = this
@@ -637,10 +660,15 @@ export default {
   mounted() {
     var _this = this
     _this.warehouseOptionsGet()
+    _this.handleTimer()
     _this.link = localStorage.getItem('menulink')
     Bus.$on('needLogin', (val) => {
       _this.isLoggedIn()
     })
+
+    _this.timer = setInterval(() => {
+      _this.handleTimer()
+    }, 30000)
   },
   updated() {
   },

+ 54 - 0
templates/src/pages/erp/erp.vue

@@ -0,0 +1,54 @@
+<template>
+  <q-page class="flex flex-top">
+<template>
+  <div class="q-pa-md">
+    <div class="q-gutter-y-md" style="max-width: 100%">
+      <q-tabs
+        v-model="detaillink"
+      >
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="asn" :label="$t('inbound.asn')" icon="img:statics/inbound/asn.png" :to="{ name: 'erpasn' }" exact/>
+        </transition>
+        <!-- <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="predeliverystock" :label="$t('inbound.predeliverystock')"  icon="img:statics/inbound/polist.png" :to="{ name: 'predeliverystock' }" exact/>
+        </transition>
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="preloadstock" :label="$t('inbound.preloadstock')" icon="img:statics/inbound/preloadstock.png" :to="{ name: 'preloadstock' }" exact/>
+        </transition>
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="presortstock" :label="$t('inbound.presortstock')" icon="img:statics/inbound/presortstock.png" :to="{ name: 'presortstock' }" exact/>
+        </transition> -->
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="sortstock" :label="$t('inbound.sortstock')" icon="img:statics/inbound/sortstock.png" :to="{ name: 'erpsortstock' }" exact/>
+        </transition>
+        <!-- <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="shortage" :label="$t('inbound.shortage')" icon="img:statics/inbound/shortage.png" :to="{ name: 'shortage' }" exact/>
+        </transition>
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="more" :label="$t('inbound.more')" icon="img:statics/inbound/more.png" :to="{ name: 'more' }" exact/>
+        </transition>
+        <transition appear enter-active-class="animated zoomIn">
+          <q-route-tab name="asnfinish" :label="$t('inbound.asnfinish')" icon="img:statics/inbound/asnfinish.png" :to="{ name: 'asnfinish' }" exact/>
+        </transition> -->
+      </q-tabs>
+    </div>
+  </div>
+</template>
+    <div class="main-table">
+      <router-view />
+    </div>
+  </q-page>
+</template>
+
+<script>
+export default {
+  name: 'Pageinbound',
+  data () {
+    return {
+      detaillink: 'asn'
+    }
+  },
+  methods: {
+  }
+}
+</script>

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

@@ -0,0 +1,823 @@
+<template>
+  <div>
+    <transition appear enter-active-class="animated fadeIn">
+      <q-table class="my-sticky-header-column-table shadow-24" :data="table_list" row-key="id" :separator="separator"
+        :loading="loading" :columns="columns" hide-bottom :pagination.sync="pagination" no-data-label="No data"
+        no-results-label="No data you want" :table-style="{ height: height }" flat bordered>
+        <template v-slot:top>
+          <q-btn-group push>
+
+            <q-btn :label="$t('refresh')" icon="refresh" @click="reFresh()">
+              <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                content-style="font-size: 12px">{{ $t('refreshtip') }}</q-tooltip>
+            </q-btn>
+          </q-btn-group>
+          <q-space />
+          <div class="flex items-center">
+
+            <q-input outlined rounded dense debounce="200" color="primary" v-model="filter" :placeholder="'输入单据编号搜索'"
+              @input="getSearchList()" @keyup.enter="getSearchList()">
+              <template v-slot:append>
+                <q-icon name="search" />
+              </template>
+            </q-input>
+          </div>
+        </template>
+        <template v-slot:body="props">
+
+          <q-tr :props="props">
+
+            <template v-if="props.row.id === editid">
+              <q-td key="detail" :props="props">
+                <q-btn round flat push color="black" icon="description" @click="detailData(props.row)">
+                  <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                    content-style="font-size: 12px">{{ "查看单据详情"}}</q-tooltip>
+                </q-btn>
+                </q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="detail" :props="props">
+                <q-btn round flat push color="black" icon="description" @click="detailData(props.row)">
+                  <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                    content-style="font-size: 12px">{{ "查看批次详情" }}</q-tooltip>
+                </q-btn>
+              </q-td>
+            </template>
+
+            <template v-if="props.row.id === editid">
+              <q-td key="billId" :props="props">{{ props.row.billId }}</q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="billId" :props="props">{{ props.row.billId }}</q-td>
+            </template>
+
+            <template v-if="props.row.id === editid">
+              <q-td key="number" :props="props">{{ props.row.number }}</q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="number" :props="props">{{ props.row.number }}</q-td>
+            </template>
+
+
+            <template v-if="props.row.id === editid">
+              <q-td key="type" :props="props">
+                  <q-select dense outlined square v-model="editFormData.type"
+                    :label="'单据类型'" autofocus 
+                      :options="bound_code_type_list" option-label="label" option-value="value" emit-value map-options
+                      transition-show="scale"
+                      transition-hide="scale"
+                      :rules="[val => (val && val.length > 0) || error1]" />
+              </q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="type" :props="props">
+                {{ bound_code_type_map[props.row.type] || props.row.type }}</q-td>
+             
+            </template>
+
+            <template v-if="props.row.id === editid">
+              <q-td key="department" :props="props">
+            
+            <q-select dense outlined square v-model="editFormData.department"
+                  :label="'部门'"  
+                    :options="bound_department_list" option-label="label" option-value="value" emit-value map-options
+                    transition-show="scale"
+                    transition-hide="scale"
+                    :rules="[val => (val && val.length > 0) || error1]" />
+              </q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="department" :props="props">
+                {{ bound_department_map[props.row.department] || props.row.department }}</q-td>
+            </template>
+
+            
+            <template v-if="props.row.id === editid">
+              <q-td key="date" :props="props">{{ props.row.date }}</q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="date" :props="props">{{ props.row.date }}</q-td>
+            </template>
+
+           
+
+            <template v-if="props.row.id === editid">
+              <q-td key="creater" :props="props">
+                <q-input dense outlined square v-model.number="editFormData.creater" :label="'经办人'"
+                  :rules="[val => (val && val > 0) || error1]" />
+              </q-td>
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="creater" :props="props">{{ props.row.creater }}</q-td>
+            </template>
+
+            <template v-if="props.row.id === editid">
+         
+                <q-td key="bound_status" :props="props">
+                  {{ bound_status_map[ props.row.bound_status] || props.row.bound_status }}</q-td>
+            
+            </template>
+            <template v-else-if="props.row.id !== editid">
+              <q-td key="bound_status" :props="props">
+                {{ bound_status_map[ props.row.bound_status] || props.row.bound_status }}</q-td>
+                
+         
+            </template>
+
+
+            <template v-if="!editMode">
+              <q-td key="action" :props="props" style="width: 100px">
+                
+                <q-btn round flat push color="dark" icon="trolley" @click="change_status(props.row)">
+                  <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                    content-style="font-size: 12px">单据无误</q-tooltip>
+                </q-btn>
+    
+              </q-td>
+            </template>
+            <template v-else-if="editMode">
+              <template v-if="props.row.id === editid">
+                <q-td key="action" :props="props" style="width: 100px">
+                  <q-btn round flat push color="secondary" icon="check" @click="editDataSubmit()">
+                    <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                      content-style="font-size: 12px">{{ $t('confirmedit') }}</q-tooltip>
+                  </q-btn>
+                  <q-btn round flat push color="red" icon="close" @click="editDataCancel()">
+                    <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                      content-style="font-size: 12px">{{ $t('canceledit') }}</q-tooltip>
+                  </q-btn>
+                </q-td>
+              </template>
+              <template v-else-if="props.row.id !== editid"></template>
+            </template>
+          </q-tr>
+        </template>
+      </q-table>
+    </transition>
+    <template>
+      <div v-show="max !== 0" class="q-pa-lg flex flex-center">
+        <div>{{ total }} </div>
+        <q-pagination v-model="current" color="black" :max="max" :max-pages="6" boundary-links
+          @click="getSearchList(current); paginationIpt = current" />
+        <div>
+          <input v-model="paginationIpt" @blur="changePageEnter" @keyup.enter="changePageEnter"
+            style="width: 60px; text-align: center" />
+        </div>
+      </div>
+      <div v-show="max === 0" class="q-pa-lg flex flex-center">
+        <q-btn flat push color="dark" :label="$t('no_data')"></q-btn>
+      </div>
+    </template>
+
+    <q-dialog v-model="detailForm" transition-show="jump-down" transition-hide="jump-up" >
+            <q-card style="min-width: 900px; ">
+                <q-bar class="bg-light-blue-10 text-white rounded-borders" style="height: 50px">
+                    <div>
+                        {{ "单据信息" }}
+                    </div>
+                    <q-space></q-space>
+                    <q-btn dense flat icon="close" v-close-popup>
+                        <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[20, 20]"
+                            content-style="font-size: 12px">
+                            {{ $t("index.close") }}</q-tooltip>
+                    </q-btn>
+                </q-bar>
+                <q-card-section class="q-pt-md ">
+                    <q-tabs v-model="activeTab">
+                        <q-tab name="tab1" label="单据信息" />
+                        <!-- <q-tab name="tab2" label="货物信息" /> -->
+                    </q-tabs>
+                </q-card-section>
+                <!-- 选项卡内容 -->
+                <q-tab-panels v-model="activeTab" animated>
+                    <q-tab-panel name="tab1" style="height:70px">
+                  
+                        <div class="row q-gutter-x-md">
+                            <div class="col column q-gutter-y-md">
+                              <q-input dense outlined square v-model="table_detail.date" :label="'单据时间'" :readonly=true />
+
+                            </div>
+                            <div class="col column q-gutter-y-md">
+                              <q-input dense outlined square v-model="table_detail.number" :label="'单据编码'" :readonly=true />
+                              
+                            </div>
+                        </div>
+                       
+                    </q-tab-panel>
+                    </q-tab-panels>
+    
+                    <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">{{ "批次信息" }}</div>
+                            <template v-if=" batch_detail.length > 0">
+                              <div 
+                                v-for="(item, index) in batch_detail" 
+                                :key="index"
+                                class="row q-col-gutter-md q-mb-sm"
+                              >     
+                                <div class="col" >
+                                    <q-input 
+                                      v-model="item.entryIds" 
+                                      :label="'明细id'" 
+                                      :readonly="onlyread" 
+                                      dense outlined 
+                                
+                                    />
+                                  </div>   
+                                  <div class="col"  style="min-width: 150px">
+                                    <q-input 
+                                      v-model="item.production_batch" 
+                                      :label="'批次号'" 
+                                      :readonly="onlyread" 
+                                      dense outlined 
+                                
+                                    />
+                                  </div>
+                                  <div class="col">
+                                    <q-input 
+                                      v-model="item.goods_name" 
+                                      :label="'货物名称'"
+                                      :readonly="onlyread" 
+                                      dense outlined 
+                                    />
+                                  </div>
+                                  <div class="col">
+                                    <q-input 
+                                      v-model="item.plan_qty" 
+                                      :label="'计划数量'"
+                                      :readonly="onlyread" 
+                                      dense outlined 
+                                    />
+                                  </div>
+                                  <div class="col">
+                                    <q-input 
+                                      v-model="item.goods_unit" 
+                                      :label="'单位'"
+                                      :readonly="onlyread" 
+                                      dense outlined 
+                                    />
+                                  </div>
+                             
+                              
+                              </div>
+                            </template>
+
+                          </template>
+                        </q-card-section>
+                      </q-card>
+                    </div>
+            </q-card>
+        </q-dialog>
+  </div>
+</template>
+<router-view />
+
+<script>
+import { getauth, postauth, putauth, deleteauth } from 'boot/axios_request'
+
+import { date, exportFile, LocalStorage } from 'quasar'
+import { QToggle } from 'quasar'
+
+
+export default {
+  components: {
+    QToggle
+  },
+  name: 'Pageasnlist',
+  data() {
+    return {
+   
+      createDate2: '',
+      date_range: '',
+      proxyDate: '',
+      date: '',
+      goods_code: '',
+      goods_desc: '',
+      openid: '',
+      login_name: '',
+      authin: '0',
+      warehouse_code: '',
+      warehouse_name: '',
+
+      searchUrl: '',
+      pathname: 'wms/inboundBills/',
+      pathfilename: 'bound/file/',
+
+      pathname_previous: '',
+      pathname_next: '',
+      separator: 'cell',
+      loading: false,
+      height: '',
+
+      printObj: {
+        id: 'printMe',
+        popTitle: this.$t('inbound.asn')
+      },
+      table_list: [],
+      table_detail:{},
+      batch_detail:[],
+      bound_code_type_list:[],
+      bound_code_type_map:[],
+      bound_bs_type_list:[],
+      bound_bs_type_map:[],
+      bound_desc_list:[],
+      bound_desc_map:[],
+      bound_department_list:[],
+      bound_department_map:[],
+      bound_status_list:[],
+      bound_status_map:[],
+      product_list:[],
+      product_map:[],
+
+      columns: [
+        { name :'detail',label:'详情', field: 'detail', align: 'center'},
+        { name :'billId',label:'表单序号', field: 'billId', align: 'center'},
+        { name: 'number', label: '单据编号', field: 'number', align: 'center' },
+        { name: 'type', label: '业务类型', field: 'type', align: 'center' },
+        { name: 'department', label: '部门', field: 'department', align: 'center' },
+        { name: 'date', label: '单据日期', field: 'date', align: 'center' },
+        { name: 'creater', label: '经办人', field: 'creater', align: 'center' },
+        { name: 'bound_status', label: '状态', field: 'bound_status', align: 'center' },
+        { name: 'action', label: '操作', align: 'center' }
+      ],
+      filter: '',
+      product_filter: '',
+      pagination: {
+        page: 1,
+        rowsPerPage: 11
+      },
+      newForm: false,
+      newBatchForm: false,
+      newFormData: {
+
+      },
+      newBatchFormData: {},
+      newDetailFormData:{},
+      editid: 0,
+      editFormData: {
+
+      },
+      editMode: false,
+      deleteForm: false,
+      detailForm: false,
+      deleteid: 0,
+      detailid: 0,
+      bar_code: '',
+      error1: this.$t('goods.view_goodslist.error1'),
+
+      max: 0,
+      total: 0,
+      paginationIpt: 1,
+      current: 1,
+      onlyread: false,
+      bound_batch_list: [],
+      activeTab: 'tab1',
+ 
+
+    }
+
+  },
+  computed: {
+    interval() {
+      return this.$t('download_center.start') + ' - ' + this.$t('download_center.end')
+    }
+  },
+  methods: {
+  
+    getList(params = {}) {
+      var _this = this
+      _this.loading = true
+      // 合并基础参数
+      const baseParams = {
+        page: _this.current,
+        base_type: '0',
+        page_size: _this.pagination.rowsPerPage
+      }
+
+      // 创建URLSearchParams处理参数
+      const queryParams = new URLSearchParams({
+        ...baseParams,
+        ...params
+      })
+      console.log(queryParams)
+      // 过滤空值参数
+      Array.from(queryParams.entries()).forEach(([key, value]) => {
+        if (value === '' || value === null || value === undefined) {
+          queryParams.delete(key)
+        }
+      })
+
+      getauth(`${_this.pathname}?${queryParams}`)
+        .then(res => {
+          _this.table_list = res.results
+
+          _this.total = res.count
+          _this.max = Math.ceil(res.count / _this.pagination.rowsPerPage) || 0
+          _this.pathname_previous = res.previous
+          _this.pathname_next = res.next
+        })
+        .catch(err => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
+          })
+        })
+        .finally(() => {
+          _this.loading = false
+        })
+      
+    },
+    changePageEnter() {
+      if (Number(this.paginationIpt) < 1) {
+        this.current = 1
+        this.paginationIpt = 1
+      } else if (Number(this.paginationIpt) > this.max) {
+        this.current = this.max
+        this.paginationIpt = this.max
+      } else {
+        this.current = Number(this.paginationIpt)
+      }
+      this.getSearchList(this.current)
+    },
+
+    // 带搜索条件加载
+    getSearchList(page = 1) {
+      this.current = page
+      this.paginationIpt = page
+      this.getList({
+        number__icontains: this.filter,
+        document_date__range: this.date_range
+      })
+    },
+    getfileList() {
+      var _this = this
+      _this.loading = true
+      const params = {
+        goods_desc__icontains: _this.filter,
+        document_date__range: _this.date_range
+      }
+      const queryParams = new URLSearchParams({
+        ...params
+      })
+      console.log(queryParams)
+      // 过滤空值参数
+      Array.from(queryParams.entries()).forEach(([key, value]) => {
+        if (value === '' || value === null || value === undefined) {
+          queryParams.delete(key)
+        }
+      })
+      console.log(`${_this.pathfilename}?${queryParams}`)
+      getauth(`${_this.pathfilename}?${queryParams}`)
+        .then(res => {
+          var timeStamp = Date.now()
+          var formattedString = date.formatDate(timeStamp, 'YYYYMMDDHHmmss')
+          const status = exportFile(_this.pathfilename + 'list' + formattedString + '.csv', '\uFEFF' + res, 'text/csv')
+          if (status !== true) {
+            _this.$q.notify({
+              message: 'Browser denied file download...',
+              color: 'negative',
+              icon: 'warning'
+            })
+          }
+        })
+        .catch(err => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
+          })
+        })
+        .finally(() => {
+          _this.loading = false
+        })
+    },
+
+    getListPrevious() {
+      var _this = this
+      if (LocalStorage.has('auth')) {
+        getauth(_this.pathname_previous, {})
+          .then(res => {
+            _this.table_list = res.results
+            _this.pathname_previous = res.previous
+            _this.pathname_next = res.next
+          })
+          .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      } else {
+      }
+    },
+    getListNext() {
+      var _this = this
+      if (LocalStorage.has('auth')) {
+        getauth(_this.pathname_next, {})
+          .then(res => {
+            _this.table_list = res.results
+
+            _this.pathname_previous = res.previous
+            _this.pathname_next = res.next
+          })
+          .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      }
+    },
+    reFresh() {
+      var _this = this
+      _this.getSearchList()
+    },
+
+
+    change_status(e) {
+      var _this = this
+      
+      var status_FormData = {
+        bound_date: e.bound_date,
+        bound_code: e.bound_code,
+        bound_code_type: e.bound_code_type,
+        bound_bs_type: e.bound_bs_type,
+        bound_desc: e.bound_desc,
+ 
+        bound_department: e.bound_department,
+        creater: _this.login_name,
+        bound_type :'in',
+        bound_status :'101'
+      }
+
+      // putauth(_this.pathname + e.id + '/', status_FormData)
+      //   .then(res => {
+      //     _this.editDataCancel()
+      //     _this.getSearchList()
+      //     if (res.status_code != 500) {
+      //       _this.$q.notify({
+      //         message: '开始入库',
+      //         icon: 'check',
+      //         color: 'green'
+      //       })
+      //     }
+      //   })
+      //   .catch(err => {
+      //     _this.$q.notify({
+      //       message: err.detail,
+      //       icon: 'close',
+      //       color: 'negative'
+      //     })
+      //   })
+    },
+
+    detailData(e) {
+      var _this = this
+      _this.detailForm = true
+      _this.detailid = e.billId
+      console.log("detail查询的id是:",_this.detailid)
+      getauth(_this.pathname + _this.detailid+'/')
+      .then(res =>{
+        _this.table_detail = res
+      })          
+      .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      console.log("detail查询的结果是:",_this.table_detail)
+
+      getauth('wms/materials/?bound_billId=' + _this.detailid)
+      .then(res =>{
+        _this.batch_detail = res.results
+      })          
+      .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      console.log("batch查询的结果是:",_this.batch_detail)
+      console.log("batch长度查询的结果是:",_this.batch_detail.length)
+      
+    },
+    deleteDataSubmit() {
+      var _this = this
+      deleteauth(_this.pathname + _this.deleteid + '/')
+        .then(res => {
+          _this.deleteDataCancel()
+          _this.getSearchList()
+          _this.$q.notify({
+            message: '成功删除数据',
+            icon: 'check',
+            color: 'green'
+          })
+        })
+        .catch(err => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
+          })
+        })
+    },
+    deleteDataCancel() {
+      var _this = this
+      _this.deleteForm = false
+      _this.deleteid = 0
+    },
+
+
+    updateProxy() {
+      var _this = this
+      _this.proxyDate = _this.date
+    }
+
+  },
+  created() {
+    var _this = this
+    if (LocalStorage.has('openid')) {
+      _this.openid = LocalStorage.getItem('openid')
+    } else {
+      _this.openid = ''
+      LocalStorage.set('openid', '')
+    }
+    if (LocalStorage.has('warehouse_code')) {
+      _this.warehouse_code = LocalStorage.getItem('warehouse_code')
+    } 
+    if (LocalStorage.has('warehouse_name')) {
+      _this.warehouse_name = LocalStorage.getItem('warehouse_name')
+    } 
+    if (LocalStorage.has('login_name')) {
+      _this.login_name = LocalStorage.getItem('login_name')
+    } else {
+      _this.login_name = ''
+      LocalStorage.set('login_name', '')
+    }
+    if (LocalStorage.has('auth')) {
+      const timeStamp = Date.now()
+      const formattedString = date.formatDate(timeStamp, 'YYYY/MM/DD')
+      _this.date = formattedString
+      console.log(_this.date)
+      _this.authin = '1'
+      _this.getList()
+    } else {
+      _this.authin = '0'
+    }
+    getauth('warehouse/boundcodetype/', {})
+      .then(res => {
+      
+        _this.bound_code_type_list = res.results.map(item => ({
+          label: item.bound_code_type_name,
+          value: item.bound_code_type_code
+        }))
+       // 编码 → 名称的映射(普通对象,确保响应式)
+        _this.bound_code_type_map = res.results.reduce((acc, item) => {
+          acc[item.bound_code_type_code] = item.bound_code_type_name;
+          return acc;
+        }, {});
+
+      })
+      .catch(err => {
+        _this.$q.notify({
+          message: err.detail,
+          icon: 'close',
+          color: 'negative'
+        })
+      })
+
+      getauth('warehouse/boundtype/', {})
+      .then(res => {
+      
+        _this.bound_desc_list = res.results.map(item => ({
+          label: item.bound_type_name,
+          value: item.bound_type_code
+        }))
+        // 编码 → 名称的映射(普通对象,确保响应式)
+        _this.bound_desc_map = res.results.reduce((acc, item) => {
+          acc[item.bound_type_code] = item.bound_type_name;
+          return acc;
+        }, {});
+
+      })
+      .catch(err => {
+        _this.$q.notify({
+          message: err.detail,
+          icon: 'close',
+          color: 'negative'
+        })
+      })
+
+      getauth('warehouse/department/', {})
+      .then(res => {
+        _this.bound_department_list = res.results.map(item => ({
+          label: item.department_name,
+          value: item.department_code
+        }))
+        _this.bound_department_map = res.results.reduce((acc, item) => {
+          acc[item.department_code] = item.department_name;
+          return acc;
+        }, {});
+
+      })
+      .catch(err => {
+        _this.$q.notify({
+          message: err.detail,
+          icon: 'close',
+          color: 'negative'
+        })
+      })
+
+      getauth('warehouse/boundbusiness/', {})
+      .then(res => {
+        _this.bound_bs_type_list = res.results.map(item => ({
+          label: item.bound_bs_name,
+          value: item.bound_bs_code
+        }))
+         // 编码 → 名称的映射(普通对象,确保响应式)
+        _this.bound_bs_type_map = res.results.reduce((acc, item) => {
+          acc[item.bound_bs_code] = item.bound_bs_name;
+          return acc;
+        }, {});
+
+      })
+      .catch(err => {
+        _this.$q.notify({
+          message: err.detail,
+          icon: 'close',
+          color: 'negative'
+        })
+      })
+
+      getauth('warehouse/status/', {})
+      .then(res => {
+        _this.bound_status_list = res.results.map(item => ({
+          label: item.bound_status_name,
+          value: item.bound_status_code
+        }))
+        _this.bound_status_map = res.results.reduce((acc, item) => {
+          acc[item.bound_status_code] = item.bound_status_name;
+          return acc;
+        }, {});
+
+      })
+      .catch(err => {
+        _this.$q.notify({
+          message: err.detail,
+          icon: 'close',
+          color: 'negative'
+        })
+      })
+  },
+
+  mounted() {
+    var _this = this
+    if (_this.$q.platform.is.electron) {
+      _this.height = String(_this.$q.screen.height - 290) + 'px'
+    } else {
+      _this.height = _this.$q.screen.height - 290 + '' + 'px'
+    }
+    _this.newFormData.creater = _this.login_name
+  },
+  updated() { },
+  destroyed() { },
+
+}
+</script>
+<style scoped>
+/* 添加在 <style> 中 */
+.q-date__calendar-item--selected {
+  transition: all 0.3s ease;
+  background-color: #1976d2 !important;
+}
+
+.q-date__range {
+  background-color: rgba(25, 118, 210, 0.1);
+}
+
+
+:deep(.q-field__label) {
+
+    margin-top: 8px;
+    align-self: center;
+
+}
+
+
+:deep(.q-field__control-container) {
+
+    padding-left: 50px;
+    margin-top: -5px;
+
+}
+
+</style>

+ 394 - 0
templates/src/pages/erp/erpsortstock.vue

@@ -0,0 +1,394 @@
+<template>
+  <div >
+
+    <transition appear enter-active-class="animated fadeIn">
+      <q-table class="my-sticky-header-column-table shadow-24" :data="table_list" row-key="id" :separator="separator"
+        :loading="loading" :columns="columns" hide-bottom :pagination.sync="pagination" no-data-label="No data"
+        no-results-label="No data you want" :table-style="{ height: height }" flat bordered>
+        <template v-slot:top>
+          <q-btn-group push>
+
+            <q-btn :label="$t('refresh')" icon="refresh" @click="reFresh()">
+              <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                content-style="font-size: 12px">{{ $t('refreshtip') }}</q-tooltip>
+            </q-btn>
+
+          </q-btn-group>
+
+          <q-space />
+
+          <div class="flex items-center">
+            <div class="q-mr-md">{{ $t("download_center.createTime") }}</div>
+            <q-input readonly outlined dense v-model="createDate2" :placeholder="interval">
+              <template v-slot:append>
+                <q-icon name="event" class="cursor-pointer">
+                  <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
+                    <q-date v-model="createDate1" range>
+                      <div class="row items-center justify-end q-gutter-sm">
+                        <q-btn :label="$t('index.cancel')" color="primary" flat v-close-popup />
+                        <q-btn :label="$t('index.clear')" color="primary" @click="createDate2 = ''; createDate1 = '';"
+                          v-close-popup />
+
+                      </div>
+                    </q-date>
+                  </q-popup-proxy>
+                </q-icon>
+              </template>
+            </q-input>
+            <q-btn-group push class="q-ml-md">
+            </q-btn-group>
+            <q-input outlined rounded dense debounce="300" color="primary" v-model="filter" :placeholder="$t('search')"
+              @input="getSearchList()" @keyup.enter="getSearchList()">
+              <template v-slot:append>
+                <q-icon name="search" @click="getSearchList()" />
+              </template>
+            </q-input>
+          </div>
+        </template>
+        <template v-slot:body="props">
+          <q-tr :props="props">
+            <template >
+              <q-td key="document_date" :props="props">{{ props.row.batch_detail.bound_list.bound_date }}</q-td>
+            </template>            
+            <template >
+              <q-td key="document_number" :props="props">{{ props.row.batch_detail.bound_list.bound_code }}</q-td>
+            </template>
+            <template >
+              <q-td key="document_type" :props="props">{{ props.row.batch_detail.bound_list.bound_code_type }}</q-td>
+            </template>            
+            <template >
+              <q-td key="business_type" :props="props">{{ props.row.batch_detail.bound_list.bound_bs_type }}</q-td>
+            </template>
+            <template >
+              <q-td key="iout_type" :props="props">{{ props.row.batch_detail.bound_list.bound_type  }}</q-td>
+            </template>            
+            <template >
+              <q-td key="department" :props="props">{{ props.row.batch_detail.bound_list.bound_department }}</q-td>
+            </template>            
+            <template >
+              <q-td key="warehouse_code" :props="props">{{ props.row.batch_detail.bound_batch.warehouse_code }}</q-td>
+            </template>            
+            <template >
+              <q-td key="warehouse_name" :props="props">{{ props.row.batch_detail.bound_batch.warehouse_name }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_code" :props="props">{{ props.row.batch_detail.bound_batch.goods_code }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_desc" :props="props">{{ props.row.batch_detail.bound_batch.goods_desc }}</q-td>
+            </template>            
+            
+            <template >
+              <q-td key="goods_std" :props="props">{{ props.row.batch_detail.bound_batch.goods_std }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_batch" :props="props">{{ props.row.container_detail.batch.bound_number }}</q-td>
+            </template>            
+            <template >
+              <q-td key="in_batch" :props="props">{{ props.row.container_detail.batch.goods_code}}</q-td>
+            </template>            
+            <template >
+              <q-td key="out_batch" :props="props">{{ props.row.batch_detail.bound_batch.out_batch }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_unit" :props="props">{{ props.row.batch_detail.bound_batch.goods_unit }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_in" :props="props">{{ props.row.container_detail.goods_qty }}</q-td>
+            </template>            
+            <template >
+              <q-td key="container_number" :props="props">{{ props.row.container_detail.container.container_code }}</q-td>
+            </template>            
+            <template >
+              <q-td key="goods_notes" :props="props">{{ props.row.task_wcs.message}}</q-td>
+            </template>            
+            <template >
+              <q-td key="creator" :props="props">{{ props.row.container_detail.creater}}</q-td>
+            </template>            
+ 
+
+
+
+
+
+
+          </q-tr>
+        </template>
+      </q-table>
+    </transition>
+    <template>
+      <div v-show="max !== 0" class="q-pa-lg flex flex-center">
+        <div>{{ total }} </div>
+        <q-pagination v-model="current" color="black" :max="max" :max-pages="6" boundary-links
+          @click="getSearchList(current); paginationIpt = current" />
+        <div>
+          <input v-model="paginationIpt" @blur="changePageEnter" @keyup.enter="changePageEnter"
+            style="width: 60px; text-align: center" />
+        </div>
+      </div>
+      <div v-show="max === 0" class="q-pa-lg flex flex-center">
+        <q-btn flat push color="dark" :label="$t('no_data')"></q-btn>
+      </div>
+    </template>
+
+  </div>
+</template>
+<router-view />
+
+<script>
+import { getauth, postauth, putauth, deleteauth } from 'boot/axios_request'
+import { date, exportFile, LocalStorage } from 'quasar'
+
+
+export default {
+  name: 'PageTask',
+  data() {
+    return {
+      createDate1: '',
+      createDate2: '',
+      date_range: '',
+      proxyDate: '',
+      date: '',
+      goods_code: '',
+      goods_desc: '',
+      openid: '',
+      login_name: '',
+      authin: '0',
+      searchUrl: '',
+      pathname: 'container/task/',
+
+      pathname_previous: '',
+      pathname_next: '',
+      separator: 'cell',
+      loading: false,
+      height: '',
+      viewForm: false,
+
+      table_list: [],
+      columns: [
+          { name: 'document_date', required: true, label: '入库时间', align: 'center', field: 'document_date' },
+          { name: 'document_number', label: '单据编号', field: 'document_number', align: 'center' },
+          { name: 'department', label: '部门', field: 'department', align: 'center' },
+
+          { name: 'goods_code', label: '存货编码', field: 'goods_code', align: 'center' },
+          { name: 'goods_desc', label: '存货', field: 'goods_desc', align: 'center' },
+          { name: 'goods_std', label: '规格型号', field: 'goods_std', align: 'center' },
+          { name: 'goods_batch', label: '入库批号', field: 'goods_batch', align: 'center' },
+
+
+          { name: 'goods_in', label: '入库数目', field: 'goods_in', align: 'center' },
+          { name: 'container_number', label: '托盘编码', field: 'container_number', align: 'center' },
+
+          // { name: 'goods_notes', label: '备注', field: 'goods_notes', align: 'center' },
+          { name: 'creator', label: '创建人', field: 'creator', align: 'center' },
+
+        ],
+      filter: '',
+      pagination: {
+        page: 1,
+        rowsPerPage: 11
+      },
+      current: 1,
+      max: 0,
+      total: 0,
+      paginationIpt: 1,
+      current: 1,
+
+    }
+
+  },
+  computed: {
+    interval() {
+      return this.$t('download_center.start') + ' - ' + this.$t('download_center.end')
+    }
+  },
+  methods: {
+    getList(params = {}) {
+      var _this = this
+      _this.loading = true
+      // 合并基础参数
+      const baseParams = {
+        page: _this.current,
+        page_size: _this.pagination.rowsPerPage
+      }
+
+      // 创建URLSearchParams处理参数
+      const queryParams = new URLSearchParams({
+        ...baseParams,
+        ...params
+      })
+      console.log(queryParams)
+      // 过滤空值参数
+      Array.from(queryParams.entries()).forEach(([key, value]) => {
+        if (value === '' || value === null || value === undefined) {
+          queryParams.delete(key)
+        }
+      })
+
+      getauth(`${_this.pathname}?${queryParams}`)
+        .then(res => {
+          _this.table_list = res.results
+          _this.total = res.count
+          _this.max = Math.ceil(res.count / _this.pagination.rowsPerPage) || 0
+          _this.pathname_previous = res.previous
+          _this.pathname_next = res.next
+        })
+        .catch(err => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
+          })
+        })
+        .finally(() => {
+          _this.loading = false
+        })
+    },
+    changePageEnter() {
+      if (Number(this.paginationIpt) < 1) {
+        this.current = 1
+        this.paginationIpt = 1
+      } else if (Number(this.paginationIpt) > this.max) {
+        this.current = this.max
+        this.paginationIpt = this.max
+      } else {
+        this.current = Number(this.paginationIpt)
+      }
+      this.getSearchList(this.current)
+    },
+
+    // 带搜索条件加载
+    getSearchList(page = 1) {
+      this.current = page
+      this.paginationIpt = page
+      this.getList({
+        container_detail__goods_desc__icontains: this.filter,
+        create_time__range: this.date_range
+      })
+    },
+
+    getListPrevious() {
+      var _this = this
+      if (LocalStorage.has('auth')) {
+        getauth(_this.pathname_previous, {})
+          .then(res => {
+            _this.table_list = res.results
+            _this.pathname_previous = res.previous
+            _this.pathname_next = res.next
+          })
+          .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      } else {
+      }
+    },
+    getListNext() {
+      var _this = this
+      if (LocalStorage.has('auth')) {
+        getauth(_this.pathname_next, {})
+          .then(res => {
+            _this.table_list = res.results
+
+            _this.pathname_previous = res.previous
+            _this.pathname_next = res.next
+          })
+          .catch(err => {
+            _this.$q.notify({
+              message: err.detail,
+              icon: 'close',
+              color: 'negative'
+            })
+          })
+      }
+    },
+    reFresh() {
+      var _this = this
+      _this.getSearchList()
+    },
+
+
+    updateProxy() {
+      var _this = this
+      _this.proxyDate = _this.date
+    }
+
+  },
+  created() {
+    var _this = this
+    if (LocalStorage.has('openid')) {
+      _this.openid = LocalStorage.getItem('openid')
+    } else {
+      _this.openid = ''
+      LocalStorage.set('openid', '')
+    }
+    if (LocalStorage.has('login_name')) {
+      _this.login_name = LocalStorage.getItem('login_name')
+    } else {
+      _this.login_name = ''
+      LocalStorage.set('login_name', '')
+    }
+    if (LocalStorage.has('auth')) {
+      const timeStamp = Date.now()
+      const formattedString = date.formatDate(timeStamp, 'YYYY/MM/DD')
+      _this.date = formattedString
+      console.log(_this.date)
+      _this.authin = '1'
+      _this.getList()
+    } else {
+      _this.authin = '0'
+    }
+  },
+  mounted() {
+    var _this = this
+    if (_this.$q.platform.is.electron) {
+      _this.height = String(_this.$q.screen.height - 290) + 'px'
+    } else {
+      _this.height = _this.$q.screen.height - 290 + '' + 'px'
+    }
+  },
+  updated() { },
+  destroyed() { },
+  // 在 watch 或方法中添加调试代码
+  watch: {
+    createDate1(val) {
+      if (val) {
+        if (val.to) {
+          this.createDate2 = `${val.from} - ${val.to}`
+          this.date_range = `${val.from},${val.to} `
+
+          // this.downloadhUrl = this.pathname + 'filelist/?' + 'document_date__range=' + this.date_range
+        } else {
+          this.createDate2 = `${val}`
+          this.dateArray = val.split('/')
+          this.searchUrl = this.pathname + '?' + 'document_date__year=' + this.dateArray[0] + '&' + 'document_date__month=' + this.dateArray[1] + '&' + 'document_date__day=' + this.dateArray[2]
+          // this.downloadhUrl = this.pathname + 'filelist/?' + 'document_date__year=' + this.dateArray[0] + '&' + 'document_date__month=' + this.dateArray[1] + '&' + 'document_date__day=' + this.dateArray[2]
+        }
+        this.date_range = this.date_range.replace(/\//g, '-')
+
+        this.getSearchList()
+        this.$refs.qDateProxy.hide()
+      }
+      else {
+        this.createDate2 = ''
+        this.date_range = ''
+        this.getSearchList()
+      }
+    }
+  }
+}
+</script>
+<style scoped>
+/* 添加在 <style> 中 */
+.q-date__calendar-item--selected {
+  transition: all 0.3s ease;
+  background-color: #1976d2 !important;
+}
+
+.q-date__range {
+  background-color: rgba(25, 118, 210, 0.1);
+}
+</style>

+ 16 - 0
templates/src/router/routes.js

@@ -101,6 +101,22 @@ const routes = [{
   
       ]
     },
+    {
+      path: 'erp',
+      name: 'erp',
+      component: () => import('pages/erp/erp.vue'),
+      children: [{
+        path: 'erpasn',
+        name: 'erpasn',
+        component: () => import('pages/erp/erpasn.vue')
+      },
+      {
+        path: 'erpsortstock',
+        name: 'erpsortstock',
+        component: () => import('pages/erp/erpsortstock.vue')
+      }
+      ]
+    },
     {
       path: 'inbound',
       name: 'inbound',