Przeglądaj źródła

Merge branch 'master' of http://192.168.0.115:3000/shaogen1995/qingDao_goods into master

shaogen1995 3 dni temu
rodzic
commit
59a191b9c7

+ 81 - 0
src/pages/Cledger/C2routing/index.module.scss

@@ -1,4 +1,85 @@
 .C2routing {
   :global {
+    .sider {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      .siderLeft {
+        width: 350px;
+        height: 100%;
+        display: flex;
+      }
+      .siderRight {
+        width: 0;
+        flex: 1;
+        height: 100%;
+      }
+    }
+
+    .ant-table-cell {
+      padding: 8px !important;
+    }
+  }
+}
+
+.C2siderLeftTree {
+  width: 100%;
+  margin-right: 20px;
+  background-color: var(--boxBcaColor);
+  border-radius: 10px;
+  padding: 24px;
+  padding-top: 15px;
+  :global {
+    .C2siderLeftTree1 {
+      margin-bottom: 20px;
+    }
+    .C2siderLeftTree2 {
+      height: calc(100% - 52px);
+
+      overflow-y: auto;
+      .site-tree-search-value {
+        color: red;
+        font-weight: 700;
+      }
+      .ant-tree {
+        background-color: var(--boxBcaColor);
+        min-height: 100%;
+      }
+      .ant-tree-title {
+        font-size: 18px;
+      }
+      .ant-tree-title span {
+        font-size: 18px;
+      }
+
+      .ant-tree-node-selected {
+        padding: 4px 8px !important;
+        background-color: var(--txtColor) !important;
+        .ant-tree-title span {
+          color: #fff !important;
+        }
+      }
+      .NODATA {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        color: #666666;
+        font-size: 16px;
+        height: 100%;
+        // img {
+        //   width: 150px;
+        // }
+        & > p {
+          margin-bottom: 10px;
+        }
+        div {
+          width: 80%;
+          margin-top: 8%;
+          display: flex;
+          justify-content: space-around;
+        }
+      }
+    }
   }
 }

+ 296 - 1
src/pages/Cledger/C2routing/index.tsx

@@ -1,9 +1,304 @@
-import React from 'react'
+import React, { useMemo, useState, useCallback, useRef, useEffect } from 'react'
 import styles from './index.module.scss'
