Browse Source

feat: 产成品领料单和报工单

xyh 2 years ago
parent
commit
aa277838ff

+ 2 - 2
packages/app/src/models/response/queryList.ts

@@ -167,7 +167,7 @@ export type SellOrderListData = {
   /**
    * WBS
    */
-  WBS: string;
+  wbs: string;
 };
 
 /** 移库单数据 */
@@ -236,5 +236,5 @@ export type RelocationOrderListData = {
   /**
    * WBS
    */
-  WBS: string;
+  wbs: string;
 };

+ 7 - 0
packages/app/src/pages/product-draw/context.ts

@@ -0,0 +1,7 @@
+import {createPageContext, createSearchContext, createTableSearchContext} from '@hooks';
+
+export const pageContext = createPageContext();
+export const searchContext = createSearchContext();
+
+export const contextState = {code: '', type: ''};
+export const context = createTableSearchContext(contextState);

+ 13 - 0
packages/app/src/pages/product-draw/filter/hooks.ts

@@ -0,0 +1,13 @@
+import {useContextSection} from '@hooks';
+import {context, searchContext} from '../context';
+
+export function useSearch(code: string, type: string) {
+  const {isSearching, refetch} = useContextSection(searchContext, state => state[0]);
+  const dispatch = useContextSection(context, state => state[1]);
+
+  function onSearch() {
+    dispatch({type: 'SEARCH', payload: {code, type}});
+  }
+
+  return [{isSearching, refetch}, onSearch] as const;
+}

+ 45 - 0
packages/app/src/pages/product-draw/filter/index.tsx

@@ -0,0 +1,45 @@
+import {FilterField, FilterButtonGroup, FilterSelect} from '@components';
+import {Card, Row} from 'antd';
+import {FC} from 'react';
+import {useSearch} from './hooks';
+import {useFilterField} from '@hooks';
+
+const options = [
+  {label: '全部', value: ''},
+  {label: '未出库', value: '0'},
+  {label: '已出库', value: '1'},
+];
+
+const Filter: FC = function () {
+  const [{code, type}, onChange] = useFilterField({code: '', type: ''});
+  const [{isSearching, refetch}, onSearch] = useSearch(code, type);
+
+  return (
+    <Card>
+      <Row>
+        <FilterField
+          name='semiDrawCode'
+          label='生产单号'
+          value={code}
+          onChange={onChange('code')}
+        />
+        <FilterSelect
+          name='semiDrawType'
+          value={type}
+          options={options}
+          onChange={onChange('type')}
+          label='状态'
+        />
+
+        <FilterButtonGroup
+          offset={6}
+          isSearching={isSearching}
+          onSearch={onSearch}
+          onRefresh={refetch}
+        />
+      </Row>
+    </Card>
+  );
+};
+
+export default Filter;

+ 22 - 0
packages/app/src/pages/product-draw/index.tsx

@@ -0,0 +1,22 @@
+import {PageProvider, SearchProvider, TableSearchProvider} from '@components';
+import {FC} from 'react';
+import {context, contextState, pageContext, searchContext} from './context';
+import Filter from './filter';
+import TableList from './table';
+
+const SemiDraw: FC = function () {
+  return (
+    <TableSearchProvider context={context} state={contextState}>
+      <PageProvider context={pageContext}>
+        <SearchProvider context={searchContext}>
+          <section className='content-main'>
+            <Filter />
+            <TableList />
+          </section>
+        </SearchProvider>
+      </PageProvider>
+    </TableSearchProvider>
+  );
+};
+
+export default SemiDraw;

+ 67 - 0
packages/app/src/pages/product-draw/table/index.tsx

