@@ -1,6 +1,42 @@
// 【重要】必须使用 const Component 作为组件变量名
// 运维管理 - 车辆业务 - 替换车管理( 2026年3月3日版本)
var VR _KPI _STYLE = ''
+ '.vr-kpi-stats-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-bottom:16px;}'
+ '@media (max-width:768px){.vr-kpi-stats-row{grid-template-columns:repeat(1,minmax(0,1fr));}}'
+ '.lc-alert-card{display:flex;align-items:flex-start;gap:12px;padding:14px 30px 14px 16px;border-radius:12px;border:1px solid #e2e8f0;background:#fff;position:relative;overflow:hidden;min-width:0;}'
+ '.lc-alert-card-main{flex:1;min-width:0;}'
+ '.lc-alert-card-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;}'
+ '.lc-alert-card-val{font-size:26px;font-weight:800;line-height:1.1;color:#0f172a;font-variant-numeric:tabular-nums;}'
+ '.lc-alert-card-title{font-size:13px;font-weight:600;color:#334155;margin-top:2px;}'
+ '.lc-alert-card-tip-anchor{position:absolute;top:8px;right:8px;z-index:2;line-height:0;}'
+ '.lc-alert-card-tip{width:18px;height:18px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:#94a3b8;background:rgba(255,255,255,.92);border:1px solid #e2e8f0;cursor:help;line-height:0;}'
+ '.lc-alert-card-tip:hover{color:#64748b;border-color:#cbd5e1;background:#fff;}'
+ '.lc-alert-card--total{background:linear-gradient(135deg,#f8fafc 0%,#fff 100%);}'
+ '.lc-alert-card--total .lc-alert-card-icon{background:#e2e8f0;color:#475569;}'
+ '.lc-alert-card--progress{background:linear-gradient(135deg,#fff7ed 0%,#fff 55%);border-color:#fed7aa;}'
+ '.lc-alert-card--progress .lc-alert-card-icon{background:#ffedd5;color:#ea580c;}'
+ '.lc-alert-card--progress .lc-alert-card-val{color:#c2410c;}'
+ '.lc-alert-card--completed{background:linear-gradient(135deg,#ecfdf5 0%,#fff 55%);border-color:#bbf7d0;}'
+ '.lc-alert-card--completed .lc-alert-card-icon{background:#d1fae5;color:#059669;}'
+ '.lc-alert-card--completed .lc-alert-card-val{color:#047857;}'
+ '.lc-alert-card-clickable{cursor:pointer;transition:box-shadow .2s ease,border-color .2s ease,transform .2s ease;}'
+ '.lc-alert-card-clickable:hover{box-shadow:0 4px 14px rgba(15,23,42,.08);}'
+ '.lc-alert-card-active{box-shadow:0 0 0 2px rgba(22,93,255,.2)!important;border-color:#165dff!important;}' ;
var VR _KPI _ICONS = {
total : React . createElement ( 'svg' , { width : 18 , height : 18 , viewBox : '0 0 24 24' , fill : 'none' , stroke : 'currentColor' , strokeWidth : 2 , strokeLinecap : 'round' , strokeLinejoin : 'round' } ,
React . createElement ( 'rect' , { x : 3 , y : 3 , width : 7 , height : 7 } ) , React . createElement ( 'rect' , { x : 14 , y : 3 , width : 7 , height : 7 } ) ,
React . createElement ( 'rect' , { x : 14 , y : 14 , width : 7 , height : 7 } ) , React . createElement ( 'rect' , { x : 3 , y : 14 , width : 7 , height : 7 } ) ) ,
progress : React . createElement ( 'svg' , { width : 18 , height : 18 , viewBox : '0 0 24 24' , fill : 'none' , stroke : 'currentColor' , strokeWidth : 2 , strokeLinecap : 'round' , strokeLinejoin : 'round' } ,
React . createElement ( 'circle' , { cx : 12 , cy : 12 , r : 10 } ) , React . createElement ( 'polyline' , { points : '12 6 12 12 16 14' } ) ) ,
completed : React . createElement ( 'svg' , { width : 18 , height : 18 , viewBox : '0 0 24 24' , fill : 'none' , stroke : 'currentColor' , strokeWidth : 2 , strokeLinecap : 'round' , strokeLinejoin : 'round' } ,
React . createElement ( 'path' , { d : 'M22 11.08V12a10 10 0 1 1-5.93-9.14' } ) , React . createElement ( 'polyline' , { points : '22 4 12 14.01 9 11.01' } ) )
} ;
var VR _KPI _TIP _SVG = React . createElement ( 'svg' , { width : 12 , height : 12 , viewBox : '0 0 24 24' , fill : 'none' , stroke : 'currentColor' , strokeWidth : 2.2 , strokeLinecap : 'round' , strokeLinejoin : 'round' } ,
React . createElement ( 'circle' , { cx : 12 , cy : 12 , r : 10 } ) , React . createElement ( 'line' , { x1 : 12 , y1 : 16 , x2 : 12 , y2 : 12 } ) , React . createElement ( 'line' , { x1 : 12 , y1 : 8 , x2 : 12.01 , y2 : 8 } ) ) ;
const Component = function ( ) {
var useState = React . useState ;
var useCallback = React . useCallback ;
@@ -13,19 +49,17 @@ const Component = function () {
var Select = antd . Select ;
var Button = antd . Button ;
var Table = antd . Table ;
var Tabs = antd . Tabs ;
var Modal = antd . Modal ;
var Input = antd . Input ;
var message = antd . message ;
var Tag = antd . Tag ;
var Empty = antd . Empty ;
var App = antd . App ;
var Badge = antd . Badge ;
var Popover = antd . Popover ;
var Tooltip = antd . Tooltip ;
var RangePicker = DatePicker . RangePicker ;
// 筛选展开(默认一行 3 列)
// 筛选展开(默认一行 4 列,与交车管理一致 )
var _filterExpanded = useState ( false ) ;
var _replaceDateRange = useState ( null ) ;
var _replaceType = useState ( undefined ) ;
@@ -49,8 +83,12 @@ const Component = function () {
createTimeRange : null
} ) ;
var _activeTab = useState ( 'ongoing' ) ;
var _selectedRowKeys = useState ( [ ] ) ;
var _kpiFilter = useState ( 'ongoing' ) ;
var _listPlateQuick = useState ( undefined ) ;
var _page = useState ( 1 ) ;
var _pageSize = useState ( 10 ) ;
var setPage = _page [ 1 ] ;
var setPageSize = _pageSize [ 1 ] ;
var _withdrawModalVisible = useState ( false ) ;
var _withdrawModalRecord = useState ( null ) ;
var _toPermanentModalVisible = useState ( false ) ;
@@ -83,9 +121,9 @@ const Component = function () {
{ value : '临时替换' , label : '临时替换' }
] ;
var projectNameOptions = [
{ value : 'p1 ' , label : '嘉兴氢能示范项目' } ,
{ value : 'p2 ' , label : '上海物流租赁项目' } ,
{ value : 'p3 ' , label : '杭州城配租赁项目' }
{ value : '嘉兴氢能示范项目 ' , label : '嘉兴氢能示范项目' } ,
{ value : '上海物流租赁项目 ' , label : '上海物流租赁项目' } ,
{ value : '杭州城配租赁项目 ' , label : '杭州城配租赁项目' }
] ;
var approvalStatusOptions = [
{ value : '全部' , label : '全部' } ,
@@ -171,64 +209,59 @@ const Component = function () {
var deletedIds = _deletedIds [ 0 ] ;
var appliedFilter = _appliedFilter [ 0 ] ;
var listPlateQuick = _listPlateQuick [ 0 ] ;
var kpiFilter = _kpiFilter [ 0 ] ;
var filteredOngoing = useMemo ( function ( ) {
var list = ongoingList . filter ( function ( r ) {
if ( deletedIds . indexOf ( r. id ) ! == - 1 ) return false ;
if ( appliedF ilter. replaceDateRange && appliedF ilter . replaceDateRange . length === 2 ) {
var start = appliedF ilter. replaceDateRange [ 0 ] && appliedF ilter. replaceDateRange [ 0 ] . format ? appliedF ilter. replaceDateRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var en d = appliedFilte r. replaceDateRange [ 1 ] && appliedFilter . replaceDateRang e [ 1 ] . format ? appliedFilter . replaceDateRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var rd = ( r . replaceDate || '' ) . slice ( 0 , 10 ) ;
if ( start && rd < start ) return false ;
if ( end && rd > end ) return false ;
}
if ( appliedF ilter. replaceTyp e && r . replaceTyp e !== appliedF ilter. replaceTyp e) return false ;
if ( appliedFilter . projectName && r . projectName !== appliedF ilter . projectName ) return false ;
var approval = appliedFilter . approvalStatus ;
if ( approval && approval . length > 0 && approval . indexOf ( '全部' ) === - 1 && approval . indexOf ( r . approvalStatus ) === - 1 ) return false ;
if ( appliedF ilter. original Plate && ( r . original Plate || '' ) . indexOf ( appliedF ilter. original Plate) === - 1 ) return false ;
if ( appliedF ilter. replacePlate && ( r . replacePlate || '' ) . indexOf ( appliedFilter . replacePlate ) === - 1 ) return false ;
if ( appliedF ilter. replaceReason && appliedFilter . replaceReason !== '全部' && r . replaceReason !== appliedF ilter . replaceReason ) return false ;
if ( appliedF ilter. creator && r . creator !== appliedFilter . creator ) return false ;
if ( appliedF ilter. createTimeRange && appliedF ilter . createTimeRange . length === 2 ) {
var cs = appliedF ilter. createTimeRange [ 0 ] && appliedF ilter. createTimeRange [ 0 ] . format ? appliedF ilter. createTimeRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ce = appliedFilte r. createTimeRange [ 1 ] && appliedFilter . createTimeRange [ 1 ] . format ? appliedFilter . createTimeRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ct = ( r . createTime || '' ) . slice ( 0 , 10 ) ;
if ( cs && ct < cs ) return false ;
if ( ce && ct > ce ) return false ;
}
return true ;
} ) ;
return list ;
} , [ appliedFilter , deletedIds ] ) ;
function matchAppliedFilters ( r , filter , quickPlate ) {
if ( deletedIds . indexOf ( r . id ) !== - 1 ) return false ;
if ( filter . replaceDateRange && filter . replaceDateRange . length = == 2 ) {
var start = f ilter. replaceDateRange [ 0 ] && f ilter. replaceDateRange [ 0 ] . format ? filter . replaceDateRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var end = f ilter. replaceDateRange [ 1 ] && f ilter. replaceDateRange [ 1 ] . format ? f ilter. replaceDateRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var r d = ( r . replaceDate || '' ) . slic e ( 0 , 10 ) ;
if ( start && rd < start ) return false ;
if ( end && rd > end ) return false ;
}
if ( filter . replaceType && r . replaceType !== filter . replaceType ) return false ;
if ( f ilter. projectNam e && r . projectNam e !== f ilter. projectNam e) return false ;
var approval = f ilter. ap provalStatus ;
if ( approval && approval . length > 0 && approval . indexOf ( '全部' ) === - 1 && approval . indexOf ( r . approvalStatus ) === - 1 ) return false ;
if ( filter . originalPlate && ( r . originalPlate || '' ) . indexOf ( filte r. originalPlate ) === - 1 ) return false ;
if ( f ilter. replace Plate && ( r . replace Plate || '' ) . indexOf ( f ilter. replace Plate) === - 1 ) return false ;
if ( f ilter. replaceReason && filte r. replaceReason !== '全部' && r . replaceReason !== filter . replaceReason ) return false ;
if ( f ilter. c reator && r . creator !== f ilter. c reator ) return false ;
if ( f ilter. createTimeRange && filte r. createTimeRange . length === 2 ) {
var cs = f ilter. createTimeRange [ 0 ] && f ilter. createTimeRange [ 0 ] . format ? filter . createTimeRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ce = f ilter. createTimeRange [ 1 ] && f ilter. createTimeRange [ 1 ] . format ? f ilter. createTimeRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ct = ( r . createTime || '' ) . slice ( 0 , 10 ) ;
if ( cs && ct < cs ) return false ;
if ( ce && ct > ce ) return false ;
}
if ( quickPlate && ( r . originalPlate || '' ) . indexOf ( quickPlate ) === - 1 && ( r . replacePlate || '' ) . indexOf ( quickPlate ) === - 1 ) return false ;
return true ;
}
var filteredHistory = useMemo ( function ( ) {
var list = history List. filter ( function ( r ) {
if ( deletedIds . indexOf ( r . id ) !== - 1 ) return false ;
if ( appliedFilter . replaceDateRange && appliedFilter . replaceDateRange . length === 2 ) {
var start = appliedFilter . replaceDateRange [ 0 ] && appliedFilter . replaceDateRange [ 0 ] . format ? appliedFilter . replaceDateRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var end = appliedFilter . replaceDateRange [ 1 ] && appliedFilter . replaceDateRange [ 1 ] . format ? appliedFilter . replaceDateRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var rd = ( r . replaceDate || '' ) . slice ( 0 , 10 ) ;
if ( start && rd < start ) return false ;
if ( end && rd > end ) return false ;
}
if ( appliedFilter . replaceType && r . replaceType !== appliedFilter . replaceType ) return false ;
if ( appliedFilter . projectName && r . projectName !== appliedFilter . projectName ) return false ;
if ( appliedFilter . originalPlate && ( r . originalPlate || '' ) . indexOf ( appliedFilter . originalPlate ) === - 1 ) return false ;
if ( appliedFilter . replacePlate && ( r . replacePlate || '' ) . indexOf ( appliedFilter . replacePlate ) === - 1 ) return false ;
if ( appliedFilter . replaceReason && appliedFilter . replaceReason !== '全部' && r . replaceReason !== appliedFilter . replaceReason ) return false ;
if ( appliedFilter . creator && r . creator !== appliedFilter . creator ) return false ;
if ( appliedFilter . createTimeRange && appliedFilter . createTimeRange . length === 2 ) {
var cs = appliedFilter . createTimeRange [ 0 ] && appliedFilter . createTimeRange [ 0 ] . format ? appliedFilter . createTimeRange [ 0 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ce = appliedFilter . createTimeRange [ 1 ] && appliedFilter . createTimeRange [ 1 ] . format ? appliedFilter . createTimeRange [ 1 ] . format ( 'YYYY-MM-DD' ) : '' ;
var ct = ( r . createTime || '' ) . slice ( 0 , 10 ) ;
if ( cs && ct < cs ) return false ;
if ( ce && ct > ce ) return false ;
}
return true ;
var filteredBuckets = useMemo ( function ( ) {
var ongoing = ongoing List. filter ( function ( r ) { return matchAppliedFilters ( r , appliedFilter , listPlateQuick ) ; } ) ;
var history = historyList . filter ( function ( r ) { return matchAppliedFilters ( r , appliedFilter , listPlateQuick ) ; } ) ;
var all = ongoing . concat ( history ) . sort ( function ( a , b ) {
return String ( b . replaceDate || '' ) . localeCompare ( String ( a . replaceDate || '' ) ) ;
} ) ;
return list ;
} , [ appliedFilter , deletedIds ] ) ;
return { ongoing : ongoing , history : history , all : all } ;
} , [ appliedFilter , deletedIds , listPlateQuick ]) ;
var kpiStats = useMemo ( function ( ) {
return {
total : filteredBuckets . all . length ,
ongoing : filteredBuckets . ongoing . length ,
history : filteredBuckets . history . length
} ;
} , [ filteredBuckets ] ) ;
var currentList = useMemo ( function ( ) {
if ( kpiFilter === 'history' ) return filteredBuckets . history ;
if ( kpiFilter === 'total' ) return filteredBuckets . all ;
return filteredBuckets . ongoing ;
} , [ filteredBuckets , kpiFilter ] ) ;
var handleQuery = useCallback ( function ( ) {
_appliedFilter [ 1 ] ( {
@@ -242,6 +275,7 @@ const Component = function () {
creator : _creator [ 0 ] ,
createTimeRange : _createTimeRange [ 0 ]
} ) ;
setPage ( 1 ) ;
} , [ ] ) ;
var handleReset = useCallback ( function ( ) {
@@ -265,6 +299,7 @@ const Component = function () {
creator : undefined ,
createTimeRange : null
} ) ;
setPage ( 1 ) ;
} , [ ] ) ;
var handleApprovalStatusChange = useCallback ( function ( v ) {
@@ -278,29 +313,18 @@ const Component = function () {
_approvalStatus [ 1 ] ( v ) ;
} , [ ] ) ;
var filterLabelStyle = { marginBottom : 6 , fontSize : 13 , fontWeight : 500 , color : '#475569 ' , lineHeight : 1. 4 } ;
var filterItemStyle = { marginBottom : 0 } ;
var filterLabelStyle = { display : 'block' , marginBottom : 4 , color : '#333 ' , fontSize : 1 4 } ;
var filterItemStyle = { minWidth : 0 } ;
var filterControlStyle = { width : '100%' } ;
var styles = {
page : { padding : '16px 24px 48px' , backgroundColor : '#f5f5f5' , minHeight : '100vh' , fontSize : 14 } ,
cardBody : { padding : '20px 24px' } ,
filterGrid : { display : 'grid' , gridTemplateColumns : '1fr 1fr 1fr 1fr' , gap : '16px 24px' , alignItems : 'start' } ,
filterActions : { display : 'flex' , justifyContent : 'flex-end' , alignItems : 'center' , gap : 8 , marginTop : 16 , paddingTop : 16 , borderTop : '1px solid #f1f5f9' }
} ;
var pageStyles =
'.vr-list-page{font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}' +
'.vr-list-page .vr-page-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:20px;flex-wrap:wrap}' +
'.vr-list-page .vr-filter-card,.vr-list-page .vr-list-card{border-radius:16px;border:none;box-shadow:0 4px 24px -6px rgba(15,23,42,0.08),0 0 0 1px rgba(15,23,42,0.05);margin-bottom:16px}' +
'.vr-list-page .vr-filter-card>.ant-card-head,.vr-list-page .vr-list-card>.ant-card-head{border-bottom:1px solid #f1f5f9;min-height:auto;padding:14px 20px}' +
'.vr-list-page .vr-filter-card>.ant-card-head .ant-card-head-title,.vr-list-page .vr-list-card>.ant-card-head .ant-card-head-title{font-size:15px;font-weight:600;color:#0f172a;padding:0}' +
'.vr-list-page .vr-filter-card>.ant-card-body{padding:16px 20px 20px}' +
'.vr-list-page .vr-list-card>.ant-card-body{padding:12px 16px 16px}' +
'.vr-list-page .vr-filter-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px 20px;align-items:start}' +
'@media(max-width:900px){.vr-list-page .vr-filter-grid{grid-template-columns:1fr}}' +
'.vr-list-page .vr-filter-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;padding-top:16px;border-top:1px solid #f1f5f9}' +
'.vr-list-page .vr-swap-arrow{color:#94a3b8;font-size:12px;margin:0 4px}' +
'.vr-list-page .vr-reason-text{display:block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#475569}' +
'.vr-list-page .vr-list-table .ant-table-thead>tr>th{background:#f8fafc!important;color:#475569;font-weight:600;font-size:13px}' +
'.vr-list-page .vr-list-table .ant-table-tbody>tr:hover>td{background:#f0f9ff!important}' +
'.vr-list-page .vr-list-table .ant-table-thead th,.vr-list-page .vr-list-table .ant-table-tbody td{white-space:nowrap}' +
'.vr-list-page .vr-list-table .ant-table-tbody>tr.ant-table-row-selected>td{background:#eff6ff!important}' +
'.vr-list-page .vr-tabs .ant-tabs-nav{margin-bottom:0}' +
'.vr-list-page .vr-empty{padding:48px 16px}' +
'.vr-approval-flow-popover .ant-popover-inner{padding:14px 16px;border-radius:8px}' +
'.vr-approval-flow{width:300px;max-width:min(340px,92vw)}' +
'.vr-approval-flow__item{display:flex;gap:12px;position:relative;padding-bottom:22px}' +
@@ -312,8 +336,46 @@ const Component = function () {
'.vr-approval-flow__head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:4px}' +
'.vr-approval-flow__role{font-size:14px;font-weight:600;color:rgba(0,0,0,0.88);line-height:1.4}' +
'.vr-approval-flow__meta{font-size:12px;color:rgba(0,0,0,0.45);line-height:1.5}' +
'.vr-list-page .vr-approval-status-trigger{display:inline-flex;cursor:pointer;border-radius:4px;transition:opacity .15s ease}' +
'.vr-list-page .vr-approval-status-trigger:hover{opacity:.88}' ;
'.vr-approval-status-trigger{display:inline-flex;cursor:pointer;border-radius:4px;transition:opacity .15s ease}' +
'.vr-approval-status-trigger:hover{opacity:.88}' +
'@media(max-width:900px){.vr-list-filter-grid{grid-template-columns:1fr 1fr!important}}' +
'@media(max-width:640px){.vr-list-filter-grid{grid-template-columns:1fr!important}}' ;
var cellLineMainStyle = { lineHeight : 1.45 , color : '#333' , wordBreak : 'break-all' } ;
var cellLineSubStyle = { lineHeight : 1.4 , fontSize : 12 , color : '#8c8c8c' , marginTop : 2 , wordBreak : 'break-all' } ;
var solidTagBaseStyle = { margin : 0 , border : 'none' , fontWeight : 600 , color : '#fff' , lineHeight : '20px' , flexShrink : 0 } ;
function renderCellLines ( mainText , subLines ) {
var subs = subLines || [ ] ;
return React . createElement ( 'div' , null ,
React . createElement ( 'div' , { style : cellLineMainStyle } , mainText || '—' ) ,
subs . map ( function ( line , i ) {
return React . createElement ( 'div' , { key : i , style : cellLineSubStyle } , line || '—' ) ;
} )
) ;
}
function displayBrandModel ( brand , model ) {
var b = brand && brand !== '—' ? String ( brand ) . trim ( ) : '' ;
var m = model && model !== '—' ? String ( model ) . trim ( ) : '' ;
if ( b && m ) return b + ' · ' + m ;
if ( b ) return b ;
if ( m ) return m ;
return '—' ;
}
function parseDateTimeParts ( raw ) {
if ( ! raw ) return { date : '—' , time : '—' } ;
var s = String ( raw ) . trim ( ) ;
if ( s . indexOf ( ' ' ) >= 0 ) {
var parts = s . split ( /\s+/ ) ;
var timePart = parts [ 1 ] || '—' ;
if ( timePart . length >= 8 ) timePart = timePart . slice ( 0 , 8 ) ;
else if ( timePart . length >= 5 ) timePart = timePart . slice ( 0 , 5 ) ;
return { date : parts [ 0 ] || '—' , time : timePart } ;
}
return { date : s . slice ( 0 , 10 ) , time : '—' } ;
}
function formatFlowTime ( timeStr ) {
if ( ! timeStr ) return '—' ;
@@ -419,20 +481,72 @@ const Component = function () {
} , React . createElement ( 'span' , { className : 'vr-approval-status-trigger' } , tag ) ) ;
}
function renderSolidTag ( text , bgColor ) {
if ( ! text || text === '—' ) return '—' ;
return React . createElement ( Tag , {
style : Object . assign ( { } , solidTagBaseStyle , { backgroundColor : bgColor || '#64748b' } )
} , text ) ;
}
function renderApprovalTag ( status ) {
var color = 'default ' ;
if ( status === '待审批' ) color = 'processing ' ;
else if ( status === '审批中' ) color = 'blue ' ;
else if ( status === '审批驳回' ) color = 'error ' ;
else if ( status === '未提交' ) color = 'default ' ;
else if ( status === '撤回' ) color = 'warning ' ;
else if ( status === '审批完成' ) color = 'success ' ;
return React . createElement ( Tag , { color : color , style : { margin : 0 , fontWeight : 500 } } , status || '—' ) ;
var bg = '#8c8c8c ' ;
if ( status === '待审批' ) bg = '#2563eb ' ;
else if ( status === '审批中' ) bg = '#1677ff ' ;
else if ( status === '审批驳回' ) bg = '#dc2626 ' ;
else if ( status === '未提交' ) bg = '#64748b ' ;
else if ( status === '撤回' ) bg = '#d97706 ' ;
else if ( status === '审批完成' ) bg = '#16a34a ' ;
return renderSolidTag ( status || '—' , bg );
}
function renderReplaceTypeTag ( type ) {
var color = type === '永久替换' ? 'geekblue' : type === '临时替换' ? 'gold' : 'default ' ;
return React . createElement ( Tag , { color : color , s tyl e: { margin : 0 } } , type || '—' ) ;
var bg = '#64748b ' ;
if ( typ e === '永久替换' ) bg = '#4f46e5' ;
else if ( type === '临时替换' ) bg = '#ea580c' ;
return renderSolidTag ( type || '—' , bg ) ;
}
function renderReplaceVehicleCell ( record ) {
return React . createElement ( 'div' , null ,
React . createElement ( 'div' , { style : Object . assign ( { } , cellLineMainStyle , { display : 'flex' , alignItems : 'center' , gap : 6 , flexWrap : 'wrap' } ) } ,
React . createElement ( 'span' , { style : { fontWeight : 600 } } , record . originalPlate || '—' ) ,
React . createElement ( 'span' , { style : { color : '#94a3b8' , fontWeight : 600 } } , '→' ) ,
React . createElement ( 'span' , { style : { fontWeight : 600 , color : '#165dff' } } , record . replacePlate || '—' )
) ,
React . createElement ( 'div' , { style : cellLineSubStyle } , displayBrandModel ( record . originalBrand , record . originalModel ) ) ,
React . createElement ( 'div' , { style : cellLineSubStyle } , displayBrandModel ( record . replaceBrand , record . replaceModel ) )
) ;
}
function renderProjectInfoCell ( record ) {
return React . createElement ( 'div' , { style : { minWidth : 0 } } ,
React . createElement ( 'div' , { style : { display : 'flex' , alignItems : 'center' , gap : 6 , flexWrap : 'wrap' , minWidth : 0 } } ,
React . createElement ( 'span' , {
style : { flex : '1 1 auto' , minWidth : 0 , overflow : 'hidden' , textOverflow : 'ellipsis' , whiteSpace : 'nowrap' , color : '#333' , fontWeight : 600 }
} , record . projectName || '—' ) ,
renderReplaceTypeTag ( record . replaceType )
) ,
React . createElement ( 'div' , { style : cellLineSubStyle } , record . replaceReason || '—' )
) ;
}
function renderApprovalInfoCell ( status , record ) {
var tag = renderApprovalStatusCell ( status , record ) ;
var approver = record . currentApprover && record . currentApprover !== '—' ? record . currentApprover : '—' ;
return React . createElement ( 'div' , null ,
React . createElement ( 'div' , null , tag ) ,
React . createElement ( 'div' , { style : cellLineSubStyle } , '当前审批人:' + approver )
) ;
}
function renderReplaceDateCell ( record ) {
var parsed = parseDateTimeParts ( record . replaceDate ) ;
return renderCellLines ( parsed . date , [ parsed . time ] ) ;
}
function renderCreateInfoCell ( record ) {
var parsed = parseDateTimeParts ( record . createTime ) ;
return renderCellLines ( record . creator || '—' , [ parsed . date + ( parsed . time !== '—' ? ' ' + parsed . time : '' ) ] ) ;
}
function getOperationButtons ( record , isHistory ) {
@@ -468,50 +582,55 @@ const Component = function () {
}
var tableColumns = [
{ title : '替换日期' , dataIndex : 'replaceDate' , key : 'replaceDate' , width : 168 , fixed : 'left' } ,
{
title : '替换车辆' ,
key : 'replaceVehicle' ,
width : 196 ,
fixed : 'left' ,
render : function ( _ , record ) { return renderReplaceVehicleCell ( record ) ; }
} ,
{
title : '项目信息' ,
key : 'projectInfo' ,
width : 220 ,
render : function ( _ , record ) { return renderProjectInfoCell ( record ) ; }
} ,
{
title : '替换日期' ,
key : 'replaceDate' ,
width : 118 ,
render : function ( _ , record ) { return renderReplaceDateCell ( record ) ; }
} ,
{
title : '审批状态' ,
dataIndex : 'approvalStatus' ,
key : 'approvalStatus' ,
width : 108 ,
render : function ( v , record ) { return renderApprovalStatus Cell ( v , record ) ; }
width : 132 ,
render : function ( v , record ) { return renderApprovalInfo Cell ( v , record ) ; }
} ,
{
title : '当前审批人' ,
dataIndex : 'currentApprover' ,
key : 'currentApprover' ,
width : 110 ,
render : function ( v ) {
return React . createElement ( 'span' , { style : { color : v && v !== '—' ? '#334155' : '#94a3b8' } } , v || '—' ) ;
}
} ,
{ title : '被替换车(旧车)' , dataIndex : 'originalPlate' , key : 'originalPlate' , width : 130 } ,
{ title : '品牌' , dataIndex : 'originalBrand' , key : 'originalBrand' , width : 88 } ,
{ title : '型号' , dataIndex : 'originalModel' , key : 'originalModel' , width : 100 } ,
{ title : '新车' , dataIndex : 'replacePlate' , key : 'replacePlate' , width : 110 } ,
{ title : '品牌' , dataIndex : 'replaceBrand' , key : 'replaceBrandNew' , width : 88 } ,
{ title : '型号' , dataIndex : 'replaceModel' , key : 'replaceModelNew' , width : 100 } ,
{
title : '替换类型' ,
dataIndex : 'replaceType' ,
key : 'replaceType' ,
width : 108 ,
render : function ( v ) { return renderReplaceTypeTag ( v ) ; }
} ,
{ title : '替换原因' , dataIndex : 'replaceReason' , key : 'replaceReason' , width : 100 } ,
{
title : '替换原因说明' ,
dataIndex : 'replaceReasonDesc' ,
key : 'replaceReasonDesc' ,
width : 14 0 ,
width : 16 0 ,
ellipsis : true ,
render : function ( v ) {
return React . createElement ( 'span' , { className : 'vr-reason-text ', tit le: v || '' } , v || '—' ) ;
return React . createElement ( 'span' , { title : v || ' ', sty le: { color : '#475569' } } , v || '—' ) ;
}
} ,
{ title : '创建人' , dataIndex : 'creator' , key : 'creator' , width : 90 } ,
{ title : '创建时间' , dataIndex : 'createTime' , key : 'createTime' , width : 168 } ,
{ title : '操作' , key : 'action' , width : 200 , fixed : 'right' , render : function ( _ , record ) { return getOperationButtons ( record , _activeTab [ 0 ] === 'history' ) ; } }
{
title : '创建信息' ,
key : 'createInfo' ,
width : 148 ,
render : function ( _ , record ) { return renderCreateInfoCell ( record ) ; }
} ,
{
title : '操作' ,
key : 'action' ,
width : 168 ,
fixed : 'right' ,
render : function ( _ , record ) { return getOperationButtons ( record , kpiFilter === 'history' ) ; }
}
] ;
var filterItems = [
@@ -544,63 +663,105 @@ const Component = function () {
React . createElement ( RangePicker , { style : filterControlStyle , placeholder : [ '请选择开始时间' , '请选择结束时间' ] , value : _createTimeRange [ 0 ] , onChange : function ( v ) { _createTimeRange [ 1 ] ( v ) ; } } ) )
] ;
var filterCount = _filterExpanded [ 0 ] ? 9 : 3 ;
var filterCount = _filterExpanded [ 0 ] ? 9 : 4 ;
var filterNodes = [ ] ;
for ( var i = 0 ; i < filterCount && i < filterItems . length ; i ++ ) {
filterNodes . push ( filterItems [ i ] ) ;
}
var _page = useState ( 1 ) ;
var _pageSize = useState ( 10 ) ;
var page = _page [ 0 ] ;
var setPage = _page [ 1 ] ;
var pageSize = _pageSize [ 0 ] ;
var setPageSize = _pageSize [ 1 ] ;
var currentList = _activeTab [ 0 ] === 'ongoing' ? filteredOngoing : filteredHistory ;
var displayList = useMemo ( function ( ) {
var start = ( page - 1 ) * pageSize ;
return currentList . slice ( start , start + pageSize ) ;
} , [ currentList , page , pageSize ] ) ;
var listStats = useMemo ( function ( ) {
return {
ongoing : filteredOngoing . length ,
history : filteredHistory . length ,
selected : ( _selectedRowKeys [ 0 ] || [ ] ) . length
} ;
} , [ filteredOngoing . length , filteredHistory . length , _selectedRowKeys [ 0 ] ] ) ;
var kpiExportLabelMap = { total : '全部替换车' , ongoing : '进行中的替换车' , history : '历史替换车' } ;
var rowSelection = {
selectedRowKeys : _selectedRowKeys [ 0 ] ,
onChange : function ( keys ) { _selectedRowKeys [ 1 ] ( keys ) ; } ,
fixed : true
} ;
var handleKpiCardClick = useCallback ( function ( key ) {
_kpiFilter [ 1 ] ( key ) ;
setPage ( 1 ) ;
} , [ ] ) ;
var handleListPlateQuickChange = useCallback ( function ( v ) {
_listPlateQuick [ 1 ] ( v ) ;
setPage ( 1 ) ;
} , [ ] ) ;
var handleExport = useCallback ( function ( ) {
if ( ! currentList . length ) {
message . warning ( '当前「' + ( kpiExportLabelMap [ kpiFilter ] || '替换车' ) + '」无数据可导出' ) ;
return ;
}
message . success ( '已导出 ' + currentList . length + ' 条(' + ( kpiExportLabelMap [ kpiFilter ] || '替换车' ) + ',原型)' ) ;
} , [ currentList . length , kpiFilter ] ) ;
var kpiCards = useMemo ( function ( ) {
return [
{ key : 'total' , type : 'total' , title : '全部替换车' , desc : '当前筛选条件下的全部替换车记录(含进行中与历史)' , val : kpiStats . total , icon : VR _KPI _ICONS . total } ,
{ key : 'ongoing' , type : 'progress' , title : '进行中的替换车' , desc : '审批状态为待审批、审批中、审批驳回、未提交、撤回的记录' , val : kpiStats . ongoing , icon : VR _KPI _ICONS . progress } ,
{ key : 'history' , type : 'completed' , title : '历史替换车' , desc : '审批流程已结束、状态为审批完成的记录' , val : kpiStats . history , icon : VR _KPI _ICONS . completed }
] ;
} , [ kpiStats ] ) ;
function renderKpiCard ( card ) {
var active = kpiFilter === card . key ;
return React . createElement ( 'div' , {
key : card . key ,
role : 'button' ,
tabIndex : 0 ,
className : 'lc-alert-card lc-alert-card--' + card . type + ' lc-alert-card-clickable' + ( active ? ' lc-alert-card-active' : '' ) ,
onClick : function ( ) { handleKpiCardClick ( card . key ) ; } ,
onKeyDown : function ( e ) {
if ( e . key === 'Enter' || e . key === ' ' ) {
e . preventDefault ( ) ;
handleKpiCardClick ( card . key ) ;
}
}
} ,
React . createElement ( 'div' , { className : 'lc-alert-card-tip-anchor' } ,
React . createElement ( Tooltip , { title : card . desc , placement : 'topRight' , overlayStyle : { maxWidth : 360 } } ,
React . createElement ( 'span' , {
className : 'lc-alert-card-tip' ,
role : 'img' ,
'aria-label' : card . title + '说明' ,
onClick : function ( e ) { e . stopPropagation ( ) ; } ,
onMouseDown : function ( e ) { e . stopPropagation ( ) ; }
} , VR _KPI _TIP _SVG )
)
) ,
React . createElement ( 'div' , { className : 'lc-alert-card-icon' } , card . icon ) ,
React . createElement ( 'div' , { className : 'lc-alert-card-main' } ,
React . createElement ( 'div' , { className : 'lc-alert-card-val' } , card . val ) ,
React . createElement ( 'div' , { className : 'lc-alert-card-title' } , card . title )
)
) ;
}
var tablePagination = {
current : page ,
pageSize : pageSize ,
total : currentList . length ,
showSizeChanger : true ,
showQuickJumper : true ,
showTotal : function ( t ) { return '共 ' + t + ' 条' ; } ,
pageSizeOptions : [ '10' , '20' , '50' ] ,
onChange : function ( p , ps ) { setPage ( p ) ; if ( ps ) setPageSize ( ps ) ; }
} ;
function renderTableBody ( ) {
if ( displayList . length === 0 ) {
return React . createElement ( Empty , {
className : 'vr-empty' ,
image : Empty . PRESENTED _IMAGE _SIMPLE ,
description : '暂无符合条件的替换车记录,请调整筛选条件后重试'
} ) ;
}
return React . createElement ( Table , {
rowKey : 'id' ,
rowSelection : rowSelection ,
columns : tableColumns ,
dataSource : displayList ,
size : 'small ' ,
scroll : { x : 1900 } ,
size : 'middle ' ,
tableLayout : 'fixed' ,
scroll : { x : 1180 } ,
pagination : tablePagination
} ) ;
}
@@ -614,7 +775,7 @@ const Component = function () {
筛选与列表分为2个卡片;
2.筛选:
支持通过替换日期、替换类型、项目名称、审批状态、被替换车车牌号、替换车车牌号、替换原因、创建人、创建时间进行筛选,右侧为重置、查询 、展开/收起(筛选条件以3 列显示,默认显示一行,点击展开/收起对筛选栏卡片 进行展开/收起所有筛选条件),点击查询 后,筛选条件与列表内容 联动。点击重置会回到默认筛选条件并在列表展示结果:
支持通过替换日期、替换类型、项目名称、审批状态、被替换车车牌号、替换车车牌号、替换原因、创建人、创建时间进行筛选,右侧为重置、搜索 、展开/收起(筛选条件以4 列显示,默认显示一行,点击展开/收起对筛选栏进行展开/收起所有筛选条件),点击搜索 后,筛选条件与列表及 KPI 统计 联动。点击重置会回到默认筛选条件并在列表展示结果:
2.1.替换日期:日期选择器,支持单输入框内双日历选择开始-结束时间,默认提示文本为:请选择开始时间、请选择结束时间;
2.2.替换类型:选择器,分为永久替换、临时替换两种方式;
@@ -626,10 +787,10 @@ const Component = function () {
2.8.创建人:选择器,下拉选择所有创建人;
2.9.创建时间:日期选择器,支持单输入框内双日历选择开始-结束时间,默认提示文本为:请选择开始时间、请选择结束时间;
3.列表:列表右上角为新增、导出,首列为多选,支持多选后导出对应条目 ;
列表展示所有替换车记录, 分为进行中、历史记录两个tab, 字段依次为: 替换日期、审批状态、当前审批人、被替换车( 旧车) 、品牌、型号、新车、品牌、型号、替换类型、替换原因 、替换原因说明、创建人、创建时间 、操作;
3.列表:顶部为 KPI 统计卡片(全部替换车 / 进行中的替换车 / 历史替换车),点击切换列表范围;工具栏左侧为车牌号快捷筛选,右侧为新增、导出(导出与当前 KPI 标签及筛选结果一致) ;
列表字段合并展示:替换车辆、项目信息、替换日期、审批状态 、替换原因说明、创建信息 、操作;
3.1.进行中:显示替换车申请流程未结束、暂存的记录;
3.1.进行中的替换车 :显示替换车申请流程未结束、暂存的记录;
3.1.1.替换日期: 显示格式为: YYYY-MM-DD HH:MM:SS;
3.1.2.审批状态:分为待审批、审批中、审批驳回、未提交、撤回;
3.1.3.当前审批人:显示当前待审批节点审批人,未提交/撤回等为「—」;
@@ -642,7 +803,7 @@ const Component = function () {
3.1.7.3.撤回:审批状态为审批中时显示,二次确认;
3.1.7.4.删除:审批状态为撤回/审批驳回时显示,逻辑删除,二次确认;
3.2.历史记录 :显示替换车申请流程已结束的记录;
3.2.历史替换车 :显示替换车申请流程已结束的记录;
3.2.1.替换日期: 显示格式为: YYYY-MM-DD, 显示替换车申请表单中设置的替换日期;
3.2.2.替换类型:分为:临时替换、永久替换两种,根据替换车申请表单中设置的替换类型显示;
3.2.3.项目名称:显示替换车申请表单中设置的项目名称;
@@ -663,13 +824,10 @@ const Component = function () {
列表右下方为分页符。 ` ;
var activeTab = _activeTab [ 0 ] ;
var selectedCount = ( _selectedRowKeys [ 0 ] || [ ] ) . length ;
return React . createElement ( App , null ,
React . createElement ( 'div' , { className : 'vr-list-page' , style : { minHeight : '100vh' , padding : '20px 24px 32px' , background : 'linear-gradient(180deg,#f8fafc 0%,#f1f5f9 100%)' } } ,
React . createElement ( 'style' , null , pageStyles ) ,
React . createElement ( 'div' , { className : 'vr- pag e-header' } ,
React . createElement ( 'div' , { style : styles . page } ,
React . createElement ( 'style' , null , VR _KPI _STYLE + pageStyles) ,
React . createElement ( 'div' , { style : { display : 'flex' , justifyContent : 's pac e-between' , alignItems : 'center' , marginBottom : 16 } } ,
React . createElement ( Breadcrumb , {
items : [
{ title : '运维管理' } ,
@@ -677,36 +835,64 @@ const Component = function () {
{ title : '替换车管理' }
]
} ) ,
React . createElement ( Button , { type : 'link' , style : { padding : 0 , color : '#2563eb' , fontWeight : 500 } , onClick : function ( ) { _requirementModalVisible [ 1 ] ( true ) ; } } , '查看需求说明' )
React . createElement ( Button , { type : 'link' , onClick : function ( ) { _requirementModalVisible [ 1 ] ( true ) ; } } , '查看需求说明' )
) ,
React . createElement ( Card , { className : 'vr-filter-card' , title : '筛选条件' } ,
React . createElement ( 'div' , { className : 'vr-filter-grid' } , filterNodes ) ,
React . createElement ( 'div' , { className : 'vr-filter-actions' } ,
React . createElement ( Button , { onClick : handleReset } , '重置' ) ,
React . createElement ( Button , { type : 'primary' , onClick: handleQuery } , '查询 ' ) ,
React . createElement ( Button , { type : 'link' , size : 'small' , onClick : function ( ) { _filterExpanded [ 1 ] ( ! _filterExpanded [ 0 ] ) ; } } , _filterExpanded [ 0 ] ? '收起' : '展开 ' )
React . createElement ( Card , { style : { marginBottom : 16 } } ,
React . createElement ( 'div' , { style : styles . cardBody } ,
React . createElement ( 'div' , { className : 'vr-list- filter-grid' , style : styles . filterGrid } , filterNodes ) ,
React . createElement ( 'div' , { style : styles . filterActions } ,
React . createElement ( Button , { onClick : handleReset } , '重置 ' ) ,
React . createElement ( Button , { type : 'primary' , onClick : handleQuery } , '搜索 ' ) ,
React . createElement ( Button , {
type : 'link' ,
size : 'small' ,
onClick : function ( ) { _filterExpanded [ 1 ] ( ! _filterExpanded [ 0 ] ) ; } ,
style : { display : 'inline-flex' , alignItems : 'center' , gap : 4 , padding : '0 4px' }
} ,
_filterExpanded [ 0 ] ? '收起' : '展开' ,
React . createElement ( 'svg' , {
width : 12 ,
height : 12 ,
viewBox : '0 0 24 24' ,
fill : 'none' ,
stroke : 'currentColor' ,
strokeWidth : 2 ,
strokeLinecap : 'round' ,
strokeLinejoin : 'round' ,
style : { transform : _filterExpanded [ 0 ] ? 'rotate(180deg)' : 'none' , transition : 'transform 0.2s ease' }
} , React . createElement ( 'polyline' , { points : '6 9 12 15 18 9' } ) )
)
)
)
) ,
React . createElement ( Card , { className : 'vr-list-card' , title : '替换车列表' } ,
React . createElement ( 'div' , { className : 'vr-list-table' } ,
React . createElement ( Tabs , {
className : 'vr-tabs' ,
activeKey : activeTab ,
onChange : function ( k ) { _activeTab [ 1 ] ( k ) ; _selectedRowKeys [ 1 ] ( [ ] ) ; setPage ( 1 ) ; } ,
tabBarExtraContent : React . createElement ( 'div' , { style : { display : 'flex' , gap : 8 , alignItems : 'center' , flexWrap : 'wrap' } } ,
React . createElement ( Button , { type : 'primary' , onClick : function ( ) { message . info ( '新增替换车申请(原型)' ) ; } } , '新增' ) ,
selectedCount > 0
? React . createElement ( Badge , { count : selectedCount , size : 'small' , offset : [ - 4 , 4 ] } ,
React . createElement ( Button , { onClick : function ( ) { message . info ( '导出选中 ' + selectedCount + ' 条(原型)' ) ; } } , '导出' )
)
: React . createElement ( Button , { onClick : function ( ) { message . info ( '请先勾选需要导出的记录' ) ; } } , '导出' )
React . createElement ( Card , null ,
React . createElement ( 'div' , { style : styles . cardBody } ,
React . createElement ( 'div' , { className : 'vr-kpi-stats-row' } , kpiCards . map ( renderKpiCard ) ) ,
React . createElement ( 'div' , { style : { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : 12 , flexWrap : 'wrap' , gap : 12 } } ,
Re act. createElement ( 'div' , { style : { display : 'flex' , alignItems : 'center' , gap : 8 , minWidth : 0 , flexWrap : 'wrap' } } ,
React . createElement ( 'span' , { style : { color : '#333' , fontSize : 14 , whiteSpace : 'nowrap' } } , '车牌号' ) ,
React . createElement ( Select , {
placeholder : '请输入或选择车牌号' ,
allowClear : true ,
showSearch : true ,
style : { width : 220 } ,
value : listPlateQuick ,
onChange : handleListPlateQuickChange ,
options : plateOptions ,
filterOption : function ( input , opt ) { return ( opt . label || '' ) . toString ( ) . toLowerCase ( ) . indexOf ( ( input || '' ) . toLowerCase ( ) ) !== - 1 ; }
} )
) ,
destroyInactiveTabPane : true ,
items : [
{ key : 'ongoing' , label : '进行中 (' + listStats . ongoing + ')' , children : activeTab === 'ongoing' ? renderTableBody ( ) : null } ,
{ key : 'history' , label : '历史记录 (' + listStats . history + ')' , children : activeTab === 'history' ? renderTableBody ( ) : null }
]
} )
React . createElement ( 'div' , { style : { display : 'flex' , alignItems : 'center' , gap : 8 , flexWrap : 'wrap' , marginLeft : 'auto' } } ,
React . createElement ( 'span' , { style : { fontSize : 13 , color : '#64748b' } } ,
'当前标签:' ,
React . createElement ( 'span' , { style : { color : '#334155' , fontWeight : 600 } } , kpiExportLabelMap [ kpiFilter ] || '—' ) ,
' · 导出与列表一致'
) ,
React . createElement ( Button , { type : 'primary' , onClick : function ( ) { message . info ( '新增替换车申请(原型)' ) ; } } , '新增' ) ,
React . createElement ( Button , { onClick : handleExport } , '导出' )
)
) ,
renderTableBody ( )
)
) ,
React . createElement ( Modal , {
@@ -736,7 +922,6 @@ const Component = function () {
if ( prev . indexOf ( rec . id ) !== - 1 ) return prev ;
return prev . concat ( rec . id ) ;
} ) ;
_selectedRowKeys [ 1 ] ( function ( prev ) { return prev . filter ( function ( k ) { return k !== rec . id ; } ) ; } ) ;
}
message . success ( '已逻辑删除(原型)' ) ;
_deleteModalVisible [ 1 ] ( false ) ;