+import { selectObj, getDictFu } from '@/utils/dataChange'
+import { openLink } from '@/utils/history'
+import TableList from '@/pages/Zother/TableList'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { API_getGoodsList } from '@/store/action/Cledger/C1ledger'
+import { baseFormData } from '@/pages/Zother/data'
+import { goodsSonTableC } from '@/utils/tableData'
+import { Button, Tree, Input, TreeDataNode } from 'antd'
+import { filterTreeByName } from '@/pages/Isystem/I2dict/data'
+
+const C2topSearch = [
+  {
+    type: 'input',
+    key: 'searchKey',
+    placeholder: '搜索藏品登记号、藏品名称'
+  },
+  {
+    type: 'cascader',
+    key: 'textureDictId',
+    placeholder: '质地',
+    options: getDictFu('质地')
+  },
+  {
+    type: 'select',
+    key: 'tornLevel',
+    placeholder: '完残程度',
+    options: selectObj['完残程度']
+  },
+  // TODO
+  {
+    type: 'select',
+    key: 'status',
+    placeholder: '入藏状态',
+    options: selectObj['藏品入藏状态']
+  },
+  {
+    type: 'select',
+    key: 'siteStatus',
+    placeholder: '库存状态',
+    options: selectObj['藏品库存状态']
+  }
+]
+
+const C2baseFormData = {
+  ...baseFormData,
+  typeDictId: '',
+  ageDictId: '',
+  textureDictId: ''
+}
+
+const C2columnsTempAdd = [
+  ...goodsSonTableC(false),
+  ['select', '入藏状态', 'status', selectObj['藏品入藏状态']],
+  ['txt', '库存状态', 'siteStatus'],
+  ['txt', '库房位置', 'siteLoc']
+]
+
+// 递归收集树中所有节点的 key(用于默认全选)
+const getAllTreeKeys = (nodes: TreeDataNode[]): string[] => {
+  const keys: string[] = []
+  const walk = (list: TreeDataNode[]) => {
+    list.forEach(node => {
+      keys.push(node.key as string)
+      if (node.children?.length) walk(node.children)
+    })
+  }
+  walk(nodes)
+  return keys
+}
+
+const C2siderLeftTree = ({ setExtraParams }: { setExtraParams: (params: any) => void }) => {
+  const { treeData: dictAll } = useSelector((state: RootState) => state.E1tag)
+  // 当前选中的树节点ID(高亮)
+  const [acShu, setAcShu] = useState('')
+  // 勾选中的节点 key,默认全部选中
+  const [checkedKeys, setCheckedKeys] = useState<string[]>([])
+  const hasSetDefaultChecked = useRef(false)
+
+  // 点击树节点
+  const onSelect = (id: any) => {
+    if (id[0]) setAcShu(id[0])
+  }
+
+  // 搜索高亮
+  const [value, setValue] = useState('')
+  const [value2, setValue2] = useState('')
+
+  const timeRef = useRef(-1)
+  const valueChange = useCallback((val: string) => {
+    setValue(val.trim())
+    clearTimeout(timeRef.current)
+    timeRef.current = window.setTimeout(() => {
+      setValue2(val.trim())
+    }, 500)
+  }, [])
+
+  // 将带 id/name/num/children 的树数据转为 TreeDataNode,keyPrefix 用于区分分类并传给后端
+  const loopToTreeNodes = useCallback(
+    (dataTemp: any[], keyPrefix: string): TreeDataNode[] => {
+      const data = dataTemp || []
+      return data.map(item => {
+        const strTitle = ((item.num ? item.num + ' ' : '') + item.name) as string
+        const strTitleD = strTitle.toUpperCase()
+        const valueD = value.toUpperCase()
+        const index = strTitleD.indexOf(valueD)
+        const beforeStr = strTitle.substring(0, index)
+        const afterStr = strTitle.slice(index + value.length)
+        const title =
+          index > -1 ? (
+            <span key={item.id}>
+              {beforeStr}
+              <span className='site-tree-search-value'>{value}</span>
+              {afterStr}
+            </span>
+          ) : (
+            <span key={item.id}>{strTitle}</span>
+          )
+        const key = `${keyPrefix}-${item.id}`
+        if (item.children?.length) {
+          return { title, key, children: loopToTreeNodes(item.children, keyPrefix) }
+        }
+        return { title, key }
+      })
+    },
+    [value]
+  )
+
+  // 按节点名称筛选:藏品类别、藏品年代、藏品标签(树)、藏品级别(平铺)
+  const categoryFiltered = useMemo(() => {
+    const list = getDictFu('藏品类别') || []
+    return value2 ? filterTreeByName(list, value2) : list
+  }, [value2])
+
+  const ageFiltered = useMemo(() => {
+    const list = getDictFu('藏品年代') || []
+    return value2 ? filterTreeByName(list, value2) : list
+  }, [value2])
+
+  const tagTreeFiltered = useMemo(() => {
+    return value2 ? filterTreeByName(dictAll, value2) : dictAll
+  }, [dictAll, value2])
+
+  const levelFiltered = useMemo(() => {
+    const list = selectObj['藏品级别'] || []
+    if (!value2) return list
+    const key = value2.toUpperCase()
+    return list.filter((item: { label: string }) => item.label.toUpperCase().includes(key))
+  }, [value2])
+
+  // 四个数据源合并为一棵树:藏品类别、藏品年代、藏品标签、藏品级别(key 带前缀便于拆分为分类参数)
+  const treeData = useMemo(() => {
+    const rootCategory: TreeDataNode = {
+      key: 'root-类别',
+      title: '藏品类别',
+      children: loopToTreeNodes(categoryFiltered, 'type')
+    }
+    const rootAge: TreeDataNode = {
+      key: 'root-年代',
+      title: '藏品年代',
+      children: loopToTreeNodes(ageFiltered, 'age')
+    }
+    const rootTag: TreeDataNode = {
+      key: 'root-标签',
+      title: '藏品标签',
+      children: loopToTreeNodes(tagTreeFiltered, 'tag')
+    }
+    const rootLevel: TreeDataNode = {
+      key: 'root-级别',
+      title: '藏品级别',
+      children: levelFiltered.map((item: { value: string; label: string }) => ({
+        key: `level-${item.value}`,
+        title: item.label
+      }))
+    }
+
+    return [rootCategory, rootAge, rootTag, rootLevel]
+  }, [loopToTreeNodes, categoryFiltered, ageFiltered, tagTreeFiltered, levelFiltered])
+
+  // 根据勾选 key 列表解析为后端需要的分类参数字符串(逗号隔开)
+  const getExtraParamsFromKeys = useCallback((keyList: string[]) => {
+    const subTypeDictId = keyList.filter(k => k.startsWith('type-')).map(k => k.slice(5))
+    const subAgeDictId = keyList.filter(k => k.startsWith('age-')).map(k => k.slice(4))
+    const subTagIds = keyList.filter(k => k.startsWith('tag-')).map(k => k.slice(4))
+    const subLevel = keyList.filter(k => k.startsWith('level-')).map(k => k.slice(6))
+    return { subTypeDictId, subAgeDictId, subTagIds, subLevel }
+  }, [])
+
+  // 首次有树数据时默认全部选中
+  useEffect(() => {
+    if (!hasSetDefaultChecked.current && treeData?.length) {
+      const allKeys = getAllTreeKeys(treeData)
+      if (allKeys.length) {
+        setCheckedKeys(allKeys)
+        // 全选树的筛选条件按理等于查询全部,所以先不设置参数,避免多余请求,还是有差别,那还是多请求一次吧
+        setExtraParams(getExtraParamsFromKeys(allKeys))
+        hasSetDefaultChecked.current = true
+      }
+    }
+  }, [treeData, getExtraParamsFromKeys, setExtraParams])
+
+  const onCheckNode = (keys: any) => {
+    const next = Array.isArray(keys) ? keys : (keys as { checked: React.Key[] }).checked
+    const keyList = (next as string[]).filter((k): k is string => typeof k === 'string')
+    setCheckedKeys(keyList)
+    setExtraParams(getExtraParamsFromKeys(keyList))
+  }
+
+  return (
+    <div className={styles.C2siderLeftTree}>
+      <div className='C2siderLeftTree1'>
+        <Input
+          style={{ width: 300 }}
+          placeholder='请输入节点名称'
+          maxLength={30}
+          showCount
+          value={value}
+          onChange={e => valueChange(e.target.value)}
+          allowClear
+        />
+      </div>
+      <div className='C2siderLeftTree2'>
+        {treeData?.length ? (
+          <Tree
+            checkable
+            defaultExpandAll={true}
+            treeData={treeData}
+            selectedKeys={[acShu]}
+            checkedKeys={checkedKeys}
+            onCheck={(keys, _info) => {
+              onCheckNode(keys)
+            }}
+            onSelect={onSelect}
+          />
+        ) : null}
+      </div>
+    </div>
+  )
+}
+
 function C2routing() {
+  const tableInfo = useSelector((state: RootState) => state.C1ledger.tableInfo)
+  const [extraParams, setExtraParams] = useState<any>({})
+  // 故事管理/藏品总账定制右侧内容
+  const storyTableListToprr = ({
+    clickSearch,
+    resetSelectFu
+  }: {
+    clickSearch: () => void
+    resetSelectFu: () => void
+  }) => {
+    return (
+      <>
+        <Button type='primary' onClick={clickSearch}>
+          查询
+        </Button>
+        <Button onClick={resetSelectFu}>重置</Button>
+      </>
+    )
+  }
+
+  // 故事管理/藏品总账定制右侧操作按钮
+  const storyTableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: any) => (
+          <Button size='small' type='text' onClick={() => openLink(`/goodsLook/${item.id}`)}>
+            查看
+          </Button>
+        )
+      }
+    ]
+  }, [])
+
   return (
     <div className={styles.C2routing}>
       <div className='pageTitle'>藏品分账</div>
+      <div className='sider'>
+        <div className='siderLeft'>
+          <C2siderLeftTree setExtraParams={setExtraParams} />
+        </div>
+        <div className='siderRight'>
+          <TableList
+            baseFormData={C2baseFormData}
+            getListAPI={API_getGoodsList}
+            pageKey='routing'
+            tableInfo={tableInfo}
+            columnsTemp={C2columnsTempAdd}
+            rightBtnWidth={140}
+            leftRowWidth={'20%'}
+            yHeight={592}
+            searchDom={C2topSearch}
+            storyTableLastBtn={storyTableLastBtn}
+            storyTableListToprr={storyTableListToprr}
+            extraParams={extraParams}
+          />
+        </div>
+      </div>
     </div>
   )
 }