@@ -0,0 +1,67 @@
+import {FC} from 'react';
+import {Card} from 'antd';
+import {Table} from '@components';
+import {context, pageContext, searchContext} from '../context';
+import {SemiDrawListData} from '@models';
+import {NORMAL_TABLE_WIDTH, MIDDLE_TABLE_WIDTH, SMALL_TABLE_WIDTH} from '@utils';
+import {ColumnsType} from 'antd/es/table';
+import {getSemiManufacturesDrawList} from '@apis';
+import {useContextSection, useQueryTableList} from '@hooks';
+
+const columns: ColumnsType<SemiDrawListData> = [
+  {title: '要货单编号', dataIndex: 'askGoodsId', key: 'askGoodsId', width: NORMAL_TABLE_WIDTH},
+  {title: '物料名称', dataIndex: 'materialName', key: 'materialName', width: MIDDLE_TABLE_WIDTH},
+  {title: '物料编号', dataIndex: 'materialCode', key: 'materialCode', width: NORMAL_TABLE_WIDTH},
+  {title: '数量', dataIndex: 'num', key: 'num', width: SMALL_TABLE_WIDTH},
+  {
+    title: '生产订单号',
+    dataIndex: 'productionCode',
+    key: 'productionCode',
+    width: NORMAL_TABLE_WIDTH,
+  },
+  {title: '要料部门', dataIndex: 'department', key: 'department', width: NORMAL_TABLE_WIDTH},
+  {
+    title: '状态',
+    dataIndex: 'type',
+    key: 'type',
+    render(_, {type}) {
+      return type === '0' ? '未出库' : '已出库';
+    },
+    width: SMALL_TABLE_WIDTH,
+  },
+];
+
+const TableList: FC = function () {
+  const params = useContextSection(context, function ([{code, type}]) {
+    return {
+      partType: '产成品' as const,
+      productionCode: code,
+      type,
+      askGoodsId: '',
+    };
+  });
+
+  const [{data, count}] = useQueryTableList({
+    queryFn: getSemiManufacturesDrawList,
+    params,
+    pageContext,
+    searchContext,
+  });
+
+  return (
+    <>
+      <Card className='table-wrapper'>
+        <Table
+          data-testid='semi_draw_table'
+          data={data}
+          columns={columns}
+          count={count}
+          pageContext={pageContext}
+          searchContext={searchContext}
+        />
+      </Card>
+    </>
+  );
+};
+
+export default TableList;

+ 18 - 0
packages/app/src/pages/product-draw/table/modal/Info.tsx

@@ -0,0 +1,18 @@
+import {ModalField} from '@components';
+import {FC} from 'react';
+import {useControl, useWatchId} from './hooks';
+
+type Props = {id: string};
+
+const Info: FC<Props> = function ({id}) {
+  const control = useControl();
+  useWatchId(id);
+
+  return (
+    <>
+      <ModalField name='semiDrawNum' type='number' control={control} label='出库数量' />
+    </>
+  );
+};
+
+export default Info;

+ 114 - 0
packages/app/src/pages/product-draw/table/modal/hooks.ts

@@ -0,0 +1,114 @@
+import {getSemiManufacturesDrawInfo, semiManufacturesOut} from '@apis';
+import {yupResolver} from '@hookform/resolvers/yup';
+import {useQueryDataInfo} from '@hooks';
+import {SemiDrawListData} from '@models';
+import {userStore} from '@stores';
+import {useMutation, useQueryClient} from '@tanstack/react-query';
+import {message} from 'antd';
+import {useEffect} from 'react';
+import {useForm, useFormContext} from 'react-hook-form';
+import {number, object} from 'yup';
+import {useStore} from 'zustand';
+
+type FormState = {
+  semiDrawNum: number;
+};
+
+const validate = object({
+  semiDrawNum: number().required('请输入出库数量').typeError('请输入数字').min(1, '不能小于1个'),
+});
+
+function useInfoData(id: string) {
+  const client = useQueryClient();
+
+  return function () {
+    return client.getQueryData<SemiDrawListData>([getSemiManufacturesDrawInfo.name, id]);
+  };
+}
+
+function useQuery(onClose: () => void, onFetch: () => void) {
+  return useMutation({
+    mutationFn: semiManufacturesOut,
+    onSuccess({msg}) {
+      if (msg === '200') {
+        onClose();
+        onFetch();
+        message.success('出库成功');
+      }
+    },
+  });
+}
+
+export function useFormState({
+  visible,
+  id,
+  onClose,
+  onFetch,
+}: {
+  visible: boolean;
+  id: string;
+  onClose: () => void;
+  onFetch: () => void;
+}) {
+  const formInstance = useForm<FormState>({
+    defaultValues: {
+      semiDrawNum: 0,
+    },
+    resolver: yupResolver(validate),
+  });
+
+  const {clearErrors, handleSubmit} = formInstance;
+
+  useEffect(
+    function () {
+      visible && clearErrors();
+    },
+    [visible, clearErrors],
+  );
+
+  const getInfo = useInfoData(id);
+  const {isLoading, mutate} = useQuery(onClose, onFetch);
+  const userId = useStore(userStore, state => String(state.id));
+
+  const onSubmit = handleSubmit(function ({semiDrawNum}) {
+    const info = getInfo();
+
+    if (!info) message.error('未获取到信息');
+    else {
+      const {materialId, askGoodsId, materialCode, companyNumber, wbs} = info;
+      mutate({
+        materialId,
+        askGoodsId,
+        userId,
+        warehousingNum: String(semiDrawNum),
+        wllbCode: materialCode,
+        companyNumber,
+        wbs,
+      });
+    }
+  });
+
+  return [{formInstance, isLoading}, {onSubmit}] as const;
+}
+
+export function useControl() {
+  const {control} = useFormContext<FormState>();
+
+  return control;
+}
+
+export function useWatchId(id: string) {
+  const data = useQueryDataInfo({
+    queryFn: getSemiManufacturesDrawInfo,
+    params: [id],
+    enabled: Boolean(id),
+  });
+  const {setValue} = useFormContext<FormState>();
+
+  useEffect(
+    function () {
+      setValue('semiDrawNum', Number(data?.num ?? '0'));
+    },
+    [data, setValue],
+  );
+}

