xyh 2 лет назад
Родитель
Сommit
8a684d30ac

+ 13 - 0
packages/app/src/apis/queryList.ts

@@ -4,6 +4,8 @@ import {
   GetReserveWarningListParams,
   DeadProductsListData,
   ReserveWarningListData,
+  GetStockListParams,
+  StockListData,
 } from '@models';
 import {request} from './request';
 
@@ -30,3 +32,14 @@ export function getReserveWarningList(
     data,
   });
 }
+
+/** 库存查询 */
+export function getStockList(
+  data: GetStockListParams,
+): BaseListResult<StockListData> {
+  return request({
+    method: 'GET',
+    url: `${BASE_URL}/storageLocation`,
+    data,
+  });
+}

+ 1 - 1
packages/app/src/apis/request.ts

@@ -10,7 +10,7 @@ const http = axios.create({
     'Content-Type': 'application/json',
     'Cache-Control': 'no-cache',
   },
-  timeout: 5000,
+  timeout: 10000,
 });
 
 const exportReg = /export|excel/i;

+ 1 - 0
packages/app/src/components/modal/PageModal.tsx

@@ -5,6 +5,7 @@ const styles: ReactModal.Styles = {
   content: {
     width: '80vw',
     height: '90vh',
+    position: 'relative',
   },
 };
 

+ 9 - 4
packages/app/src/components/page-provider/index.tsx

@@ -1,12 +1,17 @@
 import {createPageContext, usePageContextReducer} from '@hooks';
-import {ChildrenFC} from '@utils';
+import {ChildrenFC, PAGE_SIZE_LIST} from '@utils';
 
 type Props = {
-  context: ReturnType<typeof createPageContext>
+  context: ReturnType<typeof createPageContext>;
+  initPageSize?: string;
 };
 
