Преглед изворни кода

修复3d渲染角度以及新增弹框

pm пре 3 месеци
родитељ
комит
0a82dca0aa
2 измењених фајлова са 87 додато и 4 уклоњено
  1. 5 0
      src/components/lockCabinet/LockCabinet3D.css
  2. 82 4
      src/components/lockCabinet/MapData.tsx

+ 5 - 0
src/components/lockCabinet/LockCabinet3D.css

@@ -670,6 +670,11 @@
   transform: translateZ(15px);
 }
 
+/* 可点击仓位:鼠标指针 */
+.lc3dSlotClickable {
+  cursor: pointer;
+}
+
 .lc3dLockNumber {
   position: absolute;
   top: -16px;

+ 82 - 4
src/components/lockCabinet/MapData.tsx

@@ -1,5 +1,5 @@
 import React, { useState, useEffect, useRef, useCallback } from 'react';
-import { Modal, message } from 'antd';
+import { Modal, message, Button } from 'antd';
 import { Clock } from 'lucide-react';
 import { slotApi, LockCabinetSlotVO, SlotPageParam } from '../../api/lockCabinet/slots';
 import { lockCabinetApi, LockCabinetVO } from '../../api/lockCabinet';
@@ -20,11 +20,16 @@ export default function MapData({ cabinetId }: MapDataProps) {
   const [updateTime, setUpdateTime] = useState<string | null>(null);
   const [dialogVisible, setDialogVisible] = useState(false);
   const [errorInfo, setErrorInfo] = useState('');
+
+  // 仓位详情弹框:钥匙仓/锁仓点击展示
+  const [slotDetailVisible, setSlotDetailVisible] = useState(false);
+  const [slotDetailType, setSlotDetailType] = useState<'key' | 'lock'>('key');
+  const [slotDetailNo, setSlotDetailNo] = useState(1);
   
   // 3D 控制状态
   const [isDragging, setIsDragging] = useState(false);
   const previousMousePosition = useRef({ x: 0, y: 0 });
-  const rotation = useRef({ x: -5, y: -25 });
+  const rotation = useRef({ x: 0, y: 0 });
   // 用户缩放(在自适应 fitScale 的基础上)
   const userScale = useRef(1);
   const [fitScale, setFitScale] = useState(1);
@@ -247,6 +252,12 @@ export default function MapData({ cabinetId }: MapDataProps) {
     return rows;
   }, [slotData]);
 
+  const openSlotDetail = (type: 'key' | 'lock', slotNo: number) => {
+    setSlotDetailType(type);
+    setSlotDetailNo(slotNo);
+    setSlotDetailVisible(true);
+  };
+
   // 从机柜详情 remark 解析钥匙/锁仓状态(keys/locks,slotNo,status: online/offline),用于 3D 仓位渲染
   const remarkSlots = React.useMemo(() => {
     const keyOnline: Record<number, boolean> = {};
@@ -424,7 +435,14 @@ export default function MapData({ cabinetId }: MapDataProps) {
                               : (slot?.status === '1' || slot?.isOccupied === '1' ? 'lc3dKeyIndicatorRed' : 'lc3dKeyIndicatorGreen');
 
                             return (
-                              <div key={idx} className="lc3dKeySlot">
+                              <div
+                                key={idx}
+                                className="lc3dKeySlot lc3dSlotClickable"
+                                role="button"
+                                tabIndex={0}
+                                onMouseDown={(e) => e.stopPropagation()}
+                                onClick={() => openSlotDetail('key', slotNo)}
+                              >
                                 <span className="lc3dKeyNumber">{slotNo}</span>
                                 {isOnlineFromRemark && (
                                   <img src={keyImg} alt="钥匙" className="lc3dSlotHardwareImg" style={{ width: 30, height: 30 }} title="在线" />
@@ -450,7 +468,14 @@ export default function MapData({ cabinetId }: MapDataProps) {
                                 ? (isOnlineFromRemark ? 'lc3dLockIndicatorRed' : 'lc3dLockIndicatorGreen')
                                 : (slot?.status === '1' || slot?.isOccupied === '1' ? 'lc3dLockIndicatorRed' : 'lc3dLockIndicatorOff');
                               return (
-                                <div key={slotIdx} className="lc3dLockSlot">
+                                <div
+                                  key={slotIdx}
+                                  className="lc3dLockSlot lc3dSlotClickable"
+                                  role="button"
+                                  tabIndex={0}
+                                  onMouseDown={(e) => e.stopPropagation()}
+                                  onClick={() => openSlotDetail('lock', num)}
+                                >
                                   <span className="lc3dLockNumber">{num}</span>
                                   {isOnlineFromRemark && (
                                     <img src={lockImg} alt="锁" className="lc3dSlotHardwareLockImg" style={{ width: 30, height: 20 }} title="在线" />
@@ -605,6 +630,59 @@ export default function MapData({ cabinetId }: MapDataProps) {
         </div>
       </div>
 
+      {/* 仓位详情弹框:钥匙仓/锁仓点击展示,参考挂锁详情样式 */}
+      <Modal
+        title={slotDetailType === 'key' ? `钥匙-${slotDetailNo} - 详情` : `挂锁-${slotDetailNo} - 详情`}
+        open={slotDetailVisible}
+        onCancel={() => setSlotDetailVisible(false)}
+        footer={[
+          <Button key="edit" type="primary" onClick={() => { message.info('编辑功能待接入'); }}>
+            编辑
+          </Button>,
+          <Button key="delete" danger onClick={() => { message.info('删除功能待接入'); }}>
+            删除
+          </Button>,
+        ]}
+        width={480}
+        destroyOnClose
+      >
+        <div className="pt-2">
+          <div className="text-base font-semibold text-gray-900 mb-4">基本信息</div>
+          <div className="space-y-0 border-t border-gray-100">
+            <div className="flex justify-between items-center py-3 border-b border-gray-100">
+              <span className="text-gray-600">设备名称</span>
+              <span className="text-gray-900 font-medium">
+                {slotDetailType === 'key' ? `钥匙-${slotDetailNo}` : `挂锁-${slotDetailNo}`}
+              </span>
+            </div>
+            <div className="flex justify-between items-center py-3 border-b border-gray-100">
+              <span className="text-gray-600">NFC编号</span>
+              <span className="text-gray-900 font-medium">
+                {slotDetailType === 'key' ? `KEY${String(slotDetailNo).padStart(3, '0')}` : `LOCK${String(slotDetailNo).padStart(3, '0')}`}
+              </span>
+            </div>
+            <div className="flex justify-between items-center py-3 border-b border-gray-100">
+              <span className="text-gray-600">设备类型</span>
+              <span className="text-gray-900 font-medium">{slotDetailType === 'key' ? '钥匙' : '锁具'}</span>
+            </div>
+            <div className="flex justify-between items-center py-3 border-b border-gray-100">
+              <span className="text-gray-600">状态</span>
+              <span className="inline-flex px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-700 border border-green-200">启用</span>
+            </div>
+            <div className="flex justify-between items-center py-3 border-b border-gray-100">
+              <span className="text-gray-600">在线状态</span>
+              <span className={`inline-flex px-3 py-1 rounded-full text-sm font-medium border ${
+                (slotDetailType === 'key' ? remarkSlots.keyOnline[slotDetailNo] : remarkSlots.lockOnline[slotDetailNo])
+                  ? 'bg-green-100 text-green-700 border-green-200'
+                  : 'bg-gray-100 text-gray-600 border-gray-200'
+              }`}>
+                {(slotDetailType === 'key' ? remarkSlots.keyOnline[slotDetailNo] : remarkSlots.lockOnline[slotDetailNo]) ? '在线' : '离线'}
+              </span>
+            </div>
+          </div>
+        </div>
+      </Modal>
+
       {/* 异常信息对话框 */}
       <Modal
         title="异常信息"