+ 39 - 0
packages/app/src/pages/product-draw/table/modal/index.tsx

@@ -0,0 +1,39 @@
+import {ErrorBoundary, Loading, Modal} from '@components';
+import {FC, Suspense} from 'react';
+import {useFormState} from './hooks';
+import {FormProvider} from 'react-hook-form';
+import Info from './Info';
+
+type Props = {
+  visible: boolean;
+  id: string;
+  onClose: () => void;
+  onFetch: () => void;
+};
+
+const PutModal: FC<Props> = function ({visible, id, onClose, onFetch}) {
+  const [{formInstance, isLoading}, {onSubmit}] = useFormState({visible, id, onClose, onFetch});
+
+  return (
+    <Modal
+      visible={visible}
+      title='领料出库'
+      onClose={onClose}
+      onSubmit={onSubmit}
+      testId='semi_draw_modal'
+      isLoading={isLoading}
+      height='400px'
+      width='560px'
+    >
+      <FormProvider {...formInstance}>
+        <ErrorBoundary>
+          <Suspense fallback={<Loading tip='正在获取信息' />}>
+            <Info id={id} />
+          </Suspense>
+        </ErrorBoundary>
+      </FormProvider>
+    </Modal>
+  );
+};
+
+export default PutModal;

+ 18 - 0
packages/app/src/pages/product-report/context.ts

@@ -0,0 +1,18 @@
+import {
+  TableSearchContext,
+  createPageContext,
+  createSearchContext,
+  createTableSearchContext,
+} from '@hooks';
+import {GetNoticeListParams, OriginalListParams} from '@models';
+
+export const pageContext = createPageContext();
+export const searchContext = createSearchContext();
+
+export const contextState = {type: '', code: '', startTime: '', endTime: ''};
+export const context = createTableSearchContext(contextState);
+export function contextStateSelector([{type, code, startTime, endTime}]: TableSearchContext<
+  typeof contextState
+>): OriginalListParams<GetNoticeListParams> {
+  return {partType: '产成品', startTime, endTime, type, materialCode: code};
+}

+ 23 - 0
packages/app/src/pages/product-report/filter/hooks.ts

@@ -0,0 +1,23 @@
+import {useContextSection} from '@hooks';
+import {context, searchContext} from '../context';
+
+export function useSearch({
+  startTime,
+  endTime,
+  type,
+  code,
+}: {
+  startTime: string;
+  endTime: string;
+  type: string;
+  code: string;
+}) {
+  const {isSearching, refetch} = useContextSection(searchContext, state => state[0]);
+  const dispatch = useContextSection(context, state => state[1]);
+
+  function onSearch() {
+    dispatch({type: 'SEARCH', payload: {startTime, endTime, type, code}});
+  }
+
+  return [{isSearching, refetch}, onSearch] as const;
+}

+ 51 - 0
packages/app/src/pages/product-report/filter/index.tsx

