| | |
| | | PORT=3000 |
| | | EXTEND_ESLINT=true |
| | | REACT_APP_API_URL=http://vwpmxwbhv59i.guyubao.com |
| | | REACT_APP_API_URL=http://192.168.110.64:9092 |
| | | REACT_APP_ENV=development |
| | |
| | | const loadList = async () => { |
| | | setLoading(true); |
| | | try { |
| | | const response = await request('/t-lens-series/seriesList', { |
| | | const response = await request('/t-lens-series/seriesListOrder', { |
| | | data: { |
| | | brandId: props.brandId, |
| | | }, |
| | |
| | | const validate = async () => { |
| | | await form.validate(); |
| | | // 检查镜片和镜架是否有库存 |
| | | for (const item of orderGoodsList) { |
| | | switch (item.goodsType) { |
| | | case GoodsTypeFrame: { |
| | | if (frameStock == null || frameStock <= 0) { |
| | | throw new Error('镜架库存不足,请重新选择'); |
| | | } |
| | | break; |
| | | } |
| | | case GoodsTypeLeftLens: { |
| | | if (leftLensStock == null || leftLensStock <= 0) { |
| | | throw new Error('镜片(L)库存不足,请重新选择'); |
| | | } |
| | | break; |
| | | } |
| | | case GoodsTypeRightLens: { |
| | | if (rightLensStock == null || rightLensStock <= 0) { |
| | | throw new Error('镜片(R)库存不足,请重新选择'); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | // for (const item of orderGoodsList) { |
| | | // switch (item.goodsType) { |
| | | // case GoodsTypeFrame: { |
| | | // if (frameStock == null || frameStock <= 0) { |
| | | // throw new Error('镜架库存不足,请重新选择'); |
| | | // } |
| | | // break; |
| | | // } |
| | | // case GoodsTypeLeftLens: { |
| | | // if (leftLensStock == null || leftLensStock <= 0) { |
| | | // throw new Error('镜片(L)库存不足,请重新选择'); |
| | | // } |
| | | // break; |
| | | // } |
| | | // case GoodsTypeRightLens: { |
| | | // if (rightLensStock == null || rightLensStock <= 0) { |
| | | // throw new Error('镜片(R)库存不足,请重新选择'); |
| | | // } |
| | | // break; |
| | | // } |
| | | // } |
| | | // } |
| | | return orderGoodsList; |
| | | }; |
| | | |
| | |
| | | </Button> |
| | | </PermissionWrapper> |
| | | <PermissionWrapper |
| | | requiredPermissions={['stocks/lensOperation/generate/index']} |
| | | > |
| | | <Button |
| | | type="primary" |
| | | onClick={() => { |
| | | history.push('/stocks/lensOperation/generate/index'); |
| | | }} |
| | | icon={<IconDownload />} |
| | | > |
| | | 库存生成 |
| | | </Button> |
| | | </PermissionWrapper> |
| | | <PermissionWrapper |
| | | requiredPermissions={['stocks/lensStoreOrder/index']} |
| | | > |
| | | <Button |
New file |
| | |
| | | import React, { |
| | | useState, |
| | | useRef, |
| | | useEffect, |
| | | useContext, |
| | | useCallback, |
| | | forwardRef, |
| | | useImperativeHandle, |
| | | } from 'react'; |
| | | import { |
| | | Button, |
| | | Table, |
| | | Input, |
| | | Select, |
| | | Form, |
| | | FormInstance, |
| | | InputNumber, |
| | | Message, |
| | | TableColumnProps, |
| | | Popconfirm, |
| | | } from '@arco-design/web-react'; |
| | | import request from '@/request/request'; |
| | | const FormItem = Form.Item; |
| | | import { v4 as uuidv4 } from 'uuid'; |
| | | import { getBallMirrorList, getColumnMirrorList } from '@/utils/mirror'; |
| | | const EditableContext = React.createContext<{ |
| | | getForm?: () => FormInstance; |
| | | validateFields?: () => Promise<any>; |
| | | }>({}); |
| | | |
| | | const DataTableContext = React.createContext({ |
| | | brandList: [] as any[], |
| | | seriesList: {} as Record<number, any[]>, |
| | | operationType: '', |
| | | }); |
| | | |
| | | function EditableRow(props) { |
| | | const { children, record, className, onRef, ...rest } = props; |
| | | const refForm = useRef(null); |
| | | |
| | | const getForm = () => refForm.current; |
| | | const validateFields = useCallback(() => { |
| | | if (refForm.current) { |
| | | return refForm.current.validate(); |
| | | } else { |
| | | return undefined; |
| | | } |
| | | }, [refForm]); |
| | | useEffect(() => { |
| | | onRef && onRef(validateFields); |
| | | }, [onRef, validateFields]); |
| | | |
| | | return ( |
| | | <EditableContext.Provider |
| | | value={{ |
| | | getForm, |
| | | validateFields, |
| | | }} |
| | | > |
| | | <Form |
| | | style={{ display: 'table-row' }} |
| | | // eslint-disable-next-line react/no-children-prop |
| | | children={children} |
| | | ref={refForm} |
| | | wrapper="tr" |
| | | wrapperProps={rest} |
| | | className={`${className} editable-row`} |
| | | /> |
| | | </EditableContext.Provider> |
| | | ); |
| | | } |
| | | const ballMirrorList = getBallMirrorList(); |
| | | const columnMirrorList = getColumnMirrorList(); |
| | | |
| | | function EditableCell(props) { |
| | | const { children, className, rowData, column, onHandleSave } = props; |
| | | const ref = useRef(null); |
| | | const refInput = useRef(null); |
| | | const { brandList, seriesList, operationType } = useContext(DataTableContext); // 获取共享的 brandList 和 seriesList |
| | | const { getForm } = useContext(EditableContext); |
| | | const [editing, setEditing] = useState(column.key != 'op' && column.editable); |
| | | const cellValueChangeHandler = (value) => { |
| | | const form = getForm(); |
| | | if ( |
| | | [ |
| | | 'brandId', |
| | | 'seriesId', |
| | | 'type', |
| | | 'refractiveIndex', |
| | | 'ballMirror', |
| | | 'columnMirror', |
| | | ].indexOf(column.dataIndex) > -1 |
| | | ) { |
| | | const values = { |
| | | [column.dataIndex]: value, |
| | | }; |
| | | onHandleSave && onHandleSave({ ...rowData, ...values }); |
| | | } else { |
| | | form.validate([column.dataIndex], (errors, values) => { |
| | | if (!errors || !errors[column.dataIndex]) { |
| | | // setEditing(!editing); |
| | | onHandleSave && onHandleSave({ ...rowData, ...values }); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | if (editing) { |
| | | const getSeriesTypeList = (series: any) => { |
| | | const typeNameList = ['球面', '非球面', '双非']; |
| | | const list = []; |
| | | [series.sphere, series.asphericSurface, series.doubleNon].forEach( |
| | | (item, index) => { |
| | | try { |
| | | const jsonData = JSON.parse(item); |
| | | if (jsonData.length > 0) { |
| | | list.push({ |
| | | label: typeNameList[index], |
| | | value: index + 1, |
| | | }); |
| | | } |
| | | } catch (e) {} |
| | | } |
| | | ); |
| | | return list; |
| | | }; |
| | | |
| | | const getSeriesRefractionIndexList = (series: any, type: number) => { |
| | | let jsonData = []; |
| | | switch (type) { |
| | | case 1: |
| | | try { |
| | | jsonData = JSON.parse(series.sphere); |
| | | } catch (e) {} |
| | | break; |
| | | case 2: |
| | | try { |
| | | jsonData = JSON.parse(series.asphericSurface); |
| | | } catch (e) {} |
| | | break; |
| | | case 3: |
| | | try { |
| | | jsonData = JSON.parse(series.doubleNon); |
| | | } catch (e) {} |
| | | break; |
| | | } |
| | | return jsonData; |
| | | }; |
| | | |
| | | const currentSeriesList = seriesList[rowData['brandId']] || []; |
| | | const currentTypeList = []; |
| | | const currentrefractiveIndexList = []; |
| | | let currentSeries = null; |
| | | if (rowData['seriesId']) { |
| | | currentSeries = currentSeriesList.find( |
| | | (model) => model.id == rowData['seriesId'] |
| | | ); |
| | | if (currentSeries) { |
| | | currentTypeList.push(...getSeriesTypeList(currentSeries)); |
| | | if (rowData['type']) { |
| | | currentrefractiveIndexList.push( |
| | | ...getSeriesRefractionIndexList(currentSeries, rowData['type']) |
| | | ); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div ref={ref}> |
| | | {column.key == 'brandId' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | defaultValue={rowData[column.dataIndex]} |
| | | > |
| | | {brandList.map((brand) => { |
| | | return ( |
| | | <Select.Option |
| | | key={brand.id} |
| | | value={brand.id} |
| | | disabled={brand.status === 2} |
| | | > |
| | | {brand.name} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'seriesId' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | value={rowData[column.dataIndex]} |
| | | showSearch |
| | | filterOption={(inputValue, option) => { |
| | | if (!option.props) { |
| | | return false; |
| | | } |
| | | console.warn(inputValue, option); |
| | | return ( |
| | | ((option.props?.value || '') + '') |
| | | .toLowerCase() |
| | | .indexOf(inputValue.toLowerCase()) >= 0 || |
| | | (option.props?.children || '') |
| | | .toLowerCase() |
| | | .indexOf(inputValue.toLowerCase()) >= 0 |
| | | ); |
| | | }} |
| | | > |
| | | {currentSeriesList.map((model) => { |
| | | return ( |
| | | <Select.Option |
| | | key={model.id} |
| | | value={model.id} |
| | | disabled={model.status === 2} |
| | | > |
| | | {model.name} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'type' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | value={rowData[column.dataIndex]} |
| | | > |
| | | {currentTypeList.map((item) => { |
| | | return ( |
| | | <Select.Option key={item.value} value={item.value}> |
| | | {item.label} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'refractiveIndex' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | value={rowData[column.dataIndex]} |
| | | > |
| | | {currentrefractiveIndexList.map((item) => { |
| | | return ( |
| | | <Select.Option |
| | | key={item.refractiveIndex} |
| | | value={item.refractiveIndex} |
| | | > |
| | | {item.refractiveIndex} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'ballMirror' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | value={rowData[column.dataIndex]} |
| | | renderFormat={(option, value) => { |
| | | return option ? ( |
| | | <span>{`${(+option.value / 100).toFixed(2)}`}</span> |
| | | ) : ( |
| | | value |
| | | ); |
| | | }} |
| | | > |
| | | {ballMirrorList.map((item) => { |
| | | return ( |
| | | <Select.Option key={item} value={item}> |
| | | {item} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'columnMirror' && ( |
| | | <Select |
| | | onChange={cellValueChangeHandler} |
| | | value={rowData[column.dataIndex]} |
| | | > |
| | | {columnMirrorList.map((item) => { |
| | | return ( |
| | | <Select.Option key={item} value={item}> |
| | | {item} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | )} |
| | | {column.key == 'total' && ( |
| | | <FormItem |
| | | style={{ marginBottom: 0 }} |
| | | labelCol={{ span: 0 }} |
| | | wrapperCol={{ span: 24 }} |
| | | initialValue={rowData[column.dataIndex]} |
| | | field={column.dataIndex} |
| | | rules={[{ required: true, message: '数量是必填项' }]} |
| | | > |
| | | <InputNumber |
| | | min={0} |
| | | ref={refInput} |
| | | max={ |
| | | ['store', 'rollback'].includes(operationType) |
| | | ? undefined |
| | | : rowData['inventory'] |
| | | } |
| | | onBlur={cellValueChangeHandler} |
| | | /> |
| | | </FormItem> |
| | | )} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | return ( |
| | | <div className={column.editable ? `editable-cell ${className}` : className}> |
| | | {children} |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | const DataTable = forwardRef( |
| | | ( |
| | | props: { onChange?: (data: any) => void; storeId: number; type: string }, |
| | | ref |
| | | ) => { |
| | | useImperativeHandle(ref, () => ({ |
| | | loadList, |
| | | validateData, |
| | | })); |
| | | |
| | | const [brandList, setBrandList] = useState<any[]>([]); |
| | | const [seriesList, setSeriesList] = useState<Record<number, any[]>>({}); |
| | | |
| | | const [data, setData] = useState([]); |
| | | |
| | | // 当storeId变更了过后,要重新加载库存 |
| | | useEffect(() => { |
| | | rebuildListToInventory(); |
| | | }, [props.storeId]); |
| | | |
| | | const rebuildListToInventory = async () => { |
| | | const newData = [...data]; |
| | | for (let i = 0; i < newData.length; i++) { |
| | | const row = newData[i]; |
| | | if ( |
| | | row['brandId'] && |
| | | row['seriesId'] && |
| | | row['ballMirror'] != undefined && |
| | | row['ballMirror'] != '' && |
| | | row['columnMirror'] && |
| | | row['type'] && |
| | | row['refractiveIndex'] |
| | | ) { |
| | | row.inventory = await loadInventory(row); |
| | | } |
| | | } |
| | | setData(newData); |
| | | props.onChange && props.onChange(newData); |
| | | }; |
| | | |
| | | const columns: TableColumnProps[] = [ |
| | | { |
| | | title: '品牌', |
| | | dataIndex: 'brandId', |
| | | editable: true, |
| | | width: '10%', |
| | | align: 'center', |
| | | }, |
| | | { |
| | | title: '系列膜层', |
| | | dataIndex: 'seriesId', |
| | | editable: true, |
| | | width: '10%', |
| | | align: 'center', |
| | | }, |
| | | { |
| | | title: '球/非', |
| | | dataIndex: 'type', |
| | | editable: true, |
| | | width: '10%', |
| | | align: 'center', |
| | | }, |
| | | { |
| | | title: '折射率', |
| | | dataIndex: 'refractiveIndex', |
| | | editable: true, |
| | | width: '12%', |
| | | align: 'center', |
| | | }, |
| | | |
| | | { |
| | | title: '供应商', |
| | | dataIndex: 'supplier', |
| | | width: '10%', |
| | | align: 'center', |
| | | }, |
| | | |
| | | { |
| | | title: '操作', |
| | | dataIndex: 'op', |
| | | width: '10%', |
| | | align: 'center', |
| | | render: (_, record, recordIndex) => ( |
| | | <Popconfirm |
| | | title="提示" |
| | | content="确认删除吗?" |
| | | onOk={() => { |
| | | handleRemoveRow(recordIndex); |
| | | }} |
| | | > |
| | | <Button type="text" size="small" status="danger"> |
| | | 删除 |
| | | </Button> |
| | | </Popconfirm> |
| | | ), |
| | | }, |
| | | ]; |
| | | |
| | | const [loading, setLoading] = useState(false); |
| | | const loadList = async () => { |
| | | setLoading(true); |
| | | try { |
| | | const response = await request('/t-brand/pageList', { |
| | | data: { |
| | | pageNum: 1, |
| | | pageSize: 999999999, |
| | | type: 2, |
| | | }, |
| | | method: 'POST', |
| | | }); |
| | | if (response.code === 200) { |
| | | setBrandList(response.data.records || []); |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | } finally { |
| | | setLoading(false); |
| | | } |
| | | }; |
| | | |
| | | const loadModelList = async (brandId) => { |
| | | if (seriesList[brandId]) { |
| | | return; |
| | | } |
| | | try { |
| | | const response = await request('/t-lens-series/pageList', { |
| | | data: { |
| | | pageNum: 1, |
| | | pageSize: 99999999, |
| | | brandId, |
| | | }, |
| | | method: 'POST', |
| | | }); |
| | | if (response.code === 200) { |
| | | seriesList[brandId] = response.data.records || []; |
| | | setSeriesList({ ...seriesList }); |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | }; |
| | | |
| | | useEffect(() => { |
| | | loadList(); |
| | | }, []); |
| | | |
| | | const loadInventory = async (values) => { |
| | | if ( |
| | | values.brandId && |
| | | values.seriesId && |
| | | values.type && |
| | | values.refractiveIndex && |
| | | values.columnMirror |
| | | ) { |
| | | try { |
| | | const response = await request( |
| | | '/t-warehousing/getCurrentByParamLens', |
| | | { |
| | | data: { |
| | | ...values, |
| | | lensType: values.type, |
| | | storeId: props.storeId, |
| | | |
| | | ballMirror: |
| | | values.ballMirror === undefined || values.ballMirror === null |
| | | ? undefined |
| | | : ((values.ballMirror || 0) / 100).toFixed(2), |
| | | }, |
| | | method: 'POST', |
| | | } |
| | | ); |
| | | const payload = response.data; |
| | | return payload; |
| | | } catch (e) { |
| | | Message.error(e.message); |
| | | } |
| | | } else { |
| | | return 0; |
| | | } |
| | | }; |
| | | |
| | | async function handleSave(row) { |
| | | const newData = [...data]; |
| | | const index = newData.findIndex((item) => row.key === item.key); |
| | | |
| | | if (row['brandId']) { |
| | | const currentBrand = brandList.find( |
| | | (brand) => brand.id == row['brandId'] |
| | | ); |
| | | row.brand = currentBrand?.name; |
| | | // 如果品牌变了,型号也要清空 |
| | | if (newData[index].brandId !== row.brandId) { |
| | | row.seriesId = undefined; |
| | | row.series = ''; |
| | | row.type = undefined; |
| | | row.refractiveIndex = ''; |
| | | row.supplier = ''; |
| | | } |
| | | } |
| | | if (row['seriesId']) { |
| | | const currentSeries = (seriesList[row['brandId']] || []).find( |
| | | (model) => model.id == row['seriesId'] |
| | | ); |
| | | row.series = currentSeries?.name; |
| | | row.inventory = currentSeries?.inventory; |
| | | row.supplier = currentSeries?.supplier; |
| | | // 如果品牌变了,型号也要清空 |
| | | if (newData[index].seriesId !== row.seriesId) { |
| | | console.warn('应该被清除了'); |
| | | row.type = undefined; |
| | | row.refractiveIndex = ''; |
| | | } |
| | | } |
| | | row.inventory = await loadInventory(row); |
| | | console.warn('row', row); |
| | | newData.splice(index, 1, { ...newData[index], ...row }); |
| | | setData(newData); |
| | | props.onChange && props.onChange(newData); |
| | | if (row['brandId']) { |
| | | await loadModelList(row.brandId); |
| | | } |
| | | } |
| | | |
| | | const handleRemoveRow = (index) => { |
| | | const newData = [...data]; |
| | | newData.splice(index, 1); |
| | | setData(newData); |
| | | }; |
| | | |
| | | function addRow() { |
| | | // 找到默认的品牌 |
| | | const defaultBrand = brandList.find((brand) => brand.isMain == 1); |
| | | setData( |
| | | data.concat({ |
| | | key: uuidv4(), |
| | | brand: defaultBrand?.name || '', |
| | | brandId: defaultBrand?.id || undefined, |
| | | seriesId: undefined, |
| | | series: '', |
| | | type: undefined, |
| | | refractiveIndex: '', |
| | | ballMirror: '', |
| | | columnMirror: '', |
| | | inventory: undefined, |
| | | supplier: '', |
| | | total: undefined, |
| | | }) |
| | | ); |
| | | if (defaultBrand?.id || 0) { |
| | | loadModelList(defaultBrand.id); |
| | | } |
| | | } |
| | | |
| | | function validateData() { |
| | | if (!data.length) { |
| | | throw new Error('请添加数据'); |
| | | } |
| | | // 依次校验每一行数据 |
| | | // 开始挨个挨个检查 |
| | | for (let i = 0; i < data.length; i++) { |
| | | const row = data[i]; |
| | | data[i].ballMirror = |
| | | row.ballMirror === undefined || row.ballMirror === null |
| | | ? undefined |
| | | : ((row.ballMirror || 0) / 100).toFixed(2); |
| | | if (!row.brand) { |
| | | throw new Error(`第${i + 1}行未选择品牌`); |
| | | } |
| | | if (!row.seriesId) { |
| | | throw new Error(`第${i + 1}行未选择系列`); |
| | | } |
| | | if (!row.type) { |
| | | throw new Error(`第${i + 1}行未选择球/非类型`); |
| | | } |
| | | if (!row.refractiveIndex) { |
| | | throw new Error(`第${i + 1}行未选择折射率`); |
| | | } |
| | | if (!row.ballMirror) { |
| | | throw new Error(`第${i + 1}行未选择球镜`); |
| | | } |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | return ( |
| | | <DataTableContext.Provider |
| | | value={{ brandList, seriesList, operationType: props.type }} |
| | | > |
| | | <Table |
| | | data={data} |
| | | loading={loading} |
| | | components={{ |
| | | body: { |
| | | row: EditableRow, |
| | | cell: EditableCell, |
| | | }, |
| | | }} |
| | | pagination={false} |
| | | columns={columns.map((column) => |
| | | column.editable |
| | | ? { |
| | | ...column, |
| | | onCell: () => ({ |
| | | onHandleSave: handleSave, |
| | | }), |
| | | } |
| | | : column |
| | | )} |
| | | /> |
| | | <div |
| | | style={{ marginTop: 10, display: 'flex', justifyContent: 'flex-end' }} |
| | | > |
| | | <Button type="primary" onClick={addRow}> |
| | | 添加 |
| | | </Button> |
| | | </div> |
| | | </DataTableContext.Provider> |
| | | ); |
| | | } |
| | | ); |
| | | |
| | | export default DataTable; |
New file |
| | |
| | | import React, { useEffect, useMemo, useRef, useState } from 'react'; |
| | | import { |
| | | Button, |
| | | Card, |
| | | Form, |
| | | Input, |
| | | Grid, |
| | | Message, |
| | | Divider, |
| | | Result, |
| | | Select, |
| | | } from '@arco-design/web-react'; |
| | | import { useHistory } from 'react-router-dom'; |
| | | import StoreSelect from '@/components/StoreSelect'; |
| | | import request from '@/request/request'; |
| | | import DataTable from '../components/DataTable'; |
| | | import ExcelTable from '../components/ExcelTable'; |
| | | import BrandSelect from '@/components/BrandSelect'; |
| | | import PermissionWrapper from '@/components/PermissionWrapper'; |
| | | import { getUserStoreId } from '@/utils/constants'; |
| | | |
| | | const { useForm } = Form; |
| | | const { Row, Col } = Grid; |
| | | |
| | | export default function Import(props: { onModeChange?: () => void }) { |
| | | // 获取页面路由参数 |
| | | const history = useHistory(); |
| | | const [form] = useForm(); |
| | | |
| | | const [loading, setLoading] = useState(false); |
| | | const dataTableRef = useRef(null); |
| | | |
| | | const [isSuccess, setIsSuccess] = useState(false); |
| | | |
| | | const brandSelectRef = useRef(null); |
| | | |
| | | const [seriesList, setSeriesList] = useState([]); |
| | | const [seriesLoading, setSeriesLoading] = useState(false); |
| | | const [seriesTypeList, setSeriesTypeList] = useState([]); |
| | | const [seriesRefractionIndexList, setSeriesRefractionIndexList] = useState( |
| | | [] |
| | | ); |
| | | const loadSeriesList = async (brandId: number) => { |
| | | setSeriesList([]); |
| | | setSeriesTypeList([]); |
| | | setSeriesRefractionIndexList([]); |
| | | form.setFieldsValue({ |
| | | seriesId: undefined, |
| | | type: undefined, |
| | | refractiveIndex: undefined, |
| | | }); |
| | | |
| | | setSeriesLoading(true); |
| | | try { |
| | | const response = await request('/t-lens-series/pageList', { |
| | | data: { |
| | | pageNum: 1, |
| | | pageSize: 9999999, |
| | | brandId, |
| | | }, |
| | | method: 'POST', |
| | | }); |
| | | const payload = response.data; |
| | | setSeriesList(payload.records ?? []); |
| | | } catch (e) { |
| | | Message.error(e.message); |
| | | setSeriesList([]); |
| | | } finally { |
| | | setSeriesLoading(false); |
| | | } |
| | | }; |
| | | |
| | | const rebuildSeriesTypeList = (seriesId: number) => { |
| | | form.setFieldsValue({ |
| | | type: undefined, |
| | | refractiveIndex: undefined, |
| | | }); |
| | | setSeriesTypeList([]); |
| | | setSeriesRefractionIndexList([]); |
| | | const record = seriesList.find((item) => item.id === seriesId); |
| | | if (!record) return; |
| | | const typeNameList = ['球面', '非球面', '双非']; |
| | | const list = []; |
| | | [record.sphere, record.asphericSurface, record.doubleNon].forEach( |
| | | (item, index) => { |
| | | try { |
| | | const jsonData = JSON.parse(item); |
| | | if (jsonData.length > 0) { |
| | | list.push({ |
| | | label: typeNameList[index], |
| | | value: index + 1, |
| | | }); |
| | | } |
| | | } catch (e) {} |
| | | } |
| | | ); |
| | | setSeriesTypeList(list); |
| | | }; |
| | | |
| | | const rebuildSeriesRefractionIndexList = (seriesId: number, type: number) => { |
| | | form.setFieldsValue({ |
| | | refractiveIndex: undefined, |
| | | }); |
| | | setSeriesRefractionIndexList([]); |
| | | const record = seriesList.find((item) => item.id === seriesId); |
| | | if (!record) return; |
| | | let jsonData = []; |
| | | switch (type) { |
| | | case 1: |
| | | try { |
| | | jsonData = JSON.parse(record.sphere); |
| | | } catch (e) {} |
| | | break; |
| | | case 2: |
| | | try { |
| | | jsonData = JSON.parse(record.asphericSurface); |
| | | } catch (e) {} |
| | | break; |
| | | case 3: |
| | | try { |
| | | jsonData = JSON.parse(record.doubleNon); |
| | | } catch (e) {} |
| | | break; |
| | | } |
| | | console.warn(jsonData, record); |
| | | setSeriesRefractionIndexList(jsonData); |
| | | }; |
| | | |
| | | const buildFormValues = (formValue, dataList) => { |
| | | const formatedFormValues = []; |
| | | const fieldValueMap = { |
| | | value0: '-0.00', |
| | | value1: '-0.50', |
| | | value2: '-0.75', |
| | | value3: '-1.00', |
| | | value4: '-1.25', |
| | | value5: '-1.50', |
| | | value6: '-1.75', |
| | | value7: '-2.00', |
| | | }; |
| | | const brandList = brandSelectRef.current.getList(); |
| | | console.warn(brandList); |
| | | const brand = brandList.find((item) => item.id === formValue.brandId); |
| | | if (!brand) { |
| | | Message.error('品牌信息不存在'); |
| | | return formatedFormValues; |
| | | } |
| | | const series = seriesList.find((item) => item.id === formValue.seriesId); |
| | | if (!series) { |
| | | Message.error('系列信息不存在'); |
| | | return formatedFormValues; |
| | | } |
| | | dataList.forEach((item) => { |
| | | Object.keys(fieldValueMap).forEach((key) => { |
| | | // 如果有值,就注入咯 |
| | | if (item[key]) { |
| | | formatedFormValues.push({ |
| | | total: +item[key], // 数量 |
| | | columnMirror: fieldValueMap[key], // 球镜 |
| | | ballMirror: item.label, // 柱镜 |
| | | brand: brand.name, // 品牌 |
| | | refractiveIndex: formValue.refractiveIndex, // 折射率 |
| | | series: series.name, //系列 |
| | | seriesId: formValue.seriesId, |
| | | supplier: '', // 供应商 |
| | | type: formValue.type, // 1球面,2非球面,3双非 |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | return formatedFormValues; |
| | | }; |
| | | const [updateModelId, setUpdateModelId] = useState(null); |
| | | |
| | | const handleSubmit = async () => { |
| | | if (loading) return; |
| | | try { |
| | | await form.validate(); |
| | | const values = form.getFieldsValue(); |
| | | setLoading(true); |
| | | const dataList = |
| | | dataTableRef.current && dataTableRef.current.validateData(); |
| | | console.warn('dataList', dataList); |
| | | const formatedValueList = buildFormValues(values, dataList); |
| | | if (formatedValueList.length === 0) { |
| | | Message.error('数据不符合提交条件'); |
| | | return; |
| | | } |
| | | console.warn('formatedValueList', formatedValueList); |
| | | |
| | | const response = await request('/t-warehousing/outBoundLens', { |
| | | data: { |
| | | lensWarehousingDetails: formatedValueList, |
| | | storeId: values.storeId, |
| | | remark: values.remark, |
| | | status: 4, |
| | | type: 2, |
| | | id: null, |
| | | }, |
| | | method: 'POST', |
| | | }); |
| | | setUpdateModelId(response.data); |
| | | setIsSuccess(true); |
| | | form.resetFields(); |
| | | } catch (e) { |
| | | if (!e.hasOwnProperty('errors')) { |
| | | Message.error(e.message); |
| | | } |
| | | } finally { |
| | | setLoading(false); |
| | | } |
| | | }; |
| | | |
| | | return ( |
| | | <> |
| | | {!isSuccess ? ( |
| | | <Card |
| | | title="镜片出库单" |
| | | extra={ |
| | | <Button onClick={props.onModeChange} type="primary"> |
| | | 普通模式 |
| | | </Button> |
| | | } |
| | | > |
| | | <Form |
| | | form={form} |
| | | layout="vertical" |
| | | labelAlign="left" |
| | | labelCol={{ span: 8 }} |
| | | wrapperCol={{ span: 16 }} |
| | | initialValues={{ |
| | | storeId: getUserStoreId(), |
| | | }} |
| | | onChange={(changeValue, values) => { |
| | | if (changeValue.brandId) { |
| | | loadSeriesList(changeValue.brandId); |
| | | } |
| | | if (changeValue.seriesId) { |
| | | rebuildSeriesTypeList(changeValue.seriesId); |
| | | } |
| | | if (changeValue.type) { |
| | | rebuildSeriesRefractionIndexList( |
| | | values.seriesId, |
| | | changeValue.type |
| | | ); |
| | | } |
| | | }} |
| | | > |
| | | <Row gutter={20}> |
| | | <Col span={6}> |
| | | <Form.Item |
| | | label="店铺" |
| | | field="storeId" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择店铺' }]} |
| | | > |
| | | <StoreSelect /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={18}></Col> |
| | | <Col span={6}> |
| | | <Form.Item |
| | | label="镜片品牌" |
| | | field="brandId" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择品牌' }]} |
| | | > |
| | | <BrandSelect type={2} ref={brandSelectRef} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item |
| | | label="镜片系列" |
| | | field="seriesId" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择系列' }]} |
| | | > |
| | | <Select placeholder="请选择镜片系列" loading={seriesLoading}> |
| | | {seriesList.map((item) => { |
| | | return ( |
| | | <Select.Option key={item.id} value={item.id}> |
| | | {item.name} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item |
| | | label="球/非" |
| | | field="type" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择' }]} |
| | | > |
| | | <Select placeholder="请选择"> |
| | | {seriesTypeList.map((item) => { |
| | | return ( |
| | | <Select.Option key={item.value} value={item.value}> |
| | | {item.label} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item |
| | | label="折射率" |
| | | field="refractiveIndex" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择折射率' }]} |
| | | > |
| | | <Select placeholder="请选择"> |
| | | {seriesRefractionIndexList.map((item) => { |
| | | return ( |
| | | <Select.Option |
| | | key={item.refractiveIndex} |
| | | value={item.refractiveIndex} |
| | | > |
| | | {item.refractiveIndex} |
| | | </Select.Option> |
| | | ); |
| | | })} |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> |
| | | <Divider /> |
| | | <Col span={24}> |
| | | <ExcelTable ref={dataTableRef} /> |
| | | </Col> |
| | | <Divider /> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | label="备注" |
| | | field="remark" |
| | | layout="horizontal" |
| | | // rules={[{ required: true, message: '请输入备注' }]} |
| | | > |
| | | <Input.TextArea rows={5} /> |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | <div |
| | | style={{ |
| | | display: 'flex', |
| | | alignItems: 'center', |
| | | justifyContent: 'center', |
| | | marginTop: 20, |
| | | }} |
| | | > |
| | | <Button type="primary" loading={loading} onClick={handleSubmit}> |
| | | 提交出库单 |
| | | </Button> |
| | | </div> |
| | | </Card> |
| | | ) : ( |
| | | <Card> |
| | | <Result |
| | | status="success" |
| | | title="出入库记录提交成功!" |
| | | extra={[ |
| | | <Button |
| | | key="back" |
| | | onClick={() => { |
| | | // history.replace('/stocks/spectaclesFrame/index'); |
| | | history.go(-1); |
| | | }} |
| | | style={{ marginRight: 10 }} |
| | | > |
| | | 返回上一页 |
| | | </Button>, |
| | | <PermissionWrapper |
| | | requiredPermissions={['print/lens']} |
| | | key="print" |
| | | > |
| | | <Button |
| | | key="print" |
| | | type="primary" |
| | | onClick={() => { |
| | | history.push( |
| | | `/print/lens?navbar=false&menu=false&footer=false&whiteBgContent=true&id=${updateModelId}` |
| | | ); |
| | | }} |
| | | > |
| | | 打印出入库单 |
| | | </Button> |
| | | </PermissionWrapper>, |
| | | ]} |
| | | ></Result> |
| | | </Card> |
| | | )} |
| | | </> |
| | | ); |
| | | } |
New file |
| | |
| | | import React, { useEffect, useMemo, useRef, useState } from 'react'; |
| | | import { useHistory } from 'react-router-dom'; |
| | | import { Modal } from '@arco-design/web-react'; |
| | | import Normal from './normal'; |
| | | import Import from './import'; |
| | | export default function OutBoundIndex() { |
| | | // 获取页面路由参数 |
| | | const history = useHistory(); |
| | | const [mode, setMode] = useState('normal'); |
| | | const onChangeMode = (changeType) => { |
| | | Modal.confirm({ |
| | | title: '提示', |
| | | content: '确认要切换模式吗?切换后现有的数据将被清除!', |
| | | onOk: () => { |
| | | setMode(changeType); |
| | | }, |
| | | }); |
| | | }; |
| | | return ( |
| | | <> |
| | | {mode === 'normal' ? ( |
| | | <Normal |
| | | onModeChange={() => { |
| | | onChangeMode('import'); |
| | | }} |
| | | /> |
| | | ) : ( |
| | | <Import |
| | | onModeChange={() => { |
| | | onChangeMode('normal'); |
| | | }} |
| | | /> |
| | | )} |
| | | </> |
| | | ); |
| | | } |
New file |
| | |
| | | import React, { useEffect, useMemo, useRef, useState } from 'react'; |
| | | import { |
| | | Button, |
| | | Card, |
| | | Form, |
| | | Input, |
| | | Grid, |
| | | Message, |
| | | Divider, |
| | | Result, |
| | | Empty, |
| | | } from '@arco-design/web-react'; |
| | | import { useHistory } from 'react-router-dom'; |
| | | import StoreSelect from '@/components/StoreSelect'; |
| | | import request from '@/request/request'; |
| | | import DataTable from '../components/DataTable1'; |
| | | import { getUserStoreId } from '@/utils/constants'; |
| | | import PermissionWrapper from '@/components/PermissionWrapper'; |
| | | |
| | | const { useForm } = Form; |
| | | const { Row, Col } = Grid; |
| | | |
| | | export default function Normal(props: { onModeChange?: () => void }) { |
| | | // 获取页面路由参数 |
| | | const history = useHistory(); |
| | | const [form] = useForm(); |
| | | |
| | | const [loading, setLoading] = useState(false); |
| | | const dataTableRef = useRef(null); |
| | | |
| | | const [isSuccess, setIsSuccess] = useState(false); |
| | | const [updateModelId, setUpdateModelId] = useState(null); |
| | | |
| | | const handleSubmit = async () => { |
| | | if (loading) return; |
| | | try { |
| | | await form.validate(); |
| | | const values = form.getFieldsValue(); |
| | | setLoading(true); |
| | | const dataList = |
| | | dataTableRef.current && dataTableRef.current.validateData(); |
| | | const response = await request('/t-lens-series/addGoods', { |
| | | data: { |
| | | lensWarehousingDetails: dataList, |
| | | ...values, |
| | | }, |
| | | method: 'POST', |
| | | }); |
| | | Message.success('生成库存成功'); |
| | | history.go(-1); |
| | | // setUpdateModelId(response.data); |
| | | // setIsSuccess(true); |
| | | form.resetFields(); |
| | | } catch (e) { |
| | | if (!e.hasOwnProperty('errors')) { |
| | | Message.error(e.message); |
| | | } |
| | | } finally { |
| | | setLoading(false); |
| | | } |
| | | }; |
| | | const currentStoreId = Form.useWatch('storeId', form); |
| | | |
| | | return ( |
| | | <> |
| | | {!isSuccess ? ( |
| | | <Card |
| | | title="镜片库存生成" |
| | | // extra={ |
| | | // <Button onClick={props.onModeChange} type="primary"> |
| | | // 编辑模式 |
| | | // </Button> |
| | | // } |
| | | > |
| | | <Form |
| | | form={form} |
| | | layout="vertical" |
| | | labelAlign="left" |
| | | labelCol={{ span: 4 }} |
| | | wrapperCol={{ span: 20 }} |
| | | initialValues={{ |
| | | storeId: getUserStoreId(), |
| | | }} |
| | | > |
| | | <Row gutter={20}> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | label="店铺" |
| | | field="storeId" |
| | | layout="horizontal" |
| | | rules={[{ required: true, message: '请选择店铺' }]} |
| | | > |
| | | <StoreSelect |
| | | style={{ |
| | | width: 200, |
| | | }} |
| | | /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Divider /> |
| | | <Col span={24}> |
| | | {currentStoreId ? ( |
| | | <DataTable |
| | | storeId={currentStoreId} |
| | | ref={dataTableRef} |
| | | type="rollback" |
| | | /> |
| | | ) : ( |
| | | <Empty description="请先选择店铺" /> |
| | | )} |
| | | </Col> |
| | | <Divider /> |
| | | <Col span={12}> |
| | | |
| | | </Col> |
| | | <Col span={12}></Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | label="备注" |
| | | field="remark" |
| | | layout="horizontal" |
| | | // rules={[{ required: true, message: '请输入备注' }]} |
| | | > |
| | | <Input.TextArea rows={5} placeholder='请输入备注'/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | <div |
| | | style={{ |
| | | display: 'flex', |
| | | alignItems: 'center', |
| | | justifyContent: 'center', |
| | | marginTop: 20, |
| | | }} |
| | | > |
| | | <Button type="primary" loading={loading} onClick={handleSubmit}> |
| | | 生成库存 |
| | | </Button> |
| | | </div> |
| | | </Card> |
| | | ) : ( |
| | | <Card> |
| | | <Result |
| | | status="success" |
| | | title="出入库记录提交成功!" |
| | | extra={[ |
| | | <Button |
| | | key="back" |
| | | onClick={() => { |
| | | // history.replace('/stocks/spectaclesFrame/index'); |
| | | history.go(-1); |
| | | }} |
| | | style={{ marginRight: 10 }} |
| | | > |
| | | 返回上一页 |
| | | </Button>, |
| | | <PermissionWrapper |
| | | requiredPermissions={['print/lens']} |
| | | key="print" |
| | | > |
| | | <Button |
| | | key="print" |
| | | type="primary" |
| | | onClick={() => { |
| | | history.push( |
| | | `/print/lens?navbar=false&menu=false&footer=false&whiteBgContent=true&id=${updateModelId}` |
| | | ); |
| | | }} |
| | | > |
| | | 打印出入库单 |
| | | </Button> |
| | | </PermissionWrapper>, |
| | | ]} |
| | | ></Result> |
| | | </Card> |
| | | )} |
| | | </> |
| | | ); |
| | | } |
| | |
| | | import DataTable from '../components/DataTable'; |
| | | import ExcelTable from '../components/ExcelTable'; |
| | | import BrandSelect from '@/components/BrandSelect'; |
| | | import { getUserStoreId } from '@/utils/constants'; |
| | | |
| | | const { useForm } = Form; |
| | | const { Row, Col } = Grid; |
| | |
| | | labelAlign="left" |
| | | labelCol={{ span: 8 }} |
| | | wrapperCol={{ span: 16 }} |
| | | initialValues={{}} |
| | | initialValues={{ |
| | | storeId: getUserStoreId(), |
| | | }} |
| | | onChange={(changeValue, values) => { |
| | | if (changeValue.brandId) { |
| | | loadSeriesList(changeValue.brandId); |
| | |
| | | ignore: true, |
| | | }, |
| | | { |
| | | name: '镜片库存生成', |
| | | requiredPermissions: [], |
| | | oneOfPerm: false, |
| | | key: 'stocks/lensOperation/generate/index', |
| | | ignore: true, |
| | | }, |
| | | { |
| | | name: '镜片出入库记录', |
| | | requiredPermissions: [], |
| | | oneOfPerm: false, |