Procházet zdrojové kódy

add 回收统计页面

haveyou před 1 rokem
rodič
revize
8c08872ce6
32 změnil soubory, kde provedl 1715 přidání a 64 odebrání
  1. 19 7
      src/components/CommonPage/CommonTable.vue
  2. 6 0
      src/layout/index.vue
  3. 2 2
      src/views/recycleLogistics/arrivalSign/components/arrivalSign-search.vue
  4. 4 4
      src/views/recycleLogistics/components/order-search.vue
  5. 2 2
      src/views/recycleLogistics/transferSign/components/page-search.vue
  6. 2 18
      src/views/recycleService/location/components/location-edit.vue
  7. 1 1
      src/views/recycleService/location/components/location-import.vue
  8. 3 20
      src/views/recycleService/location/components/location-search.vue
  9. 21 10
      src/views/recycleService/location/index.vue
  10. 62 0
      src/views/statistic/after-sales/components/page-search.vue
  11. 76 0
      src/views/statistic/after-sales/index.vue
  12. 67 0
      src/views/statistic/arrivalSign/components/page-search.vue
  13. 63 0
      src/views/statistic/arrivalSign/index.vue
  14. 67 0
      src/views/statistic/audit/components/page-search.vue
  15. 77 0
      src/views/statistic/audit/index.vue
  16. 67 0
      src/views/statistic/defect/components/page-search.vue
  17. 63 0
      src/views/statistic/defect/index.vue
  18. 67 0
      src/views/statistic/entry/components/page-search.vue
  19. 80 0
      src/views/statistic/entry/index.vue
  20. 67 0
      src/views/statistic/inspection/components/page-search.vue
  21. 63 0
      src/views/statistic/inspection/index.vue
  22. 137 0
      src/views/statistic/overview/components/map-card.vue
  23. 59 0
      src/views/statistic/overview/components/pie-chart.vue
  24. 33 0
      src/views/statistic/overview/components/rank-list.vue
  25. 75 0
      src/views/statistic/overview/components/stat-card.vue
  26. 133 0
      src/views/statistic/overview/index.vue
  27. 74 0
      src/views/statistic/recycleOrder/components/page-search.vue
  28. 67 0
      src/views/statistic/recycleOrder/index.vue
  29. 67 0
      src/views/statistic/unpacking/components/page-search.vue
  30. 62 0
      src/views/statistic/unpacking/index.vue
  31. 67 0
      src/views/statistic/weight/components/page-search.vue
  32. 62 0
      src/views/statistic/weight/index.vue

+ 19 - 7
src/components/CommonPage/CommonTable.vue

@@ -1,5 +1,5 @@
 <template>
-  <ele-card :body-style="{ paddingTop: '8px',...bodyStyle }" flex-table>
+  <ele-card :body-style="{ paddingTop: '8px', ...bodyStyle }" :flex-table="flexTable">
     <!-- 表格 -->
     <ele-pro-table
       ref="tableRef"
@@ -42,7 +42,8 @@
     pageUrl: { type: String, default: '/system/post/list' },
     exportUrl: { type: String, default: '/system/post/export' },
     columns: { type: Array, default: () => [] },
-    bodyStyle: { type: Object, default: () => ({}) }
+    bodyStyle: { type: Object, default: () => ({}) },
+    flexTable: { type: Boolean, default: true }
   });
   let { proxy } = getCurrentInstance();
 
@@ -74,7 +75,7 @@
   };
 
   /** 批量操作 */
