瀏覽代碼

库房设置

shaogen1995 5 月之前
父節點
當前提交
b33e7d6dc0

+ 141 - 0
src/pages/D_storeManage/D2storSet/D2edit.tsx

@@ -0,0 +1,141 @@
+import React, { useCallback, useEffect, useRef } from 'react'
+import styles from './index.module.scss'
+import { Button, Form, FormInstance, Input, Modal, Radio, Select } from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { useDispatch, useSelector } from 'react-redux'
+import { getUserListAPI } from '@/store/action/Z6user'
+import { RootState } from '@/store'
+import { D2_APIedit, D2_APIgetInfo } from '@/store/action/D2storSet'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  sId: number
+  succToLookFu: (id: number) => void
+  closeFu: () => void
+}
+
+function D2edit({ sId, succToLookFu, closeFu }: Props) {
+  // 获取用户列表
+  const dispatch = useDispatch()
+  useEffect(() => {
+    dispatch(
+      getUserListAPI({
+        pageNum: 1,
+        pageSize: 99999,
+        searchKey: ''
+      })
+    )
+  }, [dispatch])
+
+  const userList = useSelector((state: RootState) => state.Z6user.tableInfo.list)
+
+  // 设置表单ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await D2_APIgetInfo(id)
+    if (res.code === 0) FormBoxRef.current?.setFieldsValue(res.data)
+  }, [])
+
+  useEffect(() => {
+    if (sId > 0) getInfoFu(sId)
+    else FormBoxRef.current?.setFieldsValue({ enable: 1 })
+  }, [getInfoFu, sId])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    // return MessageFu.warning("有表单不符号规则!");
+  }, [])
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      const res = await D2_APIedit({
+        ...values,
+        id: sId > 0 ? sId : null
+      })
+      if (res.code === 0) {
+        MessageFu.success(sId > 0 ? '编辑成功' : '新增成功')
+        succToLookFu(res.data.id)
+        closeFu()
+      }
+    },
+    [closeFu, sId, succToLookFu]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.D2edit}
+      open={true}
+      title={sId > 0 ? '编辑' : '新增'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='D2aMain'>
+        <Form
+          scrollToFirstError={true}
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+        >
+          <Form.Item
+            label='仓库名称'
+            name='name'
+            rules={[{ required: true, message: '请输入仓库名称' }]}
+          >
+            <Input maxLength={30} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item
+            label='仓库编码'
+            name='num'
+            rules={[{ required: true, message: '请输入仓库编码' }]}
+          >
+            <Input maxLength={30} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item
+            label='仓库负责人'
+            name='managerUserId'
+            rules={[{ required: true, message: '请选择仓库负责人' }]}
+          >
+            <Select
+              placeholder='请选择'
+              options={userList.map(v => ({ value: v.id, label: v.realName || v.userName }))}
+            />
+          </Form.Item>
+
+          <Form.Item label='仓库说明' name='description'>
+            <TextArea maxLength={500} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item label='仓库状态' name='enable' rules={[{ required: true, message: '' }]}>
+            <Radio.Group>
+              <Radio value={1}>启用</Radio>
+              <Radio value={0}>禁用</Radio>
+            </Radio.Group>
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type='primary' htmlType='submit'>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoD2edit = React.memo(D2edit)
+
+export default MemoD2edit

+ 53 - 0
src/pages/D_storeManage/D2storSet/D2look/index.module.scss

@@ -0,0 +1,53 @@
+.D2look {
+  overflow-y: auto;
+  :global {
+    .D2Ltop1 {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .D2Ltop1_1 {
+        font-size: 16px;
+        font-weight: 700;
+      }
+    }
+
+    .D2Ltop {
+      background-color: #fff;
+      padding: 20px 24px 24px;
+      border-radius: 10px;
+
+      .D2Ltop2 {
+        margin-top: 15px;
+        padding-top: 15px;
+        border-top: 1px #ccc solid;
+        font-size: 16px;
+        .D2Ltop2_1 {
+          margin-bottom: 5px;
+          display: flex;
+          & > div {
+            width: 100px;
+            text-align: right;
+            font-weight: 700;
+          }
+          & > p {
+            width: calc(100% - 100px);
+            word-wrap: break-word;
+          }
+        }
+      }
+    }
+
+    .D2Ltable {
+      margin-top: 15px;
+      background-color: #fff;
+      padding: 20px 24px 24px;
+      border-radius: 10px;
+      .D2Ltop1 {
+        margin-bottom: 15px;
+      }
+      .ant-table-cell {
+        padding: 8px !important;
+      }
+    }
+  }
+}

+ 115 - 0
src/pages/D_storeManage/D2storSet/D2look/index.tsx

@@ -0,0 +1,115 @@
+import React, { useCallback, useEffect, useState } from 'react'
+import styles from './index.module.scss'
+import { useParams } from 'react-router-dom'
+import { D2_APIdel, D2_APIgetInfo } from '@/store/action/D2storSet'
+import { Button } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import history from '@/utils/history'
+import { TypeD2list } from '../type'
+import D2edit from '../D2edit'
+import MyTable from '@/components/MyTable'
+import { D2tableCSon } from '@/utils/tableData'
+
+const topArr = [
+  { name: '仓库名称', key: 'name' },
+  { name: '仓库编码', key: 'num' },
+  { name: '仓库负责人', key: 'managerUser' },
+  { name: '仓库说明', key: 'description' }
+  // { name: '仓库状态', key: 'enable' }
+]
+
+function D2look() {
+  const { id: sId } = useParams<any>()
+
+  const [info, setInfo] = useState({} as TypeD2list)
+
+  const getInfoFu = useCallback(async () => {
+    const res = await D2_APIgetInfo(sId)
+    if (res.code === 0) {
+      setInfo(res.data)
+    }
+  }, [sId])
+
+  useEffect(() => {
+    getInfoFu()
+  }, [getInfoFu])
+
+  // 点击删除
+  const delTableFu = useCallback(async () => {
+    const res = await D2_APIdel(sId)
+    if (res.code === 0) {
+      MessageFu.success('删除成功!')
+      history.go(-1)
+    }
+  }, [sId])
+
+  const [editId, setEditId] = useState(0)
+
+  return (
+    <div className={styles.D2look}>
+      <div className='pageTitle'>库房设置-查看</div>
+
+      <div className='D2Ltop'>
+        <div className='D2Ltop1'>
+          <div className='D2Ltop1_1'>库房信息</div>
+          <div>
+            <Button type='primary' onClick={() => setEditId(sId)}>
+              编辑
+            </Button>
+            &emsp;
+            <MyPopconfirm
+              txtK='删除'
+              onConfirm={() => delTableFu()}
+              Dom={<Button danger>删除</Button>}
+            />
+            &emsp;
+            <Button onClick={() => history.go(-1)}>返回</Button>
+          </div>
+        </div>
+        {info.id ? (
+          <div className='D2Ltop2'>
+            {topArr.map(item => (
+              <div className='D2Ltop2_1' key={item.name}>
+                <div>{item.name}:</div>
+                <p>{info[item.key as 'name'] || '(空)'}</p>
+              </div>
+            ))}
+            <div className='D2Ltop2_1'>
+              <div>仓库状态:</div>
+              <p>{info.enable ? '启用' : '禁用'}</p>
+            </div>
+          </div>
+        ) : null}
+      </div>
+
+      {/* 下面的表格 */}
+      <div className='D2Ltable'>
+        <div className='D2Ltop1'>
+          <div className='D2Ltop1_1'>库位信息</div>
+          <div>
+            <Button type='primary' onClick={() => history.push(`/storSet_site/${sId}`)}>
+              设置
+            </Button>
+          </div>
+        </div>
+        <MyTable
+          list={info.site || []}
+          columnsTemp={D2tableCSon}
+          lastBtn={[]}
+          pagingInfo={false}
+          widthSet={{ description: 700 }}
+        />
+      </div>
+
+      {/* 编辑弹窗 */}
+      {editId ? (
+        <D2edit sId={editId} succToLookFu={() => getInfoFu()} closeFu={() => setEditId(0)} />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoD2look = React.memo(D2look)
+
+export default MemoD2look

+ 282 - 0
src/pages/D_storeManage/D2storSet/D2site/D2Sadd.tsx

@@ -0,0 +1,282 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Checkbox, InputNumber, Modal, Select } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { D2SlistType } from './D2Sarea'
+import { D2_APIaddAdd, D2_APIaddEdit, D2_APIgetAreaList } from '@/store/action/D2storSet'
+import TextArea from 'antd/es/input/TextArea'
+import { MessageFu } from '@/utils/message'
+import { TypeD2listSite } from '../type'
+
+type ArrType = {
+  name: string
+  num1: null | number
+  num2: null | number
+  flag: boolean
+}
+
+type ArrResType = {
+  description: string
+  id: number | null
+  layer1: number | null
+  layer2: number | null
+  layer3: number | null
+  regionId: number | null
+  storageId: number
+}
+
+type Props = {
+  addObj: TypeD2listSite
+  sId: number
+  addTableFu: () => void
+  closeFu: () => void
+}
+
+function D2Sadd({ addObj, sId, addTableFu, closeFu }: Props) {
+  useEffect(() => {
+    if (addObj.id > 0) {
+      setRegionId(addObj.regionId)
+      setArr([
+        { name: '排架编码', num1: addObj.layer1, num2: null, flag: false },
+        { name: '层数编码', num1: addObj.layer2, num2: null, flag: false },
+        { name: '层格编码', num1: addObj.layer3, num2: null, flag: false }
+      ])
+      setDescription(addObj.description)
+    }
+  }, [addObj])
+
+  // 所有区域的下拉框数据
+  const [list, setList] = useState<D2SlistType[]>([])
+
+  const getListFu = useCallback(async () => {
+    const res = await D2_APIgetAreaList(sId)
+    if (res.code === 0) {
+      setList(res.data)
+      if (addObj.id < 0 && res.data.length) setRegionId(res.data[0].id)
+    }
+  }, [addObj.id, sId])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 区域
+  const [regionId, setRegionId] = useState<number | null>(null)
+
+  const [arr, setArr] = useState<ArrType[]>([
+    { name: '排架编码', num1: null, num2: null, flag: false },
+    { name: '层数编码', num1: null, num2: null, flag: false },
+    { name: '层格编码', num1: null, num2: null, flag: false }
+  ])
+
+  // 描述
+  const [description, setDescription] = useState('')
+
+  // 输入框改变
+  const inputChangeFu = useCallback(
+    (name: string, key: 'num1' | 'num2' | 'flag', val: number | boolean) => {
+      setArr(
+        arr.map(v => ({
+          ...v,
+          [key]: v.name === name ? val : v[key]
+        }))
+      )
+    },
+    [arr]
+  )
+
+  // 勾选了一个批量
+  const isDoTow = useMemo(() => {
+    return arr.some(v => v.flag)
+  }, [arr])
+
+  // 点击确定
+  const isOkBtn = useCallback(async () => {
+    let flag = ''
+    arr.forEach((v, i) => {
+      if (!v.num1) flag = '请输入正整数编码'
+      else if (v.flag) {
+        // 勾选了批量
+        if (!v.num2) flag = '请输入正整数编码'
+        else {
+          if (v.num2 <= v.num1) flag = `右侧的值需要大于左侧`
+          else {
+            if (i <= 1) {
+              if (v.num2 - v.num1 > 5) flag = `排架/层数右侧值最多只能比左侧大5`
+            } else {
+              if (v.num2 - v.num1 > 10) flag = `层格右侧值最多只能比左侧大10`
+            }
+          }
+        }
+      }
+    })
+    if (flag) return MessageFu.warning(flag)
+
+    const arrRes: ArrResType[] = []
+
+    let objRes = {} as ArrResType
+
+    if (!arr[0].flag && !arr[1].flag && !arr[2].flag) {
+      // 一个都没有勾选
+      objRes = {
+        description,
+        id: addObj.id > 0 ? addObj.id : null,
+        layer1: arr[0].num1,
+        layer2: arr[1].num1,
+        layer3: arr[2].num1,
+        regionId,
+        storageId: Number(sId)
+      }
+      arrRes.push(objRes)
+    } else {
+      // 生成每个元素对应的可能值数组
+      const possibleValues = arr.map(element => {
+        if (element.flag) {
+          const length = element.num2! - element.num1! + 1
+          return Array.from({ length }, (_, i) => element.num1! + i)
+        } else {
+          return [element.num1]
+        }
+      })
+
+      // 计算笛卡尔积
+      const cartesianProduct = (arrays: any) => {
+        return arrays.reduce(
+          (acc: any, currentArray: any) =>
+            acc.flatMap((prevArr: any) =>
+              currentArray.map((currentItem: any) => [...prevArr, currentItem])
+            ),
+          [[]]
+        )
+      }
+
+      // 生成组合并转换为目标对象数组
+      const combinations = cartesianProduct(possibleValues as any)
+      const newArr = combinations.map(([num1, num2, num3]: any) => ({ num1, num2, num3 }))
+
+      newArr.forEach((v: any) => {
+        arrRes.push({
+          description: '',
+          id: null,
+          layer1: v.num1,
+          layer2: v.num2,
+          layer3: v.num3,
+          regionId,
+          storageId: Number(sId)
+        })
+      })
+    }
+
+    // console.log(123, arrRes)
+
+    // if (1 + 1 === 2) return
+
+    const res = addObj.id > 0 ? await D2_APIaddEdit(objRes) : await D2_APIaddAdd(arrRes)
+
+    if (res.code === 0) {
+      MessageFu.success(addObj.id > 0 ? '编辑成功' : '新增成功')
+      addTableFu()
+      closeFu()
+    }
+  }, [addObj.id, addTableFu, arr, closeFu, description, regionId, sId])
+
+  return (
+    <Modal
+      wrapClassName={styles.D2Sarea}
+      open={true}
+      title={addObj.id > 0 ? '编辑库位' : '新增库位'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='D2Smain'>
+        <div className='formBox'>
+          <div className='formBox1'>
+            <span>* </span>区域:
+          </div>
+          <div className='formBox2'>
+            <Select
+              style={{ width: 200 }}
+              value={regionId}
+              onChange={e => setRegionId(e)}
+              options={list.map(v => ({ value: v.id, label: v.name }))}
+            />
+          </div>
+        </div>
+
+        {arr.map((item, index) => (
+          <div className='formBox' key={item.name}>
+            <div className='formBox1'>
+              <span>* </span>
+              {item.name}:
+            </div>
+            <div className='formBox2'>
+              <InputNumber
+                style={{ width: 140 }}
+                min={1}
+                max={1000}
+                precision={0}
+                placeholder='请填入非负整数'
+                value={item.num1}
+                onChange={e => inputChangeFu(item.name, 'num1', e as number)}
+              />
+
+              {item.flag ? (
+                <span>
+                  {' '}
+                  ~{' '}
+                  <InputNumber
+                    style={{ width: 140 }}
+                    min={1}
+                    max={1000}
+                    precision={0}
+                    placeholder='请填入非负整数'
+                    value={item.num2}
+                    onChange={e => inputChangeFu(item.name, 'num2', e as number)}
+                  />
+                </span>
+              ) : null}
+            </div>
+
+            {addObj.id > 0 ? null : (
+              <Checkbox
+                checked={item.flag}
+                onChange={e => inputChangeFu(item.name, 'flag', e.target.checked)}
+              >
+                批量新增{' '}
+                {item.flag ? (
+                  <span className='D2Stit'>右侧的值最多比左侧的值大{index <= 1 ? '5' : '10'}</span>
+                ) : null}
+              </Checkbox>
+            )}
+          </div>
+        ))}
+
+        <div className='formBox formBoxTow' hidden={isDoTow}>
+          <div className='formBox1'>库位说明:</div>
+          <div className='formBox2'>
+            <TextArea
+              maxLength={200}
+              showCount
+              placeholder='请输入内容'
+              value={description}
+              onChange={e => setDescription(e.target.value)}
+            />
+          </div>
+        </div>
+
+        <div className='D2Sbtn'>
+          <Button type='primary' onClick={isOkBtn}>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </div>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoD2Sadd = React.memo(D2Sadd)
+
+export default MemoD2Sadd

+ 203 - 0
src/pages/D_storeManage/D2storSet/D2site/D2Sarea.tsx

@@ -0,0 +1,203 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Modal, Table } from 'antd'
+import {
+  D2_APIareaDelCheck,
+  D2_APIareaDels,
+  D2_APIareaEdit,
+  D2_APIgetAreaList
+} from '@/store/action/D2storSet'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import { D2checkDuplicate } from './data'
+
+type Props = {
+  sId: number
+  closeFu: () => void
+}
+
+export type D2SlistType = {
+  id: string
+  name: string
+  description: string
+  parentId: number
+}
+
+function D2Sarea({ sId, closeFu }: Props) {
+  const [list, setList] = useState<D2SlistType[]>([])
+
+  const getListFu = useCallback(async () => {
+    const res = await D2_APIgetAreaList(sId)
+    if (res.code === 0) {
+      setList(res.data)
+    }
+  }, [sId])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击新增
+  const addTable = useCallback(() => {
+    setList([...list, { id: `new${Date.now()}`, name: '', description: '', parentId: sId }])
+  }, [list, sId])
+
+  // 输入框变化
+  const inputChangeFu = useCallback(
+    (id: string, val: string, key: 'name' | 'description') => {
+      let valRes = key === 'name' ? val.toUpperCase() : val
+      valRes = valRes.trim()
+
+      const newList = list.map(v => ({
+        ...v,
+        [key]: v.id === id ? valRes : v[key]
+      }))
+      setList(newList)
+    },
+    [list]
+  )
+
+  // 存在数据库中的id为number(true) 新增的为string
+  const idFlagFu = useCallback((id: string) => {
+    return typeof id === 'number'
+  }, [])
+
+  // 把存在数据库中的列表删除id记下来
+  const delIds = useRef<string[]>([])
+
+  // 点击删除
+  const delByIdFu = useCallback(
+    async (id: string) => {
+      if (idFlagFu(id)) {
+        // 在数据库中了,需要检查
+        const res = await D2_APIareaDelCheck(id)
+        if (res.code === 0) {
+          if (res.data) {
+            MessageFu.warning('该区域存在关联库位,无法删除')
+          } else {
+            // 假删除
+            setList(list.filter(v => v.id !== id))
+            // id存起来 点提交的时候真删除
+            delIds.current.push(id)
+          }
+        }
+      } else {
+        // 没有在数据库中,直接删除
+        setList(list.filter(v => v.id !== id))
+      }
+    },
+    [idFlagFu, list]
+  )
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: '区域名称',
+        render: (item: D2SlistType) => (
+          <Input
+            placeholder='请输入内容'
+            maxLength={30}
+            showCount
+            value={item.name}
+            onChange={e => inputChangeFu(item.id, e.target.value, 'name')}
+          />
+        )
+      },
+      {
+        title: '区域说明',
+        render: (item: D2SlistType) => (
+          <Input
+            placeholder='请输入内容'
+            maxLength={30}
+            showCount
+            value={item.description}
+            onChange={e => inputChangeFu(item.id, e.target.value, 'description')}
+          />
+        )
+      },
+
+      {
+        title: '操作',
+        width: 100,
+        render: (item: D2SlistType) => (
+          <MyPopconfirm txtK='删除' onConfirm={() => delByIdFu(item.id)} />
+        )
+      }
+    ]
+  }, [delByIdFu, inputChangeFu])
+
+  // 点击提交
+  const isOkBtn = useCallback(async () => {
+    if (list.some(v => !v.name)) {
+      MessageFu.warning('区域名称不能为空')
+    } else {
+      const res = await D2_APIareaEdit(
+        list.map(v => ({
+          id: idFlagFu(v.id) ? v.id : null,
+          description: v.description,
+          name: v.name,
+          parentId: Number(v.parentId)
+        }))
+      )
+      if (res.code === 0) {
+        if (delIds.current.length) {
+          const res2 = await D2_APIareaDels(delIds.current)
+          if (res2.code === 0) {
+            MessageFu.success('提交成功')
+            closeFu()
+          }
+        } else {
+          MessageFu.success('提交成功')
+          closeFu()
+        }
+      }
+    }
+  }, [closeFu, idFlagFu, list])
+
+  return (
+    <Modal
+      wrapClassName={styles.D2Sarea}
+      open={true}
+      title={
+        <div className='D2Stop'>
+          区域设置
+          <Button type='primary' onClick={addTable}>
+            新增
+          </Button>
+        </div>
+      }
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='D2Smain'>
+        <Table
+          scroll={{ y: 500 }}
+          dataSource={list}
+          columns={columns}
+          rowKey='id'
+          pagination={false}
+          size='small'
+        />
+
+        <div className='D2Sbtn'>
+          <Button type='primary' onClick={isOkBtn} disabled={D2checkDuplicate(list).length > 0}>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          <p hidden={D2checkDuplicate(list).length === 0}>
+            区域名称重复{' '}
+            {D2checkDuplicate(list).map(v => (
+              <span key={v}>{v}&emsp;</span>
+            ))}
+          </p>
+        </div>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoD2Sarea = React.memo(D2Sarea)
+
+export default MemoD2Sarea

+ 15 - 0
src/pages/D_storeManage/D2storSet/D2site/data.ts

@@ -0,0 +1,15 @@
+import { D2SlistType } from './D2Sarea'
+
+// 重复的区域名称判断
+export const D2checkDuplicate = (items: D2SlistType[]): string[] => {
+  const nameMap: Record<string, number> = {}
+
+  // 统计每个 name 出现的次数
+  items.forEach(item => {
+    const name = item.name.toUpperCase()
+    nameMap[name] = (nameMap[name] || 0) + 1
+  })
+
+  // 提取重复的 name
+  return Object.keys(nameMap).filter(name => nameMap[name] > 1)
+}

+ 81 - 0
src/pages/D_storeManage/D2storSet/D2site/index.module.scss

@@ -0,0 +1,81 @@
+.D2site {
+  padding: 24px;
+  border-radius: 10px;
+  background-color: #fff;
+  :global {
+    .D2Stop {
+      text-align: right;
+    }
+    .D2Stable {
+      margin-top: 15px;
+      .ant-table-cell {
+        padding: 8px !important;
+      }
+    }
+  }
+}
+
+// 区域设置弹窗
+.D2Sarea {
+  :global {
+    .D2Stop {
+      display: flex;
+      justify-content: space-between;
+      padding-bottom: 10px;
+    }
+
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+    }
+
+    .D2Smain {
+      padding-top: 15px;
+      .D2Sbtn {
+        margin-top: 15px;
+        text-align: center;
+        & > p {
+          margin-top: 5px;
+          color: #ff4d4f;
+        }
+      }
+
+      // 新增库位
+      .formBox {
+        display: flex;
+        margin-bottom: 20px;
+        width: 100%;
+        display: flex;
+        align-items: center;
+        .formBox1 {
+          width: 100px;
+          text-align: right;
+          & > span {
+            color: #ff4d4f;
+          }
+        }
+        .formBox2 {
+          width: 298px;
+          margin-right: 15px;
+        }
+        .D2Stit {
+          color: #999;
+          font-size: 12px;
+        }
+      }
+      .formBoxTow {
+        align-items: self-start;
+        .formBox2 {
+          width: 600px;
+        }
+      }
+    }
+  }
+}

+ 111 - 0
src/pages/D_storeManage/D2storSet/D2site/index.tsx

@@ -0,0 +1,111 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { useParams } from 'react-router-dom'
+import { Button } from 'antd'
+import history from '@/utils/history'
+import MyTable from '@/components/MyTable'
+import { D2tableCSon } from '@/utils/tableData'
+import { D2_APIaddDels, D2_APIgetSiteList } from '@/store/action/D2storSet'
+import { TypeD2listSite } from '../type'
+import D2Sarea from './D2Sarea'
+import D2Sadd from './D2Sadd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+function D2site() {
+  const { id: sId } = useParams<any>()
+
+  const getListFu = useCallback(async () => {
+    const res = await D2_APIgetSiteList(sId)
+    if (res.code === 0) {
+      setList(res.data)
+    }
+  }, [sId])
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const [list, setList] = useState<TypeD2listSite[]>([])
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await D2_APIaddDels([id])
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        width: 240,
+        render: (item: TypeD2listSite) => {
+          return (
+            <>
+              <Button size='small' type='text' onClick={() => setAddObj(item)}>
+                编辑
+              </Button>
+              <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+            </>
+          )
+        }
+      }
+    ]
+  }, [delTableFu])
+
+  // 区域设置
+  const [areaShow, setAreaShow] = useState(false)
+
+  // 新增库位
+  const [addObj, setAddObj] = useState({} as TypeD2listSite)
+
+  return (
+    <div className={styles.D2site}>
+      <div className='pageTitle'>库房设置-库位设置</div>
+
+      <div className='D2Stop'>
+        <Button type='primary' onClick={() => setAreaShow(true)}>
+          区域设置
+        </Button>
+        &emsp;
+        <Button type='primary' onClick={() => setAddObj({ id: -1 } as TypeD2listSite)}>
+          新增库位
+        </Button>
+        &emsp;
+        <Button onClick={() => history.go(-1)}>返回</Button>
+      </div>
+
+      <div className='D2Stable'>
+        <MyTable
+          yHeight={700}
+          list={list}
+          columnsTemp={D2tableCSon}
+          lastBtn={tableLastBtn}
+          pagingInfo={false}
+          widthSet={{ description: 700 }}
+        />
+      </div>
+
+      {/* 区域设置弹窗 */}
+      {areaShow ? <D2Sarea sId={sId} closeFu={() => setAreaShow(false)} /> : null}
+
+      {/* 新增库位弹窗 */}
+      {addObj.id ? (
+        <D2Sadd
+          addObj={addObj}
+          sId={sId}
+          addTableFu={getListFu}
+          closeFu={() => setAddObj({} as TypeD2listSite)}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoD2site = React.memo(D2site)
+
+export default MemoD2site

+ 23 - 1
src/pages/D_storeManage/D2storSet/index.module.scss

@@ -8,9 +8,10 @@
       justify-content: space-between;
       .D2topll {
         display: flex;
+        align-items: center;
         .ant-input {
           margin-right: 15px;
-          width: 180px;
+          width: 140px;
         }
         .ant-select {
           width: 100px;
@@ -26,3 +27,24 @@
     }
   }
 }
+
+// 编辑弹窗页面
+.D2edit {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+    }
+
+    .D2aMain {
+      padding-top: 15px;
+    }
+  }
+}

