Bladeren bron

feat: 增加软件绑定类

xyh 2 jaren geleden
bovenliggende
commit
f9999d5d32

+ 2 - 4
package.json

@@ -113,12 +113,10 @@
   },
   "lint-staged": {
     "**/*/*.css": [
-      "stylelint",
-      "prettier --write"
+      "stylelint"
     ],
     "**/*/*.{js,jsx,ts,tsx}": [
-      "eslint",
-      "prettier --write"
+      "eslint"
     ]
   }
 }

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

@@ -17,3 +17,4 @@ export * from './inventory';
 export * from './warehousing';
 export * from './traceBack';
 export * from './adjustment';
+export * from './softwareBind';

+ 64 - 0
packages/app/src/apis/softwareBind.ts

@@ -0,0 +1,64 @@
+import {
+  AddSoftwareBindParams,
+  BaseListResult,
+  BaseResult,
+  EditSoftwareBindParams,
+  GetSoftwareBindListParams,
+  SoftwareBindData,
+} from '@models';
+import {request} from './request';
+
+const BASE_URL = '/delivery';
+
+/** 查询物料和软件绑定列表 */
+export function getSoftwareBindList(
+  data: GetSoftwareBindListParams,
+  signal?: AbortSignal,
+): BaseListResult<SoftwareBindData> {
+  return request({
+    method: 'GET',
+    data,
+    signal,
+    url: `${BASE_URL}/getEquipmentBindingSoftware`,
+  });
+}
+
+/** 获取详情 */
+export function getSoftwareBindInfo(
+  id: string,
+  signal?: AbortSignal,
+): BaseListResult<SoftwareBindData> {
+  return request({
+    method: 'GET',
+    data: {id, page: '1', limit: '1'},
+    signal,
+    url: `${BASE_URL}/getEquipmentBindingSoftware`,
+  });
+}
+
+/** 新增 */
+export function addSoftwareBind(data: AddSoftwareBindParams): BaseResult {
+  return request({
+    method: 'POST',
+    data,
+    url: `${BASE_URL}/addEquipmentBindingSoftware`,
+  });
+}
+
+/** 修改 */
+export function editSoftwareBind(data: EditSoftwareBindParams): BaseResult {
+  return request({
+    method: 'PUT',
+    data,
+    url: `${BASE_URL}/updateEquipmentBindingSoftware`,
+  });
+}
+
+/** 删除 */
+export function deleteSoftWare(id: string): BaseResult {
+  return request({
+    method: 'DELETE',
+    data: {id},
+    url: `${BASE_URL}/delEquipmentBindingSoftware`,
+  });
+}

+ 1 - 0
packages/app/src/models/request/index.ts

@@ -40,3 +40,4 @@ export * from './inventory';
 export * from './warehousing';
 export * from './traceBack';
 export * from './adjustment';
+export * from './softwareBind';

+ 22 - 0
packages/app/src/models/request/softwareBind.ts

@@ -0,0 +1,22 @@
+import {ListParams} from '.';
+
+/** 获取列表 */
+export type GetSoftwareBindListParams = {
+  /** 物料编号 */
+  equipmentCode: string;
+  /** 软件物料编号 */
+  softwareCode: string;
+} & ListParams;
+
+/** 新增 */
+export type AddSoftwareBindParams = {
+  /** 物料编号 */
+  equipmentCode: string;
+  /** 软件物料编号 */
+  softwareCode: string;
+};
+
+/** 修改 */
+export type EditSoftwareBindParams = AddSoftwareBindParams & {
+  id: string;
+};

+ 1 - 0
packages/app/src/models/response/index.ts

@@ -55,3 +55,4 @@ export * from './gs';
 export * from './inventory';
 export * from './traceBack';
 export * from './adjustment';
+export * from './softwareBind';

+ 12 - 0
packages/app/src/models/response/softwareBind.ts

@@ -0,0 +1,12 @@
+/** 绑定数据 */
+export type SoftwareBindData = {
+  id: string;
+  /** 物料编号 */
+  equipmentCode: string;
+  /** 物料名称 */
+  equipmentName: string;
+  /** 软件类物料编号 */
+  softwareCode: string;
+  /** 软件类物料名称 */
+  softwareName: string;
+};