@@ -0,0 +1,51 @@
+import {FilterButtonGroup, FilterDatePicker, FilterField, FilterSelect} from '@components';
+import {useFilterField, useRangeDate} from '@hooks';
+import {Card, Row} from 'antd';
+import {FC} from 'react';
+import {useSearch} from './hooks';
+
+const options = [
+  {label: '全部', value: ''},
+  {label: '未入库', value: '0'},
+  {label: '已入库', value: '1'},
+];
+
+const Filter: FC = function () {
+  const [{dates, start, end}, onDatesChange] = useRangeDate();
+  const [{type, code}, onChange] = useFilterField({code: '', type: ''});
+  const [{isSearching, refetch}, onSearch] = useSearch({
+    startTime: start,
+    endTime: end,
+    type,
+    code,
+  });
+
+  return (
+    <Card>
+      <Row>
+        <FilterField
+          name='semiReportCode'
+          label='物料编号'
+          value={code}
+          onChange={onChange('code')}
+        />
+        <FilterSelect
+          options={options}
+          name='semiReportType'
+          label='状态'
+          value={type}
+          onChange={onChange('type')}
+        />
+        <FilterDatePicker
+          name='rawMaterialDates'
+          label='报工时间'
+          value={dates}
+          onChange={onDatesChange}
+        />
+        <FilterButtonGroup isSearching={isSearching} onSearch={onSearch} onRefresh={refetch} />
+      </Row>
+    </Card>
+  );
+};
+
+export default Filter;

+ 22 - 0
packages/app/src/pages/product-report/index.tsx

@@ -0,0 +1,22 @@
+import {PageProvider, SearchProvider, TableSearchProvider} from '@components';
+import {FC} from 'react';
+import {context, contextState, pageContext, searchContext} from './context';
+import Filter from './filter';
+import TableList from './table';
+
+const SemiReport: FC = function () {
+  return (
+    <TableSearchProvider context={context} state={contextState}>
+      <PageProvider context={pageContext}>
+        <SearchProvider context={searchContext}>
+          <section className='content-main'>
+            <Filter />
+            <TableList />
+          </section>
+        </SearchProvider>
+      </PageProvider>
+    </TableSearchProvider>
+  );
+};
+
+export default SemiReport;

+ 60 - 0
packages/app/src/pages/product-report/table/index.tsx

@@ -0,0 +1,60 @@
+import {FC} from 'react';
+import {Card} from 'antd';
+import {Table} from '@components';
+import {context, contextStateSelector, pageContext, searchContext} from '../context';
+import {NoticeListData} from '@models';
+import {MIDDLE_TABLE_WIDTH, HUGE_TABLE_WIDTH, SMALL_TABLE_WIDTH, NORMAL_TABLE_WIDTH} from '@utils';
+import {ColumnsType} from 'antd/es/table';
+import {getNoticeList} from '@apis';
+import {useContextSection, useQueryTableList} from '@hooks';
+
+const columns: ColumnsType<NoticeListData> = [
+  {title: '报工单号', dataIndex: 'noticeId', key: 'noticeId', width: MIDDLE_TABLE_WIDTH},
+  {title: '物料名称', dataIndex: 'materialName', key: 'materialName', width: HUGE_TABLE_WIDTH},
+  {title: '物料编号', dataIndex: 'wllbCode', key: 'wllbCode', width: MIDDLE_TABLE_WIDTH},
+  {title: '数量', dataIndex: 'num', key: 'num', width: SMALL_TABLE_WIDTH},
+  {
+    title: '生产批次',
+    dataIndex: 'productionCode',
+    key: 'productionCode',
+    width: MIDDLE_TABLE_WIDTH,
+  },
+  {title: '分录号', dataIndex: 'entryNumber', key: 'entryNumber', width: NORMAL_TABLE_WIDTH},
+  {
+    title: '状态',
+    dataIndex: 'type',
+    key: 'type',
+    render(_, {type}) {
+      return type === '0' ? '未入库' : '已入库';
+    },
+    width: SMALL_TABLE_WIDTH,
+  },
+];
+
+const TableList: FC = function () {
+  const params = useContextSection(context, contextStateSelector);
+
+  const [{count, data}] = useQueryTableList({
+    queryFn: getNoticeList,
+    params,
+    pageContext,
+    searchContext,
+  });
+
+  return (
+    <>
+      <Card className='table-wrapper'>
+        <Table
+          data-testid='semi_report_table'
+          columns={columns}
+          data={data}
+          pageContext={pageContext}
+          searchContext={searchContext}
+          count={count}
+        />
+      </Card>
+    </>
+  );
+};
+
+export default TableList;

+ 17 - 0
packages/app/src/pages/product-report/table/modal/Info.tsx

