feat: sync full workspace including web modules, docs, and configurations to Gitea
Optimized the root .gitignore to exclude virtual environments, node modules, and temp folders to ensure clean and lightweight version tracking. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
BIN
web端/运维管理/.DS_Store
vendored
BIN
web端/运维管理/.DS_Store
vendored
Binary file not shown.
@@ -161,7 +161,7 @@ const loadOperateDraftsForDisplay = () => {
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
return merged;
|
||||
return merged;
|
||||
};
|
||||
|
||||
const DEFAULT_FILTER = {
|
||||
@@ -1094,7 +1094,7 @@ const Component = function AnnualReviewWebList() {
|
||||
<a className="action-link" onClick={() => goHandlePage(row)} role="button" tabIndex={0}>
|
||||
办理
|
||||
</a>
|
||||
),
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ const Component = function () {
|
||||
id: 'pair_' + pairIdRef.current,
|
||||
replaceType: undefined,
|
||||
replaceReason: undefined,
|
||||
replaceFee: '',
|
||||
replaceReasonDesc: '',
|
||||
originalPlate: undefined,
|
||||
originalVin: '',
|
||||
@@ -289,10 +290,12 @@ const Component = function () {
|
||||
return;
|
||||
}
|
||||
var incomplete = pairs.find(function (p) {
|
||||
return !p.originalPlate || !p.replacePlate || !p.replaceType || !p.replaceReason;
|
||||
if (!p.originalPlate || !p.replacePlate || !p.replaceType || !p.replaceReason) return true;
|
||||
if (p.replaceReason === '客户原因' && !(p.replaceFee || '').toString().trim()) return true;
|
||||
return false;
|
||||
});
|
||||
if (incomplete) {
|
||||
message.warning('请完善每条替换的新车、替换类型与替换原因');
|
||||
message.warning('请完善每条替换的新车、替换类型、替换原因及客户原因下的替换费用');
|
||||
return;
|
||||
}
|
||||
message.success('已提交 ' + pairs.length + ' 条替换车申请(原型)');
|
||||
@@ -584,7 +587,12 @@ const Component = function () {
|
||||
placeholder: '请选择',
|
||||
style: { width: '100%' },
|
||||
value: pair.replaceReason,
|
||||
onChange: function (v) { updatePair(pair.id, { replaceReason: v }); },
|
||||
onChange: function (v) {
|
||||
updatePair(pair.id, {
|
||||
replaceReason: v,
|
||||
replaceFee: v === '客户原因' ? pair.replaceFee : ''
|
||||
});
|
||||
},
|
||||
allowClear: true,
|
||||
options: [
|
||||
{ value: '客户原因', label: '客户原因' },
|
||||
@@ -592,6 +600,24 @@ const Component = function () {
|
||||
]
|
||||
})
|
||||
),
|
||||
pair.replaceReason === '客户原因'
|
||||
? renderField(
|
||||
'替换费用',
|
||||
true,
|
||||
React.createElement(Input, {
|
||||
placeholder: '请输入替换费用',
|
||||
style: { width: '100%' },
|
||||
value: pair.replaceFee || '',
|
||||
addonBefore: '¥',
|
||||
onChange: function (e) {
|
||||
var val = e.target.value.replace(/[^\d.]/g, '');
|
||||
var parts = val.split('.');
|
||||
if (parts.length > 2) val = parts[0] + '.' + parts.slice(1).join('');
|
||||
updatePair(pair.id, { replaceFee: val });
|
||||
}
|
||||
})
|
||||
)
|
||||
: null,
|
||||
renderField(
|
||||
'替换原因说明',
|
||||
false,
|
||||
|
||||
@@ -54,6 +54,7 @@ const Component = function () {
|
||||
id: 'pair_2',
|
||||
replaceType: '临时替换',
|
||||
replaceReason: '客户原因',
|
||||
replaceFee: '500.00',
|
||||
replaceReasonDesc: '',
|
||||
originalPlate: '浙A55555',
|
||||
originalBrand: '重汽',
|
||||
@@ -163,7 +164,7 @@ const Component = function () {
|
||||
React.createElement('div', { className: 'vr-req-doc__meta' }, '数字化资产 ONEOS 运管平台 · 运维管理 · 车辆业务 · 替换车管理 · 查看'),
|
||||
specSection('1. 页面定位', ['只读查看替换车申请详情,布局与新增/编辑一致,不可修改任何字段。']),
|
||||
specSection('2. 展示内容', [
|
||||
'2.1 车辆替换明细:每条被替换车一张卡片,含被替换车信息、替换说明、替换车辆;卡片标题展示被替换与替换车牌。',
|
||||
'2.1 车辆替换明细:每条被替换车一张卡片,含被替换车信息、替换说明、替换车辆;卡片标题展示被替换与替换车牌;替换原因为「客户原因」时展示替换费用(只读)。',
|
||||
'2.2 项目信息:客户名称、项目名称、项目类型(全单一份)。',
|
||||
'2.3 审批情况:竖向步骤条展示审批节点、审批人、审批时间。'
|
||||
]),
|
||||
@@ -220,6 +221,15 @@ const Component = function () {
|
||||
{ className: 'vr-form-grid vr-form-grid--reason' },
|
||||
renderField('替换类型', React.createElement(Input, { value: pair.replaceType, disabled: true })),
|
||||
renderField('替换原因', React.createElement(Input, { value: pair.replaceReason, disabled: true })),
|
||||
pair.replaceReason === '客户原因'
|
||||
? renderField(
|
||||
'替换费用',
|
||||
React.createElement(Input, {
|
||||
value: pair.replaceFee ? '¥' + pair.replaceFee : '—',
|
||||
disabled: true
|
||||
})
|
||||
)
|
||||
: null,
|
||||
renderField(
|
||||
'替换原因说明',
|
||||
React.createElement(Input.TextArea, {
|
||||
@@ -302,7 +312,11 @@ const Component = function () {
|
||||
{ title: '查看' }
|
||||
]
|
||||
}),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalVisible(true); } }, '查看需求说明')
|
||||
React.createElement(
|
||||
Button,
|
||||
{ type: 'link', style: { padding: 0, flexShrink: 0 }, onClick: function () { setRequirementModalVisible(true); } },
|
||||
'查看需求说明'
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
Card,
|
||||
|
||||
@@ -41,6 +41,7 @@ const Component = function () {
|
||||
id: 'pair_2',
|
||||
replaceType: '临时替换',
|
||||
replaceReason: '客户原因',
|
||||
replaceFee: '500.00',
|
||||
replaceReasonDesc: '',
|
||||
originalPlate: '浙A55555',
|
||||
originalVin: 'LGHXCAE28M5555555',
|
||||
@@ -61,6 +62,7 @@ const Component = function () {
|
||||
id: 'pair_' + pairIdRef.current,
|
||||
replaceType: undefined,
|
||||
replaceReason: undefined,
|
||||
replaceFee: '',
|
||||
replaceReasonDesc: '',
|
||||
originalPlate: undefined,
|
||||
originalVin: '',
|
||||
@@ -324,10 +326,12 @@ const Component = function () {
|
||||
return;
|
||||
}
|
||||
var incomplete = pairs.find(function (p) {
|
||||
return !p.originalPlate || !p.replacePlate || !p.replaceType || !p.replaceReason;
|
||||
if (!p.originalPlate || !p.replacePlate || !p.replaceType || !p.replaceReason) return true;
|
||||
if (p.replaceReason === '客户原因' && !(p.replaceFee || '').toString().trim()) return true;
|
||||
return false;
|
||||
});
|
||||
if (incomplete) {
|
||||
message.warning('请完善每条替换的新车、替换类型与替换原因');
|
||||
message.warning('请完善每条替换的新车、替换类型、替换原因及客户原因下的替换费用');
|
||||
return;
|
||||
}
|
||||
message.success('已提交 ' + pairs.length + ' 条替换车申请(原型)');
|
||||
@@ -455,7 +459,7 @@ const Component = function () {
|
||||
'4.2 被替换车辆信息(只读):车牌号、品牌、型号;品牌/型号占位「选择车辆后自动显示」。',
|
||||
'4.3 替换说明',
|
||||
' 4.3.1 替换类型:必填,单选——永久替换、临时替换。',
|
||||
' 4.3.2 替换原因:必填,单选——客户原因、车辆原因。',
|
||||
' 4.3.2 替换原因:必填,单选——客户原因、车辆原因;选「客户原因」时右侧展示「替换费用」必填输入框(¥ 前缀,仅数字与小数点)。',
|
||||
' 4.3.3 替换原因说明:选填,多行文本,最多 500 字,占位「请说明替换原因」,显示字数统计。',
|
||||
'4.4 替换车辆',
|
||||
' 4.4.1 新车:必填,单选下拉,支持搜索;未选被替换车时禁用,占位「请先选择被替换车辆」。',
|
||||
@@ -487,7 +491,7 @@ const Component = function () {
|
||||
]),
|
||||
specSection('9. 校验与提示汇总', [
|
||||
'请选择被替换车辆并完善替换信息',
|
||||
'请完善每条替换的新车、替换类型与替换原因',
|
||||
'请完善每条替换的新车、替换类型、替换原因及客户原因下的替换费用',
|
||||
'多台替换须为同一客户、同一项目,已忽略不同项目的车辆',
|
||||
'该新车已在其他替换项中选择',
|
||||
'请先选择被替换车辆'
|
||||
@@ -623,7 +627,12 @@ const Component = function () {
|
||||
placeholder: '请选择',
|
||||
style: { width: '100%' },
|
||||
value: pair.replaceReason,
|
||||
onChange: function (v) { updatePair(pair.id, { replaceReason: v }); },
|
||||
onChange: function (v) {
|
||||
updatePair(pair.id, {
|
||||
replaceReason: v,
|
||||
replaceFee: v === '客户原因' ? pair.replaceFee : ''
|
||||
});
|
||||
},
|
||||
allowClear: true,
|
||||
options: [
|
||||
{ value: '客户原因', label: '客户原因' },
|
||||
@@ -631,6 +640,24 @@ const Component = function () {
|
||||
]
|
||||
})
|
||||
),
|
||||
pair.replaceReason === '客户原因'
|
||||
? renderField(
|
||||
'替换费用',
|
||||
true,
|
||||
React.createElement(Input, {
|
||||
placeholder: '请输入替换费用',
|
||||
style: { width: '100%' },
|
||||
value: pair.replaceFee || '',
|
||||
addonBefore: '¥',
|
||||
onChange: function (e) {
|
||||
var val = e.target.value.replace(/[^\d.]/g, '');
|
||||
var parts = val.split('.');
|
||||
if (parts.length > 2) val = parts[0] + '.' + parts.slice(1).join('');
|
||||
updatePair(pair.id, { replaceFee: val });
|
||||
}
|
||||
})
|
||||
)
|
||||
: null,
|
||||
renderField(
|
||||
'替换原因说明',
|
||||
false,
|
||||
|
||||
@@ -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 (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;
|
||||
var approval = appliedFilter.approvalStatus;
|
||||
if (approval && approval.length > 0 && approval.indexOf('全部') === -1 && approval.indexOf(r.approvalStatus) === -1) 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;
|
||||
});
|
||||
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 = filter.replaceDateRange[0] && filter.replaceDateRange[0].format ? filter.replaceDateRange[0].format('YYYY-MM-DD') : '';
|
||||
var end = filter.replaceDateRange[1] && filter.replaceDateRange[1].format ? filter.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 (filter.replaceType && r.replaceType !== filter.replaceType) return false;
|
||||
if (filter.projectName && r.projectName !== filter.projectName) return false;
|
||||
var approval = filter.approvalStatus;
|
||||
if (approval && approval.length > 0 && approval.indexOf('全部') === -1 && approval.indexOf(r.approvalStatus) === -1) return false;
|
||||
if (filter.originalPlate && (r.originalPlate || '').indexOf(filter.originalPlate) === -1) return false;
|
||||
if (filter.replacePlate && (r.replacePlate || '').indexOf(filter.replacePlate) === -1) return false;
|
||||
if (filter.replaceReason && filter.replaceReason !== '全部' && r.replaceReason !== filter.replaceReason) return false;
|
||||
if (filter.creator && r.creator !== filter.creator) return false;
|
||||
if (filter.createTimeRange && filter.createTimeRange.length === 2) {
|
||||
var cs = filter.createTimeRange[0] && filter.createTimeRange[0].format ? filter.createTimeRange[0].format('YYYY-MM-DD') : '';
|
||||
var ce = filter.createTimeRange[1] && filter.createTimeRange[1].format ? filter.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 = historyList.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 = ongoingList.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: 14 };
|
||||
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, style: { margin: 0 } }, type || '—');
|
||||
var bg = '#64748b';
|
||||
if (type === '永久替换') 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 renderApprovalStatusCell(v, record); }
|
||||
width: 132,
|
||||
render: function (v, record) { return renderApprovalInfoCell(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: 140,
|
||||
width: 160,
|
||||
ellipsis: true,
|
||||
render: function (v) {
|
||||
return React.createElement('span', { className: 'vr-reason-text', title: v || '' }, v || '—');
|
||||
return React.createElement('span', { title: v || '', style: { 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-page-header' },
|
||||
React.createElement('div', { style: styles.page },
|
||||
React.createElement('style', null, VR_KPI_STYLE + pageStyles),
|
||||
React.createElement('div', { style: { display: 'flex', justifyContent: 'space-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 } },
|
||||
React.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);
|
||||
|
||||
Reference in New Issue
Block a user