-const PageProvider: ChildrenFC<Props> = function({children, context}) {
-  const state = usePageContextReducer();
+const PageProvider: ChildrenFC<Props> = function({
+  children,
+  context,
+  initPageSize = PAGE_SIZE_LIST[0],
+}) {
+  const state = usePageContextReducer({pageSize: Number(initPageSize), page: 1});
   const {Provider} = context;
 
   return <Provider value={state}>{children}</Provider>;

+ 3 - 1
packages/app/src/components/table/index.tsx

@@ -14,6 +14,7 @@ type Props<T> = {
   rowKey?: string,
   'data-testid': string,
   scrollX?: number,
+  pageSizeList?: string[]
 };
 
 const Table: FC<Props<any>> = function<T extends Record<string, any>>(props: Props<T>) {
@@ -25,6 +26,7 @@ const Table: FC<Props<any>> = function<T extends Record<string, any>>(props: Pro
     count,
     rowKey,
     scrollX,
+    pageSizeList = PAGE_SIZE_LIST,
   } = props;
   const [{page, pageSize}, {onPageChange}] = usePage(pageContext);
   const [isSearching] = useTableSearchState(searchContext);
@@ -36,7 +38,7 @@ const Table: FC<Props<any>> = function<T extends Record<string, any>>(props: Pro
       dataSource={data}
       pagination={{
         pageSize,
-        pageSizeOptions: PAGE_SIZE_LIST,
+        pageSizeOptions: pageSizeList,
         total: count,
         showSizeChanger: true,
         onChange: onPageChange,

+ 1 - 0
packages/app/src/hooks/index.ts

@@ -9,3 +9,4 @@ export * from './use-put-data';
 export * from './use-range-date';
 export * from './use-filter-field';
 export * from './use-table-search';
+export * from './use-modal-close';

+ 16 - 0
packages/app/src/hooks/use-modal-close/index.tsx

@@ -0,0 +1,16 @@
+import {useEventListener} from 'ahooks';
+import {useRef} from 'react';
+
+export function useModalClose() {
+  const ref = useRef<HTMLDivElement>(null);
+
+  useEventListener(
+    'click',
+    function() {
+      (ref.current?.closest('.ReactModal__Overlay') as HTMLDivElement)?.click();
+    },
+    {target: ref},
+  );
+
+  return ref;
+}

+ 8 - 0
packages/app/src/models/request/queryList.ts

@@ -13,3 +13,11 @@ export type GetReserveWarningListParams = {
   /** 物料编号 */
   wllbCode: string;
 } & ListParams;
+
+/** 获取库存信息 */
+export type GetStockListParams = {
+  /** 库位code */
+  storageLocationCode: string;
+  /** 物料tldid */
+  materialId: string;
+} & ListParams;

+ 13 - 0
packages/app/src/models/response/queryList.ts

@@ -49,3 +49,16 @@ export type ReserveWarningListData = {
    */
   minNum: string;
 };
+
+/** 库存信息 */
+export type StockListData = {
+  id: string;
+  /** 库位名称 */
+  storageLocationName: string;
+  /** 物料名称 */
+  name: string;
+  /** 物料code */
+  code: string;
+  /** 物料数量 */
+  sum: number;
+};

+ 2 - 2
packages/app/src/pages/menu-id/index.tsx

@@ -9,7 +9,7 @@ import {
   usePIdContextState,
 } from './context';
 import TableList from './table';
-import {ChildrenFC} from '@utils';
+import {ChildrenFC, MODAL_PAGE_SIZE_LIST} from '@utils';
 import {PageProvider, SearchProvider, TableSearchProvider} from '@components';
 
 type Props = {
@@ -28,7 +28,7 @@ const ChildMenu: FC<Props> = function({id}) {
     <PIdProvider id={id}>
       <TableSearchProvider context={context} state={contextState}>
         <SearchProvider context={searchContext}>
-          <PageProvider context={pageContext}>
+          <PageProvider context={pageContext} initPageSize={MODAL_PAGE_SIZE_LIST[0]}>
             <section className='content-main' data-testid='child_menu'>
               <Filter />
               <TableList />

+ 2 - 0
packages/app/src/pages/menu-id/table/index.tsx

@@ -4,6 +4,7 @@ import MenuModal from './modal';
 import {useHandle, useList} from './hooks';
 import {pageContext, searchContext} from '../context';
 import {Table, TableTools} from '@components';
+import {MODAL_PAGE_SIZE_LIST} from '@utils';
 
 const TableList: FC = function() {
   const [{data, count}, {refetch}] = useList();
@@ -21,6 +22,7 @@ const TableList: FC = function() {
           pageContext={pageContext}
           searchContext={searchContext}
           count={count}
+          pageSizeList={MODAL_PAGE_SIZE_LIST}
         />
       </Card>
       <MenuModal visible={visible} onClose={onModalClose} id={editId} onFetch={refetch} />

+ 24 - 0
packages/app/src/pages/stock/context.ts

@@ -0,0 +1,24 @@
+import {
+  TableSearchContext,
+  createPageContext,
+  createSearchContext,
+  createTableSearchContext,
+} from '@hooks';
+import {GetStockListParams, OriginalListParams} from '@models';
+
+export const pageContext = createPageContext();
+export const searchContext = createSearchContext();
+
+export const contextState = {
+  materialId: '',
+  locationCode: '',
+};
+export const context = createTableSearchContext(contextState);
+export function contextStateSelector(
+  [{materialId, locationCode}]: TableSearchContext<typeof contextState>,
+): OriginalListParams<GetStockListParams> {
+  return {
+    materialId,
+    storageLocationCode: locationCode,
+  };
+}

+ 12 - 0
packages/app/src/pages/stock/filter/hooks.ts

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

+ 54 - 0
packages/app/src/pages/stock/filter/index.tsx

@@ -0,0 +1,54 @@
+import {FilterButtonGroup, FilterSelect} from '@components';
+import {useContextSection, useDictionaryOptions, useFilterField, useStorageOptions} from '@hooks';
+import {Card, Row} from 'antd';
+import {FC} from 'react';
+import {searchContext} from '../context';
+import {useSearch} from './hooks';
+
+const Filter: FC = function() {
+  const [{material, location}, onChange] = useFilterField({material: '', location: ''});
+  const materialOptions = useDictionaryOptions(
+    '物料字典',
+    true,
+    state => state.tldId,
+  );
+  const locationOptions = useStorageOptions(true);
+  const {isSearching, refetch} = useContextSection(
+    searchContext,
+    state => state[0],
+  );
+  const onSearch = useSearch(material, location);
+
+  return (
+    <Card>
+      <Row>
+        <FilterSelect
+          options={materialOptions}
+          name='semiReportType'
+          label='物料'
+          value={material}
+          onChange={onChange('material')}
+          showSearch
+        />
+
+        <FilterSelect
+          options={locationOptions}
+          name='semiReportType'
+          label='库位'
+          value={location}
+          onChange={onChange('location')}
+          showSearch
+        />
+
+        <FilterButtonGroup
+          isSearching={isSearching}
+          onSearch={onSearch}
+          onRefresh={refetch}
+          offset={6}
+        />
+      </Row>
+    </Card>
+  );
+};
+
+export default Filter;

+ 22 - 0
packages/app/src/pages/stock/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 Stock: 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 Stock;

+ 14 - 0
packages/app/src/pages/stock/table/hooks.ts

@@ -0,0 +1,14 @@
+import {useContextSection, useQueryTableList} from '@hooks';
+import {context, contextStateSelector, pageContext, searchContext} from '../context';
+import {getStockList} from '@apis';
+
+export function useList() {
+  const params = useContextSection(context, contextStateSelector);
+
+  return useQueryTableList({
+    queryFn: getStockList,
+    params,
+    pageContext,
+    searchContext,
+  });
+}

+ 33 - 0
packages/app/src/pages/stock/table/index.tsx

@@ -0,0 +1,33 @@
+import {Card} from 'antd';
+import {FC} from 'react';
+import {useList} from './hooks';
+import {ColumnsType} from 'antd/es/table';
+import {StockListData} from '@models';
+import {Table} from '@components';
+import {pageContext, searchContext} from '../context';
+
+const columns: ColumnsType<StockListData> = [
+  {title: '物料名称', dataIndex: 'name', key: 'name'},
+  {title: '物料编号', dataIndex: 'code', key: 'code'},
+  {title: '数量', dataIndex: 'sum', key: 'sum'},
+  {title: '库位名称', dataIndex: 'storageLocationName', key: 'storageLocationName'},
+];
+
+const TableList: FC = function() {
+  const [{data, count}] = useList();
+
+  return (
+    <Card className='table-wrapper'>
+      <Table
+        data-testid='stock_table'
+        data={data}
+        count={count}
+        pageContext={pageContext}
+        searchContext={searchContext}
+        columns={columns}
+      />
+    </Card>
+  );
+};
+
+export default TableList;

+ 3 - 0
packages/app/src/routes/index.tsx

@@ -31,6 +31,7 @@ import {
   PURCHASE_PATH,
   MATERIAL_BIND_PATH,
   PURCHASE_TIMEOUT_PATH,
+  STOCK_PATH,
 } from './name';
 import {
   Container,
@@ -57,6 +58,7 @@ import {
   ReserveWarning,
   Quality,
   PurchaseOrderTimeout,
+  Stock,
 } from './routes';
 import DeadProduct from '@pages/dead-product';
 import PurchaseOrder from '@pages/purchase-order';
@@ -93,6 +95,7 @@ export const routes: RouteObject[] = [
       {path: PURCHASE_PATH, element: <PurchaseOrder />},
       {path: MATERIAL_BIND_PATH, element: <MaterialBind />},
       {path: PURCHASE_TIMEOUT_PATH, element: <PurchaseOrderTimeout />},
+      {path: STOCK_PATH, element: <Stock />},
     ],
   },
   {path: LOGIN_PATH, element: <Login />},

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

@@ -61,3 +61,5 @@ export const PURCHASE_PATH = '/purchase';
 export const PURCHASE_TIMEOUT_PATH = '/purchasetimeout';
 /** 用户和物料绑定 */
 export const MATERIAL_BIND_PATH = '/materialbind';
+/** 库存明细 */
+export const STOCK_PATH = '/stock';

+ 4 - 0
packages/app/src/routes/routes.tsx

@@ -104,3 +104,7 @@ export const PurchaseOrderTimeout = lazy(() => import(
   /* webpackChunkName: "purchaseOrderTimeout" */
   '@pages/purchase-order-timeout'
 ));
+export const Stock = lazy(() => import(
+  /* webpackChunkName: "stock" */
+  '@pages/stock'
+));

+ 1 - 1
packages/app/src/utils/constants.ts

@@ -7,7 +7,7 @@ export const MODAL_PAGE_SIZE_LIST = ['5', ...PAGE_SIZE_LIST];
 /** 请求域名 */
 export const NETWORK_URL = process.env.NODE_ENV === 'development'
 // 147
-  ? 'http://192.168.118:9560'
+  ? 'http://192.168.147:9560'
   : 'http://8.142.144.205:9560';
 export const E2E_NETWORK_URL = 'http://e2e.test.cn';
 /** 导出错误提示 */