+ 14 - 0
packages/app/src/pages/software-bind/context.ts

@@ -0,0 +1,14 @@
+import {
+  createPageContext,
+  createSearchContext,
+  createTableSearchContext,
+} from '@hooks';
+import {GetSoftwareBindListParams, OriginalListParams} from '@models';
+
+export const pageContext = createPageContext();
+export const searchContext = createSearchContext();
+export const contextState: OriginalListParams<GetSoftwareBindListParams> = {
+  equipmentCode: '',
+  softwareCode: '',
+};
+export const context = createTableSearchContext(contextState);

+ 53 - 0
packages/app/src/pages/software-bind/filter/index.tsx

@@ -0,0 +1,53 @@
+import {
+  useContextSection,
+  useFilterField,
+  useTableSearchToolEvents,
+} from '@hooks';
+import {FC} from 'react';
+import {context, contextState, searchContext} from '../context';
+import {Card} from 'antd';
+import {FilterButtonGroup, FilterField, FilterFieldWrapper} from '@components';
+
+const Filter: FC = function() {
+  const [fields, {onChange, resetState}] = useFilterField(
+    {...contextState},
+    true,
+  );
+  const [, {onSearch, onReset}] = useTableSearchToolEvents(
+    context,
+    fields,
+    {
+      resetCallback: resetState,
+    },
+  );
+  const isSearching = useContextSection(
+    searchContext,
+    state => state[0].isSearching,
+  );
+
+  return (
+    <Card>
+      <FilterFieldWrapper onSearch={onSearch} testId='sofware_filter'>
+        <FilterField
+          label='物料编码'
+          name='equipmentCode'
+          value={fields.equipmentCode}
+          onChange={onChange('equipmentCode')}
+        />
+        <FilterField
+          label='软件类编号'
+          name='softwareCode'
+          value={fields.softwareCode}
+          onChange={onChange('softwareCode')}
+        />
+        <FilterButtonGroup
+          onSearch={onSearch}
+          isSearching={isSearching}
+          onReset={onReset}
+        />
+      </FilterFieldWrapper>
+    </Card>
+  );
+};
+
+export default Filter;

+ 23 - 0
packages/app/src/pages/software-bind/index.tsx

@@ -0,0 +1,23 @@
+import {TableSearchProvider, PageProvider, SearchProvider} from '@components';
+
+import {FC} from 'react';
+import {context, pageContext, searchContext, contextState} from './context';
+import Filter from './filter';
+import TableList from './table';
+
+const SoftwareBind: 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 SoftwareBind;

+ 63 - 0
packages/app/src/pages/software-bind/table/hooks.tsx

@@ -0,0 +1,63 @@
+import {deleteSoftWare} from '@apis';
+import {useTableDeleteEvent, useTableModalEvent} from '@hooks';
+import {SoftwareBindData} from '@models';
+import {
+  DOUBLE_BTN_WIDTH,
+  MATERIAL_CODE_COL_WIDTH,
+  MATERIAL_NAME_COL_WIDTH,
+} from '@utils';
+import {Button} from 'antd';
+import {ColumnsType} from 'antd/es/table';
+
+const tableColumns: ColumnsType<SoftwareBindData> = [
+  {title: '物料编号', width: MATERIAL_CODE_COL_WIDTH, dataIndex: 'equipmentCode'},
+  {title: '物料名称', width: MATERIAL_NAME_COL_WIDTH, dataIndex: 'equipmentName'},
+  {title: '软件类物料编号', width: MATERIAL_CODE_COL_WIDTH, dataIndex: 'softwareCode'},
+  {title: '软件类物料名称', width: MATERIAL_NAME_COL_WIDTH, dataIndex: 'softwareName'},
+];
+
+export function useColumns(onFetch: () => void) {
+  const [
+    {visible, editId: editData},
+    {onClose, onAdd, onEdit},
+  ] = useTableModalEvent({id: '', code: '', softwareCode: ''});
+  const [deleteId, onDelete] = useTableDeleteEvent(
+    deleteSoftWare,
+    onFetch,
+    {label: '软件类绑定'},
+  );
+
+  const columns: ColumnsType<SoftwareBindData> = [
+    ...tableColumns, {
+      title: '操作',
+      dataIndex: 'id',
+      key: 'id',
+      fixed: 'right',
+      width: DOUBLE_BTN_WIDTH,
+      render(_, {id, equipmentName, equipmentCode, softwareCode}) {
+        return (
+          <>
+            <Button
+              type='text'
+              className='ant-text-btn-color-primary'
+              disabled={deleteId === id}
+              onClick={onEdit({id, code: equipmentCode, softwareCode})}
+            >
+              修改
+            </Button>
+            <Button
+              type='text'
+              danger
+              loading={deleteId === id}
+              onClick={onDelete(id, equipmentName)}
+            >
+              删除
+            </Button>
+          </>
+        );
+      },
+    },
+  ];
+
+  return [{columns, visible, editData}, {onClose, onAdd}] as const;
+}

