Browse Source

feat(delivery): 添加所属企业筛选和订单类型筛选功能

zhangtao 2 weeks ago
parent
commit
692712653a

+ 2 - 2
.env.test

@@ -2,9 +2,9 @@
 # VITE_SERVICE_BASE_URL=http://74949mkfh190.vicp.fun
 # VITE_SERVICE_BASE_URL=http://192.168.1.253:8114 #付
 # VITE_SERVICE_BASE_URL=http://192.168.0.157:8114 #王
-# VITE_SERVICE_BASE_URL=http://192.168.1.166:8114 #张
+VITE_SERVICE_BASE_URL=http://192.168.1.166:8114 #张
 # VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
-VITE_SERVICE_BASE_URL=https://shop.platform.zswlgz.com #服务器
+# VITE_SERVICE_BASE_URL=https://shop.platform.zswlgz.com #服务器
 
 
 # other backend service base url, test environment

+ 1 - 1
.vscode/settings.json

@@ -3,7 +3,7 @@
     "source.fixAll.eslint": "explicit",
     "source.organizeImports": "never"
   },
-  "editor.formatOnSave": true,
+  "editor.formatOnSave": false,
   "eslint.validate": [
     "html",
     "css",

+ 8 - 1
src/components/zt/ApiSelect/api-select.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { computed, onMounted, ref, unref } from 'vue';
+import { computed, nextTick, onMounted, ref, unref } from 'vue';
 import { useDebounceFn } from '@vueuse/core';
 import { get } from '@/utils/zt/lodashChunk';
 import { isFunction } from '@/utils/zt/is';
@@ -51,6 +51,13 @@ async function fetchApi() {
   const res = await api(params);
   options.value = unref(bindValue).pagination ? [...options.value, ...res.data.records] : get(res, props.resultFeild);
   fetchLoading.value = false;
+  if (props.setDefaultValue) {
+    console.log(options.value[0], unref(bindValue).valueFeild, 'options.value');
+
+    nextTick(() => {
+      modelVlaue.value = options.value[0][unref(bindValue).valueFeild as string];
+    });
+  }
   if (props.getOptions) {
     props.getOptions(options.value);
   }

+ 4 - 0
src/components/zt/ApiSelect/type/index.ts

@@ -46,4 +46,8 @@ export interface ApiSelectProps extends /* @vue-ignore */ SelectProps {
    * 获取options
    */
   getOptions?: (options: any) => any;
+  /**
+   * 是否设置默认值
+   */
+  setDefaultValue?: boolean;
 }

+ 11 - 0
src/service/api/common.ts

@@ -56,3 +56,14 @@ export function fetchChannelList(data: any) {
     params: data
   });
 }
+
+/**
+ * 获取当前登录用户的所属企业
+ * @returns
+ */
+export function fetchGetLoginUserList() {
+  return request<Api.goods.Channel[]>({
+    url: '/platform/channel/list',
+    method: 'get'
+  });
+}

+ 3 - 2
src/service/api/delivery/normal-orde/index.ts

@@ -17,10 +17,11 @@ export function fetchGetDeliveryOrderList(data: any) {
  *  获取快递订单状态数量
  * @returns
  */
-export function fetchGetDeliveryStatusNum() {
+export function fetchGetDeliveryStatusNum(data: any) {
   return request<Api.delivery.DeliveryStatusNum>({
     url: '/platform/order/deliverListStatusNum',
-    method: 'get'
+    method: 'get',
+    params: data
   });
 }
 

+ 12 - 0
src/utils/common.ts

@@ -56,3 +56,15 @@ export function toggleHtmlClass(className: string) {
     remove
   };
 }
+
+/**
+ * 统一导出方法
+ * @param url
+ * @param params
+ */
+export function commonExport(url: string, params: any) {
+  const queryParams = new URLSearchParams(params).toString();
+  const baseUrl = `${import.meta.env.VITE_SERVICE_BASE_URL}${url}`;
+  const fullUrl = queryParams ? `${baseUrl}?${queryParams}` : baseUrl;
+  window.open(fullUrl, '_blank');
+}

+ 21 - 0
src/views/delivery/after-sales-order/after-sales-order.ts

@@ -13,6 +13,27 @@ export const SearchForm: FormSchema[] = [
       valueFeild: 'shopId'
     }
   },
