fix bug
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
<template>
|
||||
<div class="vehicle-attachment-table">
|
||||
<div class="vehicle-attachment-table__toolbar">
|
||||
<el-button type="primary" :disabled="!rows.length" @click="batchDownload">
|
||||
批量下载
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="rows" border @selection-change="selectedRows = $event">
|
||||
<el-table-column v-if="!readonly" type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column label="文件名" min-width="240" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span
|
||||
class="vehicle-attachment-table__file-name"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@click="previewAttachment(row)"
|
||||
@keydown.enter="previewAttachment(row)"
|
||||
@keydown.space.prevent="previewAttachment(row)"
|
||||
>
|
||||
{{ attachmentName(row) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件描述" min-width="220">
|
||||
<template #default="{ row, $index }">
|
||||
<span v-if="readonly">{{ row.description || '-' }}</span>
|
||||
<el-input
|
||||
v-else
|
||||
:model-value="row.description"
|
||||
maxlength="200"
|
||||
placeholder="请输入"
|
||||
@update:model-value="value => updateDescription($index, value)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件大小" width="120" align="center">
|
||||
<template #default="{ row }">{{ formatFileSize(row.size) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="180" align="center" sortable />
|
||||
<el-table-column v-if="!readonly" label="操作" width="100" align="center" fixed="right">
|
||||
<template #default="{ $index }">
|
||||
<el-link type="danger" @click="removeAttachment($index)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="!readonly" class="vehicle-attachment-table__upload">
|
||||
<vehicle-attachment-upload
|
||||
:model-value="rows"
|
||||
:file-types="attachmentFileTypes"
|
||||
:max-size="500"
|
||||
:show-tip="true"
|
||||
tip="支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过500M"
|
||||
:show-file-list="false"
|
||||
button-text="上传附件"
|
||||
@update:model-value="handleUploadChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="documentPreviewVisible"
|
||||
:title="previewFile.name || '附件预览'"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
width="90%"
|
||||
top="4vh"
|
||||
class="vehicle-attachment-table__viewer-dialog"
|
||||
>
|
||||
<pdf-preview
|
||||
v-if="documentPreviewVisible && previewFile.url && previewFile.isPdf"
|
||||
:source="previewFile.url"
|
||||
@error="handlePreviewError"
|
||||
/>
|
||||
<open-file-viewer
|
||||
v-else-if="documentPreviewVisible && previewFile.url"
|
||||
:file="previewFile.url"
|
||||
:file-name="previewFile.name"
|
||||
:mime-type="previewFile.mimeType"
|
||||
width="100%"
|
||||
height="72vh"
|
||||
fit="contain"
|
||||
theme="auto"
|
||||
locale="zh-CN"
|
||||
:toolbar="viewerToolbar"
|
||||
:plugins="viewerPlugins"
|
||||
@unsupported="handlePreviewUnsupported"
|
||||
@error="handlePreviewError"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<el-image-viewer
|
||||
v-if="imagePreviewVisible"
|
||||
:url-list="imagePreviewUrls"
|
||||
:initial-index="imagePreviewIndex"
|
||||
@close="imagePreviewVisible = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElImageViewer } from 'element-plus';
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
import { fallbackPlugin, imagePlugin, officePlugin, textPlugin } from '@open-file-viewer/core';
|
||||
import '@open-file-viewer/core/style.css';
|
||||
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||
import PdfPreview from '@/components/pdf-preview/main.vue';
|
||||
import { downloadFileByUrl } from '@/utils/util';
|
||||
|
||||
const attachmentFileTypes = [
|
||||
'pdf',
|
||||
'bmp',
|
||||
'jpeg',
|
||||
'png',
|
||||
'jpg',
|
||||
'doc',
|
||||
'docx',
|
||||
'ppt',
|
||||
'pptx',
|
||||
'xlsx',
|
||||
'xls',
|
||||
'eml',
|
||||
'msg',
|
||||
'zip',
|
||||
];
|
||||
|
||||
const viewerPlugins = [
|
||||
imagePlugin(),
|
||||
officePlugin({ pdf: { workerSrc: pdfWorkerSrc, useFetchData: true } }),
|
||||
textPlugin(),
|
||||
fallbackPlugin(),
|
||||
];
|
||||
|
||||
export default {
|
||||
name: 'VehicleAttachmentTable',
|
||||
components: {
|
||||
ElImageViewer,
|
||||
OpenFileViewer,
|
||||
PdfPreview,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [Array, String, Object],
|
||||
default: () => [],
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
attachmentFileTypes,
|
||||
selectedRows: [],
|
||||
imagePreviewVisible: false,
|
||||
imagePreviewUrls: [],
|
||||
imagePreviewIndex: 0,
|
||||
documentPreviewVisible: false,
|
||||
previewFile: {},
|
||||
viewerPlugins,
|
||||
viewerToolbar: {
|
||||
download: true,
|
||||
fullscreen: true,
|
||||
print: true,
|
||||
rotate: true,
|
||||
zoom: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
rows() {
|
||||
if (Array.isArray(this.modelValue)) return this.modelValue;
|
||||
if (this.modelValue && typeof this.modelValue === 'object') return [this.modelValue];
|
||||
if (!this.modelValue) return [];
|
||||
try {
|
||||
const rows = JSON.parse(this.modelValue);
|
||||
return Array.isArray(rows) ? rows : [];
|
||||
} catch (error) {
|
||||
return String(this.modelValue)
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean)
|
||||
.map(item => ({ name: item, url: item }));
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
attachmentName(row = {}) {
|
||||
return row.originalName || row.name || row.fileName || '附件';
|
||||
},
|
||||
attachmentUrl(row = {}) {
|
||||
return row.url || row.link || row.fileUrl || row.downloadUrl || row.domain || row.src || '';
|
||||
},
|
||||
attachmentExtension(row = {}) {
|
||||
const source = String(this.attachmentName(row) || this.attachmentUrl(row)).split('?')[0];
|
||||
const index = source.lastIndexOf('.');
|
||||
return index > -1 ? source.slice(index + 1).toLowerCase() : '';
|
||||
},
|
||||
isImage(row) {
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(this.attachmentExtension(row));
|
||||
},
|
||||
isPdf(row) {
|
||||
const mimeType = String(row.mimeType || row.contentType || '').toLowerCase();
|
||||
return mimeType.includes('application/pdf') || this.attachmentExtension(row) === 'pdf';
|
||||
},
|
||||
emitRows(rows) {
|
||||
this.$emit('update:modelValue', rows);
|
||||
},
|
||||
handleUploadChange(rows) {
|
||||
const uploadUserName = this.$store.getters.userInfo?.realName || '';
|
||||
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
this.emitRows(
|
||||
(rows || []).map(row => ({
|
||||
...row,
|
||||
description: row.description || '',
|
||||
uploadUserName: row.uploadUserName || uploadUserName,
|
||||
uploadTime: row.uploadTime || uploadTime,
|
||||
}))
|
||||
);
|
||||
},
|
||||
updateDescription(index, description) {
|
||||
const rows = this.rows.map((row, rowIndex) =>
|
||||
rowIndex === index ? { ...row, description } : row
|
||||
);
|
||||
this.emitRows(rows);
|
||||
},
|
||||
removeAttachment(index) {
|
||||
const rows = [...this.rows];
|
||||
rows.splice(index, 1);
|
||||
this.emitRows(rows);
|
||||
},
|
||||
formatFileSize(size) {
|
||||
if (!size) return '';
|
||||
const value = Number(size);
|
||||
if (!Number.isFinite(value)) return String(size);
|
||||
if (value < 1024) return `${value}B`;
|
||||
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)}KB`;
|
||||
return `${(value / 1024 / 1024).toFixed(1)}MB`;
|
||||
},
|
||||
downloadAttachment(row) {
|
||||
const url = this.attachmentUrl(row);
|
||||
if (!url) {
|
||||
this.$message.warning('附件地址为空,无法下载');
|
||||
return;
|
||||
}
|
||||
downloadFileByUrl(url, this.attachmentName(row));
|
||||
},
|
||||
batchDownload() {
|
||||
const rows = this.selectedRows.length ? this.selectedRows : this.rows;
|
||||
rows.forEach(this.downloadAttachment);
|
||||
},
|
||||
previewAttachment(row) {
|
||||
const url = this.attachmentUrl(row);
|
||||
if (!url) {
|
||||
this.$message.warning('附件地址为空,无法预览');
|
||||
return;
|
||||
}
|
||||
if (this.isImage(row)) {
|
||||
this.imagePreviewUrls = this.rows
|
||||
.filter(item => this.isImage(item) && this.attachmentUrl(item))
|
||||
.map(item => this.attachmentUrl(item));
|
||||
this.imagePreviewIndex = Math.max(this.imagePreviewUrls.indexOf(url), 0);
|
||||
this.imagePreviewVisible = true;
|
||||
return;
|
||||
}
|
||||
const isPdf = this.isPdf(row);
|
||||
this.previewFile = {
|
||||
name: this.attachmentName(row),
|
||||
url,
|
||||
mimeType: isPdf ? 'application/pdf' : row.mimeType || row.contentType || '',
|
||||
isPdf,
|
||||
};
|
||||
this.documentPreviewVisible = true;
|
||||
},
|
||||
handlePreviewUnsupported() {
|
||||
this.$message.warning('当前文件暂不支持在线预览');
|
||||
},
|
||||
handlePreviewError() {
|
||||
this.$message.error('附件预览失败');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vehicle-attachment-table {
|
||||
width: 100%;
|
||||
|
||||
&__toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__file-name {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__file-name:hover,
|
||||
&__file-name:focus-visible {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&__upload {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 12px;
|
||||
|
||||
:deep(.vehicle-attachment-upload) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table th.el-table__cell) {
|
||||
height: 42px;
|
||||
padding: 8px 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
:deep(.el-table td.el-table__cell) {
|
||||
height: 52px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
:global(.vehicle-attachment-table__viewer-dialog .el-dialog__body) {
|
||||
padding: 12px 16px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -9,7 +9,7 @@ export const option = {
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: false,
|
||||
selection: true,
|
||||
addBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
|
||||
@@ -172,6 +172,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -177,6 +177,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -148,6 +148,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -132,6 +132,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -166,6 +166,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -138,6 +138,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -134,6 +134,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -89,6 +89,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -33,7 +33,7 @@ export const processStatusDic = [
|
||||
export const option = {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 960,
|
||||
dialogWidth: 1200,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 88,
|
||||
@@ -208,6 +208,7 @@ export const option = {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
filterable
|
||||
:loading="cityLoading"
|
||||
:disabled="isCityDisabled"
|
||||
:placeholder="isParentRegionLocked ? '自动带出' : '请先选择国家'"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
@change="handleCityChange"
|
||||
>
|
||||
@@ -155,9 +155,7 @@
|
||||
filterable
|
||||
:loading="districtLoading"
|
||||
:disabled="isDistrictDisabled"
|
||||
:placeholder="
|
||||
isParentRegionLocked ? '自动带出' : form.cityCode ? '请选择区县' : '选择城市后再选择区县'
|
||||
"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
@change="handleDistrictChange"
|
||||
>
|
||||
@@ -443,7 +441,7 @@ export default {
|
||||
hide: true,
|
||||
span: 12,
|
||||
order: 88,
|
||||
placeholder: '自动带出',
|
||||
placeholder: '请选择',
|
||||
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
@@ -472,7 +470,7 @@ export default {
|
||||
},
|
||||
dicData: [],
|
||||
span: 12,
|
||||
placeholder: '选择城市后再选择区县',
|
||||
placeholder: '请选择',
|
||||
rules: [{ required: true, message: '请选择区县', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8651,15 +8651,18 @@ export default {
|
||||
handleTaskDriverSelect(target, item = {}) {
|
||||
const value = item.driverName || item.name || '';
|
||||
const driverPhone = item.mobile || item.phone || item.driverPhone || '';
|
||||
const drivingVehicle = String(item.drivingVehicle || '').trim();
|
||||
if (target === 'dispatch') {
|
||||
this.dispatchItemForm.driverId = item.id || '';
|
||||
this.dispatchItemForm.driverName = value;
|
||||
if (driverPhone) this.dispatchItemForm.driverPhone = driverPhone;
|
||||
if (drivingVehicle) this.dispatchItemForm.vehicleNo = drivingVehicle;
|
||||
return;
|
||||
}
|
||||
this.form.driverId = item.id || '';
|
||||
this.form.driverName = value;
|
||||
if (driverPhone) this.form.driverPhone = driverPhone;
|
||||
if (drivingVehicle) this.form.vehicleNo = drivingVehicle;
|
||||
},
|
||||
handleTaskDriverChange(value) {
|
||||
const driver = this.taskDriverOptions.find(item =>
|
||||
@@ -8670,6 +8673,9 @@ export default {
|
||||
if (driver) {
|
||||
this.form.driverPhone =
|
||||
driver.mobile || driver.phone || driver.driverPhone || this.form.driverPhone || '';
|
||||
if (String(driver.drivingVehicle || '').trim()) {
|
||||
this.form.vehicleNo = String(driver.drivingVehicle).trim();
|
||||
}
|
||||
}
|
||||
},
|
||||
getTaskCargoTypeOptionsKey(path = []) {
|
||||
@@ -12348,6 +12354,9 @@ export default {
|
||||
driver.driverPhone ||
|
||||
this.dispatchItemForm.driverPhone ||
|
||||
'';
|
||||
if (String(driver.drivingVehicle || '').trim()) {
|
||||
this.dispatchItemForm.vehicleNo = String(driver.drivingVehicle).trim();
|
||||
}
|
||||
}
|
||||
},
|
||||
getDispatchCargoRowOptions(row = {}) {
|
||||
|
||||
@@ -543,7 +543,12 @@ export default {
|
||||
driverOptionKey(item) { return item.id || item.driverId || this.driverOptionLabel(item) || item.mobile; },
|
||||
handleDriverChange(route, value) {
|
||||
const driver = this.driverOptions.find(item => this.driverOptionLabel(item) === value);
|
||||
if (driver) route.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
|
||||
if (driver) {
|
||||
route.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
|
||||
if (String(driver.drivingVehicle || '').trim()) {
|
||||
route.vehicleNo = String(driver.drivingVehicle).trim();
|
||||
}
|
||||
}
|
||||
},
|
||||
async loadCarrierOptions() {
|
||||
this.carrierLoading = true;
|
||||
@@ -577,6 +582,8 @@ export default {
|
||||
route.driverName = this.driverOptionLabel(item);
|
||||
route.driverId = item.id || item.driverId || '';
|
||||
route.driverPhone = item.mobile || item.driverPhone || item.phone || route.driverPhone || '';
|
||||
const drivingVehicle = String(item.drivingVehicle || '').trim();
|
||||
if (drivingVehicle) route.vehicleNo = drivingVehicle;
|
||||
},
|
||||
setDriverInput(segmentNo, element) {
|
||||
if (element) this.driverInputs[segmentNo] = element;
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
<template>
|
||||
<basic-container class="contract-change-page">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="auto">
|
||||
<section class="change-section">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="auto" class="contract-change-form">
|
||||
<section class="change-section contract-basic-section">
|
||||
<div class="dialog-section-title">基本信息</div>
|
||||
<el-row :gutter="28">
|
||||
<el-col :span="24"><el-form-item label="变更类型"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="一式(份)"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /></div></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="回款账期(天)"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" maxlength="2000" show-word-limit /></el-form-item></el-col>
|
||||
</el-row>
|
||||
<div class="contract-basic-section__grid">
|
||||
<el-form-item label="变更类型" class="contract-basic-section__change-type"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item>
|
||||
<el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item>
|
||||
<el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item>
|
||||
<el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item>
|
||||
<el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item>
|
||||
<el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item>
|
||||
<el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item>
|
||||
<el-form-item label="合同期限">
|
||||
<div class="contract-basic-section__date-range">
|
||||
<el-date-picker v-model="period[0]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
|
||||
<span>至</span>
|
||||
<el-date-picker v-model="period[1]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item>
|
||||
<el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item>
|
||||
<el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item>
|
||||
<el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item>
|
||||
<el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item>
|
||||
<el-form-item label="一式(份)"><el-input v-model="form.copyCount" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('copyCount', value)" /></el-form-item>
|
||||
<el-form-item label="回款账期(天)"><el-input v-model="form.paymentDays" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('paymentDays', value)" /></el-form-item>
|
||||
</div>
|
||||
<el-form-item label="备注" class="contract-basic-section__remark"><el-input v-model="form.remark" type="textarea" :rows="2" maxlength="2000" show-word-limit placeholder="请输入备注" /></el-form-item>
|
||||
</section>
|
||||
|
||||
<section class="change-section">
|
||||
@@ -103,10 +109,10 @@ const viewerPlugins = [
|
||||
textPlugin(),
|
||||
fallbackPlugin(),
|
||||
];
|
||||
const normalizeOptionalInteger = value => {
|
||||
if (value === undefined || value === null || value === '' || Number(value) < 0) return null;
|
||||
const normalizeOptionalPositiveInteger = value => {
|
||||
if (value === undefined || value === null || value === '') return null;
|
||||
const number = Number(value);
|
||||
return Number.isFinite(number) ? Math.trunc(number) : null;
|
||||
return Number.isInteger(number) && number > 0 ? number : null;
|
||||
};
|
||||
|
||||
export default {
|
||||
@@ -116,9 +122,10 @@ export default {
|
||||
mounted() { this.load(); },
|
||||
watch: { settlementConfigTab(tab, oldTab) { if (tab === oldTab) return; if (oldTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; this.settlementRule = { ...(tab === 'pre' ? this.preSettlementConfig : this.formalSettlementConfig) }; } },
|
||||
methods: {
|
||||
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, copyCount: normalizeOptionalInteger(data.copyCount), paymentDays: normalizeOptionalInteger(data.paymentDays), changeType: '合同信息变更' }; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
|
||||
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, copyCount: normalizeOptionalPositiveInteger(data.copyCount), paymentDays: normalizeOptionalPositiveInteger(data.paymentDays), changeType: '合同信息变更' }; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
|
||||
parse(value) { try { const result = JSON.parse(value || '[]'); return Array.isArray(result) ? result : []; } catch { return []; } },
|
||||
parseObject(value) { try { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15, ...(JSON.parse(value || '{}') || {}) }; } catch { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15 }; } },
|
||||
positiveIntegerInput(prop, value) { this.form[prop] = String(value ?? '').replace(/\D/g, '').replace(/^0+/, ''); },
|
||||
addPlan() { this.planEditorIndex = -1; this.planEditor = { planName: `计费方案${this.plans.length + 1}`, defaultPlan: !this.plans.length, remark: '', rules: [{}] }; this.planDialogVisible = true; },
|
||||
editPlan(row, index) { this.planEditorIndex = index; this.planEditor = JSON.parse(JSON.stringify(row)); this.planDialogVisible = true; },
|
||||
toggleDefaultPlan(value) { if (value) this.plans.forEach(item => { item.defaultPlan = false; }); },
|
||||
@@ -139,21 +146,36 @@ export default {
|
||||
formatFileSize(value) { const size = Number(value || 0); return size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(2)}MB` : `${Math.max(1, Math.ceil(size / 1024))}KB`; },
|
||||
handleChangeMaterial(event) { if (event.raw) this.changeMaterials.push(event.raw); },
|
||||
addPaymentRatioRow() { this.paymentRatioRows.push({ paymentTerm: `第${this.paymentRatioRows.length + 1}笔`, ratioLimit: '', remark: '' }); },
|
||||
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, copyCount: normalizeOptionalInteger(this.form.copyCount), paymentDays: normalizeOptionalInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeReason, changeReason: this.form.changeReason }); this.$message.success('变更已提交'); this.$router.back(); },
|
||||
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeReason, changeReason: this.form.changeReason }); this.$message.success('变更已提交'); this.$router.back(); },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.contract-change-page { min-height: 100%; background: #fff; }
|
||||
.change-section { padding: 20px 24px; border-bottom: 1px solid #eff1f7; }
|
||||
.contract-change-page { min-height: 100%; background: #f5f6fa; }
|
||||
.contract-change-page :deep(.basic-container__card) { border: 0; background: transparent; box-shadow: none; }
|
||||
.contract-change-form { background: #f5f6fa; }
|
||||
.change-section { padding: 20px 24px; background: #fff; border-bottom: 1px solid #eff1f7; }
|
||||
.contract-basic-section { margin-bottom: 12px; padding: 14px 16px 16px; overflow: hidden; background: #fff; border-bottom: 0; border-radius: 6px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); }
|
||||
.contract-basic-section > .dialog-section-title { margin-bottom: 20px; color: #303133; }
|
||||
.contract-basic-section__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 48px; }
|
||||
.contract-basic-section__change-type { grid-column: 1 / -1; }
|
||||
.contract-basic-section__remark { width: 100%; margin-bottom: 0 !important; }
|
||||
.contract-basic-section__date-range { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; width: 360px; max-width: 100%; }
|
||||
.contract-basic-section__date-range span { color: #606266; }
|
||||
.contract-basic-section__date-range :deep(.el-date-editor) { width: auto; min-width: 0; }
|
||||
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 16px; }
|
||||
.contract-basic-section :deep(.el-form-item__label) { flex: 0 0 96px !important; width: 96px !important; height: auto; padding-right: 12px; white-space: normal; word-break: break-all; line-height: 18px; }
|
||||
.contract-basic-section :deep(.el-form-item__content) { min-width: 0; }
|
||||
.contract-basic-section :deep(.el-input),
|
||||
.contract-basic-section :deep(.el-select),
|
||||
.contract-basic-section :deep(.el-date-editor) { width: 360px; max-width: 100%; }
|
||||
.dialog-section-title { margin-bottom: 18px; font-size: 16px; font-weight: 600; }
|
||||
.dialog-section-title::before { display: inline-block; width: 4px; height: 16px; margin-right: 8px; vertical-align: -2px; background: #409eff; content: ''; }
|
||||
.section-head { display: flex; align-items: center; justify-content: space-between; }
|
||||
.change-table { margin: 16px 0; }
|
||||
.ratio-tip { margin-bottom: 8px; color: #f56c6c; }
|
||||
.unit { margin-left: 8px; }
|
||||
.inline-field { display: flex; align-items: center; gap: 8px; }
|
||||
.attachment-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 12px; }
|
||||
.attachment-upload { display: flex; justify-content: flex-start; margin-top: 12px; }
|
||||
.attachment-upload .vehicle-attachment-upload { width: auto; }
|
||||
@@ -162,4 +184,6 @@ export default {
|
||||
.settlement-form { display: grid; grid-template-columns: repeat(3, minmax(240px, 1fr)); gap: 8px 28px; }
|
||||
.change-reason-section { border: 1px dashed #ff8f9a; margin: 20px 16px; }
|
||||
.page-footer { display: flex; gap: 16px; padding: 20px 40px; border-top: 1px solid #eff1f7; }
|
||||
@media (max-width: 1200px) { .contract-basic-section__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px; } }
|
||||
@media (max-width: 768px) { .contract-basic-section__grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
@@ -225,14 +225,16 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属组织" prop="organizationName">
|
||||
<el-cascader
|
||||
<el-tree-select
|
||||
v-model="selectedOrganizationId"
|
||||
:options="organizationOptions"
|
||||
:props="organizationCascaderProps"
|
||||
:data="organizationOptions"
|
||||
:props="organizationTreeSelectProps"
|
||||
node-key="id"
|
||||
placeholder="请选择"
|
||||
check-strictly
|
||||
clearable
|
||||
filterable
|
||||
:show-all-levels="false"
|
||||
:render-after-expand="false"
|
||||
@visible-change="visible => visible && loadOrganizationOptions()"
|
||||
@change="handleOrganizationChange"
|
||||
/>
|
||||
@@ -1234,13 +1236,11 @@ export default {
|
||||
contractFormatOptions() {
|
||||
return this.columnOptions('contractFormat');
|
||||
},
|
||||
organizationCascaderProps() {
|
||||
organizationTreeSelectProps() {
|
||||
return {
|
||||
label: 'label',
|
||||
value: 'id',
|
||||
children: 'children',
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
};
|
||||
},
|
||||
settlementRuleEnabled() {
|
||||
@@ -1688,7 +1688,8 @@ export default {
|
||||
this.organizationLoading = true;
|
||||
getDeptTree(this.userInfo?.tenantId)
|
||||
.then(res => {
|
||||
this.organizationOptions = this.normalizeOrganizationTree(res.data?.data || []);
|
||||
const organizationTree = this.excludeExternalOrganization(res.data?.data || []);
|
||||
this.organizationOptions = this.normalizeOrganizationTree(organizationTree);
|
||||
this.organizationFlatOptions = this.flattenOrganizationTree(this.organizationOptions);
|
||||
const column = this.findColumn(this.tableOption.column, 'organizationName');
|
||||
if (column) column.dicData = this.organizationOptions;
|
||||
@@ -1698,6 +1699,17 @@ export default {
|
||||
this.organizationLoading = false;
|
||||
});
|
||||
},
|
||||
excludeExternalOrganization(tree = []) {
|
||||
return tree.reduce((result, item) => {
|
||||
const organizationName = item.title || item.deptName || item.name || item.label || '';
|
||||
if (String(organizationName).trim() === '外部组织') return result;
|
||||
result.push({
|
||||
...item,
|
||||
children: this.excludeExternalOrganization(item.children || []),
|
||||
});
|
||||
return result;
|
||||
}, []);
|
||||
},
|
||||
normalizeOrganizationTree(tree) {
|
||||
return (tree || []).map(item => {
|
||||
const label = item.title || item.deptName || item.name || item.label || '';
|
||||
@@ -2279,6 +2291,7 @@ export default {
|
||||
:deep(.el-input),
|
||||
:deep(.el-select),
|
||||
:deep(.el-cascader),
|
||||
:deep(.el-tree-select),
|
||||
:deep(.el-input-number),
|
||||
:deep(.el-date-editor) {
|
||||
width: 360px;
|
||||
|
||||
@@ -2331,6 +2331,9 @@ export default {
|
||||
if (driver && !this.dialogForm.driverPhone) {
|
||||
this.dialogForm.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
|
||||
}
|
||||
if (String(driver?.drivingVehicle || '').trim()) {
|
||||
this.dialogForm.vehicleNo = String(driver.drivingVehicle).trim();
|
||||
}
|
||||
},
|
||||
fetchDriverSuggestions(queryString, callback) {
|
||||
this.loadDriverOptions(String(queryString || '').trim())
|
||||
@@ -2350,6 +2353,8 @@ export default {
|
||||
this.dialogForm.driverName = value;
|
||||
const phone = item.mobile || item.driverPhone || item.phone || '';
|
||||
if (phone) this.dialogForm.driverPhone = phone;
|
||||
const drivingVehicle = String(item.drivingVehicle || '').trim();
|
||||
if (drivingVehicle) this.dialogForm.vehicleNo = drivingVehicle;
|
||||
}
|
||||
},
|
||||
handleMileageInput(value) {
|
||||
|
||||
@@ -157,31 +157,31 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="业务部门" prop="businessDeptId">
|
||||
<el-select
|
||||
<el-tree-select
|
||||
v-model="form.businessDeptId"
|
||||
:data="businessDeptTreeOptions"
|
||||
:props="deptTreeSelectProps"
|
||||
node-key="value"
|
||||
placeholder="请选择业务部门"
|
||||
check-strictly
|
||||
filterable
|
||||
clearable
|
||||
:render-after-expand="false"
|
||||
:disabled="isBasicInfoReadonly"
|
||||
@change="handleBusinessDeptChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in deptOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="承办部门" prop="undertakeDeptId">
|
||||
<el-cascader
|
||||
<el-tree-select
|
||||
v-model="form.undertakeDeptId"
|
||||
style="width: 100%"
|
||||
:data="deptTreeOptions"
|
||||
:props="deptTreeSelectProps"
|
||||
node-key="value"
|
||||
placeholder="请选择承办部门"
|
||||
check-strictly
|
||||
clearable
|
||||
filterable
|
||||
:options="deptTreeOptions"
|
||||
:props="deptCascaderProps"
|
||||
:render-after-expand="false"
|
||||
:disabled="isBasicInfoReadonly"
|
||||
@change="handleUndertakeDeptChange"
|
||||
/>
|
||||
@@ -823,6 +823,15 @@ const emptyForm = () => ({
|
||||
changeReason: '',
|
||||
});
|
||||
|
||||
const optionalSentinelFields = [
|
||||
'projectScale',
|
||||
'estimatedProfit',
|
||||
'fundDemand',
|
||||
'receivableDays',
|
||||
'paymentDays',
|
||||
'cargoQuantity',
|
||||
];
|
||||
|
||||
const changeTypeOptions = [
|
||||
{ label: '项目变更', value: '项目变更' },
|
||||
{ label: '项目备案调整', value: '项目备案调整' },
|
||||
@@ -885,7 +894,7 @@ export default {
|
||||
};
|
||||
const validateDays = (rule, value, callback) => {
|
||||
if (value === '' || value === undefined || value === null) {
|
||||
callback(new Error(`请输入${rule.label}`));
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
const number = Number(value);
|
||||
@@ -961,10 +970,10 @@ export default {
|
||||
},
|
||||
],
|
||||
receivableDays: [
|
||||
{ required: true, label: '应收账款回款期限', validator: validateDays, trigger: 'blur' },
|
||||
{ label: '应收账款回款期限', validator: validateDays, trigger: 'blur' },
|
||||
],
|
||||
paymentDays: [
|
||||
{ required: true, label: '回款账期', validator: validateDays, trigger: 'blur' },
|
||||
{ label: '回款账期', validator: validateDays, trigger: 'blur' },
|
||||
],
|
||||
projectScale: [{ label: '项目规模', validator: validateAmount, trigger: 'blur' }],
|
||||
estimatedProfit: [{ label: '预估利润', validator: validateAmount, trigger: 'blur' }],
|
||||
@@ -997,13 +1006,12 @@ export default {
|
||||
],
|
||||
},
|
||||
deptOptions: [],
|
||||
businessDeptTreeOptions: [],
|
||||
deptTreeOptions: [],
|
||||
deptCascaderProps: {
|
||||
deptTreeSelectProps: {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
children: 'children',
|
||||
emitPath: false,
|
||||
checkStrictly: true,
|
||||
},
|
||||
cargoTypeOptions: [],
|
||||
selectedCustomerId: [],
|
||||
@@ -1415,13 +1423,12 @@ export default {
|
||||
...row,
|
||||
fundLimit: this.formatAmount(row.fundLimit),
|
||||
receivableLimit: this.formatAmount(row.receivableLimit),
|
||||
...(this.dialogReadonly
|
||||
? {
|
||||
projectScale: this.normalizeReadonlyAmount(row.projectScale),
|
||||
estimatedProfit: this.normalizeReadonlyAmount(row.estimatedProfit),
|
||||
fundDemand: this.normalizeReadonlyAmount(row.fundDemand),
|
||||
}
|
||||
: {}),
|
||||
projectScale: this.normalizeOptionalSentinel(row.projectScale),
|
||||
estimatedProfit: this.normalizeOptionalSentinel(row.estimatedProfit),
|
||||
fundDemand: this.normalizeOptionalSentinel(row.fundDemand),
|
||||
receivableDays: this.normalizeOptionalSentinel(row.receivableDays),
|
||||
paymentDays: this.normalizeOptionalSentinel(row.paymentDays),
|
||||
cargoQuantity: this.normalizeOptionalSentinel(row.cargoQuantity),
|
||||
};
|
||||
const form = {
|
||||
...emptyForm(),
|
||||
@@ -1589,6 +1596,9 @@ export default {
|
||||
...this.form,
|
||||
fundLimit: this.formatAmount(this.form.fundLimit),
|
||||
receivableLimit: this.formatAmount(this.form.receivableLimit),
|
||||
...Object.fromEntries(
|
||||
optionalSentinelFields.map(key => [key, this.normalizeOptionalSentinel(this.form[key], null)])
|
||||
),
|
||||
businessStartDate,
|
||||
businessEndDate,
|
||||
customerJson: JSON.stringify(this.customerRows),
|
||||
@@ -1732,8 +1742,11 @@ export default {
|
||||
.filter(Boolean);
|
||||
},
|
||||
normalizeReadonlyAmount(value) {
|
||||
return this.normalizeOptionalSentinel(value);
|
||||
},
|
||||
normalizeOptionalSentinel(value, emptyValue = '') {
|
||||
return value === null || value === undefined || value === '' || Number(value) === -1
|
||||
? ''
|
||||
? emptyValue
|
||||
: value;
|
||||
},
|
||||
mergeCustomerOptions(options = [], selectedOptions = []) {
|
||||
@@ -1789,9 +1802,13 @@ export default {
|
||||
loadDeptOptions() {
|
||||
getDeptTree().then(res => {
|
||||
const deptTree = res.data.data || [];
|
||||
const businessDeptTree = ['add', 'edit'].includes(this.dialogType)
|
||||
? this.excludeExternalOrganization(deptTree)
|
||||
: deptTree;
|
||||
const undertakeDeptTree =
|
||||
this.dialogType === 'add' ? this.excludeExternalOrganization(deptTree) : deptTree;
|
||||
this.deptOptions = this.flattenDept(deptTree);
|
||||
this.deptOptions = this.flattenDept(businessDeptTree);
|
||||
this.businessDeptTreeOptions = this.toDeptCascaderOptions(businessDeptTree);
|
||||
this.deptTreeOptions = this.toDeptCascaderOptions(undertakeDeptTree);
|
||||
});
|
||||
},
|
||||
@@ -1852,7 +1869,9 @@ export default {
|
||||
getCustomerArchiveList(1, 100, {
|
||||
customerType: type,
|
||||
status: 1,
|
||||
...(type === '客户' ? { approvalStatus: 'approved' } : {}),
|
||||
...(this.dialogType !== 'add' && type === '客户'
|
||||
? { approvalStatus: 'approved' }
|
||||
: {}),
|
||||
})
|
||||
.then(res => {
|
||||
const records = (res.data.data && res.data.data.records) || [];
|
||||
@@ -1934,6 +1953,10 @@ export default {
|
||||
return row;
|
||||
},
|
||||
handleNumberInput(prop, value) {
|
||||
if (optionalSentinelFields.includes(prop) && Number(value) === -1) {
|
||||
this.form[prop] = '';
|
||||
return;
|
||||
}
|
||||
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||
const parts = text.split('.');
|
||||
this.form[prop] =
|
||||
@@ -1948,6 +1971,10 @@ export default {
|
||||
this.form[prop] = this.formatAmount(this.form[prop]);
|
||||
},
|
||||
handleIntegerInput(prop, value) {
|
||||
if (optionalSentinelFields.includes(prop) && Number(value) === -1) {
|
||||
this.form[prop] = '';
|
||||
return;
|
||||
}
|
||||
this.form[prop] = String(value || '').replace(/[^\d]/g, '');
|
||||
},
|
||||
handleAttachmentChange(list) {
|
||||
@@ -2098,6 +2125,7 @@ export default {
|
||||
|
||||
:deep(.el-input),
|
||||
:deep(.el-select),
|
||||
:deep(.el-tree-select),
|
||||
:deep(.el-date-editor) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
v-if="vehicleDetail[item.prop]"
|
||||
:src="vehicleDetail[item.prop]"
|
||||
:preview-src-list="imageUrls"
|
||||
:initial-index="item.previewIndex"
|
||||
preview-teleported
|
||||
fit="cover"
|
||||
/>
|
||||
@@ -312,13 +313,18 @@ export default {
|
||||
);
|
||||
},
|
||||
imageFields() {
|
||||
let previewIndex = 0;
|
||||
return [
|
||||
['行驶证主页面', 'drivingLicenseImage'],
|
||||
['行驶证主页反页', 'drivingLicenseMainBack'],
|
||||
['行驶证副页正页', 'drivingLicenseViceFront'],
|
||||
['行驶证副页反页', 'drivingLicenseViceBack'],
|
||||
['道路运输证', 'roadTransportCertImage'],
|
||||
].map(([label, prop]) => ({ label, prop }));
|
||||
].map(([label, prop]) => {
|
||||
const item = { label, prop, previewIndex };
|
||||
if (this.vehicleDetail[prop]) previewIndex += 1;
|
||||
return item;
|
||||
});
|
||||
},
|
||||
imageUrls() {
|
||||
return this.imageFields.map(item => this.vehicleDetail[item.prop]).filter(Boolean);
|
||||
|
||||
@@ -204,6 +204,29 @@
|
||||
<el-input v-model="driverForm.address" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="驾驶车辆" prop="drivingVehicle">
|
||||
<el-input
|
||||
v-model="driverForm.drivingVehicle"
|
||||
maxlength="30"
|
||||
clearable
|
||||
placeholder="请输入或选择车辆"
|
||||
>
|
||||
<template #append>
|
||||
<el-tooltip content="选择车辆" placement="top">
|
||||
<el-button
|
||||
:icon="List"
|
||||
:disabled="readonly"
|
||||
aria-label="选择车辆"
|
||||
@click="openVehicleSelector"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="岗位" prop="postList">
|
||||
<el-checkbox-group v-model="driverForm.postList">
|
||||
@@ -487,6 +510,64 @@
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="vehicleSelectorVisible"
|
||||
title="选择车辆"
|
||||
append-to-body
|
||||
width="92%"
|
||||
top="4vh"
|
||||
class="vehicle-selector-dialog"
|
||||
@closed="resetVehicleSelector"
|
||||
>
|
||||
<avue-crud
|
||||
v-if="vehicleSelectorVisible"
|
||||
ref="vehicleSelectorCrud"
|
||||
v-model="vehicleSelectorForm"
|
||||
v-model:page="vehicleSelectorPage"
|
||||
:option="vehicleSelectorOption"
|
||||
:table-loading="vehicleSelectorLoading"
|
||||
:data="vehicleSelectorData"
|
||||
@search-change="vehicleSelectorSearchChange"
|
||||
@search-reset="vehicleSelectorSearchReset"
|
||||
@current-change="vehicleSelectorCurrentChange"
|
||||
@size-change="vehicleSelectorSizeChange"
|
||||
@refresh-change="vehicleSelectorRefreshChange"
|
||||
@on-load="loadVehicleSelector"
|
||||
>
|
||||
<template #plateNo="{ row }">
|
||||
<span>{{ row.plateNo || '-' }}</span>
|
||||
</template>
|
||||
<template #organizationName="{ row }">
|
||||
{{ String(row.organizationName || '').replace(/^[\s\u3000]+/, '') }}
|
||||
</template>
|
||||
<template #boundDriver>
|
||||
<span>-</span>
|
||||
</template>
|
||||
<template #certificationStatus="{ row }">
|
||||
<el-tag :type="getVehicleCertificationStatus(row).type" class="status-text">
|
||||
{{ getVehicleCertificationStatus(row).label }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-tag :type="row.status === 1 ? 'primary' : 'info'" class="status-text">
|
||||
{{ row.status === 1 ? '启用' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #drivingLicenseEndDate="{ row }">
|
||||
{{ formatEndDate(row.drivingLicenseEndDate, row.drivingLicenseLongTerm) }}
|
||||
</template>
|
||||
<template #roadTransportCertEndDate="{ row }">
|
||||
{{ formatEndDate(row.roadTransportCertEndDate, row.roadTransportCertLongTerm) }}
|
||||
</template>
|
||||
<template #annualReviewEndDate="{ row }">
|
||||
{{ formatEndDate(row.annualReviewEndDate, row.annualReviewLongTerm) }}
|
||||
</template>
|
||||
<template #menu="{ row }">
|
||||
<el-link type="primary" @click="selectDrivingVehicle(row)">选择</el-link>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
@@ -494,7 +575,9 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import { ElLoading } from 'element-plus';
|
||||
import { List } from '@element-plus/icons-vue';
|
||||
import { option } from '@/option/transportCapacity/driver';
|
||||
import { option as transportVehicleOption } from '@/option/transportCapacity/transport-vehicle';
|
||||
import {
|
||||
getList,
|
||||
getDetail,
|
||||
@@ -506,6 +589,7 @@ import {
|
||||
recognitionTransportCertificates,
|
||||
recognizeBaiduOcr,
|
||||
} from '@/api/transportCapacity/driver';
|
||||
import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { getLazyTree } from '@/api/base/region';
|
||||
@@ -515,6 +599,25 @@ import { getUploadHeaders } from '@/utils/upload';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import ImageUploadField from '@/components/image-upload-field/main.vue';
|
||||
|
||||
const vehicleSelectorOption = {
|
||||
...transportVehicleOption,
|
||||
height: 430,
|
||||
selection: false,
|
||||
addBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
viewBtn: false,
|
||||
columnBtn: false,
|
||||
menuWidth: 90,
|
||||
menuFixed: 'right',
|
||||
column: transportVehicleOption.column.map(column => ({
|
||||
...column,
|
||||
dicData: Array.isArray(column.dicData)
|
||||
? column.dicData.map(item => ({ ...item }))
|
||||
: column.dicData,
|
||||
})),
|
||||
};
|
||||
|
||||
const emptyForm = () => ({
|
||||
id: '',
|
||||
driverName: '',
|
||||
@@ -526,6 +629,7 @@ const emptyForm = () => ({
|
||||
addressRegionPath: [],
|
||||
addressRegion: '',
|
||||
address: '',
|
||||
drivingVehicle: '',
|
||||
postList: ['司机'],
|
||||
posts: '',
|
||||
idCardFront: '',
|
||||
@@ -560,6 +664,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
option,
|
||||
List,
|
||||
form: {},
|
||||
query: {
|
||||
expireStatus: '',
|
||||
@@ -581,6 +686,17 @@ export default {
|
||||
expired: 0,
|
||||
},
|
||||
driverBox: false,
|
||||
vehicleSelectorVisible: false,
|
||||
vehicleSelectorLoading: false,
|
||||
vehicleSelectorOption,
|
||||
vehicleSelectorForm: {},
|
||||
vehicleSelectorData: [],
|
||||
vehicleSelectorSearchForm: {},
|
||||
vehicleSelectorPage: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
total: 0,
|
||||
},
|
||||
readonly: false,
|
||||
driverForm: emptyForm(),
|
||||
drivingLicenseUploads: {},
|
||||
@@ -745,6 +861,11 @@ export default {
|
||||
this.organizationOptions = this.formatDeptOptions(res.data.data || []);
|
||||
const column = this.findColumn(this.option.column, 'organizationName');
|
||||
column.dicData = this.organizationOptions;
|
||||
const vehicleColumn = this.findColumn(
|
||||
this.vehicleSelectorOption.column,
|
||||
'organizationName'
|
||||
);
|
||||
vehicleColumn.dicData = this.organizationOptions;
|
||||
if (this.driverBox && !this.driverForm.id && !this.driverForm.organizationName) {
|
||||
this.driverForm.organizationName = this.getCurrentOrganizationName();
|
||||
}
|
||||
@@ -952,6 +1073,75 @@ export default {
|
||||
this.submitLoading = false;
|
||||
this.$refs.driverForm?.clearValidate();
|
||||
},
|
||||
openVehicleSelector() {
|
||||
if (this.readonly) return;
|
||||
this.vehicleSelectorPage.currentPage = 1;
|
||||
this.vehicleSelectorVisible = true;
|
||||
},
|
||||
resetVehicleSelector() {
|
||||
this.vehicleSelectorForm = {};
|
||||
this.vehicleSelectorData = [];
|
||||
this.vehicleSelectorSearchForm = {};
|
||||
this.vehicleSelectorPage = {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
normalizeVehicleSelectorQuery(params = {}) {
|
||||
const query = {
|
||||
...this.vehicleSelectorSearchForm,
|
||||
...params,
|
||||
};
|
||||
if (Array.isArray(query.organizationName)) {
|
||||
query.organizationName = query.organizationName[query.organizationName.length - 1] || '';
|
||||
}
|
||||
return query;
|
||||
},
|
||||
loadVehicleSelector(page = this.vehicleSelectorPage, params = {}) {
|
||||
this.vehicleSelectorLoading = true;
|
||||
getVehicleList(page.currentPage, page.pageSize, this.normalizeVehicleSelectorQuery(params))
|
||||
.then(res => {
|
||||
const data = res.data.data || {};
|
||||
this.vehicleSelectorData = data.records || [];
|
||||
this.vehicleSelectorPage.total = data.total || 0;
|
||||
})
|
||||
.finally(() => {
|
||||
this.vehicleSelectorLoading = false;
|
||||
});
|
||||
},
|
||||
vehicleSelectorSearchChange(params, done) {
|
||||
this.vehicleSelectorSearchForm = params;
|
||||
this.vehicleSelectorPage.currentPage = 1;
|
||||
this.loadVehicleSelector(this.vehicleSelectorPage, params);
|
||||
done();
|
||||
},
|
||||
vehicleSelectorSearchReset() {
|
||||
this.vehicleSelectorSearchForm = {};
|
||||
this.vehicleSelectorPage.currentPage = 1;
|
||||
this.loadVehicleSelector();
|
||||
},
|
||||
vehicleSelectorCurrentChange(currentPage) {
|
||||
this.vehicleSelectorPage.currentPage = currentPage;
|
||||
},
|
||||
vehicleSelectorSizeChange(pageSize) {
|
||||
this.vehicleSelectorPage.pageSize = pageSize;
|
||||
},
|
||||
vehicleSelectorRefreshChange() {
|
||||
this.loadVehicleSelector();
|
||||
},
|
||||
selectDrivingVehicle(row) {
|
||||
this.driverForm.drivingVehicle = row.plateNo || '';
|
||||
this.vehicleSelectorVisible = false;
|
||||
},
|
||||
getVehicleCertificationStatus(row) {
|
||||
const statusMap = {
|
||||
0: { label: '认证中', type: 'warning' },
|
||||
1: { label: '已认证', type: 'success' },
|
||||
2: { label: '已驳回', type: 'danger' },
|
||||
};
|
||||
return statusMap[row.certificationStatus] || { label: '-', type: 'info' };
|
||||
},
|
||||
setImage(prop, url) {
|
||||
this.driverForm[prop] = url;
|
||||
this.$refs.driverForm?.validateField(prop);
|
||||
|
||||
@@ -96,22 +96,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
@@ -142,6 +130,7 @@ import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/accident-record';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -152,6 +141,9 @@ const createTimeRangeMap = {
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -83,22 +83,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
@@ -128,12 +116,16 @@ import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/annual-inspection-record';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -146,9 +146,11 @@
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="信用等级" prop="creditLevel" width="120" align="center" />
|
||||
<el-table-column label="标准说明" prop="standardDescription" min-width="320" />
|
||||
<el-table-column v-if="!readonly" label="操作" width="160" align="center">
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-link type="primary" @click="openStandard(row, $index)">编辑</el-link>
|
||||
<el-link type="primary" @click="openStandard(row, $index)">
|
||||
{{ readonly ? '查看' : '编辑' }}
|
||||
</el-link>
|
||||
<el-link type="danger" v-if="!readonly" @click="removeStandard($index)"
|
||||
>删除</el-link
|
||||
>
|
||||
@@ -450,7 +452,7 @@
|
||||
</el-form>
|
||||
</section-card>
|
||||
<template #footer>
|
||||
<el-button @click="standardBox = false">取消</el-button>
|
||||
<el-button @click="standardBox = false">{{ readonly ? '关闭' : '取消' }}</el-button>
|
||||
<el-button type="primary" v-if="!readonly" @click="saveStandard">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -4160,11 +4160,13 @@ export default {
|
||||
)}分`
|
||||
);
|
||||
this.calculateScore(this.currentScore);
|
||||
if (prop === 'reviewScore') this.logReviewScoreSummary();
|
||||
return;
|
||||
}
|
||||
}
|
||||
detail[prop] = normalized;
|
||||
this.calculateScore(this.currentScore);
|
||||
if (prop === 'reviewScore') this.logReviewScoreSummary();
|
||||
},
|
||||
handleScoreDecimalInput(prop, value) {
|
||||
const normalized = String(value || '')
|
||||
@@ -4217,6 +4219,15 @@ export default {
|
||||
return sum + this.getScoreItemFullScore(item);
|
||||
}, 0);
|
||||
},
|
||||
logReviewScoreSummary() {
|
||||
const details = this.currentScore.details || [];
|
||||
console.log('[评分详情] 复评评分结果', {
|
||||
复评总分: this.currentScore.reviewScore,
|
||||
总分: this.getScoreFullMark(details),
|
||||
得分率: `${this.currentScore.scoreRate}%`,
|
||||
匹配到的信用等级: this.currentScore.creditLevel || '',
|
||||
});
|
||||
},
|
||||
matchCreditStandard(score, scoreRate) {
|
||||
const standards = (score.standards || [])
|
||||
.filter(item => item && item.creditLevel)
|
||||
|
||||
@@ -85,10 +85,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="ETC记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -111,12 +111,16 @@ import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/etc-record';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -122,22 +122,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="保养记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -169,6 +157,7 @@ import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
@@ -180,6 +169,7 @@ const createTimeRangeMap = {
|
||||
export default {
|
||||
components: {
|
||||
AddressMapPicker,
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
const validateNonNegative = (rule, value, callback) => {
|
||||
@@ -377,6 +367,7 @@ export default {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
|
||||
@@ -106,22 +106,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="维修记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -153,6 +141,7 @@ import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
@@ -164,6 +153,7 @@ const createTimeRangeMap = {
|
||||
export default {
|
||||
components: {
|
||||
AddressMapPicker,
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
const validateNonNegative = (rule, value, callback) => {
|
||||
@@ -362,6 +352,7 @@ export default {
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
hide: true,
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
@@ -542,9 +533,14 @@ export default {
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
formatMileage(value, unit) {
|
||||
if (value === undefined || value === null || value === '') return '';
|
||||
if (this.normalizeMileageValue(value) === null) return '';
|
||||
return `${Math.max(Number(value), 0)} ${unit || '公里'}`;
|
||||
},
|
||||
normalizeMileageValue(value) {
|
||||
if (value === undefined || value === null || value === '' || Number(value) === -1)
|
||||
return null;
|
||||
return value;
|
||||
},
|
||||
formatAttachments(value) {
|
||||
if (!value) return '';
|
||||
if (Array.isArray(value)) return `${value.length} 个`;
|
||||
@@ -595,6 +591,7 @@ export default {
|
||||
const values = { ...row };
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
values.mileage = this.normalizeMileageValue(values.mileage);
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
@@ -676,6 +673,7 @@ export default {
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
detail.mileageUnit = detail.vehicleType === '船舶' ? '海里' : '公里';
|
||||
detail.mileage = this.normalizeMileageValue(detail.mileage);
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
})
|
||||
|
||||
@@ -149,10 +149,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
@@ -183,6 +183,7 @@ import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/mileage-record';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -193,6 +194,9 @@ const createTimeRangeMap = {
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -116,10 +116,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="油电记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -143,12 +143,16 @@ import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/oil-electric-record';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -85,10 +85,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="其他费用记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -112,12 +112,16 @@ import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/other-expense-record';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -94,22 +94,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
@@ -139,6 +127,7 @@ import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/tire-replacement-record';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -149,6 +138,9 @@ const createTimeRangeMap = {
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -74,10 +74,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="变更记录数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
@@ -102,6 +102,7 @@ import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/transport-change-record';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -112,6 +113,9 @@ const createTimeRangeMap = {
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
|
||||
@@ -128,22 +128,10 @@
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
@@ -182,6 +170,7 @@ import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/violation-record';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -194,6 +183,7 @@ const createTimeRangeMap = {
|
||||
export default {
|
||||
components: {
|
||||
AddressMapPicker,
|
||||
VehicleAttachmentTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -519,6 +509,7 @@ export default {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
processStatus: '未处理',
|
||||
attachments: [],
|
||||
};
|
||||
this.updateVehicleTypeDisplays('车辆');
|
||||
this.updateProcessResultDisplay('未处理');
|
||||
|
||||
+172
-172
@@ -1,177 +1,177 @@
|
||||
<template>
|
||||
<basic-container>
|
||||
<div class="wel">
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-platform-eleme"
|
||||
text="开始菜单1"
|
||||
time="1"
|
||||
background="/img/bg/bg3.jpg"
|
||||
color="#d56259"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-eleme"
|
||||
text="开始菜单2"
|
||||
time="2"
|
||||
background="/img/bg/bg2.jpg"
|
||||
color="#419ce7"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-delete-solid"
|
||||
text="开始菜单3"
|
||||
time="3"
|
||||
color="#56b69b"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-delete"
|
||||
text="开始菜单4"
|
||||
time="4"
|
||||
color="#d44858"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-tools"
|
||||
text="开始菜单5"
|
||||
time="5"
|
||||
color="#3a1f7e"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="410"
|
||||
:height="height"
|
||||
icon="el-icon-setting"
|
||||
text="开始菜单6"
|
||||
time="6"
|
||||
background="/img/bg/bg1.jpg"
|
||||
dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"
|
||||
color="#422829"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-user-solid"
|
||||
text="开始菜单7"
|
||||
time="7"
|
||||
color="#613cbd"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-star-off"
|
||||
text="开始菜单8"
|
||||
time="8"
|
||||
color="#da542e"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-goods"
|
||||
text="开始菜单9"
|
||||
time="9"
|
||||
color="#2e8aef"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-circle-check"
|
||||
text="开始菜单10"
|
||||
time="10"
|
||||
color="#3d17b8"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-platform"
|
||||
text="开始菜单11"
|
||||
time="11"
|
||||
color="#e31462"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-fold"
|
||||
text="开始菜单12"
|
||||
time="12"
|
||||
color="#d9532d"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="410"
|
||||
:height="height"
|
||||
icon="el-icon-s-open"
|
||||
text="开始菜单13"
|
||||
time="13"
|
||||
dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"
|
||||
color="#b72147"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-flag"
|
||||
text="开始菜单14"
|
||||
time="14"
|
||||
color="#01a100"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-data"
|
||||
text="开始菜单15"
|
||||
time="15"
|
||||
color="#0c56bf"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-grid"
|
||||
text="开始菜单16"
|
||||
time="16"
|
||||
color="#0098a9"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-release"
|
||||
text="开始菜单17"
|
||||
time="17"
|
||||
background="/img/bg/bg2.jpg"
|
||||
color="#209bdf"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="width"
|
||||
:height="height"
|
||||
icon="el-icon-s-home"
|
||||
text="开始菜单18"
|
||||
time="18"
|
||||
background="/img/bg/bg3.jpg"
|
||||
color="#603bbc"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="515"
|
||||
:height="height"
|
||||
icon="el-icon-s-promotion"
|
||||
text="开始菜单19"
|
||||
time="19"
|
||||
dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"
|
||||
color="#009bad"
|
||||
></basic-block>
|
||||
<basic-block
|
||||
:width="515"
|
||||
:height="height"
|
||||
icon="el-icon-s-custom"
|
||||
text="开始菜单20"
|
||||
time="20"
|
||||
background="/img/bg/bg4.jpg"
|
||||
dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"
|
||||
color="#d74e2a"
|
||||
></basic-block>
|
||||
</div>
|
||||
<!-- <div class="wel">-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-platform-eleme"-->
|
||||
<!-- text="开始菜单1"-->
|
||||
<!-- time="1"-->
|
||||
<!-- background="/img/bg/bg3.jpg"-->
|
||||
<!-- color="#d56259"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-eleme"-->
|
||||
<!-- text="开始菜单2"-->
|
||||
<!-- time="2"-->
|
||||
<!-- background="/img/bg/bg2.jpg"-->
|
||||
<!-- color="#419ce7"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-delete-solid"-->
|
||||
<!-- text="开始菜单3"-->
|
||||
<!-- time="3"-->
|
||||
<!-- color="#56b69b"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-delete"-->
|
||||
<!-- text="开始菜单4"-->
|
||||
<!-- time="4"-->
|
||||
<!-- color="#d44858"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-tools"-->
|
||||
<!-- text="开始菜单5"-->
|
||||
<!-- time="5"-->
|
||||
<!-- color="#3a1f7e"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="410"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-setting"-->
|
||||
<!-- text="开始菜单6"-->
|
||||
<!-- time="6"-->
|
||||
<!-- background="/img/bg/bg1.jpg"-->
|
||||
<!-- dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"-->
|
||||
<!-- color="#422829"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-user-solid"-->
|
||||
<!-- text="开始菜单7"-->
|
||||
<!-- time="7"-->
|
||||
<!-- color="#613cbd"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-star-off"-->
|
||||
<!-- text="开始菜单8"-->
|
||||
<!-- time="8"-->
|
||||
<!-- color="#da542e"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-goods"-->
|
||||
<!-- text="开始菜单9"-->
|
||||
<!-- time="9"-->
|
||||
<!-- color="#2e8aef"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-circle-check"-->
|
||||
<!-- text="开始菜单10"-->
|
||||
<!-- time="10"-->
|
||||
<!-- color="#3d17b8"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-platform"-->
|
||||
<!-- text="开始菜单11"-->
|
||||
<!-- time="11"-->
|
||||
<!-- color="#e31462"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-fold"-->
|
||||
<!-- text="开始菜单12"-->
|
||||
<!-- time="12"-->
|
||||
<!-- color="#d9532d"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="410"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-open"-->
|
||||
<!-- text="开始菜单13"-->
|
||||
<!-- time="13"-->
|
||||
<!-- dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"-->
|
||||
<!-- color="#b72147"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-flag"-->
|
||||
<!-- text="开始菜单14"-->
|
||||
<!-- time="14"-->
|
||||
<!-- color="#01a100"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-data"-->
|
||||
<!-- text="开始菜单15"-->
|
||||
<!-- time="15"-->
|
||||
<!-- color="#0c56bf"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-grid"-->
|
||||
<!-- text="开始菜单16"-->
|
||||
<!-- time="16"-->
|
||||
<!-- color="#0098a9"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-release"-->
|
||||
<!-- text="开始菜单17"-->
|
||||
<!-- time="17"-->
|
||||
<!-- background="/img/bg/bg2.jpg"-->
|
||||
<!-- color="#209bdf"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="width"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-home"-->
|
||||
<!-- text="开始菜单18"-->
|
||||
<!-- time="18"-->
|
||||
<!-- background="/img/bg/bg3.jpg"-->
|
||||
<!-- color="#603bbc"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="515"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-promotion"-->
|
||||
<!-- text="开始菜单19"-->
|
||||
<!-- time="19"-->
|
||||
<!-- dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"-->
|
||||
<!-- color="#009bad"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- <basic-block-->
|
||||
<!-- :width="515"-->
|
||||
<!-- :height="height"-->
|
||||
<!-- icon="el-icon-s-custom"-->
|
||||
<!-- text="开始菜单20"-->
|
||||
<!-- time="20"-->
|
||||
<!-- background="/img/bg/bg4.jpg"-->
|
||||
<!-- dept="这是一段很长的很长很长很长的描述这是一段很长的很长很长很长的描述"-->
|
||||
<!-- color="#d74e2a"-->
|
||||
<!-- ></basic-block>-->
|
||||
<!-- </div>-->
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user