+ 48 - 0
packages/app/src/pages/software-bind/table/index.tsx

@@ -0,0 +1,48 @@
+import {useContextSection, useQueryTableList} from '@hooks';
+import {FC} from 'react';
+import {context, pageContext, searchContext} from '../context';
+import {getSoftwareBindList} from '@apis';
+import {Card} from 'antd';
+import {Table, TableTools} from '@components';
+import {useColumns} from './hooks';
+import PutModal from './modal';
+
+const TableList: FC = function() {
+  const params = useContextSection(context, state => state[0]);
+  const [{data, count}, {refetch}] = useQueryTableList({
+    queryFn: getSoftwareBindList,
+    params,
+    pageContext,
+    searchContext,
+  });
+  const [{columns, visible, editData}, {onAdd, onClose}] = useColumns(refetch);
+
+  return (
+    <>
+      <Card className='table-wrapper'>
+        <TableTools
+          pageContext={pageContext}
+          searchContext={searchContext}
+          onAdd={onAdd}
+        />
+
+        <Table
+          pageContext={pageContext}
+          searchContext={searchContext}
+          data={data}
+          count={count}
+          columns={columns}
+        />
+      </Card>
+
+      <PutModal
+        visible={visible}
+        {...editData}
+        onClose={onClose}
+        onFetch={refetch}
+      />
+    </>
+  );
+};
+
+export default TableList;

+ 66 - 0
packages/app/src/pages/software-bind/table/modal/hooks.ts

@@ -0,0 +1,66 @@
+import {addSoftwareBind, editSoftwareBind} from '@apis';
+import {yupResolver} from '@hookform/resolvers/yup';
+import {usePutData} from '@hooks';
+import {useEffect} from 'react';
+import {useForm} from 'react-hook-form';
+import {object, string} from 'yup';
+
+type FormState = {
+  materialCode: string;
+  softwareCode: string;
+};
+
+const validate = object({
+  materialCode: string().required('请选择物料信息'),
+  softwareCode: string().required('请选择软件类物料信息'),
+});
+
+export function useFormState({
+  visible,
+  onFetch,
+  onClose,
+  id,
+  code,
+  softwareCode,
+}: {
+  visible: boolean;
+  id: string;
+  onFetch: () => void;
+  onClose: () => void;
+  code: string;
+  softwareCode: string;
+}) {
+  const {clearErrors, handleSubmit, setValue, control} = useForm<FormState>({
+    defaultValues: {materialCode: '', softwareCode: ''},
+    resolver: yupResolver(validate),
+  });
+
+  useEffect(
+    function() {
+      visible && clearErrors();
+    },
+    [clearErrors, visible],
+  );
+
+  useEffect(
+    function() {
+      setValue('materialCode', code);
+      setValue('softwareCode', softwareCode);
+    },
+    [code, setValue, softwareCode],
+  );
+
+  const [isLoading, {addMutate, editMutate}] = usePutData({
+    addFn: addSoftwareBind,
+    editFn: editSoftwareBind,
+    onFetch,
+    onClose,
+  });
+  const onSubmit = handleSubmit(function({materialCode, softwareCode}) {
+    id.length === 0
+      ? addMutate({equipmentCode: materialCode, softwareCode})
+      : editMutate({equipmentCode: materialCode, softwareCode, id});
+  });
+
+  return [{control, isLoading}, {onSubmit}] as const;
+}