+  {
+    label: '订单类型',
+    component: 'NSelect',
+    field: 'dvyType',
+    componentProps: {
+      options: [
+        {
+          label: '全部',
+          value: ''
+        },
+        {
+          label: '快递',
+          value: 1
+        },
+        {
+          label: '配送',
+          value: 3
+        }
+      ]
+    }
+  },
   {
     label: '退款编号',
     component: 'NInput',

+ 46 - 8
src/views/delivery/after-sales-order/index.vue

@@ -1,10 +1,13 @@
 <script setup lang="tsx">
-import { reactive, ref, unref, useTemplateRef, watch } from 'vue';
+import { nextTick, reactive, ref, unref, useTemplateRef, watch } from 'vue';
 import { NImage, NTag } from 'naive-ui';
 import { fetchGetAfterSalesOrderList, fetchGetAfterSalesStatusNum } from '@/service/api/delivery/after-sales-order';
+import { fetchGetLoginUserList } from '@/service/api/common';
 import { useAppStore } from '@/store/modules/app';
 import { defaultTransform, useNaivePaginatedTable } from '@/hooks/common/table';
+import { useAuth } from '@/hooks/business/auth';
 import { copyTextToClipboard } from '@/utils/zt';
+import { commonExport } from '@/utils/common';
 import { $t } from '@/locales';
 import { useForm } from '@/components/zt/Form/hooks/useForm';
 import NormalMoadl from '../normal-order/component/normal-modal.vue';
@@ -17,9 +20,31 @@ const activeTab = ref(0);
 const statusList = ref<{ label: string; value: number; num?: number; key: string }[]>([]);
 const orderMoadl = useTemplateRef('orderMoadl');
 const AfterSalesModal = useTemplateRef('AfterSalesModal');
-
-const [registerSearchForm, { getFieldsValue }] = useForm({
-  schemas: SearchForm,
+const channelIdList = ref([]);
+const [registerSearchForm, { getFieldsValue, setFieldsValue }] = useForm({
+  schemas: [
+    {
+      field: 'channelIdList',
+      label: '所属企业',
+      component: 'ApiSelect',
+      componentProps: {
+        api: () => fetchGetLoginUserList(),
+        labelFeild: 'channelName',
+        valueFeild: 'id',
+        multiple: true,
+        onUpdateValue: () => {
+          nextTick(() => {
+            handleSearch();
+          });
+        },
+        getOptions: async (options: any) => {
+          await setFieldsValue({ channelIdList: [options[0].id] });
+          handleSearch();
+        }
+      }
+    },
+    ...SearchForm
+  ],
   showAdvancedButton: false,
   labelWidth: 120,
   layout: 'horizontal',
@@ -37,6 +62,7 @@ const searchParams = reactive({
 const { columns, data, loading, getData, mobilePagination } = useNaivePaginatedTable({
   api: () => fetchGetAfterSalesOrderList({ ...searchParams, returnMoneySts: activeTab.value, ...unref(searchForm) }),
   transform: response => defaultTransform(response),
+  immediate: false,
   paginationProps: {
     pageSizes: import.meta.env.VITE_PAGE_SIZE.split(',').map(Number)
   },
@@ -295,24 +321,29 @@ function handleSearch() {
     delete form.createTime;
   }
   searchForm.value = form;
+  channelIdList.value = form.channelIdList;
+
   getData();
   getNums();
 }
 function handleReset() {
   searchForm.value = getFieldsValue();
+  searchForm.value.channelIdList = channelIdList.value;
+  setFieldsValue({ channelIdList: channelIdList.value });
   getData();
   getNums();
 }
 function handleExport() {
-  window.$message?.warning('功能开发中...');
+  const form = getFieldsValue();
+  commonExport('/platform/orderRefund/export', form);
 }
 </script>
 
 <template>
   <div class="flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
     <NCard :bordered="false" size="small">
-      <NCollapse display-directive="show">
-        <NCollapseItem title="搜索">
+      <NCollapse display-directive="show" default-expanded-names="search">
+        <NCollapseItem title="搜索" name="search">
           <BasicForm @register-form="registerSearchForm" @submit="handleSearch" @reset="handleReset" />
         </NCollapseItem>
       </NCollapse>
@@ -336,7 +367,14 @@ function handleExport() {
         </NScrollbar>
       </template>
       <template #header-extra>
-        <NButton size="small" type="primary" class="ml20px mt30px" ghost @click="handleExport">
+        <NButton
+          v-if="useAuth().hasAuth('order:user:export')"
+          size="small"
+          type="primary"
+          class="ml20px mt30px"
+          ghost
+          @click="handleExport"
+        >
           <template #icon>
             <SvgIcon icon="mingcute:file-export-line"></SvgIcon>
           </template>

+ 3 - 3
src/views/delivery/after-sales-order/order-modal.vue

@@ -20,7 +20,7 @@ const isRefundIng = ref(false);
 const goodsMoney = computed(() => {
   // 后端不算,让前端算
   return orderInfo.value?.orderRefundSkuList?.reduce((acc, item) => {
-    return acc + Number(item.orderItem.productTotalAmount) * Number(item.orderItem.prodCount);
+    return acc + Number(item.orderItem.price) * Number(item.orderItem.prodCount);
   }, 0);
 });
 
@@ -93,9 +93,9 @@ function getImgFils() {
           <div>退款件数: {{ orderInfo.goodsNum || '---' }}件</div>
         </NDescriptionsItem>
         <NDescriptionsItem label="购买信息">
-          <div>商品总额: {{ goodsMoney || '---' }}</div>
+          <div>商品总额: {{ goodsMoney?.toFixed(2) || '---' }}</div>
           <div>
-            配送费({{ dvyStatus[orderInfo.dvyType as keyof typeof dvyStatus]||'--' }}):
+            配送费({{ dvyStatus[orderInfo.dvyType as keyof typeof dvyStatus] || '--' }}):
             {{ orderInfo.freightAmount || '---' }}元
           </div>
           <div>积分抵扣: {{ (orderInfo.orderOffsetPoints / 100).toFixed(2) || '---' }}元</div>

+ 57 - 14
src/views/delivery/normal-order/index.vue

@@ -1,10 +1,13 @@
 <script setup lang="tsx">
-import { reactive, ref, unref, useTemplateRef, watch } from 'vue';
+import { nextTick, reactive, ref, unref, useTemplateRef, watch } from 'vue';
 import { NImage, NTag } from 'naive-ui';
 import { fetchGetDeliveryOrderList, fetchGetDeliveryStatusNum } from '@/service/api/delivery/normal-orde';
+import { fetchGetLoginUserList } from '@/service/api/common';
 import { useAppStore } from '@/store/modules/app';
 import { defaultTransform, useNaivePaginatedTable } from '@/hooks/common/table';
+import { useAuth } from '@/hooks/business/auth';
 import { copyTextToClipboard } from '@/utils/zt';
+import { commonExport } from '@/utils/common';
 import { $t } from '@/locales';
 import { useForm } from '@/components/zt/Form/hooks/useForm';
 import { SearchForm, ShippingButton, dvyStatus, orderStatus, refundStatus } from './normal-order';
@@ -16,9 +19,36 @@ const activeTab = ref('all');
 const statusList = ref<{ label: string; value: string; num?: number }[]>([]);
 const orderMoadl = useTemplateRef('orderMoadl');
 const ShipmentModal = useTemplateRef('Shipment');
-
-const [registerSearchForm, { getFieldsValue }] = useForm({
-  schemas: SearchForm,
+const channelIdList = ref([]);
+const searchForm = ref();
+const searchParams = reactive({
+  current: 1,
+  size: 10
+});
+const [registerSearchForm, { getFieldsValue, setFieldsValue }] = useForm({
+  schemas: [
+    {
+      field: 'channelIdList',
+      label: '所属企业',
+      component: 'ApiSelect',
+      componentProps: {
+        api: () => fetchGetLoginUserList(),
+        labelFeild: 'channelName',
+        valueFeild: 'id',
+        multiple: true,
+        onUpdateValue: () => {
+          nextTick(() => {
+            handleSearch();
+          });
+        },
+        getOptions: async (options: any) => {
+          await setFieldsValue({ channelIdList: [options[0].id] });
+          handleSearch();
+        }
+      }
+    },
+    ...SearchForm
+  ],
   showAdvancedButton: false,
   labelWidth: 120,
   layout: 'horizontal',
@@ -28,14 +58,10 @@ const [registerSearchForm, { getFieldsValue }] = useForm({
   },
   collapsedRows: 1
 });
-const searchForm = ref();
-const searchParams = reactive({
-  current: 1,
-  size: 10
-});
 const { columns, data, loading, getData, mobilePagination } = useNaivePaginatedTable({
   api: () => fetchGetDeliveryOrderList({ ...searchParams, orderStatus: activeTab.value, ...unref(searchForm) }),
   transform: response => defaultTransform(response),
+  immediate: false,
   paginationProps: {
     pageSizes: import.meta.env.VITE_PAGE_SIZE.split(',').map(Number)
   },
@@ -199,6 +225,7 @@ const { columns, data, loading, getData, mobilePagination } = useNaivePaginatedT
     }
   ]
 });
+
 async function handleDeivery(row: Api.delivery.deliveryOrder) {
   if (!row.orderNumber) {
     window.$message?.error('订单异常');
@@ -214,7 +241,7 @@ function handleOpenMoadl(row: Api.delivery.deliveryOrder) {
   orderMoadl.value?.open(String(row.orderNumber));
 }
 async function getNums() {
-  const { data: keyData } = await fetchGetDeliveryStatusNum();
+  const { data: keyData } = await fetchGetDeliveryStatusNum({ ...getFieldsValue() });
   if (!keyData) return;
   const orderStatusList = [
     {
@@ -270,12 +297,20 @@ function handleSearch() {
     form.endTime = form.createTime[1];
     delete form.createTime;
   }
+  channelIdList.value = form.channelIdList;
+  // if (form.channelIdList) {
+  //   form.channelIdList = form.channelIdList.join(',');
+  // }
   searchForm.value = form;
   getData();
+  getNums();
 }
 function handleReset() {
   searchForm.value = getFieldsValue();
+  searchForm.value.channelIdList = channelIdList.value;
+  setFieldsValue({ channelIdList: channelIdList.value });
   getData();
+  getNums();
 }
 async function handleCopy(row: Api.delivery.deliveryOrder) {
   if (!row.orderNumber) {
@@ -289,15 +324,16 @@ function handleRefsh() {
   getNums();
 }
 function handleExport() {
-  window.$message?.warning('功能开发中...');
+  const form = getFieldsValue();
+  commonExport('/platform/order/export', form);
 }
 </script>
 
 <template>
   <div class="flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
     <NCard :bordered="false" size="small">
-      <NCollapse display-directive="show">
-        <NCollapseItem title="搜索">
+      <NCollapse display-directive="show" default-expanded-names="search">
+        <NCollapseItem title="搜索" name="search">
           <BasicForm @register-form="registerSearchForm" @submit="handleSearch" @reset="handleReset" />
         </NCollapseItem>
       </NCollapse>
@@ -321,7 +357,14 @@ function handleExport() {
         </NScrollbar>
       </template>
       <template #header-extra>
-        <NButton size="small" type="primary" class="ml20px mt30px" ghost @click="handleExport">
+        <NButton
+          v-if="useAuth().hasAuth('order:user:export')"
+          size="small"
+          type="primary"
+          class="ml20px mt30px"
+          ghost
+          @click="handleExport"
+        >
           <template #icon>
             <SvgIcon icon="mingcute:file-export-line"></SvgIcon>
           </template>

+ 21 - 0
src/views/delivery/normal-order/normal-order.ts

@@ -15,6 +15,27 @@ export const SearchForm: FormSchema[] = [
       valueFeild: 'shopId'
     }
   },
+  {
+    label: '订单类型',
+    component: 'NSelect',
+    field: 'dvyType',
+    componentProps: {
+      options: [
+        {
+          label: '全部',
+          value: ''
+        },
+        {
+          label: '快递',
+          value: 1
+        },
+        {
+          label: '配送',
+          value: 3
+        }
+      ]
+    }
+  },
   {
     label: '订单编号',
     component: 'NInput',

+ 2 - 4
src/views/goods/store-goods/index.vue

@@ -10,6 +10,7 @@ import {
   fetchSetUpChannels
 } from '@/service/api/goods/store-goods';
 import { areAllItemsAllFieldsFilled } from '@/utils/zt';
+import { commonExport } from '@/utils/common';
 import { useTable } from '@/components/zt/Table/hooks/useTable';
 import SvgIcon from '@/components/custom/svg-icon.vue';
 import { useModal } from '@/components/zt/Modal/hooks/useModal';
@@ -335,10 +336,7 @@ getData();
 async function handleExport() {
   const form = getSeachForm();
   // 将form对象转换为查询参数字符串
-  const queryParams = new URLSearchParams(form).toString();
-  const baseUrl = `${import.meta.env.VITE_SERVICE_BASE_URL}/shop/shopProd/export`;
-  const fullUrl = queryParams ? `${baseUrl}?${queryParams}` : baseUrl;
-  window.open(fullUrl, '_blank');
+  commonExport('/shop/shopProd/export', form);
 }
 </script>
 

+ 22 - 3
src/views/government/user-list/index.vue

@@ -1,5 +1,5 @@
 <script setup lang="tsx">
-import { useTemplateRef } from 'vue';
+import { nextTick, useTemplateRef } from 'vue';
 import { NButton, NPopconfirm, NSwitch } from 'naive-ui';
 import {
   fetchAddUser,
@@ -11,6 +11,7 @@ import {
 } from '@/service/api/government/user-list';
 import { fetchGetAllChannelList } from '@/service/api/goods/store-goods';
 import { useAuth } from '@/hooks/business/auth';
+import { commonExport } from '@/utils/common';
 import { useTable } from '@/components/zt/Table/hooks/useTable';
 import { useModalFrom } from '@/components/zt/ModalForm/hooks/useModalForm';
 import { useModal } from '@/components/zt/Modal/hooks/useModal';
@@ -73,7 +74,7 @@ const columns: NaiveUI.TableColumn<Api.government.userList>[] = [
   }
 ];
 
-const [registerTable, { refresh, setTableLoading }] = useTable({
+const [registerTable, { refresh, setTableLoading, setFieldsValue: setSearchValues }] = useTable({
   searchFormConfig: {
     schemas: [
       {
@@ -83,7 +84,17 @@ const [registerTable, { refresh, setTableLoading }] = useTable({
         componentProps: {
           api: fetchGetAllChannelList,
           labelFeild: 'channelName',
-          valueFeild: 'id'
+          valueFeild: 'id',
+          multiple: true,
+          onUpdateValue: () => {
+            nextTick(() => {
+              handleSearch();
+            });
+          },
+          getOptions: async (options: any) => {
+            await setSearchValues({ channelIdList: [options[0].id] });
+            handleSearch();
+          }
         }
       },
       {
@@ -279,6 +290,13 @@ async function handleSubmitImport(file: File) {
   }
   importTemplateRef.value?.setSubLoading(false);
 }
+function handleSearch() {
+  refresh();
+}
+function handleExport() {
+  const form = getFieldsValue();
+  commonExport('/admin/enterprise/export', form);
+}
 </script>
 
 <template>
@@ -304,6 +322,7 @@ async function handleSubmitImport(file: File) {
       </template>
       <template #prefix>
         <NSpace>
+          <NButton v-if="useAuth().hasAuth('user:list:export-btn')" size="small" @click="handleExport">导出</NButton>
           <NButton v-if="useAuth().hasAuth('user:list:export')" size="small" @click="openImportModal">导入员工</NButton>
           <NButton v-if="useAuth().hasAuth('user:list:exportRecord')" size="small" @click="openModalFail">
             导入记录

+ 13 - 0
src/views/manage/user/index.vue

@@ -11,6 +11,7 @@ import {
   fetchGetUserList
 } from '@/service/api';
 import { fetchGetDepartmentList } from '@/service/api/system-department';
+import { fetchGetAllChannelList } from '@/service/api/goods/store-goods';
 import { useTable } from '@/components/zt/Table/hooks/useTable';
 import { $t } from '@/locales';
 import { useModalFrom } from '@/components/zt/ModalForm/hooks/useModalForm';
@@ -137,6 +138,18 @@ const [registerModalForm, { openModal, closeModal, getFieldsValue, setFieldsValu
             minlength: 2
           }
         },
+        {
+          field: 'channelIdList',
+          label: '所属企业',
+          component: 'ApiSelect',
+          required: true,
+          componentProps: {
+            api: () => fetchGetAllChannelList(),
+            labelFeild: 'channelName',
+            valueFeild: 'id',
+            multiple: true
+          }
+        },
         {
           field: 'deptIds',
           label: '归属部门',