+ 6 - 0
src/pages/Cledger/C3goodsInfo/index.module.scss

@@ -1,4 +1,10 @@
 .C3goodsInfo {
   :global {
+    .TableListToprr {
+      align-items: flex-start;
+    }
+    .ant-table-cell {
+      padding: 8px !important;
+    }
   }
 }

+ 135 - 2
src/pages/Cledger/C3goodsInfo/index.tsx

@@ -1,9 +1,142 @@
-import React from 'react'
+import React, { useMemo } from 'react'
 import styles from './index.module.scss'
+import { selectObj, getDictFu } from '@/utils/dataChange'
+import { openLink } from '@/utils/history'
+import TableList from '@/pages/Zother/TableList'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { API_getGoodsList } from '@/store/action/Cledger/C1ledger'
+import { baseFormData } from '@/pages/Zother/data'
+import { goodsSonTableC } from '@/utils/tableData'
+import { Button } from 'antd'
+
+const C1topSearch = [
+  {
+    type: 'input',
+    key: 'searchKey',
+    placeholder: '搜索藏品登记号、藏品名称'
+  },
+  {
+    type: 'input',
+    key: 'searchTagName',
+    placeholder: `搜索藏品标签`
+  },
+  {
+    type: 'select',
+    key: 'level',
+    placeholder: '级别',
+    options: selectObj['藏品级别']
+  },
+  {
+    type: 'cascader',
+    key: 'typeDictId',
+    placeholder: '类别',
+    options: getDictFu('藏品类别')
+  },
+  {
+    type: 'cascader',
+    key: 'ageDictId',
+    placeholder: '年代',
+    options: getDictFu('藏品年代')
+  },
+  {
+    type: 'cascader',
+    key: 'textureDictId',
+    placeholder: '质地',
+    options: getDictFu('质地')
+  },
+  {
+    type: 'select',
+    key: 'tornLevel',
+    placeholder: '完残程度',
+    options: selectObj['完残程度']
+  },
+  // TODO
+  {
+    type: 'select',
+    key: 'status',
+    placeholder: '入藏状态',
+    options: selectObj['藏品入藏状态']
+  },
+  {
+    type: 'select',
+    key: 'siteStatus',
+    placeholder: '库存状态',
+    options: selectObj['藏品库存状态']
+  },
+  {
+    type: 'select',
+    key: 'siteLoc',
+    placeholder: `搜索库房位置`
+  }
+]
+
+const C1baseFormData = {
+  ...baseFormData,
+  typeDictId: '',
+  ageDictId: '',
+  textureDictId: ''
+}
+
+const columnsTempAdd = [
+  ...goodsSonTableC(false),
+  ['select', '入藏状态', 'status', selectObj['藏品入藏状态']],
+  ['txt', '库存状态', 'siteStatus'],
+  ['txt', '库房位置', 'siteLoc']
+]
+
 function C3goodsInfo() {
+  const tableInfo = useSelector((state: RootState) => state.C1ledger.tableInfo)
+
+  // 故事管理/藏品总账定制右侧内容
+  const storyTableListToprr = ({
+    clickSearch,
+    resetSelectFu
+  }: {
+    clickSearch: () => void
+    resetSelectFu: () => void
+  }) => {
+    return (
+      <>
+        <Button type='primary' onClick={clickSearch}>
+          查询
+        </Button>
+        <Button onClick={resetSelectFu}>重置</Button>
+      </>
+    )
+  }
+
+  // 故事管理/藏品总账定制右侧操作按钮
+  const storyTableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: any) => (
+          <Button size='small' type='text' onClick={() => openLink(`/goodsLook/${item.id}`)}>
+            查看
+          </Button>
+        )
+      }
+    ]
+  }, [])
+
   return (
     <div className={styles.C3goodsInfo}>
-      <div className='pageTitle'>藏品信息</div>
+      <div className='pageTitle'>藏品总账</div>
+
+      <TableList
+        baseFormData={C1baseFormData}
+        getListAPI={API_getGoodsList}
+        pageKey='ledger'
+        tableInfo={tableInfo}
+        columnsTemp={columnsTempAdd}
+        rightBtnWidth={140}
+        leftRowWidth={'20%'}
+        yHeight={592}
+        searchDom={C1topSearch}
+        storyTableListToprr={storyTableListToprr}
+        storyTableLastBtn={storyTableLastBtn}
+      />
     </div>
   )
 }

