lanxin 1 неделя назад
Родитель
Сommit
5ef33295c4

+ 3 - 0
src/components/MyTable/index.tsx

@@ -104,6 +104,9 @@ function MyTable({
           let res = item[v[2]] ? dayjs(item[v[2]]).format('YYYY-MM-DD') : isNull
           return res
         },
+        minute: (item: any) => {
+          return Math.floor(item[v[2]] / 60)
+        },
         img: (item: any) => (
           <div className='tableImgAuto'>
             <ImageLazy

+ 4 - 1
src/components/Z0sonTable/index.tsx

@@ -8,6 +8,7 @@ import { openLink } from '@/utils/history'
 import classNames from 'classnames'
 import MyPopconfirm from '../MyPopconfirm'
 import { APIgetGoodsInfo } from '@/store/action/Bresource/B1overview'
+import { MessageFu } from '@/utils/message'
 
 type Props = {
   kuList: antdSelectType[]
@@ -74,8 +75,10 @@ function Z0sonTable({
                     type='text'
                     onClick={async () => {
                       const res = await APIgetGoodsInfo(formDefId, item.id)
-                      if (res.code === 0) {
+                      if (res.code === 0 && res.data && res.data.id != null) {
                         openLink(`/goodsLook/${item.id}/${formDefId}`)
+                      } else if (res.code === 0) {
+                        MessageFu.warning('该资源不存在或已被注销')
                       }
                     }}
                   >

+ 99 - 107
src/components/Z3upFiles/index.module.scss

@@ -3,138 +3,130 @@
     a {
       color: black;
     }
+
     .Z3Btn {
       & > span {
         font-size: 14px;
         color: #999;
       }
     }
-    .Z3files {
-      .ZTbox1ImgRow {
-        display: inline-block;
-        margin: 15px 20px 10px 0;
-        width: 100px;
-        height: 125px;
-        position: relative;
-        position: relative;
-
-        // 修复图片闪动问题:确保拖拽手柄有固定尺寸
-        .ZTbox1ImgRowDragHandle {
-          width: 100px;
-          height: 100px;
-          cursor: grab;
-
-          &:active {
-            cursor: grabbing;
-          }
-        }
 
-        // 第一张作为封面
-        .ZTbox1ImgRowCover {
-          font-size: 12px;
-          line-height: 22px;
-          position: absolute;
-          left: 0;
-          top: 0;
-          width: 100%;
-          height: 24px;
-          background-color: rgba(0, 0, 0, 0.8);
-          color: #fff;
-          text-align: center;
-          pointer-events: none;
-        }
+    .ZTbox1ImgList {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 16px 20px;
+      padding-top: 12px;
+    }
 
-        .ZTbox1ImgRowIcon {
-          width: 100%;
-          background-color: rgba(0, 0, 0, 0.6);
-          color: #fff;
-          display: flex;
-          justify-content: space-around;
-          font-size: 16px;
+    .Z3filesList {
+      margin-top: 8px;
+      max-width: 786px;
+    }
 
-          a {
-            color: #fff !important;
-          }
-        }
+    .ZTbox1ImgRow {
+      width: 100px;
+      height: 125px;
+      position: relative;
 
-        .ZTbox1ImgRowX {
-          cursor: pointer;
-          position: absolute;
-          right: -10px;
-          top: -10px;
-          z-index: 99;
-          background-color: rgba(0, 0, 0, 0.8);
-          width: 20px;
-          height: 20px;
-          border-radius: 50%;
-          font-size: 16px;
-          color: #fff;
-          display: flex;
-          justify-content: center;
-          align-items: center;
+      .ZTbox1ImgRowDragHandle {
+        width: 100px;
+        height: 100px;
+        cursor: grab;
+        touch-action: none;
+
+        &:active {
+          cursor: grabbing;
         }
       }
 
-      .Z3filesRow {
+      .ZTbox1ImgRowCover {
+        font-size: 12px;
+        line-height: 22px;
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 24px;
+        background-color: rgba(0, 0, 0, 0.8);
+        color: #fff;
+        text-align: center;
+        pointer-events: none;
+      }
+
+      .ZTbox1ImgRowIcon {
         width: 100%;
-        max-width: 786px;
+        background-color: rgba(0, 0, 0, 0.6);
+        color: #fff;
         display: flex;
-        align-items: center;
-        padding: 0px 12px;
-        border: 1px solid #d9d9d9;
-        border-radius: 6px;
-        margin: 2px;
-        background: #fff;
-        transition: all 0.3s;
-
-        &:hover {
-          border-color: #40a9ff;
-          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-        }
+        justify-content: space-around;
+        font-size: 16px;
 
-        &.dragging {
-          opacity: 0.5;
-          background: #f0f0f0;
+        a {
+          color: #fff !important;
         }
+      }
 
-        &.dragOverlay {
-          box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
-          transform: rotate(5deg);
-        }
+      .ZTbox1ImgRowX {
+        cursor: pointer;
+        position: absolute;
+        right: -10px;
+        top: -10px;
+        z-index: 99;
+        background-color: rgba(0, 0, 0, 0.8);
+        width: 20px;
+        height: 20px;
+        border-radius: 50%;
+        font-size: 16px;
+        color: #fff;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+    }
 
-        .dragHandle {
-          cursor: grab;
-          margin-right: 12px;
-          color: #999;
-          padding: 4px;
+    .Z3filesRow {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding: 4px 12px;
+      border: 1px solid #d9d9d9;
+      border-radius: 6px;
+      margin: 4px 0;
+      background: #fff;
+      cursor: grab;
+      touch-action: none;
+
+      &:active {
+        cursor: grabbing;
+      }
 
-          &:active {
-            cursor: grabbing;
-          }
+      &:hover {
+        border-color: #40a9ff;
+      }
 
-          &:hover {
-            color: #40a9ff;
-          }
-        }
+      .dragHandle {
+        margin-right: 12px;
+        color: #999;
+      }
 
-        .Z3files1 {
-          flex: 1;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-        }
+      .Z3files1 {
+        flex: 1;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
 
-        .Z3files2 {
-          display: flex;
-          align-items: center;
+      .Z3files2 {
+        display: flex;
+        align-items: center;
+        cursor: default;
 
-          .anticon {
-            cursor: pointer;
-            color: rgb(126, 124, 124);
+        .anticon {
+          cursor: pointer;
+          color: rgb(126, 124, 124);
 
-            &:hover {
-              color: #40a9ff;
-            }
+          &:hover {
+            color: #40a9ff;
           }
         }
       }

+ 139 - 196
src/components/Z3upFiles/index.tsx

@@ -13,11 +13,19 @@ import {
 } from '@ant-design/icons'
 import classNames from 'classnames'
 import { baseURL } from '@/utils/http'
-import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, closestCenter } from '@dnd-kit/core'
+import {
+  DndContext,
+  DragEndEvent,
+  PointerSensor,
+  closestCenter,
+  useSensor,
+  useSensors
+} from '@dnd-kit/core'
 import {
   SortableContext,
   useSortable,
   verticalListSortingStrategy,
+  rectSortingStrategy,
   arrayMove
 } from '@dnd-kit/sortable'
 import { CSS } from '@dnd-kit/utilities'
@@ -28,56 +36,47 @@ import MyPopconfirm from '../MyPopconfirm'
 import { forwardRef, useImperativeHandle } from 'react'
 import { authFilesLookFu, FileListType } from './data'
 
-// ----------------这个组件用于外面一级的附件上传
-
 interface SortableFileItemProps {
   file: FileListType
   onDelete: (id: number) => void
   isLook: boolean
-  index: number
-  disabled?: boolean
-  oneIsCover?: boolean
+  isCover?: boolean
 }
-// 修复性能问题:移除不必要的状态和事件处理
+
 const SortableFileItem = React.memo(
-  ({ file, onDelete, isLook, index, disabled, oneIsCover }: SortableFileItemProps) => {
+  ({ file, onDelete, isLook, isCover }: SortableFileItemProps) => {
     const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
       id: file.id,
-      disabled: disabled || isLook // 修复拖动禁用问题
+      disabled: isLook
     })
 
-    const style = {
+    const style: React.CSSProperties = {
       transform: CSS.Transform.toString(transform),
       transition,
       opacity: isDragging ? 0.5 : 1
     }
 
-    // 修复按钮点击问题:阻止事件冒泡
+    const dragBind = isLook ? undefined : { ...attributes, ...listeners }
+
     const handleButtonClick = useCallback((e: React.MouseEvent, callback: () => void) => {
-      e.stopPropagation() // 修复按钮点击无效问题:阻止事件冒泡到拖拽元素
+      e.stopPropagation()
       callback()
     }, [])
 
+    const stopPointer = useCallback((e: React.PointerEvent) => {
+      e.stopPropagation()
+    }, [])
+
     if (file.type === 'img') {
       return (
-        <div
-          ref={setNodeRef}
-          style={style}
-          className={classNames('ZTbox1ImgRow', isDragging ? 'dragging' : '')}
-        >
-          {/* 修复按钮点击无效问题:将拖拽手柄单独放置,不覆盖操作按钮 */}
-          <div
-            className='ZTbox1ImgRowDragHandle'
-            {...attributes}
-            {...listeners}
-            style={{ cursor: isLook ? 'default' : 'grab' }}
-          >
+        <div ref={setNodeRef} style={style} className='ZTbox1ImgRow'>
+          <div className='ZTbox1ImgRowDragHandle' {...dragBind}>
             {file.thumb || file.filePath ? (
               <ImageLazy noLook={true} width={100} height={100} src={file.thumb || file.filePath} />
             ) : null}
           </div>
 
-          {oneIsCover && index === 0 ? <div className='ZTbox1ImgRowCover'>封面</div> : null}
+          {isCover ? <div className='ZTbox1ImgRowCover'>封面</div> : null}
 
           <div className='ZTbox1ImgRowIcon'>
             <EyeOutlined
@@ -99,7 +98,7 @@ const SortableFileItem = React.memo(
               download
               target='_blank'
               rel='noreferrer'
-              onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
+              onClick={e => e.stopPropagation()}
             >
               <DownloadOutlined rev={undefined} />
             </a>
@@ -113,75 +112,66 @@ const SortableFileItem = React.memo(
                 <CloseOutlined
                   className='ZTbox1ImgRowX'
                   rev={undefined}
-                  onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
+                  onClick={e => e.stopPropagation()}
                 />
               }
             />
           )}
         </div>
       )
-    } else {
-      return (
-        <div
-          ref={setNodeRef}
-          style={style}
-          className={classNames('Z3filesRow', isDragging ? 'dragging' : '')}
-        >
-          {!isLook && (
-            <div className='dragHandle' {...attributes} {...listeners}>
-              <MenuOutlined rev={undefined} />
-            </div>
-          )}
-          <div className='Z3files1' title={file.fileName}>
-            {file.fileName}
+    }
+
+    return (
+      <div ref={setNodeRef} style={style} className='Z3filesRow' {...dragBind}>
+        {!isLook && (
+          <div className='dragHandle'>
+            <MenuOutlined rev={undefined} />
           </div>
-          <div className='Z3files2'>
-            {authFilesLookFu(file.fileName, '') ? (
-              <>
-                <EyeOutlined
-                  rev={undefined}
-                  title='查看'
-                  onClick={e =>
-                    handleButtonClick(e, () => authFilesLookFu(file.fileName, file.filePath))
-                  }
-                />
-                &emsp;
-              </>
-            ) : null}
-            <a
-              title='下载'
-              href={baseURL + file.filePath}
-              download={file.fileName}
-              target='_blank'
-              rel='noreferrer'
-              onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
+        )}
+        <div className='Z3files1' title={file.fileName}>
+          {file.fileName}
+        </div>
+        <div className='Z3files2' onPointerDown={stopPointer}>
+          {authFilesLookFu(file.fileName, '') ? (
+            <>
+              <EyeOutlined
+                rev={undefined}
+                title='查看'
+                onClick={e =>
+                  handleButtonClick(e, () => authFilesLookFu(file.fileName, file.filePath))
+                }
+              />
+              &emsp;
+            </>
+          ) : null}
+          <a
+            title='下载'
+            href={baseURL + file.filePath}
+            download={file.fileName}
+            target='_blank'
+            rel='noreferrer'
+            onClick={e => e.stopPropagation()}
+          >
+            <DownloadOutlined rev={undefined} />
+          </a>
+          &emsp;
+          {!isLook && (
+            <Popconfirm
+              title='删除后无法恢复,是否删除?'
+              okText='删除'
+              cancelText='取消'
+              onConfirm={() => onDelete(file.id)}
+              okButtonProps={{ loading: false }}
             >
-              <DownloadOutlined rev={undefined} />
-            </a>
-            &emsp;
-            {!isLook && (
-              <Popconfirm
-                title='删除后无法恢复,是否删除?'
-                okText='删除'
-                cancelText='取消'
-                onConfirm={() => onDelete(file.id)}
-                okButtonProps={{ loading: false }}
-              >
-                <CloseOutlined
-                  rev={undefined}
-                  title='删除'
-                  onClick={e => e.stopPropagation()} // 修复按钮点击无效问题
-                />
-              </Popconfirm>
-            )}
-          </div>
+              <CloseOutlined rev={undefined} title='删除' onClick={e => e.stopPropagation()} />
+            </Popconfirm>
+          )}
         </div>
-      )
-    }
+      </div>
+    )
   }
 )
 
-// ------------------------------------------
 type Props = {
   dirCode: string
   myUrl: string
@@ -197,7 +187,6 @@ type Props = {
   ref: any
 }
 
-// 修复类型检查问题:统一使用dnd-kit管理所有拖拽
 function Z3upFilesRef(
   {
     isLook = false,
@@ -216,25 +205,25 @@ function Z3upFilesRef(
 ) {
   const [list, setList] = useState<FileListType[]>([])
 
-  // 修复图片闪动问题:分别管理图片和非图片的排序
   const { imageFiles, otherFiles } = useMemo(() => {
     const arr = list || []
-    const imgArr = arr.filter(v => v.type === 'img')
-    const otherArr = arr.filter(v => v.type !== 'img')
-    return { imageFiles: imgArr, otherFiles: otherArr }
+    return {
+      imageFiles: arr.filter(v => v.type === 'img'),
+      otherFiles: arr.filter(v => v.type !== 'img')
+    }
   }, [list])
 
-  const fileList = useMemo(() => {
-    return [...imageFiles, ...otherFiles]
-  }, [imageFiles, otherFiles])
-
-  const [activeId, setActiveId] = useState<number | null>(null)
+  const fileList = useMemo(() => [...imageFiles, ...otherFiles], [imageFiles, otherFiles])
+  const imageIds = useMemo(() => imageFiles.map(f => f.id), [imageFiles])
+  const otherIds = useMemo(() => otherFiles.map(f => f.id), [otherFiles])
   const myInput = useRef<HTMLInputElement>(null)
 
-  // 修复性能问题:使用useMemo缓存文件ID数组
-  const fileIds = useMemo(() => fileList.map(f => f.id), [fileList])
+  const sensors = useSensors(
+    useSensor(PointerSensor, {
+      activationConstraint: { distance: 5 }
+    })
+  )
 
-  // 上传多个文件
   const handeUpPhoto = useCallback(
     async (e: React.ChangeEvent<HTMLInputElement>) => {
       if (!e.target.files || e.target.files.length === 0) return
@@ -246,7 +235,6 @@ function Z3upFilesRef(
           `最多可上传${maxCount}个文件,当前选中${files.length}个文件,还可上传${maxCount - fileList.length}个文件`
         )
 
-      // 逐个上传文件
       for (const file of files) {
         if (size && file.size > size * 1024 * 1024) {
           MessageFu.warning(`文件"${file.name}"超过${size}M限制!`)
@@ -289,89 +277,33 @@ function Z3upFilesRef(
     [dirCode, fileList.length, formDefId, fromData, maxCount, moduleId, myUrl, size]
   )
 
-  // 修复拖拽逻辑问题:统一使用dnd-kit管理拖拽
-  const handleDragStart = useCallback((event: DragStartEvent) => {
-    setActiveId(Number(event.active.id))
+  const handleDragEnd = useCallback((event: DragEndEvent) => {
+    const { active, over } = event
+    if (!over || active.id === over.id) return
+
+    setList(items => {
+      const sameId = (a: number | string, b: number | string) => String(a) === String(b)
+      const isImg = (id: typeof active.id) => items.find(item => sameId(item.id, id))?.type === 'img'
+      if (isImg(active.id) !== isImg(over.id)) return items
+
+      const group = items.filter(item => (isImg(active.id) ? item.type === 'img' : item.type !== 'img'))
+      const rest = items.filter(item => (isImg(active.id) ? item.type !== 'img' : item.type === 'img'))
+      const oldIndex = group.findIndex(item => sameId(item.id, active.id))
+      const newIndex = group.findIndex(item => sameId(item.id, over.id))
+      if (oldIndex < 0 || newIndex < 0) return items
+      const moved = arrayMove(group, oldIndex, newIndex)
+      return isImg(active.id) ? [...moved, ...rest] : [...rest, ...moved]
+    })
   }, [])
 
-  // 修复拖拽交换问题:增加类型检查,只有同类型文件才能交换
-  const handleDragEnd = useCallback(
-    (event: DragEndEvent) => {
-      const { active, over } = event
-      setActiveId(null)
-
-      if (over && active.id !== over.id) {
-        const activeFile = fileList.find(item => item.id === active.id)
-        const overFile = fileList.find(item => item.id === over.id)
-
-        // 修复类型检查问题:只有同类型文件才能交换位置
-        if (activeFile && overFile && activeFile.type === overFile.type) {
-          setList(items => {
-            const oldIndex = items.findIndex(item => item.id === active.id)
-            const newIndex = items.findIndex(item => item.id === over.id)
-            return arrayMove(items, oldIndex, newIndex)
-          })
-        }
-      }
-    },
-    [fileList]
-  )
-
-  // 列表删除某一个文件
-  const delImgListFu = useCallback(
-    (id: number) => {
-      setList(prev => prev.filter(v => v.id !== id))
-    },
-    [setList]
-  )
-
-  // 获取当前拖拽的文件
-  const activeFile = useMemo(() => {
-    return activeId ? fileList.find(file => file.id === activeId) : null
-  }, [activeId, fileList])
-
-  // 修复拖拽覆盖层显示问题
-  const renderDragOverlay = useCallback(() => {
-    if (!activeFile) return null
-
-    if (activeFile.type === 'img') {
-      return (
-        <div className={classNames('ZTbox1ImgRow', 'dragOverlay')}>
-          {activeFile.thumb || activeFile.filePath ? (
-            <ImageLazy
-              noLook={true}
-              width={100}
-              height={100}
-              src={activeFile.thumb || activeFile.filePath}
-            />
-          ) : null}
-          <div className='ZTbox1ImgRowIcon' style={{ opacity: 0.5 }}>
-            <EyeOutlined rev={undefined} />
-            <DownloadOutlined rev={undefined} />
-          </div>
-        </div>
-      )
-    } else {
-      return (
-        <div className={classNames('Z3filesRow', 'dragOverlay')}>
-          <div className='dragHandle'>
-            <MenuOutlined rev={undefined} />
-          </div>
-          <div className='Z3files1' title={activeFile.fileName}>
-            {activeFile.fileName}
-          </div>
-          <div className='Z3files2'>{/* 拖拽时隐藏操作按钮 */}</div>
-        </div>
-      )
-    }
-  }, [activeFile])
+  const delImgListFu = useCallback((id: number) => {
+    setList(prev => prev.filter(v => v.id !== id))
+  }, [])
 
-  // 设置数据
-  const sonSetListFu = useCallback((list: FileListType[]) => {
-    setList(list)
+  const sonSetListFu = useCallback((nextList: FileListType[]) => {
+    setList(nextList)
   }, [])
 
-  // 返回数据
   const sonResListFu = useCallback(() => {
     const obj = {
       list: fileList || [],
@@ -380,7 +312,6 @@ function Z3upFilesRef(
     }
     if (oneIsCover && fileList.length) {
       const findObj = fileList.find(v => v.type === 'img')
-
       if (findObj) {
         obj.thumb = findObj.thumb
         obj.thumbPc = findObj.filePath
@@ -389,7 +320,6 @@ function Z3upFilesRef(
     return obj
   }, [fileList, oneIsCover])
 
-  // 可以让父组件调用子组件的方法
   useImperativeHandle(ref, () => ({
     sonSetListFu,
     sonResListFu
@@ -420,30 +350,43 @@ function Z3upFilesRef(
         )}
 
         <div className='Z3files'>
-          <DndContext
-            collisionDetection={closestCenter}
-            onDragStart={handleDragStart}
-            onDragEnd={handleDragEnd}
-          >
-            <SortableContext items={fileIds} strategy={verticalListSortingStrategy}>
-              {fileList.map((file, index) => (
-                <SortableFileItem
-                  key={file.id}
-                  file={file}
-                  onDelete={delImgListFu}
-                  isLook={isLook}
-                  index={index}
-                  oneIsCover={oneIsCover}
-                />
-              ))}
-            </SortableContext>
-            <DragOverlay>{renderDragOverlay()}</DragOverlay>
+          <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
+            {imageFiles.length > 0 && (
+              <div className='ZTbox1ImgList'>
+                <SortableContext items={imageIds} strategy={rectSortingStrategy}>
+                  {imageFiles.map((file, index) => (
+                    <SortableFileItem
+                      key={file.id}
+                      file={file}
+                      onDelete={delImgListFu}
+                      isLook={isLook}
+                      isCover={!!oneIsCover && index === 0}
+                    />
+                  ))}
+                </SortableContext>
+              </div>
+            )}
+
+            {otherFiles.length > 0 && (
+              <div className='Z3filesList'>
+                <SortableContext items={otherIds} strategy={verticalListSortingStrategy}>
+                  {otherFiles.map(file => (
+                    <SortableFileItem
+                      key={file.id}
+                      file={file}
+                      onDelete={delImgListFu}
+                      isLook={isLook}
+                    />
+                  ))}
+                </SortableContext>
+              </div>
+            )}
           </DndContext>
         </div>
 
         <div className='fileTit' hidden={isLook}>
           {tips}
-          ;支持按住Ctrl键选择多个文件上传;按住鼠标拖动图片 / 拖动附件左侧图标 可调整顺序
+          ;支持按住 Ctrl 多选上传;拖动图片或附件可调整顺序
           <div
             className={classNames(
               'noUpThumb',

+ 4 - 2
src/pages/Bresource/B1overview/index.tsx

@@ -42,7 +42,7 @@ function B1overview() {
   const getFormZiFu = useCallback(async (id: number) => {
     const res = await Z1_APIgetFormZiDuan(id)
     if (res.code === 0) {
-      const list: any[] = res.data || {}
+      const list: any[] = Array.isArray(res.data) ? res.data : []
       setFormZi(list.filter(v => !B1searchFile.includes(v.fieldLabel)))
     }
   }, [])
@@ -342,7 +342,9 @@ function B1overview() {
                 />
               </div>
 
-              {formZi.map(item => (
+              {formZi
+                .filter(v => v.queryType)
+                .map(item => (
                 <div key={item.id} className='sgLeftRow'>
                   {item.tag === '文本' ? (
                     <Input

+ 1 - 0
src/pages/Login/index.tsx

@@ -75,6 +75,7 @@ export default function Login() {
       }
     } else if (res.code === 3014) {
       MessageFu.warning('账号不存在或密码错误,请联系管理员!')
+      LoginGetCodeFu()
     } else if (res.code === -1 && res.msg === '验证码有误') {
       LoginGetCodeFu()
     }

+ 11 - 18
src/pages/Zother/AddGood/index.tsx

@@ -18,7 +18,7 @@ import { RootState } from '@/store'
 import AddZiYuan from './AddZiYuan'
 import SelectGoods from '../SelectGoods'
 import { C1_APIgetGoodsListByFaBu } from '@/store/action/CinStorage/C1resIn'
-import { ziYuanChangeFu, ziYuanShowFu } from '../data'
+import { ziYuanChangeFu, ziYuanFormIdsToArr, ziYuanFormIdsToMap, ziYuanShowFu } from '../data'
 type Props = {
   sId: number
   closeFu: () => void
@@ -47,8 +47,8 @@ function AddGood({ formDefId, sId, closeFu, succFu, formZi, kuList, ziYuanNow }:
 
   const getInfoFu = useCallback(async () => {
     const res = await APIgetGoodsInfo(formDefId, sId)
-    if (res.code === 0) {
-      const data = res.data
+    const data = res?.data
+    if (res.code === 0 && data && data.id != null) {
       oldInfoRef.current = { ...data }
       jiLianKey.forEach(v => {
         if (data[v] === '0') data[v] = null
@@ -71,8 +71,8 @@ function AddGood({ formDefId, sId, closeFu, succFu, formZi, kuList, ziYuanNow }:
 
       // 关联资源
       if (data.form_ids) {
-        const obj = JSON.parse(data.form_ids || '{}')
-        if (typeof obj === 'object') {
+        const obj = ziYuanFormIdsToMap(data.form_ids)
+        if (Object.keys(obj).length) {
           const res3 = await APIgetZiYuanInfo(obj)
 
           if (res3.code === 0) {
@@ -136,20 +136,13 @@ function AddGood({ formDefId, sId, closeFu, succFu, formZi, kuList, ziYuanNow }:
       if (fileObj && fileObj.required === 1 && flieList.length === 0)
         return MessageFu.warning('请上传附件')
 
-      let form_ids: any = null
+      let form_ids: string | null = null
 
       const ziYuanFlag = formZi.find(v => v.tag === '关联资源')
       if (ziYuanFlag) {
-        let flag = true
-
-        for (const k in ziYuanObj) {
-          if (ziYuanObj[k] && ziYuanObj[k].length) {
-            flag = false
-            form_ids = form_ids || {}
-            form_ids[k] = ziYuanObj[k].map((c: any) => c.id).join(',')
-          }
-        }
-        if (ziYuanFlag.required === 1 && flag) return MessageFu.warning('请至少关联一个资源')
+        const formIdsArr = ziYuanFormIdsToArr(ziYuanObj)
+        form_ids = formIdsArr.length ? JSON.stringify(formIdsArr) : null
+        if (ziYuanFlag.required === 1 && !form_ids) return MessageFu.warning('请至少关联一个资源')
       }
 
       jiLianKey.forEach(v => {
@@ -162,7 +155,7 @@ function AddGood({ formDefId, sId, closeFu, succFu, formZi, kuList, ziYuanNow }:
         thumb: imgObj.thumb || '',
         thumbPc: imgObj.filePath || '',
         file_ids: flieList.map((v: any) => v.id).join(','),
-        form_ids: form_ids ? JSON.stringify(form_ids) : null,
+        form_ids,
 
         // 新增的时候自己添加的字段
         display: oldInfoRef.current.display || 0,
@@ -175,7 +168,7 @@ function AddGood({ formDefId, sId, closeFu, succFu, formZi, kuList, ziYuanNow }:
       //   console.log('-------', obj)
       //   return
       // }
-
+      // console.log('-------', obj)
       const res = await APIsaveGoods(formDefId, obj)
       if (res.code === 0) {
         closeFu()

+ 12 - 9
src/pages/Zother/SelectGoods/index.tsx

@@ -25,6 +25,7 @@ type Props = {
   canObj?: any //其他额外的参数
   // 关联资源,不能选择自己
   ziYuanNow?: any
+  skipCoverCheck?: boolean // 注销等场景跳过封面校验
 }
 
 function SelectGoods({
@@ -37,7 +38,8 @@ function SelectGoods({
   formZi,
   isOne,
   canObj,
-  ziYuanNow
+  ziYuanNow,
+  skipCoverCheck
 }: Props) {
   const [formData, setFormData] = useState({ ...selectTopBase, formDefId })
   const formDataRef = useRef({ ...selectTopBase, formDefId })
@@ -162,17 +164,18 @@ function SelectGoods({
 
   // 点击提交
   const btnOk = useCallback(() => {
-    dataResFu(checkArr, formDefId)
-    // 检查入库资源是否有封面
-    console.log(checkArr)
-    const hasCover = checkArr.some(v => v.thumb)
-    if (!hasCover) {
-      MessageFu.error('资源未上传封面,提交失败')
-      return
+    // 检查入库资源是否有封面(注销等场景跳过)
+    if (!skipCoverCheck) {
+      const hasCover = checkArr.some(v => v.thumb)
+      if (!hasCover) {
+        MessageFu.error('资源未上传封面,提交失败')
+        return
+      }
     }
+    dataResFu(checkArr, formDefId)
     if (!isOne) MessageFu.success('提交成功')
     closeFu()
-  }, [checkArr, closeFu, dataResFu, formDefId, isOne])
+  }, [checkArr, closeFu, dataResFu, formDefId, isOne, skipCoverCheck])
 
   // 页码变化
   const paginationChange = useCallback(

+ 9 - 6
src/pages/Zother/Z0edit/index.tsx

@@ -45,7 +45,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
   const getGoodsInfoFu = useCallback(
     async (id: number) => {
       const res = await APIgetGoodsInfo(fId, id)
-      if (res.code === 0) {
+      if (res.code === 0 && res.data && res.data.id != null) {
         setSnaps([res.data])
       }
     },
@@ -71,7 +71,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
   // 创建订单
   const createFu = useCallback(async () => {
     const res = await APIobj['创建订单']()
-    if (res.code === 0) {
+    if (res.code === 0 && res.data) {
       setInfo(res.data)
     }
   }, [APIobj])
@@ -84,6 +84,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
       editPageToTopFu()
 
       const data = res.data
+      if (!data || data.id == null) return
       setInfo(data)
       // 设置有关资源的信息
       // 资源清单快照信息id对比
@@ -160,6 +161,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
       else {
         const snapsArr: any[] = []
         snaps.forEach((v, i) => {
+          if (!v || v.id == null) return
           snapsArr.push({
             formDataId: v.id,
             formDefId: Number(info.formDefId || fId),
@@ -305,7 +307,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
   const tableBtnFu = useCallback(
     (val: '编辑' | '删除', id: number) => {
       if (val === '删除') {
-        setSnaps(snaps.filter(v => v.id !== id))
+        setSnaps(snaps.filter(v => v && v.id !== id))
         MessageFu.success('删除成功')
       } else setEditId(id)
     },
@@ -317,7 +319,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
       <div className='pageTitle'>
         资源{pageKey.txt}-{pageKeyTxt}&emsp;资源库:{kuTxt || '-'}
       </div>
-      {info.id && kuTxt ? (
+      {info?.id && kuTxt ? (
         <div className='editMain'>
           {/* ----------------审批-------------------- */}
           {key === '3' ? (
@@ -538,7 +540,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
         </div>
       ) : null}
 
-      {info.id && loding && !kuTxt ? (
+      {info?.id && loding && !kuTxt ? (
         <div className='Z0null'>请先在 系统管理-资源库管理 添加数据</div>
       ) : null}
       {/* 选择资源 */}
@@ -552,6 +554,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
           kuList={kuList}
           formZi={formZi}
           isOne={selcctOne}
+          skipCoverCheck={pageKey.txt === '注销'}
         />
       ) : null}
 
@@ -565,7 +568,7 @@ function Z0edit({ pageKey, APIobj, topArr, selectInfo, selcctOne = false }: Prop
             if (val === '新增') setSnaps([obj, ...snaps])
             else {
               const arr = snaps.map(v => {
-                return obj.id === v.id ? obj : v
+                return obj.id === v?.id ? obj : v
               })
               setSnaps(arr)
             }

+ 3 - 3
src/pages/Zother/ZgoodsInfo/Zg1txt/index.tsx

@@ -4,7 +4,7 @@ import { baseFormType } from '@/pages/Zsystem/Z1sysSet/data'
 import ImageLazy from '@/components/ImageLazy'
 import { dictIdByName } from '@/utils'
 import { APIgetZiYuanInfo } from '@/store/action/Bresource/B1overview'
-import { ziYuanChangeFu, ziYuanShowFu } from '../../data'
+import { ziYuanChangeFu, ziYuanFormIdsToMap, ziYuanShowFu } from '../../data'
 
 export type FormTxtType = {
   key: string
@@ -54,9 +54,9 @@ function Zg1txt({ info, formZi, kuList }: Props) {
 
   const getZiYuanInfoFu = useCallback(async (val: string) => {
     if (val) {
-      const obj = JSON.parse(val || '{}')
+      const obj = ziYuanFormIdsToMap(val)
 
-      if (typeof obj === 'object') {
+      if (Object.keys(obj).length) {
         const res3 = await APIgetZiYuanInfo(obj)
 
         if (res3.code === 0) {

+ 22 - 14
src/pages/Zother/ZgoodsInfo/index.tsx

@@ -37,11 +37,13 @@ function ZgoodsInfo() {
   const [kuList, setKuList] = useState<antdSelectType[]>([])
 
   const [errFlag, setErrFlag] = useState(false)
+  const [notFound, setNotFound] = useState(false)
   const [kuChecked, setKuChecked] = useState(false)
 
   useEffect(() => {
     setKuChecked(false)
     setErrFlag(false)
+    setNotFound(false)
     setkuTxt('')
 
     if (!hasKuScopeAuth(fId)) {
@@ -76,11 +78,13 @@ function ZgoodsInfo() {
   const [fileList, setFileList] = useState<FileListType[]>([])
 
   const getInfoFu = useCallback(async () => {
+    setInfo({})
+    setFileList([])
+    setNotFound(false)
     const res = await APIgetGoodsInfo(fId, id)
+    const data = res?.data
 
-    if (res.code === 0) {
-      const data = res.data
-
+    if (res.code === 0 && data && data.id != null) {
       setInfo(data)
 
       // 设置附件
@@ -88,9 +92,12 @@ function ZgoodsInfo() {
         const res2 = await APIgetFileList(data.file_ids.split(','))
 
         if (res2.code === 0) {
-          setFileList(res2.data)
+          setFileList(res2.data || [])
         }
       }
+    } else {
+      setNotFound(true)
+      if (res.code === 0) MessageFu.warning('该资源不存在或已被注销')
     }
   }, [fId, id])
 
@@ -148,12 +155,7 @@ function ZgoodsInfo() {
             key: '1',
             label: '修改',
             onClick: () => {
-              // 发布状态 发布中
-              if (info.status_publish === 2) {
-                MessageFu.warning(`当前藏品为发布中状态,请完成申请下架审批后再修改`)
-              } else {
-                authorityFu(310, '资源入库', () => setEditId(info.id))
-              }
+              authorityFu(310, '资源入库', () => setEditId(info.id))
             }
           },
           {
@@ -162,7 +164,9 @@ function ZgoodsInfo() {
             onClick: () => {
               // 发布状态 未发布
               if ([2, 3].includes(info.status_publish)) {
-                MessageFu.warning(`当前藏品为发布中状态,请完成申请下架审批后再注销`)
+                MessageFu.warning(
+                  `当前藏品为${selectTxt('发布状态', info.status_publish)}状态,请完成申请下架审批后再注销`
+                )
               } else {
                 authorityFu(320, '资源注销', () =>
                   history.push(`/resDel_edit/1/null/${fId}?gId=${info.id}`)
@@ -224,14 +228,14 @@ function ZgoodsInfo() {
     ]
 
     return arr
-  }, [fId, info])
+  }, [fId, info, selectTxt])
   return (
     <div className={styles.ZgoodsInfo}>
       <div className='pageTitle'>
         资源详情&emsp;{errFlag ? null : '资源库:'}
         {kuTxt}
       </div>
-      {info.id && kuTxt ? (
+      {info?.id && kuTxt ? (
         <>
           <div className='ZGtop1'>
             <p title={info.name}>{info.name}</p>
@@ -282,7 +286,11 @@ function ZgoodsInfo() {
           </div>
         </>
       ) : null}
-      {errFlag ? <div className='Z0null'>请先在 系统管理-资源库管理 添加数据</div> : null}
+      {errFlag ? (
+        <div className='Z0null'>请先在 系统管理-资源库管理 添加数据</div>
+      ) : notFound ? (
+        <div className='Z0null'>该资源不存在或已被注销</div>
+      ) : null}
       {/* 新增/编辑 资源 */}
       {editId ? (
         <AddGood

+ 40 - 1
src/pages/Zother/data.tsx

@@ -140,9 +140,48 @@ export const ziYuanShowFu = (ziYuanObj: any, kuList: any[]) => {
 
 export const ziYuanChangeFu = (list: any[]) => {
   const obj: any = {}
-  list.forEach(v => {
+  ;(list || []).forEach(v => {
+    if (!v) return
     if (obj[v.form_def_id]) obj[v.form_def_id].push(v)
     else obj[v.form_def_id] = [v]
   })
   return obj
 }
+
+/** 关联资源 → [{"44":["2953","2960"]}] */
+export const ziYuanFormIdsToArr = (ziYuanObj: Record<string, any[]>) => {
+  const arr: Record<string, string[]>[] = []
+  for (const k in ziYuanObj) {
+    if (ziYuanObj[k]?.length) {
+      arr.push({
+        [k]: ziYuanObj[k].filter((c: any) => c && c.id != null).map((c: any) => String(c.id))
+      })
+    }
+  }
+  return arr
+}
+
+/** form_ids 字符串 → findDataMap 入参 { "44": "2953,2960" },兼容旧对象格式 */
+export const ziYuanFormIdsToMap = (val: string) => {
+  const map: Record<string, string> = {}
+  if (!val) return map
+  try {
+    const parsed = JSON.parse(val)
+    if (Array.isArray(parsed)) {
+      parsed.forEach((item: any) => {
+        if (!item || typeof item !== 'object') return
+        for (const k in item) {
+          const ids = item[k]
+          const str = Array.isArray(ids) ? ids.join(',') : String(ids ?? '')
+          if (!str) continue
+          map[k] = map[k] ? `${map[k]},${str}` : str
+        }
+      })
+    } else if (parsed && typeof parsed === 'object') {
+      return parsed
+    }
+  } catch {
+    /* ignore */
+  }
+  return map
+}

+ 1 - 1
src/pages/Zsystem/Z2dict/Z2add.tsx

@@ -175,7 +175,7 @@ function Z2add({ addInfo, addFu, closeFu }: Props) {
             rules={[{ required: true, message: '请输入字典名称' }]}
             getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
           >
-            <Input maxLength={20} showCount placeholder='请输入内容' />
+            <Input maxLength={50} showCount placeholder='请输入内容' />
           </Form.Item>
 
           <Form.Item

+ 1 - 1
src/pages/Zuse/UseFormZi.tsx

@@ -25,7 +25,7 @@ export function UseFormZi(id: number, filterArr?: string[]) {
   const getListFu = useCallback(async () => {
     const res = await Z1_APIgetFormZiDuan(id)
     if (res.code === 0) {
-      const list: any[] = res.data || {}
+      const list: any[] = Array.isArray(res.data) ? res.data : []
       setFormZi(list)
       setFormBi(
         list.filter(

+ 1 - 1
src/store/action/Zsystem/Z7userSet.ts

@@ -23,7 +23,7 @@ export const getUserListAPI = (data: any, back?: () => void): any => {
  * 删除用户
  */
 export const userRemoveAPI = (id: number) => {
-  return http.get(`cms/flow/remove/${id}`)
+  return http.get(`sys/user/removes/${id}`)
 }
 
 /**

+ 1 - 0
src/utils/authority.ts

@@ -29,6 +29,7 @@ export const filterKuListByScope = <T extends { value: number | string }>(list:
 
 // 列表页面的审批按钮是否显示,true为显示
 export const tableListAuditBtnFu = (item: any) => {
+  console.log('-------', item)
   let flag = false
   const { status, currentAuditUserIds } = item
   // 当前用户id

+ 10 - 1
src/utils/http.ts

@@ -80,6 +80,8 @@ http.interceptors.response.use(
     } else if (response.data.code !== 3014) {
       if (response.config.url?.includes('cms/form/data/detail') && response.data.code === -1)
         MessageFu.warning('该资源数据已被注销')
+      else if (response.config.url?.includes('cms/importExcel/uploadExcel'))
+        MessageFu.warning('上传失败,可能是EXCEL表头与资源库字段不一致')
       else MessageFu.warning(response.data.msg)
     }
 
@@ -95,7 +97,14 @@ http.interceptors.response.use(
         if (store.getState().A0Layout.closeUpFile.state) MessageFu.warning('取消上传!')
         else MessageFu.error('网络繁忙,请稍后重试!')
       } else {
-        if (
+        const isExcelUpload = err.config?.url?.includes('cms/importExcel/uploadExcel')
+        if (isExcelUpload) {
+          MessageFu.warning('上传失败,可能是EXCEL表头与资源库字段不一致')
+          if ([401, 403].includes(err.response?.data?.code)) {
+            removeTokenInfo()
+            loginOutFu()
+          }
+        } else if (
           err.response &&
           err.response.data &&
           err.response.data.msg &&

+ 1 - 1
src/utils/tableData.ts

@@ -21,7 +21,7 @@ export const A2TableC = [
   ['txt', '角色', 'roleName'],
   ['txt', '总访问次数', 'pcs_visit'],
   ['txt', '阅读文献总数', 'pcs_read'],
-  ['txt', '总阅读时长(分)', 'pcs_time']
+  ['minute', '总阅读时长(分)', 'pcs_time']
 ]
 
 export const A2sonTableC = [