@@ -0,0 +1,17 @@
+import {ModalField} from '@components';
+import {FC} from 'react';
+import {useControl, useWatchId} from './hooks';
+
+type Props = {id: string};
+const Info: FC<Props> = function ({id}) {
+  const control = useControl();
+  useWatchId(id);
+
+  return (
+    <>
+      <ModalField name='putInStoragenum' type='number' control={control} label='入库数量' />
+    </>
+  );
+};
+
+export default Info;

+ 119 - 0
packages/app/src/pages/product-report/table/modal/hooks.ts

@@ -0,0 +1,119 @@
+import {getNoticeInfo, semiManufacturesAdd} from '@apis';
+import {yupResolver} from '@hookform/resolvers/yup';
+import {useQueryDataInfo} from '@hooks';
+import {NoticeListData} from '@models';
+import {userStore} from '@stores';
+import {useMutation, useQueryClient} from '@tanstack/react-query';
+import {message} from 'antd';
+import {useEffect} from 'react';
+import {useForm, useFormContext} from 'react-hook-form';
+import {number, object} from 'yup';
+import {useStore} from 'zustand';
+
+type FormState = {
+  putInStoragenum: number;
+};
+
+const validate = object({
+  putInStoragenum: number()
+    .required('请输入入库数量')
+    .typeError('请输入数字')
+    .min(1, '不能少于1个'),
+});
+
+function useQuery(onClose: () => void, onFetch: () => void) {
+  return useMutation({
+    mutationFn: semiManufacturesAdd,
+    onSuccess({msg}) {
+      if (msg === '200') {
+        onClose();
+        onFetch();
+        message.success('入库成功');
+      }
+    },
+  });
+}
+
+function useInfoData(id: string) {
+  const client = useQueryClient();
+
+  function getData() {
+    return client.getQueryData<NoticeListData>([getNoticeInfo.name, id]);
+  }
+
+  return getData;
+}
+
+export function useFormState({
+  id,
+  visible,
+  onClose,
+  onFetch,
+}: {
+  id: string;
+  visible: boolean;
+  onClose: () => void;
+  onFetch: () => void;
+}) {
+  const formInstance = useForm<FormState>({
+    defaultValues: {
+      putInStoragenum: 0,
+    },
+    resolver: yupResolver(validate),
+  });
+  const {control, handleSubmit, clearErrors} = formInstance;
+
+  useEffect(
+    function () {
+      if (visible) clearErrors();
+    },
+    [clearErrors, visible],
+  );
+
+  const {mutate, isLoading} = useQuery(onClose, onFetch);
+  const getInfoData = useInfoData(id);
+  const userId = useStore(userStore, state => String(state.id));
+
+  const onSubmit = handleSubmit(function ({putInStoragenum}) {
+    const info = getInfoData();
+
+    if (!info) message.error('未获取到信息');
+    else {
+      const {wllbClass, companyNumber, wbs, materialId, noticeId, wllbCode} = info;
+      mutate({
+        userId,
+        companyNumber,
+        wbs,
+        wllbClass,
+        noticeId,
+        materialId,
+        warehousingNum: String(putInStoragenum),
+        wllbCode,
+      });
+    }
+  });
+
+  return [{control, isLoading, formInstance}, {onSubmit}] as const;
+}
+
+export function useControl() {
+  const {control} = useFormContext<FormState>();
+
+  return control;
+}
+
+export function useWatchId(id: string) {
+  const {setValue} = useFormContext<FormState>();
+  const data = useQueryDataInfo({
+    queryFn: getNoticeInfo,
+    params: [id],
+    enabled: Boolean(id),
+  });
+
+  useEffect(
+    function () {
+      setValue('putInStoragenum', Number(data?.num ?? '0'));
+    },
+    [data, setValue],
+  );
+}

+ 39 - 0
packages/app/src/pages/product-report/table/modal/index.tsx

@@ -0,0 +1,39 @@
+import {ErrorBoundary, Loading, Modal} from '@components';
+import {FC, Suspense} from 'react';
+import {useFormState} from './hooks';
+import {FormProvider} from 'react-hook-form';
+import Info from './Info';
+
+type Props = {
+  visible: boolean;
+  id: string;
+  onClose: () => void;
+  onFetch: () => void;
+};
+
+const PutModal: FC<Props> = function ({visible, onClose, onFetch, id}) {
+  const [{formInstance, isLoading}, {onSubmit}] = useFormState({id, onClose, onFetch, visible});
+
+  return (
+    <Modal
+      visible={visible}
+      title='报工单入库'
+      onClose={onClose}
+      onSubmit={onSubmit}
+      testId='semi_report_modal'
+      isLoading={isLoading}
+      height='400px'
+      width='560px'
+    >
+      <FormProvider {...formInstance}>
+        <ErrorBoundary>
+          <Suspense fallback={<Loading tip='正在获取信息' />}>
+            <Info id={id} />
+          </Suspense>
+        </ErrorBoundary>
+      </FormProvider>
+    </Modal>
+  );
+};
+
+export default PutModal;