-  const operatBatch = ({ method, row, url, title }) => {
+  const operatBatch = ({ method, row, url, title, data = {} }) => {
     const rows = row == null ? selections.value : [row];
     if (!rows.length) {
       EleMessage.error('请至少选择一条数据');
@@ -90,8 +91,7 @@
           message: '请求中..',
           plain: true
         });
-
-        proxy.$http[method](url)
+        proxy.$http[method](url, data)
           .then((res) => {
             if (res.data.code === 200) {
               EleMessage.success('操作成功');
@@ -124,6 +124,15 @@
     );
   }
 
+  //导出数据 进导出记录
+  function exportRecord(params, name) {
+    return proxy.$http({
+      url: props.pageConfig.exportUrl,
+      method: 'POST',
+      data: params
+    }); // 导出记录
+  }
+
   /** 导出数据 */
   const exportData = (name) => {
     const loading = EleMessage.loading({
@@ -131,8 +140,11 @@
       plain: true
     });
     tableRef.value?.fetch?.(({ where, orders }) => {
-      exportPage({ ...where, ...orders }, name)
-        .then(() => {
+      exportRecord({ ...where, ...orders }, name)
+        .then((res) => {
+          if (res.data.code === 200) {
+            EleMessage.success('操作成功,请前往导出记录下载');
+          }
           loading.close();
         })
         .catch((e) => {

+ 6 - 0
src/layout/index.vue

@@ -43,6 +43,7 @@
     @tabContextMenu="handleTabContextMenu"
     @tabSortChange="setPageTabs"
     @bodySizeChange="handleBodySizeChange"
+    @headMenuOpen="handleSideMenuOpen"
   >
     <router-layout />
     <!-- logo -->
@@ -331,6 +332,11 @@
     }
   };
 
+  //菜单点击事件
+  function handleSideMenuOpen(data, data1) {
+    console.log('handleSideMenuOpen', data, data1);
+  }
+
   /** 内容区尺寸改变事件 */
   const handleBodySizeChange = ({ width }) => {
     themeStore.setContentWidth(width ?? null);

+ 2 - 2
src/views/recycleLogistics/arrivalSign/components/arrivalSign-search.vue

@@ -23,7 +23,7 @@
     { type: 'input', label: '物流CODE', prop: 'code' },
     {
       type: 'date',
-      label: '签收时间(开始事件)',
+      label: '签收时间(开始时间)',
       prop: 'beginTime',
       props: {
         format: 'YYYY-MM-DD',
@@ -32,7 +32,7 @@
     },
     {
       type: 'date',
-      label: '签收时间(结束事件)',
+      label: '签收时间(结束时间)',
       prop: 'endTime',
       props: {
         format: 'YYYY-MM-DD',

+ 4 - 4
src/views/recycleLogistics/components/order-search.vue

@@ -21,7 +21,7 @@
     { type: 'input', label: '推送人', prop: 'bookName' },
     {
       type: 'date',
-      label: '推送时间(开始事件)',
+      label: '推送时间(开始时间)',
       prop: 'beginTime',
       props: {
         format: 'YYYY-MM-DD',
@@ -30,7 +30,7 @@
     },
     {
       type: 'date',
-      label: '推送时间(结束事件)',
+      label: '推送时间(结束时间)',
       prop: 'endTime',
       props: {
         format: 'YYYY-MM-DD',
@@ -40,7 +40,7 @@
     { type: 'input', label: '处理人', prop: 'isbn' },
     {
       type: 'date',
-      label: '建单时间(开始事件)',
+      label: '建单时间(开始时间)',
       prop: 'beginTime',
       props: {
         format: 'YYYY-MM-DD',
@@ -49,7 +49,7 @@
     },
     {
       type: 'date',
-      label: '建单时间(结束事件)',
+      label: '建单时间(结束时间)',
       prop: 'endTime',
       props: {
         format: 'YYYY-MM-DD',

+ 2 - 2
src/views/recycleLogistics/transferSign/components/page-search.vue

@@ -23,7 +23,7 @@
     { type: 'input', label: '物流CODE', prop: 'code' },
     {
       type: 'date',
-      label: '签收时间(开始事件)',
+      label: '签收时间(开始时间)',
       prop: 'beginTime',
       props: {
         format: 'YYYY-MM-DD',
@@ -32,7 +32,7 @@
     },
     {
       type: 'date',
-      label: '签收时间(结束事件)',
+      label: '签收时间(结束时间)',
       prop: 'endTime',
       props: {
         format: 'YYYY-MM-DD',

+ 2 - 18
src/views/recycleService/location/components/location-edit.vue

@@ -29,27 +29,11 @@
         prop: 'godownId',
         required: true,
         options: godownList.value.map((d) => {
-          return { label: d.name, value: d.id };
+          return { label: d.godownName, value: d.id };
         }),
         props: {
           placeholder: '请选择或输入搜索',
-          filterable: true,
-          remote: true,
-          remoteMethod: (query) => {
-            if (!query) {
-              return [];
-            }
-            return getStoreList(query).then((res) => {
-              if (res.data.code == 200) {
-                return res.data.data.map((v) => ({
-                  label: v.name,
-                  value: v.id
-                }));
-              } else {
-                return [];
-              }
-            });
-          }
+          filterable: true
         }
       },
       {

+ 1 - 1
src/views/recycleService/location/components/location-import.vue

@@ -10,7 +10,7 @@
       <el-button
         @click="
           downloadOssLink(
-            'https://shuhi.oss-cn-qingdao.aliyuncs.com/default/book_info_export_template.xlsx',
+            'https://shuhi.oss-cn-qingdao.aliyuncs.com/default/godown_import_template.xlsx',
             '库位导入模板'
           )
         "

+ 3 - 20
src/views/recycleService/location/components/location-search.vue

@@ -24,28 +24,11 @@
         label: '仓库名称',
         prop: 'godownId',
         options: godownList.value.map((d) => {
-          return { label: d.name, value: d.id };
+          return { label: d.godownName, value: d.id };
         }),
         props: {
           placeholder: '请选择或输入搜索',
-          filterable: true,
-          remote: true,
-          remoteMethod: (query) => {
-            console.log('query', query);
-            if (!query) {
-              return [];
-            }
-            return getStoreList(query).then((res) => {
-              if (res.data.code == 200) {
-                return res.data.data.map((v) => ({
-                  label: v.name,
-                  value: v.id
-                }));
-              } else {
-                return [];
-              }
-            });
-          }
+          filterable: true
         }
       },
       { type: 'input', label: '库位编码', prop: 'code' },
@@ -60,7 +43,7 @@
     ];
   });
 
-  function getStoreList(name="") {
+  function getStoreList(name = '') {
     return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
   }
   getStoreList().then((res) => {

+ 21 - 10
src/views/recycleService/location/index.vue

@@ -27,7 +27,7 @@
           plain
           :icon="DeleteOutlined"
           v-permission="'recycleService:location:batchDisabled'"
-          @click="handleBatchDelete()"
+          @click="handleBatchDisabled()"
         >
           批量停用
         </el-button>
@@ -110,16 +110,13 @@
   import CommonTable from '@/components/CommonPage/CommonTable.vue';
   import locationSearch from '@/views/recycleService/location/components/location-search.vue';
   import locationEdit from '@/views/recycleService/location/components/location-edit.vue';
-  import locationImport from '@/views/recycleService/location/components/location-import.vue'
+  import locationImport from '@/views/recycleService/location/components/location-import.vue';
   import { useDictData } from '@/utils/use-dict-data';
   import { useRouter } from 'vue-router';
   import request from '@/utils/request';
 
   defineOptions({ name: 'locationList' });
-  const [schoolLevelDicts, UseStatusDicts] = useDictData([
-    'school_level',
-    'use_status'
-  ]);
+  const [UseStatusDicts] = useDictData(['use_status']);
 
   /** 表格列配置 */
   const columns = ref([
@@ -170,15 +167,29 @@
   //批量删除
   function handleBatchDelete(row) {
     let selections = row ? [row] : pageRef.value?.getSelections();
-    let ids = selections.map((item) => item.id).join(',');
-    let url = `/baseinfo/godownposition/delete?id=${ids}`;
+    let ids = selections.map((item) => item.id);
+    let url = `/baseinfo/godownposition/delete`;
     pageRef.value?.operatBatch({
       title: '确认删除?',
-      method: 'delete',
+      method: 'post',
       url,
-      row
+      row,
+      data: [...ids]
     });
   }
+  //批量停用
+  function handleBatchDisabled() {
+    let selections = pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id);
+    let url = `/baseinfo/godownposition/setStatusBatch`;
+    pageRef.value?.operatBatch({
+      title: '确定停用选中的库位信息?',
+      method: 'post',
+      url,
+      data: { useStatus: 0, ids: [...ids] }
+    });
+  }
+
   //导出excel
   function handleExportExcel() {
     pageRef.value?.exportData('库位管理');

+ 62 - 0
src/views/statistic/after-sales/components/page-search.vue

@@ -0,0 +1,62 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 5
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 76 - 0
src/views/statistic/after-sales/index.vue

@@ -0,0 +1,76 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-radio-group @change="handleStatusChange" v-model="useStatus">
+            <el-radio-button label="售后订单实时统计" value="1" />
+            <el-radio-button label="售后订单历史统计" value="2" />
+          </el-radio-group>
+          <el-button
+            style="margin-left: 40px"
+            type="success"
+            plain
+            v-permission="'statistic:afterSales:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'afterSalesStatistic' });
+
+  const useStatus = ref('1');
+  function handleStatusChange(val) {
+    useStatus.value = val;
+    pageRef.value?.reload();
+  }
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '售后订单数', prop: 'orderNum', align: 'center' },
+    { label: '发出订单数', prop: 'bookNum', align: 'center' },
+    { label: '未发订单数', prop: 'price', align: 'center' },
+    { label: '客户申请时间', prop: 'createTime', align: 'center' },
+    { label: '仓库', prop: 'godownName', align: 'center' },
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '售后统计',
+    cacheKey: 'afterSalesStatisticTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('售后统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/arrivalSign/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '操作员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 63 - 0
src/views/statistic/arrivalSign/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:arrivalSign:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+
+  defineOptions({ name: 'arrivalSign' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '操作员', prop: 'godownName', align: 'center' },
+    { label: '到仓签收包裹数量', prop: 'orderNum', align: 'center' },
+    { label: '统计日期', prop: 'createTime', align: 'center' },
+    { label: '仓库', prop: 'godownName', align: 'center' }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '到仓签收统计',
+    cacheKey: 'arrivalSignTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('到仓签收统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/audit/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '审核员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 77 - 0
src/views/statistic/audit/index.vue

@@ -0,0 +1,77 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-radio-group @change="handleStatusChange" v-model="useStatus">
+            <el-radio-button label="订单审核实时统计" value="1" />
+            <el-radio-button label="订单审核历史统计" value="2" />
+          </el-radio-group>
+          <el-button
+            style="margin-left: 40px"
+            type="success"
+            plain
+            v-permission="'statistic:recycleOrder:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'auditOrder' });
+
+  const useStatus = ref('1');
+  function handleStatusChange(val) {
+    useStatus.value = val;
+    pageRef.value?.reload();
+  }
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '审核员', prop: 'godownName', align: 'center' },
+    { label: '审核订单量', prop: 'orderNum', align: 'center' },
+    { label: '审核书籍数量', prop: 'bookNum', align: 'center' },
+    { label: '实际回收数量', prop: 'price', align: 'center' },
+    { label: '不良率', prop: 'auditNum', align: 'center' },
+    { label: '统计日期', prop: 'createTime', align: 'center' }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '审核统计',
+    cacheKey: 'auditOrderTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('审核统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/defect/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '地区',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 63 - 0
src/views/statistic/defect/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:defect:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+
+  defineOptions({ name: 'arrivalSign' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '地区', prop: 'godownName', align: 'center' },
+    { label: '收货仓库', prop: 'godownName', align: 'center' },
+    { label: '不良率', prop: 'godownName', align: 'center' }
+    { label: '统计日期', prop: 'createTime', align: 'center' },
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '不良统计',
+    cacheKey: 'arrivalSignTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('不良统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/entry/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '审核员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 80 - 0
src/views/statistic/entry/index.vue

@@ -0,0 +1,80 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-radio-group @change="handleStatusChange" v-model="useStatus">
+            <el-radio-button label="订单审核实时统计" value="1" />
+            <el-radio-button label="订单审核历史统计" value="2" />
+          </el-radio-group>
+          <el-button
+            style="margin-left: 40px"
+            type="success"
+            plain
+            v-permission="'statistic:entry:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'entryStatistic' });
+
+  const useStatus = ref('1');
+  function handleStatusChange(val) {
+    useStatus.value = val;
+    pageRef.value?.reload();
+  }
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '录入员', prop: 'godownName', align: 'center' },
+    { label: '录入审核订单', prop: 'orderNum', align: 'center' },
+    { label: '录入书籍数量', prop: 'bookNum', align: 'center' },
+    { label: '实际回收数量', prop: 'price', align: 'center' },
+    { label: '品相良好', prop: 'price', align: 'center' },
+    { label: '品相一般', prop: 'price', align: 'center' },
+    { label: '品相极差', prop: 'price', align: 'center' },
+    { label: '不良率', prop: 'auditNum', align: 'center' },
+    { label: '审核日期', prop: 'createTime', align: 'center' }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '录入统计',
+    cacheKey: 'entryStatisticTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('录入统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/inspection/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '操作员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 63 - 0
src/views/statistic/inspection/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:inspection:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+
+  defineOptions({ name: 'inspectionList' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '操作员', prop: 'godownName', align: 'center' },
+    { label: '批次号', prop: 'orderNum', align: 'center' },
+    { label: '验收包裹数量', prop: 'godownName', align: 'center' },
+    { label: '统计日期', prop: 'createTime', align: 'center' }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '物流验收统计',
+    cacheKey: 'inspectionTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('物流验收统计');
+  }
+</script>

+ 137 - 0
src/views/statistic/overview/components/map-card.vue

@@ -0,0 +1,137 @@
+<template>
+  <el-row class="flex-auto">
+    <el-col :sm="14" :xs="24">
+      <v-chart
+        ref="userMapChartRef"
+        :option="userCountMapOption"
+        style="height: 468px"
+      />
+    </el-col>
+    <el-col :sm="10" :xs="24">
+      <rankList />
+    </el-col>
+  </el-row>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { use, registerMap } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { MapChart } from 'echarts/charts';
+  import {
+    VisualMapComponent,
+    GeoComponent,
+    TooltipComponent
+  } from 'echarts/components';
+  import VChart from 'vue-echarts';
+  import { useEcharts } from '@/utils/use-echarts';
+  import rankList from './rank-list.vue'
+  import axios from 'axios';
+
+  use([
+    CanvasRenderer,
+    MapChart,
+    VisualMapComponent,
+    GeoComponent,
+    TooltipComponent
+  ]);
+
+  const userMapChartRef = ref(null);
+
+  useEcharts([userMapChartRef]);
+
+  /** 用户分布前 10 名 */
+  const userCountDataRank = ref([]);
+
+  /** 用户分布地图配置 */
+  const userCountMapOption = reactive({});
+
+  /** 获取中国地图数据并注册地图 */
+  const registerChinaMap = () => {
+    axios.get('/json/china-provinces.geo.json').then((res) => {
+      registerMap('china', res.data);
+      getUserCountData();
+    });
+  };
+
+  /** 获取用户分布数据 */
+  const getUserCountData = () => {
+    let data = [
+      { name: '贵州', value: 570 },
+      { name: '云南', value: 8890 },
+      { name: '重庆', value: 10010 },
+      { name: '吉林', value: 5056 },
+      { name: '山西', value: 2123 },
+      { name: '天津', value: 9130 },
+      { name: '江西', value: 10170 },
+      { name: '广西', value: 6172 },
+      { name: '陕西', value: 9251 },
+      { name: '黑龙江', value: 5125 },
+      { name: '安徽', value: 9530 },
+      { name: '北京', value: 51919 },
+      { name: '福建', value: 3756 },
+      { name: '上海', value: 59190 },
+      { name: '湖北', value: 37109 },
+      { name: '湖南', value: 8966 },
+      { name: '四川', value: 31020 }
+    ];
+
+    const temp = data.sort((a, b) => b.value - a.value);
+    const min = temp[temp.length - 1].value || 0;
+    const max = temp[0].value || 1;
+    //
+    const list = temp.length > 10 ? temp.slice(0, 15) : temp;
+    userCountDataRank.value = list.map((d) => {
+      return {
+        name: d.name,
+        value: d.value,
+        percent: (d.value / max) * 100
+      };
+    });
+    //
+    Object.assign(userCountMapOption, {
+      tooltip: {
+        trigger: 'item',
+        borderWidth: 1
+      },
+      visualMap: {
+        min: min,
+        max: max,
+        text: ['高', '低'],
+        calculable: true,
+        bottom: 10
+      },
+      series: [
+        {
+          name: '用户数',
+          label: {
+            show: true
+          },
+          type: 'map',
+          map: 'china',
+          data: data
+        }
+      ]
+    });
+  };
+
+  registerChinaMap();
+</script>
+
+<style lang="scss" scoped>
+  .user-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8px;
+
+    .user-item-body {
+      flex: 1;
+      padding: 0 10px 0 12px;
+    }
+
+    :deep(.el-progress-bar__outer) {
+      background-color: transparent;
+    }
+  }
+</style>

+ 59 - 0
src/views/statistic/overview/components/pie-chart.vue

@@ -0,0 +1,59 @@
+<template>
+  <v-chart class="flex-1" ref="saleChartRef" style="height: 220px" :option="options" />
+</template>
+<script setup>
+  import VChart from 'vue-echarts';
+  import { use } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { PieChart } from 'echarts/charts';
+  import {
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    TitleComponent
+  } from 'echarts/components';
+
+  // 按需加载echarts
+  use([
+    CanvasRenderer,
+    PieChart,
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    TitleComponent
+  ]);
+
+  const options = reactive({
+    title: {
+      text: '回收折扣占比',
+      textStyle: {
+        color: '#363636',
+        fontSize: 14,
+        fontWeight: 'normal'
+      }
+    },
+    legend: {
+      right: 'right',
+      orient: 'vertical',
+      top: 'center'
+    },
+    series: [
+      {
+        name: 'Nightingale Chart',
+        type: 'pie',
+        radius: [15, 40],
+        center: ['35%', '50%'],
+        roseType: 'area',
+        itemStyle: {
+          borderRadius: 8
+        },
+        data: [
+          { value: 40, name: '≥2折' },
+          { value: 38, name: '2<至≥1' },
+          { value: 32, name: '1<至≥0.5' },
+          { value: 30, name: '≤0.5' }
+        ]
+      }
+    ]
+  });
+</script>

+ 33 - 0
src/views/statistic/overview/components/rank-list.vue

@@ -0,0 +1,33 @@
+<template>
+    <ele-data-table
+      ref="tableRef"
+      class="flex-1"
+      row-key="id"
+      :columns="columns"
+      :data="dataList"
+    ></ele-data-table>
+  </template>
+  
+  <script setup>
+    import SimpleTable from '@/components/CommonPage/SimpleTable.vue';
+    import request from '@/utils/request';
+  
+    const columns = reactive([
+      { label: '排行榜', type: 'index', align: 'center',width:70 },
+      { label: '地区', prop: 'area', align: 'center' },
+      { label: '单量', prop: 'number', align: 'center' },
+      { label: '涨幅', prop: 'up', align: 'center' }
+    ]);
+  
+    const dataList = reactive([
+      { rank: 1, area: '北京', number: 10 },
+      { rank: 2, area: '上海', number: 9 },
+      { rank: 3, area: '广州', number: 8 },
+      { rank: 4, area: '深圳', number: 7 },
+      { rank: 5, area: '成都', number: 6 },
+      { rank: 6, area: '杭州', number: 5 },
+      { rank: 7, area: '武汉', number: 4 },
+      { rank: 8, area: '西安', number: 3 },
+    ]);
+  </script>
+  

+ 75 - 0
src/views/statistic/overview/components/stat-card.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="flex flex-col items-center justify-center w-full">
+    <el-statistic :title="title" :value="98500"> </el-statistic>
+    <v-chart ref="saleChartRef" :style="{ height: height }" :option="options" />
+  </div>
+</template>
+<script setup>
+  import VChart from 'vue-echarts';
+  import { use } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { LineChart } from 'echarts/charts';
+  import {
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    ToolboxComponent
+  } from 'echarts/components';
+  import { Top, Bottom } from '@element-plus/icons-vue';
+
+  const props = defineProps({
+    title: {
+      type: String,
+      default: '统计'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '120px'
+    }
+  });
+  // 按需加载echarts
+  use([
+    CanvasRenderer,
+    LineChart,
+    GridComponent,
+    TooltipComponent,
+    LegendComponent
+  ]);
+
+  const options = reactive({
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      show: false,
+      data: ['新增用户数']
+    },
+    grid: {
+      left: '2%',
+      right: '2%',
+      bottom: '2%',
+      top: '10%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: ['1月', '2月', '3月', '4月', '5月']
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: props.title,
+        type: 'line',
+        data: [120, 132, 234, 134, 90],
+        smooth: true
+      }
+    ]
+  });
+</script>

+ 133 - 0
src/views/statistic/overview/index.vue

@@ -0,0 +1,133 @@
+<template>
+  <ele-page flex-table>
+    <ele-card flex-table>
+      <map-card class="flex-1" />
+
+      <div class="flex gap-10">
+        <div class="flex-1 stat-card">
+          <el-statistic
+            title="总审核单量"
+            :value="268500"
+            value-style="font-size:30px;color:#409eef"
+          />
+        </div>
+        <div class="flex-1 stat-card">
+          <el-statistic
+            title="总审核本数"
+            :value="268500"
+            value-style="font-size:30px;color:#409eef"
+          />
+        </div>
+        <div class="flex-1 stat-card">
+          <el-statistic
+            title="总审核金额"
+            :value="268500"
+            value-style="font-size:30px;color:#409eef"
+          />
+        </div>
+        <div class="flex-1 stat-card">
+          <el-statistic
+            title="总用户人数"
+            :value="268500"
+            value-style="font-size:30px;color:#409eef"
+          />
+        </div>
+      </div>
+      <el-divider></el-divider>
+      <div class="flex gap-4">
+        <div class="flex-1 stat-card">
+          <stat-card title="回收订单数"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="回收数量(本)"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="回收单本均价"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="待审核订单数"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="待签收订单数"></stat-card>
+        </div>
+      </div>
+      <div class="flex gap-4 mt-4">
+        <div class="flex-1 stat-card">
+          <stat-card title="今日扫描次数"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="今日扫描人数"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="用户增长数"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="待审核金额"></stat-card>
+        </div>
+        <div class="flex-1 stat-card">
+          <stat-card title="待打款金额"></stat-card>
+        </div>
+      </div>
+      <el-divider></el-divider>
+
+      <div class="flex gap-4">
+        <div style="flex: 4" class="flex flex-col">
+          <div class="flex gap-4">
+            <div class="flex-1 stat-card">
+              <stat-card title="回收订单数"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="回收数量(本)"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="回收单本均价"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="审核订单数"></stat-card>
+            </div>
+          </div>
+          <div class="flex gap-4 mt-4">
+            <div class="flex-1 stat-card">
+              <stat-card title="签收订单数"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="扫描次数"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="扫描人数"></stat-card>
+            </div>
+            <div class="flex-1 stat-card">
+              <stat-card title="用户增长数"></stat-card>
+            </div>
+          </div>
+        </div>
+
+        <div class="flex-1 flex flex-col stat-card">
+            <pie-chart />
+            <pie-chart />
+        </div>
+      </div>
+    </ele-card>
+  </ele-page>
+</template>
+
+<script setup>
+  import mapCard from '@/views/statistic/overview/components/map-card.vue';
+  import statCard from '@/views/statistic/overview/components/stat-card.vue';
+  import pieChart from '@/views/statistic/overview/components/pie-chart.vue'
+</script>
+
+<style lang="scss">
+  .stat-card {
+    border-radius: 10px;
+    background: #f8f7f6;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    .el-statistic__head {
+      text-align: center;
+    }
+  }
+</style>

+ 74 - 0
src/views/statistic/recycleOrder/components/page-search.vue

@@ -0,0 +1,74 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      @reset="reset"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'daterange',
+        label: '日期',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      },
+      {
+        type: 'select',
+        label: '仓库名称',
+        prop: 'godownId',
+        options: godownList.value.map((d) => {
+          return { label: d.godownName, value: d.id };
+        }),
+        props: {
+          placeholder: '请选择或输入搜索',
+          filterable: true
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data });
+  };
+</script>

+ 67 - 0
src/views/statistic/recycleOrder/index.vue

@@ -0,0 +1,67 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:recycleOrder:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'recycleOrder' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center',width:80 },
+    { label: '日期', prop: 'createTime', align: 'center' },
+    { label: '仓库', prop: 'godownName', align: 'center' },
+    { label: '回收订单数', prop: 'orderNum', align: 'center' },
+    { label: '回收本数', prop: 'bookNum', align: 'center' },
+    { label: '回收平均价格', prop: 'price', align: 'center' },
+    { label: '审核订单数', prop: 'auditNum', align: 'center' },
+    { label: '审核金额', prop: 'amount', align: 'center' }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '回收订单统计',
+    cacheKey: 'recycleOrderTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('回收订单统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/unpacking/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '拆包员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 62 - 0
src/views/statistic/unpacking/index.vue

@@ -0,0 +1,62 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:unpacking:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+
+  defineOptions({ name: 'unpackingStatistic' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '拆包员', prop: 'godownName', align: 'center' },
+    { label: '拆包数量', prop: 'orderNum', align: 'center' },
+    { label: '统计日期', prop: 'createTime', align: 'center' },
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '拆包统计',
+    cacheKey: 'unpackingTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('拆包统计');
+  }
+</script>

+ 67 - 0
src/views/statistic/weight/components/page-search.vue

@@ -0,0 +1,67 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+      :offset="1"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const godownList = ref([]);
+  const formItems = computed(() => {
+    return [
+      {
+        type: 'input',
+        label: '拆包员',
+        prop: 'auditName'
+      },
+      {
+        type: 'daterange',
+        label: ' ',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD',
+          valueFormat: 'YYYY-MM-DD',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  const initKeys = reactive({
+    startTime: '',
+    endTime: '',
+    godownId: ''
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data});
+  };
+</script>

+ 62 - 0
src/views/statistic/weight/index.vue

@@ -0,0 +1,62 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+      show-summary
+      :flex-table="false"
+    >
+      <template #toolbar="{ row }">
+        <div>
+          <el-button
+            type="success"
+            plain
+            v-permission="'statistic:weight:export'"
+            @click="handleExportExcel(row)"
+          >
+            导出EXCEL
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+
+  defineOptions({ name: 'weightStatistic' });
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'index', label: '#', align: 'center', width: 80 },
+    { label: '拆包员', prop: 'godownName', align: 'center' },
+    { label: '拆包数量', prop: 'orderNum', align: 'center' },
+    { label: '统计日期', prop: 'createTime', align: 'center' },
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
+    fileName: '重量统计',
+    cacheKey: 'weightStatisticTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('重量统计');
+  }
+</script>