|
@@ -1,8 +1,11 @@
|
|
|
-import React, { useState } from 'react';
|
|
|
|
|
|
|
+import React, { useState, useEffect } from 'react';
|
|
|
import { Plus, Search, Edit2, Trash2, MoreVertical, MapPin, Eye } from 'lucide-react';
|
|
import { Plus, Search, Edit2, Trash2, MoreVertical, MapPin, Eye } from 'lucide-react';
|
|
|
import { Button } from 'antd';
|
|
import { Button } from 'antd';
|
|
|
import { Button as UIButton } from './ui/button';
|
|
import { Button as UIButton } from './ui/button';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
+import { getStrDictOptions, getDictOptions, setDictOptions, getDictLabel, DICT_TYPE } from '../utils/dict';
|
|
|
|
|
+import { dictDataApi } from '../api/DictData';
|
|
|
|
|
+import { postApi, PostVO } from '../api/Post';
|
|
|
|
|
|
|
|
interface TableRow {
|
|
interface TableRow {
|
|
|
id: number;
|
|
id: number;
|
|
@@ -14,6 +17,79 @@ export default function LocationManagement() {
|
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
|
const [showAddModal, setShowAddModal] = useState(false);
|
|
const [showAddModal, setShowAddModal] = useState(false);
|
|
|
const [editingItem, setEditingItem] = useState<TableRow | null>(null);
|
|
const [editingItem, setEditingItem] = useState<TableRow | null>(null);
|
|
|
|
|
+
|
|
|
|
|
+ // 字典选项
|
|
|
|
|
+ const [powerSourceOptions, setPowerSourceOptions] = useState<Array<{ label: string; value: string }>>([]);
|
|
|
|
|
+ const [pointGroupOptions, setPointGroupOptions] = useState<Array<{ label: string; value: number }>>([]);
|
|
|
|
|
+ // 岗位列表
|
|
|
|
|
+ const [postList, setPostList] = useState<PostVO[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+ // 加载字典数据和岗位列表
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const loadDictData = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 获取岗位数据
|
|
|
|
|
+ try {
|
|
|
|
|
+ const postRes = await postApi.getPostPage({ pageNo: 1, pageSize: -1 });
|
|
|
|
|
+ const data = (postRes as any)?.data || postRes;
|
|
|
|
|
+ const posts = data?.list || [];
|
|
|
|
|
+ console.log('点位管理-岗位列表:', posts);
|
|
|
|
|
+ setPostList(posts);
|
|
|
|
|
+ } catch (postError) {
|
|
|
|
|
+ console.error('获取岗位列表失败:', postError);
|
|
|
|
|
+ setPostList([]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取能量源数据(从字典 power_source)
|
|
|
|
|
+ try {
|
|
|
|
|
+ const powerRes = await dictDataApi.getDictDataPage({ pageNo: 1, pageSize: -1, dictType: DICT_TYPE.POWER_SOURCE });
|
|
|
|
|
+ const powerData = (powerRes as any)?.list ?? (powerRes as any)?.data?.list ?? (Array.isArray(powerRes) ? powerRes : []);
|
|
|
|
|
+ const powerList = Array.isArray(powerData) ? powerData : [];
|
|
|
|
|
+ console.log('点位管理-能量源字典数据:', powerList);
|
|
|
|
|
+ setDictOptions(DICT_TYPE.POWER_SOURCE, powerList.map((item: any) => ({
|
|
|
|
|
+ dictType: DICT_TYPE.POWER_SOURCE,
|
|
|
|
|
+ label: item.label,
|
|
|
|
|
+ value: item.value,
|
|
|
|
|
+ colorType: item.colorType || '',
|
|
|
|
|
+ cssClass: item.cssClass || '',
|
|
|
|
|
+ })));
|
|
|
|
|
+ const powerOptions = getStrDictOptions(DICT_TYPE.POWER_SOURCE);
|
|
|
|
|
+ console.log('点位管理-能量源选项:', powerOptions);
|
|
|
|
|
+ setPowerSourceOptions(powerOptions);
|
|
|
|
|
+ } catch (powerError) {
|
|
|
|
|
+ console.error('获取能量源字典失败:', powerError);
|
|
|
|
|
+ setPowerSourceOptions([]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取点位分组数据(从字典 point_group)
|
|
|
|
|
+ try {
|
|
|
|
|
+ const dictRes = await dictDataApi.getDictDataPage({ pageNo: 1, pageSize: -1, dictType: DICT_TYPE.POINT_GROUP });
|
|
|
|
|
+ const data = (dictRes as any)?.list ?? (dictRes as any)?.data?.list ?? (Array.isArray(dictRes) ? dictRes : []);
|
|
|
|
|
+ const list = Array.isArray(data) ? data : [];
|
|
|
|
|
+ console.log('点位管理-点位分组字典原始数据:', list);
|
|
|
|
|
+ setDictOptions(DICT_TYPE.POINT_GROUP, list.map((item: any) => ({
|
|
|
|
|
+ dictType: DICT_TYPE.POINT_GROUP,
|
|
|
|
|
+ label: item.label,
|
|
|
|
|
+ value: item.value,
|
|
|
|
|
+ colorType: item.colorType || '',
|
|
|
|
|
+ cssClass: item.cssClass || '',
|
|
|
|
|
+ })));
|
|
|
|
|
+ const options = getDictOptions(DICT_TYPE.POINT_GROUP).map((item) => ({
|
|
|
|
|
+ label: item.label,
|
|
|
|
|
+ value: Number(item.value),
|
|
|
|
|
+ }));
|
|
|
|
|
+ console.log('点位管理-点位分组选项(转换后):', options);
|
|
|
|
|
+ setPointGroupOptions(options);
|
|
|
|
|
+ } catch (dictError) {
|
|
|
|
|
+ console.error('获取点位分组字典失败:', dictError);
|
|
|
|
|
+ setPointGroupOptions([]);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('加载字典数据失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ loadDictData();
|
|
|
|
|
+ }, []);
|
|
|
|
|
|
|
|
// 点位数据
|
|
// 点位数据
|
|
|
const locationData: TableRow[] = [
|
|
const locationData: TableRow[] = [
|
|
@@ -34,7 +110,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-01-15',
|
|
installDate: '2024-01-15',
|
|
|
lastCheck: '2025-12-01',
|
|
lastCheck: '2025-12-01',
|
|
|
checkCycle: '每月',
|
|
checkCycle: '每月',
|
|
|
- remark: '主进线断路器'
|
|
|
|
|
|
|
+ remark: '主进线断路器',
|
|
|
|
|
+ powerType: '1', // 能量源字典值
|
|
|
|
|
+ lotoId: 1, // 点位分组字典值
|
|
|
|
|
+ workstationId: 1 // 岗位ID
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
id: 2,
|
|
id: 2,
|
|
@@ -53,7 +132,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-01-15',
|
|
installDate: '2024-01-15',
|
|
|
lastCheck: '2025-12-01',
|
|
lastCheck: '2025-12-01',
|
|
|
checkCycle: '每月',
|
|
checkCycle: '每月',
|
|
|
- remark: '照明回路'
|
|
|
|
|
|
|
+ remark: '照明回路',
|
|
|
|
|
+ powerType: '2', // 能量源字典值
|
|
|
|
|
+ lotoId: 2, // 点位分组字典值
|
|
|
|
|
+ workstationId: 2 // 岗位ID
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
id: 3,
|
|
id: 3,
|
|
@@ -72,7 +154,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-01-10',
|
|
installDate: '2024-01-10',
|
|
|
lastCheck: '2025-12-03',
|
|
lastCheck: '2025-12-03',
|
|
|
checkCycle: '每周',
|
|
checkCycle: '每周',
|
|
|
- remark: '高压侧进线'
|
|
|
|
|
|
|
+ remark: '高压侧进线',
|
|
|
|
|
+ powerType: '1', // 能量源字典值
|
|
|
|
|
+ lotoId: 3, // 点位分组字典值
|
|
|
|
|
+ workstationId: 1 // 岗位ID
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
id: 4,
|
|
id: 4,
|
|
@@ -91,7 +176,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-01-10',
|
|
installDate: '2024-01-10',
|
|
|
lastCheck: '2025-11-28',
|
|
lastCheck: '2025-11-28',
|
|
|
checkCycle: '每周',
|
|
checkCycle: '每周',
|
|
|
- remark: '低压侧出线'
|
|
|
|
|
|
|
+ remark: '低压侧出线',
|
|
|
|
|
+ powerType: '2', // 能量源字典值
|
|
|
|
|
+ lotoId: 4, // 点位分组字典值
|
|
|
|
|
+ workstationId: 2 // 岗位ID
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
id: 5,
|
|
id: 5,
|
|
@@ -110,7 +198,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-03-05',
|
|
installDate: '2024-03-05',
|
|
|
lastCheck: '2025-11-30',
|
|
lastCheck: '2025-11-30',
|
|
|
checkCycle: '每月',
|
|
checkCycle: '每月',
|
|
|
- remark: '空调控制'
|
|
|
|
|
|
|
+ remark: '空调控制',
|
|
|
|
|
+ powerType: '1', // 能量源字典值
|
|
|
|
|
+ lotoId: 1, // 点位分组字典值
|
|
|
|
|
+ workstationId: 3 // 岗位ID
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
id: 6,
|
|
id: 6,
|
|
@@ -129,7 +220,10 @@ export default function LocationManagement() {
|
|
|
installDate: '2024-02-20',
|
|
installDate: '2024-02-20',
|
|
|
lastCheck: '2025-12-02',
|
|
lastCheck: '2025-12-02',
|
|
|
checkCycle: '每月',
|
|
checkCycle: '每月',
|
|
|
- remark: '动力配电'
|
|
|
|
|
|
|
+ remark: '动力配电',
|
|
|
|
|
+ powerType: '2', // 能量源字典值
|
|
|
|
|
+ lotoId: 2, // 点位分组字典值
|
|
|
|
|
+ workstationId: 1 // 岗位ID
|
|
|
},
|
|
},
|
|
|
];
|
|
];
|
|
|
|
|
|
|
@@ -243,6 +337,9 @@ export default function LocationManagement() {
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>机柜</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>机柜</th>
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '10%' }}>设备</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '10%' }}>设备</th>
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '6%' }}>电压</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '6%' }}>电压</th>
|
|
|
|
|
+ <th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>能量源</th>
|
|
|
|
|
+ <th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>点位分组</th>
|
|
|
|
|
+ <th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>岗位</th>
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>状态</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>状态</th>
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>负责人</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>负责人</th>
|
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>检查周期</th>
|
|
<th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '8%' }}>检查周期</th>
|
|
@@ -260,6 +357,73 @@ export default function LocationManagement() {
|
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.cabinet}</td>
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.cabinet}</td>
|
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.device}</td>
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.device}</td>
|
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.voltage}</td>
|
|
<td className="px-6 py-4 text-sm text-gray-900">{row.voltage}</td>
|
|
|
|
|
+ <td className="px-6 py-4 text-sm text-gray-900">
|
|
|
|
|
+ {(() => {
|
|
|
|
|
+ const powerValue = row.powerType;
|
|
|
|
|
+ // 如果值为 null、undefined 或空字符串,显示 '-'
|
|
|
|
|
+ if (powerValue === null || powerValue === undefined || powerValue === '') {
|
|
|
|
|
+ return '-';
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果字典选项已加载,尝试匹配
|
|
|
|
|
+ if (powerSourceOptions.length > 0) {
|
|
|
|
|
+ const option = powerSourceOptions.find(opt => String(opt.value) === String(powerValue));
|
|
|
|
|
+ if (option) {
|
|
|
|
|
+ return option.label;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果字典选项未加载或未匹配,显示原始值
|
|
|
|
|
+ return String(powerValue);
|
|
|
|
|
+ })()}
|
|
|
|
|
+ </td>
|
|
|
|
|
+ <td className="px-6 py-4 text-sm text-gray-900">
|
|
|
|
|
+ {(() => {
|
|
|
|
|
+ const groupValue = row.lotoId;
|
|
|
|
|
+ // 注意:0 是有效值,不能当作 falsy 处理
|
|
|
|
|
+ if (groupValue === null || groupValue === undefined || groupValue === '') {
|
|
|
|
|
+ return '-';
|
|
|
|
|
+ }
|
|
|
|
|
+ // 优先使用 getDictLabel 从字典中获取标签(它会处理类型转换)
|
|
|
|
|
+ const dictLabel = getDictLabel(DICT_TYPE.POINT_GROUP, groupValue);
|
|
|
|
|
+ if (dictLabel) {
|
|
|
|
|
+ return dictLabel;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果字典中没有找到,尝试从 pointGroupOptions 中查找
|
|
|
|
|
+ if (pointGroupOptions.length > 0) {
|
|
|
|
|
+ // 尝试多种类型匹配
|
|
|
|
|
+ const option = pointGroupOptions.find(opt =>
|
|
|
|
|
+ Number(opt.value) === Number(groupValue) ||
|
|
|
|
|
+ String(opt.value) === String(groupValue)
|
|
|
|
|
+ );
|
|
|
|
|
+ if (option) {
|
|
|
|
|
+ return option.label;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果都找不到,显示原始值
|
|
|
|
|
+ return String(groupValue);
|
|
|
|
|
+ })()}
|
|
|
|
|
+ </td>
|
|
|
|
|
+ <td className="px-6 py-4 text-sm text-gray-900">
|
|
|
|
|
+ {(() => {
|
|
|
|
|
+ const workstationId = row.workstationId;
|
|
|
|
|
+ // 如果值为 null 或 undefined,显示 '-'
|
|
|
|
|
+ if (workstationId === null || workstationId === undefined) {
|
|
|
|
|
+ return '-';
|
|
|
|
|
+ }
|
|
|
|
|
+ // 优先使用数据中的 workstationName(如果存在且不为空)
|
|
|
|
|
+ if (row.workstationName) {
|
|
|
|
|
+ return row.workstationName;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 从岗位列表中查找对应的岗位名称
|
|
|
|
|
+ if (postList.length > 0) {
|
|
|
|
|
+ const post = postList.find(p => p.id === Number(workstationId));
|
|
|
|
|
+ if (post) {
|
|
|
|
|
+ return post.name;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果都找不到,显示 ID
|
|
|
|
|
+ return String(workstationId);
|
|
|
|
|
+ })()}
|
|
|
|
|
+ </td>
|
|
|
<td className="px-6 py-4">
|
|
<td className="px-6 py-4">
|
|
|
<span
|
|
<span
|
|
|
className={`inline-flex px-3 py-1 rounded-lg text-xs ${
|
|
className={`inline-flex px-3 py-1 rounded-lg text-xs ${
|