+ 2 - 2
packages/app/src/pages/relocation-order/table/index.tsx

@@ -23,8 +23,8 @@ const columns: ColumnsType<RelocationOrderListData> = [
   },
   {
     title: 'WBS编号',
-    dataIndex: 'WBS',
-    key: 'WBS',
+    dataIndex: 'wbs',
+    key: 'wbs',
     width: NORMAL_TABLE_WIDTH,
   },
   {

+ 2 - 2
packages/app/src/pages/sell-order/table/index.tsx

@@ -29,8 +29,8 @@ const columns: ColumnsType<SellOrderListData> = [
   },
   {
     title: 'WBS编号',
-    dataIndex: 'WBS',
-    key: 'WBS',
+    dataIndex: 'wbs',
+    key: 'wbs',
     width: NORMAL_TABLE_WIDTH,
   },
   {

+ 8 - 2
packages/app/src/routes/index.tsx

@@ -37,7 +37,9 @@ import {
   GS_INTERFACE_LOG_PATH,
   PRODUCTION_REQUISITION_PATH,
   SELL_ORDER_PATH,
-  RELOCATION_ORDER_PATH,
+  PRODUCT_DRAW_PATH,
+  RELOCAT_ORDER_PATH,
+  PRODUCT_REPORT_PATH,
 } from './name';
 import {
   Container,
@@ -69,6 +71,8 @@ import {
   GSInterfaceLog,
   ProductionRequisitionOrder,
   RelcationOrder,
+  ProductDraw,
+  ProductReport,
 } from './routes';
 import DeadProduct from '@pages/dead-product';
 import PurchaseOrder from '@pages/purchase-order';
@@ -113,7 +117,9 @@ export const routes: RouteObject[] = [
       {path: GS_INTERFACE_LOG_PATH, element: <GSInterfaceLog />},
       {path: PRODUCTION_REQUISITION_PATH, element: <ProductionRequisitionOrder />},
       {path: SELL_ORDER_PATH, element: <SellOrder />},
-      {path: RELOCATION_ORDER_PATH, element: <RelcationOrder />},
+      {path: RELOCAT_ORDER_PATH, element: <RelcationOrder />},
+      {path: PRODUCT_DRAW_PATH, element: <ProductDraw />},
+      {path: PRODUCT_REPORT_PATH, element: <ProductReport />},
     ],
   },
   {path: LOGIN_PATH, element: <Login />},

+ 6 - 2
packages/app/src/routes/name.ts

@@ -90,8 +90,12 @@ export const DICTIONARY_PATH = '/dictionary/:type';
 /** gs接口日志 */
 export const GS_INTERFACE_LOG_PATH = '/log/gsinterface';
 /** 生产领用 */
-export const PRODUCTION_REQUISITION_PATH = '/production_requisition';
+export const PRODUCTION_REQUISITION_PATH = '/production/requisition';
 /** 销售单 */
 export const SELL_ORDER_PATH = '/sellorder';
 /** 移库单 */
-export const RELOCATION_ORDER_PATH = '/relocation';
+export const RELOCAT_ORDER_PATH = '/relocation';
+/** 产成品领料单 */
+export const PRODUCT_DRAW_PATH = '/product/draw';
+/** 产成品报工单 */
+export const PRODUCT_REPORT_PATH = '/product/report';

+ 7 - 1
packages/app/src/routes/routes.tsx

@@ -202,5 +202,11 @@ export const SellOrder = lazy(
   () => import(/* webpackChunkName: "sellOrder" */ '@pages/sell-order'),
 );
 export const RelcationOrder = lazy(
-  () => import(/** webpackChunkName: "relocationOrder" */ '@pages/relocation-order'),
+  () => import(/* webpackChunkName: "relocationOrder" */ '@pages/relocation-order'),
+);
+export const ProductReport = lazy(
+  () => import(/* webpackChunkName: "productReport" */ '@pages/product-report'),
+);
+export const ProductDraw = lazy(
+  () => import(/* webpackChunkName: "productDraw" */ '@pages/product-draw'),
 );