浏览代码

feat: 发货单列表功能调整

xyh 2 年之前
父节点
当前提交
bad9cdcf55

+ 1 - 0
package.json

@@ -107,6 +107,7 @@
     "ahooks": "^3.7.6",
     "classnames": "^2.3.2",
     "dayjs": "^1.11.7",
+    "klona": "^2.0.6",
     "lodash-es": "^4.17.21",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",

+ 3 - 1
pnpm-lock.yaml

@@ -64,6 +64,9 @@ dependencies:
   dayjs:
     specifier: ^1.11.7
     version: 1.11.7
+  klona:
+    specifier: ^2.0.6
+    version: 2.0.6
   lodash-es:
     specifier: ^4.17.21
     version: 4.17.21
@@ -7829,7 +7832,6 @@ packages:
   /klona@2.0.6:
     resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==}
     engines: {node: '>= 8'}
-    dev: true
 
   /known-css-properties@0.27.0:
     resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==}

+ 15 - 0
src/apis/deliver.js

@@ -65,3 +65,18 @@ export function getInfo(track, customer) {
     data: {track, customer, page: '1', limit: '1'},
   });
 }
+
+/** 清除异常 */
+export function clear(id) {
+  return put({url: `${BASE_URL}/updAnomaly`, data: {id}});
+}
+
+/**
+ *
+ *  修改预计到货时间
+ *
+ * data: {id, arrivalTime}
+ */
+export function modifyFinalDate(data) {
+  return put({url: `${BASE_URL}/updArrivalTime`, data});
+}

+ 1 - 1
src/app.config.js