+ 87 - 0
packages/app/src/pages/software-bind/table/modal/index.tsx

@@ -0,0 +1,87 @@
+import {Modal, ModalSelect} from '@components';
+import {FC, useEffect} from 'react';
+import {useFormState} from './hooks';
+import {useDictionaryWidthCode} from '@hooks';
+
+type Props = {
+  visible: boolean;
+  onClose: () => void;
+  onFetch: () => void;
+  id: string;
+  code: string;
+  softwareCode: string;
+};
+
+const PutModal: FC<Props> = function({
+  visible,
+  onClose,
+  onFetch,
+  id,
+  code,
+  softwareCode,
+}) {
+  const [{data: materialOptions, isFetching}, onMaterialSearch]
+  = useDictionaryWidthCode(
+    '物料字典',
+    {findValue: state => state.code},
+  );
+  const [
+    {data: SearviceMaterialOptions, isFetching: searviceMaterialFetching},
+    onServiceMaterialSearch,
+  ]
+  = useDictionaryWidthCode(
+    '物料字典',
+    {findValue: state => state.code},
+  );
+
+  useEffect(
+    function() {
+      onMaterialSearch(code);
+      onServiceMaterialSearch(softwareCode);
+    },
+    [code, onMaterialSearch, onServiceMaterialSearch, softwareCode],
+  );
+
+  const [
+    {control, isLoading},
+    {onSubmit},
+  ] = useFormState({
+    visible,
+    id,
+    onFetch,
+    onClose,
+    code,
+    softwareCode,
+  });
+
+  return (
+    <Modal
+      visible={visible}
+      title={`${id ? '修改' : '新增'}软件类绑定`}
+      onClose={onClose}
+      testId='software_modal'
+      onSubmit={onSubmit}
+      isLoading={isLoading}
+      height='500px'
+    >
+      <ModalSelect
+        control={control}
+        name='materialCode'
+        label='物料编号'
+        data={materialOptions}
+        onSearch={onMaterialSearch}
+        loading={isFetching}
+      />
+      <ModalSelect
+        control={control}
+        name='softwareCode'
+        label='服务类编号'
+        data={SearviceMaterialOptions}
+        onSearch={onServiceMaterialSearch}
+        loading={searviceMaterialFetching}
+      />
+    </Modal>
+  );
+};
+
+export default PutModal;

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

@@ -39,6 +39,7 @@ import {
   OTHER_OUT_PATH,
   SCREEN_PURCHASE_PATH,
   DELIVER_TRACE_PATH,
+  SOFTWARE_BIND_PATH,
 } from './name';
 import {
   Container,
@@ -79,6 +80,7 @@ import {
   OtherOut,
   ScreenPurchase,
   DeliverTraces,
+  SoftwareBind,
 } from './routes';
 import Main from '@pages/main';
 import Home from '@pages/home';
@@ -365,6 +367,13 @@ export const routes: RouteObject[] = [
       return await preloadSettings(OTHER_OUT_PATH);
     },
   },
+  {
+    path: SOFTWARE_BIND_PATH,
+    element: <SoftwareBind />,
+    async loader() {
+      return await preloadSettings(SOFTWARE_BIND_PATH);
+    },
+  },
   {
     path: SCREEN_PURCHASE_PATH,
     element: <ScreenPurchase />,

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

@@ -103,3 +103,5 @@ export const OTHER_OUT_PATH = '/other/out';
 export const SCREEN_PURCHASE_PATH = '/screen/purchase';
 /** 发货追溯 */
 export const DELIVER_TRACE_PATH = '/deliver/trace';
+/** 软件类绑定 */
+export const SOFTWARE_BIND_PATH = '/softwarebind';

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

@@ -209,3 +209,6 @@ export const ScreenPurchase = lazy(
 export const DeliverTraces = lazy(
   () => import(/* webpackChunkName: "deliverTraces" */ '@pages/deliver-trace'),
 );
+export const SoftwareBind = lazy(
+  () => import(/* webpackChunkName: "softwareBind" */'@pages/software-bind'),
+);