+ 3 - 1
src/pages/Cledger/C4file/index.tsx

@@ -162,9 +162,11 @@ function C4file() {
         >
           批量下载
         </Button>
+        &nbsp;
         <Button type='primary' onClick={clickSearch}>
           查询
         </Button>
+        &nbsp;
         <Button onClick={handleReset}>重置</Button>
       </>
     )
@@ -272,7 +274,7 @@ function C4file() {
         tableInfo={tableInfo}
         columnsTemp={goodsFileTableC}
         yHeight={585}
-        rightBtnWidth={700}
+        rightBtnWidth={720}
         leftRowWidth={'50%'}
         searchDom={C4search}
         storyTableListToprr={storyTableListToprr}

+ 33 - 29
src/pages/Fstorehouse/F1inStorage/index.tsx

@@ -25,6 +25,38 @@ function F1inStorage() {
       value: i.id
     }))
   }, [allWarehouseList])
+  const SEARCH_DOM = useMemo(
+    () => [
+      {
+        type: 'time',
+        key: ['startTime', 'endTime'],
+        placeholder: `入库日期`
+      },
+      {
+        type: 'select',
+        key: 'storageId',
+        placeholder: `库房名称`,
+        options: warehouseOptions
+      },
+      {
+        type: 'input',
+        key: 'searchKey',
+        placeholder: `请输入申请编号、发起人或藏品编号`
+      },
+      {
+        type: 'time',
+        key: ['businessStartTime', 'businessEndTime'],
+        placeholder: `发起日期`
+      },
+      {
+        type: 'select',
+        key: 'status',
+        placeholder: `申请状态`,
+        options: selectObj['藏品入库申请状态']
+      }
+    ],
+    [warehouseOptions]
+  )
 
   const dataExport = () => {
     console.log('数据导出了')
@@ -59,35 +91,7 @@ function F1inStorage() {
         columnsTemp={inStorageTableC}
         rightBtnWidth={340}
         yHeight={585}
-        searchDom={[
-          {
-            type: 'time',
-            key: ['startTime', 'endTime'],
-            placeholder: `入库日期`
-          },
-          {
-            type: 'select',
-            key: 'storageId',
-            placeholder: `库房名称`,
-            options: warehouseOptions
-          },
-          {
-            type: 'input',
-            key: 'searchKey',
-            placeholder: `请输入申请编号、发起人或藏品编号`
-          },
-          {
-            type: 'time',
-            key: ['businessStartTime', 'businessEndTime'],
-            placeholder: `发起日期`
-          },
-          {
-            type: 'select',
-            key: 'status',
-            placeholder: `申请状态`,
-            options: selectObj['藏品入库申请状态']
-          }
-        ]}
+        searchDom={SEARCH_DOM}
         storyTableListToprr={({ clickSearch, resetSelectFu }) => (
           <>
             <Button type='primary' ghost onClick={() => tableBtnFu(null, '1')}>

+ 8 - 2
src/pages/Zother/TableList/index.tsx

@@ -57,6 +57,7 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
     staBtn
   } = props
   const dispatch = useDispatch()
+  const _searchDom = useRef(searchDom)
 
   const [formData, setFormData] = useState({ ...baseFormData })
 
@@ -92,12 +93,17 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
     [formData]
   )
 
-  // 封装发送请求的函数
+  // 封装发送请求的函数(级联字段传数组中最后一个值)
   const getListFu = useCallback(() => {
     const params = {
       ...formDataRef.current,
       ...(extraParams || {})
     }
+    _searchDom.current.forEach((item: any) => {
+      if (item.type === 'cascader' && item.key && Array.isArray(params[item.key])) {
+        params[item.key] = params[item.key][params[item.key].length - 1]
+      }
+    })
     dispatch(getListAPI(params))
   }, [dispatch, getListAPI, extraParams])
 
@@ -205,7 +211,7 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
                   allowClear={true}
                   placeholder={item.placeholder}
                   style={item.style || ''}
-                  value={formData[item.key] ? formData[item.key] : null}
+                  value={formData[item.key] ?? null}
                   fieldNames={{ label: 'name', value: 'id', children: 'children' }}
                   onChange={e => setFormData({ ...formData, [item.key]: e })}
                   options={item.options}