+ 35 - 5
src/pages/D_storeManage/D2storSet/index.tsx

@@ -3,13 +3,15 @@ import styles from './index.module.scss'
 import { TypeD2form, TypeD2list } from './type'
 import { useDispatch, useSelector } from 'react-redux'
 import { D2_APIdel, D2_APIgetList } from '@/store/action/D2storSet'
-import { Button, Input, Select, Table } from 'antd'
+import { Button, Input, Select } from 'antd'
 import { D2select } from './data'
 import { RootState } from '@/store'
 import MyTable from '@/components/MyTable'
 import { D2tableC } from '@/utils/tableData'
 import MyPopconfirm from '@/components/MyPopconfirm'
 import { MessageFu } from '@/utils/message'
+import D2edit from './D2edit'
+import history from '@/utils/history'
 
 const formDataTemp: TypeD2form = {
   pageNum: 1,
@@ -99,13 +101,21 @@ function D2storSet() {
         render: (item: TypeD2list) => {
           return (
             <>
-              <Button size='small' type='text'>
+              <Button
+                size='small'
+                type='text'
+                onClick={() => history.push(`/storSet_look/${item.id}`)}
+              >
                 查看
               </Button>
-              <Button size='small' type='text'>
+              <Button
+                size='small'
+                type='text'
+                onClick={() => history.push(`/storSet_site/${item.id}`)}
+              >
                 库位设置
               </Button>
-              <Button size='small' type='text'>
+              <Button size='small' type='text' onClick={() => setEditId(item.id)}>
                 编辑
               </Button>
               <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
@@ -116,35 +126,43 @@ function D2storSet() {
     ]
   }, [delTableFu])
 
+  // 新增和编辑
+  const [editId, setEditId] = useState(0)
+
   return (
     <div className={styles.D2storSet}>
       <div className='pageTitle'>库房设置</div>
       <div className='D2top'>
         <div className='D2topll'>
+          <span>仓库名称:</span>
           <Input
             placeholder='请输入仓库名称'
             maxLength={30}
             value={formData.name}
             onChange={e => txtChangeFu(e.target.value, 'name')}
           />
+          <span>仓库编码:</span>
           <Input
             placeholder='请输入仓库编码'
             maxLength={30}
             value={formData.num}
             onChange={e => txtChangeFu(e.target.value, 'num')}
           />
+          <span>仓库负责人:</span>
           <Input
             placeholder='请输入仓库负责人'
             maxLength={30}
             value={formData.managerUser}
             onChange={e => txtChangeFu(e.target.value, 'managerUser')}
           />
+          <span>仓库说明:</span>
           <Input
             placeholder='请输入仓库说明'
             maxLength={30}
             value={formData.description}
             onChange={e => txtChangeFu(e.target.value, 'description')}
           />
+          <span>仓库状态:</span>
           <Select
             placeholder='仓库状态'
             options={D2select}
@@ -153,7 +171,10 @@ function D2storSet() {
           />
         </div>
         <div className='D2toprr'>
-          <Button type='primary'>新增</Button>&emsp;
+          <Button type='primary' onClick={() => setEditId(-1)}>
+            新增
+          </Button>
+          &emsp;
           <Button type='primary' onClick={clickSearch}>
             查询
           </Button>
@@ -174,6 +195,15 @@ function D2storSet() {
           widthSet={{ description: 500 }}
         />
       </div>
+
+      {/* 新增和编辑弹窗 */}
+      {editId ? (
+        <D2edit
+          sId={editId}
+          succToLookFu={id => history.push(`/storSet_look/${id}`)}
+          closeFu={() => setEditId(0)}
+        />
+      ) : null}
     </div>
   )
 }

+ 18 - 1
src/pages/D_storeManage/D2storSet/type.d.ts

@@ -4,7 +4,7 @@ export type TypeD2list = {
   creatorId: number
   creatorName: string
   description: string
-  enable: number
+  enable: 0 | 1
   id: number
   level: number
   managerUser: string
@@ -12,6 +12,23 @@ export type TypeD2list = {
   name: string
   num: string
   updateTime: string
+  // 库位信息
+  site: TypeD2listSite[]
+}
+
+// 分页列表里面的库位信息
+export type TypeD2listSite = {
+  createTime: string
+  creatorName: string
+  id: number
+  layer1: number
+  layer2: number
+  layer3: number
+  regionId: number
+  regionName: string
+  storageId: number
+  updateTime: string
+  description: string
 }
 
 // 发送数据

+ 12 - 6
src/pages/Layout/data.ts

@@ -249,10 +249,16 @@ export default tabLeftArr
 
 // 里面的页面,不是左边的tab栏
 export const routerSon: RouterTypeRow = [
-  // {
-  //   id: 1,
-  //   name: '001',
-  //   path: '/flow_ed',
-  //   Com: React.lazy(() => import('../A0000'))
-  // }
+  {
+    id: 1,
+    name: '库房设置-查看',
+    path: '/storSet_look/:id',
+    Com: React.lazy(() => import('../D_storeManage/D2storSet/D2look'))
+  },
+  {
+    id: 2,
+    name: '库房设置-库位设置',
+    path: '/storSet_site/:id',
+    Com: React.lazy(() => import('../D_storeManage/D2storSet/D2site'))
+  }
 ]

+ 17 - 3
src/pages/Layout/index.tsx

@@ -64,11 +64,25 @@ function Layout() {
 
     // 如果当前页面没有权限了,跳转有权限的第一个页面
     const urlAll = window.location.hash
+
     const isNowPath = urlAll.replace('#', '')
     const pathArr = tempArr.map(v => v.path)
-    if (!pathArr.includes(isNowPath)) {
-      history.push(pathArr[0])
-    }
+
+    const routerSonArr = routerSon.map(v => v.path)
+
+    const lastArr = [...pathArr, ...routerSonArr]
+
+    let flagPush = true
+
+    lastArr.forEach(v => {
+      if (v === '/') {
+        if (isNowPath === '/') flagPush = false
+      } else {
+        if (isNowPath.includes(v)) flagPush = false
+      }
+    })
+
+    if (flagPush) history.push(pathArr[0])
 
     const resList = tabLeftArr.map(v => ({
       ...v,

+ 14 - 5
src/pages/Z_system/Z1dict/Z1add.tsx

@@ -18,9 +18,10 @@ type Props = {
   addInfo: Z1AddInfoType
   addFu: () => void
   closeFu: () => void
+  isNoAcIds: string[] //没有数据或者删除了的时候-既右侧没有操作的时候用到
 }
 
-function Z1add({ addInfo, addFu, closeFu }: Props) {
+function Z1add({ addInfo, addFu, closeFu, isNoAcIds }: Props) {
   const { dictList: treeData } = useSelector((state: RootState) => state.Z1dict)
 
   // 级联选择器改变的时候 筛选当前级联的 信息出来
@@ -75,7 +76,7 @@ function Z1add({ addInfo, addFu, closeFu }: Props) {
     if (addInfo.txt === '编辑') getInfoFu(addInfo.id)
     else {
       FormBoxRef.current?.setFieldsValue({
-        sort: 20000
+        sort: 50000
       })
     }
   }, [addInfo.id, addInfo.txt, getInfoFu])
@@ -105,9 +106,17 @@ function Z1add({ addInfo, addFu, closeFu }: Props) {
 
       // 新增并且没有父级
       if (addInfo.txt === '新增' && !parentId && !ancestor) {
+        // console.log('xxx', saveIdsRef.current)
+
         parentId = saveIdsRef.current[saveIdsRef.current.length - 1]
         ancestor = saveIdsRef.current.join(',')
         // console.log(123, parentId, ancestor)
+
+        // 外层没有选中
+        if (!addInfo.acInfo.id) {
+          parentId = isNoAcIds[isNoAcIds.length - 1]
+          ancestor = isNoAcIds.join(',')
+        }
       }
 
       // let level = 1
@@ -134,7 +143,7 @@ function Z1add({ addInfo, addFu, closeFu }: Props) {
         closeFu()
       }
     },
-    [acCardInfo, addFu, addInfo.id, addInfo.txt, closeFu, parentIdArr]
+    [acCardInfo, addFu, addInfo.acInfo.id, addInfo.id, addInfo.txt, closeFu, isNoAcIds, parentIdArr]
   )
   return (
     <Modal
@@ -186,10 +195,10 @@ function Z1add({ addInfo, addFu, closeFu }: Props) {
               name='sort'
               rules={[{ required: true, message: '请输入排序值!' }]}
             >
-              <InputNumber min={1} max={20000} precision={0} placeholder='请输入' />
+              <InputNumber min={1} max={50000} precision={0} placeholder='请输入' />
             </Form.Item>
             <div className='fromRowTit'>
-              请输入1~20000的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+              请输入1~50000的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
             </div>
           </div>
 

+ 11 - 0
src/pages/Z_system/Z1dict/index.module.scss

@@ -27,6 +27,17 @@
           min-height: 100%;
           padding: 10px;
         }
+        .Z1m1llNone {
+          width: 70%;
+          height: 80%;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          color: var(--themeColor);
+          font-size: 20px;
+          letter-spacing: 4px;
+          font-weight: 700;
+        }
       }
       .Z1m1rr {
         width: calc(30% - 24px);

+ 13 - 1
src/pages/Z_system/Z1dict/index.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
 import { useDispatch, useSelector } from 'react-redux'
 import { Z1_APIdel, Z1_APIgetDict } from '@/store/action/Z1dict'
@@ -11,6 +11,8 @@ import MyPopconfirm from '@/components/MyPopconfirm'
 import { MessageFu } from '@/utils/message'
 
 function Z1dict() {
+  const [loding, setLoding] = useState(false)
+
   const dispatch = useDispatch()
 
   useEffect(() => {
@@ -20,10 +22,16 @@ function Z1dict() {
   // 级联改变
   const [topId, setTopId] = useState(['10000', '12000'])
 
+  // 传给新增、编辑子组件(没有数据或者删除了的时候-既右侧没有操作的时候)
+  const isNoAcIds = useRef<string[]>([])
+
   useEffect(() => {
+    isNoAcIds.current = ['0', ...topId]
+
     if (topId && topId.length)
       dispatch(
         Z1_APIgetDict(topId[1], data => {
+          setLoding(true)
           if (data && data.length) setAcShu(data[0].id)
         })
       )
@@ -148,6 +156,7 @@ function Z1dict() {
               options={Z1toTowFu(dictAll)}
               fieldNames={{ label: 'name', value: 'id', children: 'children' }}
               onChange={onChange}
+              allowClear={false}
             />
           ) : (
             <div style={{ width: 240 }}></div>
@@ -189,6 +198,8 @@ function Z1dict() {
               onSelect={onSelect}
             />
           ) : null}
+
+          {loding && treeDataTemp.length === 0 ? <div className='Z1m1llNone'>暂无数据</div> : null}
         </div>
         <div className='Z1m1rr'>
           {rightData.id ? (
@@ -231,6 +242,7 @@ function Z1dict() {
           addInfo={addInfo}
           addFu={() => resetFu(false)}
           closeFu={() => setAddInfo({} as Z1AddInfoType)}
+          isNoAcIds={isNoAcIds.current}
         />
       ) : null}
     </div>

+ 76 - 0
src/store/action/D2storSet.ts

@@ -22,3 +22,79 @@ export const D2_APIgetList = (data: any): any => {
 export const D2_APIdel = (id: number) => {
   return http.get(`cms/storage/st/remove/${id}`)
 }
+
+/**
+ * 库房设置-新增/编辑
+ */
+export const D2_APIedit = (data: any) => {
+  return http.post('cms/storage/st/save', data)
+}
+
+/**
+ * 库房设置-获取详情
+ */
+export const D2_APIgetInfo = (id: number) => {
+  return http.get(`cms/storage/st/detail/${id}`)
+}
+
+// ---------------------------库位设置----------------------------
+
+/**
+ * 库房设置-获取库位列表
+ */
+export const D2_APIgetSiteList = (id: number) => {
+  return http.get(`cms/storage/site/list/${id}`)
+}
+
+// ------区域-------------
+
+/**
+ * 库房设置-获取区域-列表
+ */
+export const D2_APIgetAreaList = (id: number) => {
+  return http.get(`cms/storage/region/getList/${id}`)
+}
+
+/**
+ * 库房设置-区域-删除检查
+ */
+export const D2_APIareaDelCheck = (id: string) => {
+  return http.get(`cms/storage/region/check/${id}`)
+}
+
+/**
+ * 库房设置-区域-新增/修改
+ */
+export const D2_APIareaEdit = (data: any) => {
+  return http.post('cms/storage/region/batchSave', data)
+}
+
+/**
+ * 库房设置-区域-批量删除
+ */
+export const D2_APIareaDels = (data: any) => {
+  return http.post('cms/storage/region/removes', data)
+}
+
+// ------库位-------------
+
+/**
+ * 库房设置-库位-批量删除
+ */
+export const D2_APIaddDels = (data: any) => {
+  return http.post('cms/storage/site/removes', data)
+}
+
+/**
+ * 库房设置-库位-新增
+ */
+export const D2_APIaddAdd = (data: any) => {
+  return http.post('cms/storage/site/batchSave', data)
+}
+
+/**
+ * 库房设置-库位-编辑
+ */
+export const D2_APIaddEdit = (data: any) => {
+  return http.post('cms/storage/site/edit', data)
+}

+ 18 - 18
src/types/api/layot.d.ts

@@ -1,25 +1,25 @@
 export type LookDomType = {
-  src: string;
-  type: "video" | "audio" | "model" | "";
-  flag?: boolean;
-};
+  src: string
+  type: 'video' | 'audio' | 'model' | ''
+  flag?: boolean
+}
 
 export type RouterTypeRow = {
-  id: number;
-  name: string;
-  path: string;
-  Com: React.LazyExoticComponent<React.MemoExoticComponent<() => JSX.Element>>;
-}[];
+  id: number
+  name: string
+  path: string
+  Com: React.LazyExoticComponent<React.MemoExoticComponent<() => JSX.Element>>
+}[]
 
 export type RouterType = {
-  id: number;
-  name: string;
-  son: RouterTypeRow;
-}[];
+  id: number
+  name: string
+  son: RouterTypeRow
+}[]
 
 export type FileImgListType = {
-  id: number;
-  fileName: string;
-  filePath: string;
-  type: "img" | "video" | "doc";
-};
+  id: number
+  fileName: string
+  filePath: string
+  type: 'img' | 'video' | 'doc'
+}

+ 8 - 0
src/utils/tableData.ts

@@ -22,6 +22,14 @@ export const D2tableC = [
   ['txtChange', '仓库状态', 'enable', { 0: '禁用', 1: '启用' }]
 ]
 
+export const D2tableCSon = [
+  ['txt', '区域名称', 'regionName'],
+  ['txt', '排架', 'layer1'],
+  ['txt', '层数', 'layer2'],
+  ['txt', '库位', 'layer3'],
+  ['text', '库位说明', 'description', 50]
+]
+
 export const Z2tableC = [
   ['txt', '编号类型', 'name'],
   ['txt', '前缀', 'prefix'],