@@ -1,7 +1,7 @@
 export default defineAppConfig({
   pages: [
-    'pages/customer/index',
     'pages/index/index',
+    'pages/customer/index',
     'pages/list/index',
     'pages/receive/index',
     'pages/deliver/index',

+ 1 - 0
src/hooks/index.js

@@ -2,3 +2,4 @@ export * from './use-scan-order';
 export * from './use-navigate';
 export * from './use-infinite-fetch';
 export * from './use-success-toast';
+export * from './use-params';

+ 20 - 0
src/hooks/use-params/index.js

@@ -0,0 +1,20 @@
+import {getCurrentInstance} from '@tarojs/taro';
+import {useRef} from 'react';
+
+/**
+ * 获取路由参数
+ *
+ * @example
+ *
+ * const {id} = useParams<{id: string}>();
+ *
+ */
+export function useParams() {
+  const paramsRef = useRef();
+
+  if (!paramsRef.current) {
+    paramsRef.current = getCurrentInstance().router?.params ?? {};
+  }
+
+  return paramsRef.current;
+}

+ 9 - 4
src/pages/index/hooks.js

@@ -3,7 +3,12 @@ import complateIcon from '@assets/complate.svg';
 import orderIcon from '@assets/order.svg';
 import anomalyIcon from '@assets/anomaly.svg';
 import customerIcon from '@assets/customer.svg';
-import {DELIVER_GOODS_PATH, ORDER_PATH, RECEIVE_GOODS_PATH} from '@routes';
+import {
+  CUSTOMER_PATH,
+  DELIVER_GOODS_PATH,
+  ORDER_PATH,
+  RECEIVE_GOODS_PATH,
+} from '@routes';
 import {useStore} from 'zustand';
 import {userStore} from '@stores';
 import {useEffect, useState} from 'react';
@@ -39,21 +44,21 @@ export function useBtnList() {
           next[1].children.push({
             title: '发货单',
             icon: orderIcon,
-            url: ORDER_PATH,
+            url: ORDER_PATH + '?type=0',
           });
 
         powerContext & anomalyContext &&
           next[1].children.push({
             title: '异常订单',
             icon: anomalyIcon,
-            url: '',
+            url: ORDER_PATH + '?type=1',
           });
 
         powerContext & customerContext &&
           next[1].children.push({
             title: '客户管理',
             icon: customerIcon,
-            url: '',
+            url: CUSTOMER_PATH,
           });
 
         return next;

+ 15 - 51
src/pages/list/filter/field/index.jsx

@@ -2,53 +2,27 @@ import {Input, Picker, Text, View} from '@tarojs/components';
 import {useMemo} from 'react';
 import {Switch} from '@antmjs/vantui';
 
-export default function Field({
-  title,
-  value,
-  date,
-  anomaly,
-  startTime,
-  endTime,
-  onChange,
-  onStartChange,
-  onEndChange,
-}) {
+export default function Field({title, date, showSwitch, value, onChange}) {
   const Info = useMemo(
     function () {
       if (date) {
         return (
-          <View className='flex justify-between'>
-            <Picker
-              mode='date'
-              className='w-[48%]'
-              value={startTime}
-              onChange={e => onStartChange(e.detail.value)}
-            >
-              <Input
-                className='border-0 border-b border-solid border-gray-200 mt-1 py-1'
-                placeholder={`请选择开始时间`}
-                disabled
-                value={startTime}
-              />
-            </Picker>
-            <Picker
-              mode='date'
-              className='w-[48%]'
-              value={endTime}
-              onChange={e => onEndChange(e.detail.value)}
-            >
-              <Input
-                className='border-0 border-b border-solid border-gray-200 mt-1 py-1'
-                placeholder={`请选择结束时间`}
-                disabled
-                value={endTime}
-              />
-            </Picker>
-          </View>
+          <Picker
+            mode='date'
+            value={value}
+            onChange={e => onChange(e.detail.value)}
+          >
+            <Input
+              className='border-0 border-b border-solid border-gray-200 mt-1 py-1'
+              placeholder={`请选择`}
+              disabled
+              value={value}
+            />
+          </Picker>
         );
       }
 
-      if (anomaly) {
+      if (showSwitch) {
         return (
           <Switch
             size='24px'
@@ -69,17 +43,7 @@ export default function Field({
         />
       );
     },
-    [
-      anomaly,
-      date,
-      endTime,
-      onChange,
-      onEndChange,
-      onStartChange,
-      startTime,
-      title,
-      value,
-    ],
+    [date, onChange, showSwitch, title, value],
   );
 
   return (

+ 11 - 30
src/pages/list/filter/index.jsx

@@ -7,11 +7,8 @@ export default function Filter({
   onClose,
   track,
   custom,
-  anomaly,
-  startTime,
-  endTime,
-  startTime2,
-  endTime2,
+  date,
+  state,
   onChange,
   onReset,
   onConfirm,
@@ -40,31 +37,15 @@ export default function Filter({
     >
       <Field title='卡车号' value={track} onChange={onChange('track')} />
       <Field title='客户号' value={custom} onChange={onChange('custom')} />
-      <Field
-        title='发货时间'
-        disabled
-        date
-        startTime={startTime}
-        endTime={endTime}
-        onStartChange={onChange('startTime')}
-        onEndChange={onChange('endTime')}
-      />
-      <Field
-        title='收货时间'
-        disabled
-        date
-        startTime={startTime2}
-        endTime={endTime2}
-        onStartChange={onChange('startTime2')}
-        onEndChange={onChange('endTime2')}
-      />
-      <Field
-        title='异常订单'
-        disabled
-        anomaly
-        value={anomaly}
-        onChange={onChange('anomaly')}
-      />
+      <Field title='到货时间' value={date} onChange={onChange('date')} date />
+      {state !== null && (
+        <Field
+          title='正在送货'
+          value={state}
+          showSwitch
+          onChange={onChange('state')}
+        />
+      )}
 
       <View className='flex justify-around mt-4'>
         <Button

+ 79 - 11
src/pages/list/hooks.js

@@ -1,14 +1,15 @@
+import {useMutation, useQueryClient} from '@tanstack/react-query';
 import {useState} from 'react';
+import {clear, getList, modifyFinalDate} from '@apis';
+import {showModal, showLoading, hideLoading, showToast} from '@tarojs/taro';
+import {klona} from 'klona/json';
 
-export function useField() {
+export function useField(type) {
   const [fields, setFields] = useState({
     track: '',
     custom: '',
-    anomaly: false,
-    startTime: '',
-    endTime: '',
-    startTime2: '',
-    endTime2: '',
+    state: type === '0' ? true : null,
+    date: '',
   });
 
   function onChange(key) {
@@ -21,13 +22,80 @@ export function useField() {
     setFields({
       track: '',
       custom: '',
-      anomaly: false,
-      startTime: '',
-      endTime: '',
-      startTime2: '',
-      endTime2: '',
+      state: type === '0' ? true : null,
+      date: '',
     });
   }
 
   return [fields, {onChange, reset}];
 }
+
+export function useClearException(refresh) {
+  const {mutate} = useMutation({
+    mutationFn: clear,
+    onMutate() {
+      showLoading({title: '正在提交', mask: true});
+    },
+    onSettled() {
+      hideLoading({noConflict: true});
+    },
+    onSuccess({code}) {
+      if (code === '200') {
+        refresh();
+        showToast({title: '清除成功', icon: 'success'});
+      }
+    },
+  });
+
+  return function (id, track, customer) {
+    return function () {
+      showModal({
+        title: `你确定要清除${track}-${customer}的异常吗?`,
+        success({confirm}) {
+          confirm && mutate(id);
+        },
+      });
+    };
+  };
+}
+
+export function useEditDate() {
+  const client = useQueryClient();
+
+  const {mutate} = useMutation({
+    mutationFn: modifyFinalDate,
+    onMutate() {
+      showLoading({title: '正在提交', mask: true});
+    },
+    onSettled() {
+      hideLoading({noConflict: true});
+    },
+    onSuccess({code}, {id, arrivalTime}) {
+      if (code === '200') {
+        showToast({title: '修改成功', icon: 'success'});
+
+        client.setQueryData([getList.name], function (data) {
+          const next = klona(data);
+          const len = next.pages.length;
+
+          for (let i = 0; i < len; i++) {
+            const idx = next.pages[i].data.list.findIndex(val => val.id === id);
+
+            if (idx >= 0) {
+              next.pages[i].data.list[idx].arrivalTime = arrivalTime;
+              return next;
+            }
+          }
+
+          return next;
+        });
+      }
+    },
+  });
+
+  return function (id) {
+    return function (date) {
+      mutate({id, arrivalTime: date});
+    };
+  };
+}

+ 23 - 10
src/pages/list/index.jsx

@@ -5,13 +5,17 @@ import Filter from './filter';
 import {useBoolean} from 'ahooks';
 import Item from './item';
 import {Refresh} from '@components';
-import {useField} from './hooks';
-import {useInfiniteFetch} from '@hooks';
+import {useField, useClearException, useEditDate} from './hooks';
+import {useInfiniteFetch, useParams} from '@hooks';
 import {getList} from '@apis';
 
 export default function List() {
+  const {type} = useParams();
+
   const [visible, {setFalse: onClose, setTrue: onShow}] = useBoolean();
-  const [fields, {onChange, reset}] = useField();
+
+  const [fields, {onChange, reset}] = useField(type);
+
   const [
     {data, isFetching, isFetchingNextPage, hasNextPage, isEmpty},
     {fetchNextPage, refresh},
@@ -20,16 +24,17 @@ export default function List() {
     fn: getList,
     limit: 5,
     params: {
-      agoScrq: fields.startTime,
-      endScrq: fields.endTime,
-      agoFinalTime: fields.startTime2,
-      endFinalTime: fields.endTime2,
-      customer: fields.custom,
+      states: fields?.state ?? false ? '0' : '',
+      anomaly: type,
+      arrivalTime: fields.date,
       truckNo: fields.track,
-      anomaly: fields.anomaly ? '1' : '',
+      customer: fields.custom,
     },
   });
 
+  const onClear = useClearException(refresh);
+  const onEdit = useEditDate();
+
   return (
     <>
       <Refresh
@@ -44,7 +49,15 @@ export default function List() {
       >
         <View className='h-3' />
         {(data?.pages ?? []).map(function (val) {
-          return <Item key={val.id} {...val} />;
+          return (
+            <Item
+              key={val.id}
+              {...val}
+              type={type}
+              onClear={onClear(val.id, val.truckNo, val.customer)}
+              onEdit={onEdit(val.id)}
+            />
+          );
         })}
         <View className='h-3' />
       </Refresh>

+ 40 - 8
src/pages/list/item/index.jsx

@@ -1,6 +1,5 @@
 import {usePreview} from './hooks';
-import {Button} from '@antmjs/vantui';
-import {View, Text} from '@tarojs/components';
+import {View, Text, Button, Picker} from '@tarojs/components';
 import classNames from 'classnames';
 import {TextGroup} from '@components';
 import dayjs from 'dayjs';
@@ -16,6 +15,9 @@ export default function Item({
   truckNo,
   note,
   imgs,
+  type,
+  onClear,
+  onEdit,
 }) {
   const onClick = usePreview();
 
@@ -88,17 +90,47 @@ export default function Item({
         ) : null}
       </View>
 
-      {imgs ? (
-        <View className='flex justify-end mt-2'>
+      <View className='flex justify-end mt-4 gap-3'>
+        {imgs ? (
           <Button
-            round
-            className='!m-0 border border-solid border-gray-200'
+            className={classNames(
+              'border border-solid border-gray-300',
+              'text-sm w-24 leading-8 bg-white h-8 rounded-full',
+            )}
             onClick={onClick(imgs ? imgs.split(',') : [])}
           >
             查看图片
           </Button>
-        </View>
-      ) : null}
+        ) : null}
+
+        {type === '0' && states === '0' ? (
+          <Picker
+            mode='date'
+            value={arrivalTime}
+            onChange={e => onEdit(e.detail.value)}
+          >
+            <Button
+              className={classNames(
+                'text-sm w-24 leading-8 bg-primary h-8 rounded-full',
+                'text-white',
+              )}
+            >
+              修改时间
+            </Button>
+          </Picker>
+        ) : null}
+        {type === '1' ? (
+          <Button
+            className={classNames(
+              'text-sm w-24 leading-8 bg-primary h-8 rounded-full',
+              'text-white',
+            )}
+            onClick={onClear}
+          >
+            清除异常
+          </Button>
+        ) : null}
+      </View>
     </View>
   );
 }

+ 4 - 3
src/styles/app.css

@@ -1,7 +1,4 @@
 /* stylelint-disable at-rule-no-unknown */
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
 
 view {
   box-sizing: border-box;
@@ -56,3 +53,7 @@ page {
 input {
   font-size: 16px;
 }
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;