import React, { useState } from 'react'; import { Space, Button, Segmented, Badge, message, Modal, Table, Tag } from 'antd'; import { apiPost, getExportUrl } from '../api/client'; import type { SaveChangeDto, BomItemDto, MatchMaterialRequest, MatchMaterialResponse, MatchMaterialResultDto } from '../api/types'; interface ToolBarProps { dirtyCount: number; viewMode: 'hierarchical' | 'flat'; onViewModeChange: (mode: 'hierarchical' | 'flat') => void; onRefresh: () => void; onOpenConfig: () => void; getDirtyChanges: () => SaveChangeDto[]; onSaveSuccess: (changes: SaveChangeDto[]) => void; items: BomItemDto[]; } export const ToolBar: React.FC = ({ dirtyCount, viewMode, onViewModeChange, onRefresh, onOpenConfig, getDirtyChanges, onSaveSuccess, items, }) => { const [saving, setSaving] = useState(false); const [matching, setMatching] = useState(false); const [matchResults, setMatchResults] = useState([]); const [matchModalVisible, setMatchModalVisible] = useState(false); const [matchSaving, setMatchSaving] = useState(false); const handleSave = async () => { if (dirtyCount === 0) return; setSaving(true); try { const changes = getDirtyChanges(); const res = await apiPost('/api/bom/save', { Changes: changes }); if (res.Success) { message.success(`保存成功,共更新 ${res.SavedCount} 项`); onSaveSuccess(changes); } else { message.error(`保存失败: ${res.Error}`); } } catch (e: any) { message.error(`保存失败: ${e.message}`); } finally { setSaving(false); } }; const handleExport = () => { window.open(getExportUrl(viewMode === 'flat'), '_blank'); }; const handleMatchMaterial = async () => { const emptyItems = items.filter( (item) => !item.IsAssembly && !item.Props?.['物料编码'] ); if (emptyItems.length === 0) { message.info('所有零件的物料编码均已填写'); return; } setMatching(true); try { const request: MatchMaterialRequest = { Items: emptyItems.map((item) => ({ DrawingNo: item.DrawingNo, DocPath: item.DocPath, })), }; const res = await apiPost('/api/bom/match-material', request); if (!res.Success) { message.error(`匹配失败: ${res.Error}`); return; } const matched = res.Results.filter((r) => r.Matched); if (matched.length === 0) { message.info('未找到匹配的物料编码'); return; } setMatchResults(matched); setMatchModalVisible(true); } catch (e: any) { message.error(`匹配失败: ${e.message}`); } finally { setMatching(false); } }; const handleConfirmMatch = async () => { setMatchSaving(true); try { const changes: SaveChangeDto[] = matchResults.map((r) => ({ DocPath: r.DocPath, Key: '物料编码', Value: r.PartCode, })); const res = await apiPost('/api/bom/save', { Changes: changes }); if (res.Success) { message.success(`写入成功,共更新 ${res.Results?.length ?? changes.length} 项物料编码`); onSaveSuccess(changes); setMatchModalVisible(false); setMatchResults([]); } else { message.error(`写入失败: ${res.Error}`); } } catch (e: any) { message.error(`写入失败: ${e.message}`); } finally { setMatchSaving(false); } }; const matchColumns = [ { title: '图号', dataIndex: 'DrawingNo', key: 'DrawingNo', width: 260, }, { title: '物料编码', dataIndex: 'PartCode', key: 'PartCode', width: 180, }, { title: 'PLM零件名称', dataIndex: 'PartName', key: 'PartName', width: 180, }, { title: '状态', key: 'status', width: 80, render: (_: unknown, record: MatchMaterialResultDto) => record.Matched ? 已匹配 : 未匹配, }, ]; return ( <> onViewModeChange(val as 'hierarchical' | 'flat')} />
● 已连接
{ setMatchModalVisible(false); setMatchResults([]); }} okText="确认写入" cancelText="取消" confirmLoading={matchSaving} width={760} >

以下零件已匹配到物料编码,确认后将写入SolidWorks文件属性。

); };