feat(business-crud-page): 统一独立表单页顶部页面标题样式及展示

- 独立表单页 shipping-template、transport-plan、waybill-manage 加入统一的 archive-page-form__title 页面标题支持
- 全局样式抽离 archive-page-form__title 至 element-ui.scss,实现统一样式和竖条修饰
- loading-manage/form 页面新增页标题展示,保持风格一致
- master-order 编辑模式下新增页面标题支持,动态显示编辑或新增总单
- business-crud-page 组件新增 formPageTitle 属性,支持父级传递页面标题数据
- 优化多个业务页面表格和弹窗样式,调整列宽及边框圆角阴影,提高视觉一致性
- 删除 customer-archive.vue 中重复本地标题样式定义,使用全局统一样式
- 全站弹窗分组组件 section-card 相关设计规范文档更新,强化统一卡片风格
- 移除 cargo-type.vue 添加 "新建" 按钮逻辑,调整按钮显示权限
- 统一所有新增弹窗的底部操作区浮动效果及内容区最大高度限制,提升交互体验
This commit is contained in:
2026-08-21 11:07:32 +08:00
parent 10878d4aee
commit 21b7877ff1
19 changed files with 485 additions and 189 deletions
@@ -9,24 +9,44 @@
@update:model-value="$emit('update:modelValue', $event)"
>
<div v-loading="detailLoading" class="vehicle-ledger">
<section class="vehicle-ledger__overview">
<section-card class="vehicle-ledger__overview">
<div class="vehicle-ledger__title">
<span>{{ vehicleDetail.plateNo || vehicle.plateNo }}</span>
<el-tag :type="plateColorType">{{ vehicleDetail.plateColor || '-' }}</el-tag>
<el-tag type="primary">{{ vehicleDetail.businessRelation || '-' }}</el-tag>
</div>
<el-descriptions :column="4" border>
<el-descriptions-item label="所属组织">{{ vehicleDetail.organizationName || '-' }}</el-descriptions-item>
<el-descriptions-item label="车辆类型">{{ vehicleDetail.vehicleType || '-' }}</el-descriptions-item>
<el-descriptions-item label="能源类型">{{ vehicleDetail.energyType || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属组织">{{
vehicleDetail.organizationName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="车辆类型">{{
vehicleDetail.vehicleType || '-'
}}</el-descriptions-item>
<el-descriptions-item label="能源类型">{{
vehicleDetail.energyType || '-'
}}</el-descriptions-item>
<el-descriptions-item label="外廓尺寸(mm)">{{ dimensions }}</el-descriptions-item>
<el-descriptions-item label="核定载质量(KG)">{{ vehicleDetail.approvedLoadKg ?? '-' }}</el-descriptions-item>
<el-descriptions-item label="准牵引总质量(KG)">{{ vehicleDetail.tractionMassKg ?? '-' }}</el-descriptions-item>
<el-descriptions-item label="行驶证档案编号">{{ vehicleDetail.drivingLicenseNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="道路运输证号">{{ vehicleDetail.roadTransportCertNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="行驶证有效期">{{ vehicleDetail.drivingLicenseEndDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="道路运输证有效期">{{ vehicleDetail.roadTransportCertEndDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="道路运输证年审有效期">{{ vehicleDetail.annualReviewEndDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="核定载质量(KG)">{{
vehicleDetail.approvedLoadKg ?? '-'
}}</el-descriptions-item>
<el-descriptions-item label="准牵引总质量(KG)">{{
vehicleDetail.tractionMassKg ?? '-'
}}</el-descriptions-item>
<el-descriptions-item label="行驶证档案编号">{{
vehicleDetail.drivingLicenseNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="道路运输证号">{{
vehicleDetail.roadTransportCertNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="行驶证有效期">{{
vehicleDetail.drivingLicenseEndDate || '-'
}}</el-descriptions-item>
<el-descriptions-item label="道路运输证有效期">{{
vehicleDetail.roadTransportCertEndDate || '-'
}}</el-descriptions-item>
<el-descriptions-item label="道路运输证年审有效期">{{
vehicleDetail.annualReviewEndDate || '-'
}}</el-descriptions-item>
</el-descriptions>
<div class="vehicle-ledger__images">
<div v-for="item in imageFields" :key="item.prop" class="vehicle-ledger__image-item">
@@ -41,9 +61,9 @@
<el-empty v-else :image-size="36" description="暂无图片" />
</div>
</div>
</section>
</section-card>
<el-tabs v-model="activeTab" class="vehicle-ledger__tabs" @tab-change="loadRecords">
<el-tabs type="border-card" v-model="activeTab" class="vehicle-ledger__tabs" @tab-change="loadRecords">
<el-tab-pane v-for="tab in tabs" :key="tab.name" :label="tab.label" :name="tab.name" />
</el-tabs>
<el-table v-loading="tableLoading" :data="records" border stripe>
@@ -86,56 +106,316 @@ import { getList as getChangeList } from '@/api/vehicle/transport-change-record'
import { getList as getOilElectricList } from '@/api/vehicle/oil-electric-record';
import { getList as getEtcList } from '@/api/vehicle/etc-record';
import { getList as getOtherExpenseList } from '@/api/vehicle/other-expense-record';
import SectionCard from '@/components/section-card/main.vue';
const cols = (...items) => items.map(([label, prop, width]) => ({ label, prop, width }));
const tabConfigs = [
['insurance', '保险记录', getInsuranceList, cols(['车牌号', 'vehicleNo'], ['保险类型', 'insuranceType'], ['开始日期', 'startDate'], ['结束日期', 'endDate'], ['保费', 'premium'], ['保单号', 'policyNo'])],
['violation', '违章记录', getViolationList, cols(['车牌号', 'vehicleNo'], ['驾驶人', 'driverName'], ['类型', 'violationType'], ['事项', 'violationItem'], ['违章时间', 'violationTime'], ['罚款金额', 'fineAmount'])],
['maintenance', '维修记录', getMaintenanceList, cols(['车牌号', 'vehicleNo'], ['维修人', 'maintainer'], ['维修时间', 'maintenanceTime'], ['维修位置', 'location'], ['费用', 'cost'], ['维修单位', 'company'])],
['maintenancePlan', '保养记录', getMaintenancePlanList, cols(['车牌号', 'vehicleNo'], ['保养人', 'maintainer'], ['保养时间', 'maintenanceTime'], ['保养项目', 'maintenanceItem'], ['费用', 'cost'], ['下次保养时间', 'nextMaintenanceTime'])],
['tire', '换胎记录', getTireList, cols(['车牌号', 'vehicleNo'], ['更换时间', 'replacementTime'], ['轮胎品牌', 'tireBrand'], ['轮胎规格', 'tireSpec'], ['费用', 'cost'])],
['accident', '事故记录', getAccidentList, cols(['车牌号', 'vehicleNo'], ['事故时间', 'accidentTime'], ['事故地点', 'accidentLocation'], ['事故类型', 'accidentType'], ['损失金额', 'lossAmount'])],
['annualInspection', '年检记录', getAnnualInspectionList, cols(['车牌号', 'vehicleNo'], ['年检日期', 'inspectionDate'], ['年检有效期至', 'inspectionEndDate'], ['年检机构', 'inspectionOrganization'], ['费用', 'cost'])],
['mileage', '里程记录', getMileageList, cols(['车牌号', 'vehicleNo'], ['记录时间', 'recordTime'], ['里程数', 'mileage'], ['里程单位', 'mileageUnit'], ['备注', 'remark'])],
['change', '变更记录', getChangeList, cols(['车牌号', 'vehicleNo'], ['变更类型', 'changeType'], ['变更时间', 'changeTime'], ['变更前内容', 'beforeChange'], ['变更后内容', 'afterChange'])],
['equipment', '设备台账', null, cols(['设备编码', 'equipmentCode'], ['设备名称', 'equipmentName'], ['设备类型', 'equipmentType'], ['安装日期', 'installDate'], ['状态', 'status'])],
['oilElectric', '油电台账', getOilElectricList, cols(['车牌号', 'vehicleNo'], ['加油/充电日期', 'recordDate'], ['类型', 'energyType'], ['数量', 'quantity'], ['金额', 'amount'])],
['etc', 'ETC记录', getEtcList, cols(['车牌号', 'vehicleNo'], ['交易日期', 'transactionDate'], ['交易金额', 'amount'], ['交易地点', 'location'], ['ETC卡号', 'etcCardNo'])],
['otherExpense', '其他费用记录', getOtherExpenseList, cols(['车牌号', 'vehicleNo'], ['费用日期', 'expenseDate'], ['费用类型', 'expenseType'], ['金额', 'amount'], ['备注', 'remark'])],
[
'insurance',
'保险记录',
getInsuranceList,
cols(
['车牌号', 'vehicleNo'],
['保险类型', 'insuranceType'],
['开始日期', 'startDate'],
['结束日期', 'endDate'],
['保费', 'premium'],
['保单号', 'policyNo']
),
],
[
'violation',
'违章记录',
getViolationList,
cols(
['车牌号', 'vehicleNo'],
['驾驶人', 'driverName'],
['类型', 'violationType'],
['事项', 'violationItem'],
['违章时间', 'violationTime'],
['罚款金额', 'fineAmount']
),
],
[
'maintenance',
'维修记录',
getMaintenanceList,
cols(
['车牌号', 'vehicleNo'],
['维修人', 'maintainer'],
['维修时间', 'maintenanceTime'],
['维修位置', 'location'],
['费用', 'cost'],
['维修单位', 'company']
),
],
[
'maintenancePlan',
'保养记录',
getMaintenancePlanList,
cols(
['车牌号', 'vehicleNo'],
['保养人', 'maintainer'],
['保养时间', 'maintenanceTime'],
['保养项目', 'maintenanceItem'],
['费用', 'cost'],
['下次保养时间', 'nextMaintenanceTime']
),
],
[
'tire',
'换胎记录',
getTireList,
cols(
['车牌号', 'vehicleNo'],
['更换时间', 'replacementTime'],
['轮胎品牌', 'tireBrand'],
['轮胎规格', 'tireSpec'],
['费用', 'cost']
),
],
[
'accident',
'事故记录',
getAccidentList,
cols(
['车牌号', 'vehicleNo'],
['事故时间', 'accidentTime'],
['事故地点', 'accidentLocation'],
['事故类型', 'accidentType'],
['损失金额', 'lossAmount']
),
],
[
'annualInspection',
'年检记录',
getAnnualInspectionList,
cols(
['车牌号', 'vehicleNo'],
['年检日期', 'inspectionDate'],
['年检有效期至', 'inspectionEndDate'],
['年检机构', 'inspectionOrganization'],
['费用', 'cost']
),
],
[
'mileage',
'里程记录',
getMileageList,
cols(
['车牌号', 'vehicleNo'],
['记录时间', 'recordTime'],
['里程数', 'mileage'],
['里程单位', 'mileageUnit'],
['备注', 'remark']
),
],
[
'change',
'变更记录',
getChangeList,
cols(
['车牌号', 'vehicleNo'],
['变更类型', 'changeType'],
['变更时间', 'changeTime'],
['变更前内容', 'beforeChange'],
['变更后内容', 'afterChange']
),
],
[
'equipment',
'设备台账',
null,
cols(
['设备编码', 'equipmentCode'],
['设备名称', 'equipmentName'],
['设备类型', 'equipmentType'],
['安装日期', 'installDate'],
['状态', 'status']
),
],
[
'oilElectric',
'油电台账',
getOilElectricList,
cols(
['车牌号', 'vehicleNo'],
['加油/充电日期', 'recordDate'],
['类型', 'energyType'],
['数量', 'quantity'],
['金额', 'amount']
),
],
[
'etc',
'ETC记录',
getEtcList,
cols(
['车牌号', 'vehicleNo'],
['交易日期', 'transactionDate'],
['交易金额', 'amount'],
['交易地点', 'location'],
['ETC卡号', 'etcCardNo']
),
],
[
'otherExpense',
'其他费用记录',
getOtherExpenseList,
cols(
['车牌号', 'vehicleNo'],
['费用日期', 'expenseDate'],
['费用类型', 'expenseType'],
['金额', 'amount'],
['备注', 'remark']
),
],
].map(([name, label, request, columns]) => ({ name, label, request, columns }));
export default {
components: { SectionCard },
props: { modelValue: Boolean, vehicle: { type: Object, default: () => ({}) } },
emits: ['update:modelValue'],
data() {
return { detailLoading: false, tableLoading: false, vehicleDetail: {}, activeTab: 'insurance', records: [], page: { current: 1, size: 10, total: 0 } };
return {
detailLoading: false,
tableLoading: false,
vehicleDetail: {},
activeTab: 'insurance',
records: [],
page: { current: 1, size: 10, total: 0 },
};
},
computed: {
tabs() { return tabConfigs; },
activeConfig() { return tabConfigs.find(item => item.name === this.activeTab) || tabConfigs[0]; },
activeColumns() { return this.activeConfig.columns; },
dimensions() { const v = this.vehicleDetail; return [v.outerLength, v.outerWidth, v.outerHeight].filter(item => item !== null && item !== undefined && item !== '').join('×') || '-'; },
plateColorType() { return { 黄牌: 'warning', 蓝牌: 'primary', 绿牌: 'success' }[this.vehicleDetail.plateColor] || 'info'; },
imageFields() { return [['行驶证主页面', 'drivingLicenseImage'], ['行驶证主页反页', 'drivingLicenseMainBack'], ['行驶证副页正页', 'drivingLicenseViceFront'], ['行驶证副页反页', 'drivingLicenseViceBack'], ['道路运输证', 'roadTransportCertImage']].map(([label, prop]) => ({ label, prop })); },
imageUrls() { return this.imageFields.map(item => this.vehicleDetail[item.prop]).filter(Boolean); },
tabs() {
return tabConfigs;
},
activeConfig() {
return tabConfigs.find(item => item.name === this.activeTab) || tabConfigs[0];
},
activeColumns() {
return this.activeConfig.columns;
},
dimensions() {
const v = this.vehicleDetail;
return (
[v.outerLength, v.outerWidth, v.outerHeight]
.filter(item => item !== null && item !== undefined && item !== '')
.join('×') || '-'
);
},
plateColorType() {
return (
{ 黄牌: 'warning', 蓝牌: 'primary', 绿牌: 'success' }[this.vehicleDetail.plateColor] ||
'info'
);
},
imageFields() {
return [
['行驶证主页面', 'drivingLicenseImage'],
['行驶证主页反页', 'drivingLicenseMainBack'],
['行驶证副页正页', 'drivingLicenseViceFront'],
['行驶证副页反页', 'drivingLicenseViceBack'],
['道路运输证', 'roadTransportCertImage'],
].map(([label, prop]) => ({ label, prop }));
},
imageUrls() {
return this.imageFields.map(item => this.vehicleDetail[item.prop]).filter(Boolean);
},
},
watch: {
modelValue(value) {
if (value) this.initialize();
},
},
watch: { modelValue(value) { if (value) this.initialize(); } },
methods: {
async initialize() { this.activeTab = 'insurance'; this.page.current = 1; this.vehicleDetail = { ...this.vehicle }; if (this.vehicle.id) { this.detailLoading = true; try { const res = await getDetail(this.vehicle.id); this.vehicleDetail = { ...this.vehicle, ...(res.data.data || {}) }; } finally { this.detailLoading = false; } } this.loadRecords(); },
async loadRecords() { const { request } = this.activeConfig; if (!request) { this.records = []; this.page.total = 0; return; } this.tableLoading = true; try { const res = await request(this.page.current, this.page.size, { vehicleNo: this.vehicleDetail.plateNo || this.vehicle.plateNo, vehicleType: '车辆' }); const data = res.data.data || {}; this.records = data.records || []; this.page.total = data.total || 0; } finally { this.tableLoading = false; } },
handlePageChange() { this.page.current = 1; this.loadRecords(); },
async initialize() {
this.activeTab = 'insurance';
this.page.current = 1;
this.vehicleDetail = { ...this.vehicle };
if (this.vehicle.id) {
this.detailLoading = true;
try {
const res = await getDetail(this.vehicle.id);
this.vehicleDetail = { ...this.vehicle, ...(res.data.data || {}) };
} finally {
this.detailLoading = false;
}
}
this.loadRecords();
},
async loadRecords() {
const { request } = this.activeConfig;
if (!request) {
this.records = [];
this.page.total = 0;
return;
}
this.tableLoading = true;
try {
const res = await request(this.page.current, this.page.size, {
vehicleNo: this.vehicleDetail.plateNo || this.vehicle.plateNo,
vehicleType: '车辆',
});
const data = res.data.data || {};
this.records = data.records || [];
this.page.total = data.total || 0;
} finally {
this.tableLoading = false;
}
},
handlePageChange() {
this.page.current = 1;
this.loadRecords();
},
},
};
</script>
<style lang="scss" scoped>
.vehicle-ledger__overview { padding: 16px; border: 1px solid #eff1f7; }
.vehicle-ledger__title { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; font-size: 26px; font-weight: 600; }
.vehicle-ledger__images { display: flex; gap: 16px; margin-top: 16px; overflow-x: auto; }
.vehicle-ledger__image-item { width: 150px; flex: 0 0 150px; color: #606266; text-align: center; }
.vehicle-ledger__image-item > span { display: block; margin-bottom: 8px; }
.vehicle-ledger__image-item :deep(.el-image) { width: 150px; height: 110px; border: 1px solid #eff1f7; }
.vehicle-ledger__image-item :deep(.el-empty) { height: 110px; border: 1px solid #eff1f7; }
.vehicle-ledger__tabs { margin-top: 16px; }
.vehicle-ledger__pagination { display: flex; justify-content: flex-end; margin-top: 16px; }
.vehicle-ledger__overview {
padding: 16px;
border: 1px solid #eff1f7;
}
.vehicle-ledger__title {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
font-size: 26px;
font-weight: 600;
}
.vehicle-ledger__images {
display: flex;
gap: 16px;
margin-top: 16px;
overflow-x: auto;
}
.vehicle-ledger__image-item {
width: 150px;
flex: 0 0 150px;
color: #606266;
text-align: center;
}
.vehicle-ledger__image-item > span {
display: block;
margin-bottom: 8px;
}
.vehicle-ledger__image-item :deep(.el-image) {
width: 150px;
height: 110px;
border: 1px solid #eff1f7;
}
.vehicle-ledger__image-item :deep(.el-empty) {
height: 110px;
border: 1px solid #eff1f7;
}
.vehicle-ledger__tabs {
margin-top: 16px;
}
.vehicle-ledger__pagination {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
</style>