1、完善项目
2、完善合同 3、完善费用项 4、司机管理对接OCR 5、完善运输计划 6、完善临时额度
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,15 @@
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="canMajorProjectSupplement"
|
||||
@click="openProjectDialog('majorSupplement')"
|
||||
>
|
||||
重大项目补录
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@@ -44,16 +53,6 @@
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
<el-switch
|
||||
v-if="config.enableAllDept && canViewAllDept"
|
||||
v-model="allDept"
|
||||
class="project-apply-page__scope"
|
||||
active-text="全部组织"
|
||||
inactive-text="当前组织"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="handleScopeChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #approvalStatus="{ row }">
|
||||
@@ -71,12 +70,7 @@
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
v-if="canEdit(row)"
|
||||
@click="openProjectDialog('edit', row)"
|
||||
>
|
||||
<el-button type="primary" text v-if="canEdit(row)" @click="openProjectDialog('edit', row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -88,14 +82,7 @@
|
||||
>
|
||||
{{ operation.label }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
v-if="canDelete(row)"
|
||||
@click="rowDel(row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button type="primary" text v-if="canDelete(row)" @click="rowDel(row)"> 删除 </el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
@@ -127,8 +114,25 @@
|
||||
>
|
||||
<div class="dialog-section-title">项目基本信息</div>
|
||||
<div class="project-apply-form__grid">
|
||||
<el-form-item v-if="isChangeDialog" label="变更类型" prop="changeType">
|
||||
<el-select v-model="form.changeType" placeholder="请选择变更类型">
|
||||
<el-option
|
||||
v-for="item in changeTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-if="isChangeDialog"></div>
|
||||
<el-form-item label="项目类型" prop="projectType">
|
||||
<el-select v-model="form.projectType" placeholder="请选择项目类型" clearable>
|
||||
<el-select
|
||||
v-model="form.projectType"
|
||||
placeholder="请选择项目类型"
|
||||
clearable
|
||||
:disabled="isBasicInfoReadonly || isMajorProjectSupplementDialog"
|
||||
@change="handleProjectTypeChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectTypeOptions"
|
||||
:key="item.value"
|
||||
@@ -141,10 +145,20 @@
|
||||
<el-input v-model="form.projectCode" disabled placeholder="系统自动生成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请填写项目名称" maxlength="50" />
|
||||
<el-input
|
||||
v-model="form.projectName"
|
||||
placeholder="请填写项目名称"
|
||||
maxlength="50"
|
||||
:disabled="isBasicInfoReadonly"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目简称" prop="projectShortName">
|
||||
<el-input v-model="form.projectShortName" placeholder="请填写项目简称" maxlength="20" />
|
||||
<el-input
|
||||
v-model="form.projectShortName"
|
||||
placeholder="请填写项目简称"
|
||||
maxlength="20"
|
||||
:disabled="isBasicInfoReadonly"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="业务部门" prop="businessDeptId">
|
||||
<el-select
|
||||
@@ -152,6 +166,7 @@
|
||||
placeholder="请选择业务部门"
|
||||
filterable
|
||||
clearable
|
||||
:disabled="isBasicInfoReadonly"
|
||||
@change="handleBusinessDeptChange"
|
||||
>
|
||||
<el-option
|
||||
@@ -168,6 +183,7 @@
|
||||
placeholder="请选择承办部门"
|
||||
filterable
|
||||
clearable
|
||||
:disabled="isBasicInfoReadonly"
|
||||
@change="handleUndertakeDeptChange"
|
||||
>
|
||||
<el-option
|
||||
@@ -179,7 +195,12 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目由来" prop="projectSource">
|
||||
<el-select v-model="form.projectSource" placeholder="请选择项目由来" clearable>
|
||||
<el-select
|
||||
v-model="form.projectSource"
|
||||
placeholder="请选择项目由来"
|
||||
clearable
|
||||
:disabled="isBasicInfoReadonly"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectSourceOptions"
|
||||
:key="item.value"
|
||||
@@ -189,7 +210,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目由来说明" prop="sourceRemark">
|
||||
<el-input v-model="form.sourceRemark" maxlength="300" />
|
||||
<el-input v-model="form.sourceRemark" maxlength="300" :disabled="isBasicInfoReadonly" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
@@ -368,10 +389,7 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="dialog-section-title project-apply-form__table-title">
|
||||
客户信息
|
||||
<span class="project-apply-form__tip">选择客户/承运商信息后,自动关联出客商信息</span>
|
||||
</div>
|
||||
<div class="dialog-section-title project-apply-form__table-title">客户信息</div>
|
||||
<el-table :data="customerRows" border class="project-apply-form__table">
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="customer" label="客户" min-width="160" align="center" />
|
||||
@@ -451,12 +469,7 @@
|
||||
</div>
|
||||
|
||||
<div class="project-apply-form__material-head">
|
||||
<div class="dialog-section-title project-apply-form__material-title">
|
||||
项目材料
|
||||
<span class="project-apply-form__material-warn">
|
||||
项目立项报告、考察报告、立项成本测算表、企业资质板附件未上传
|
||||
</span>
|
||||
</div>
|
||||
<div class="dialog-section-title project-apply-form__material-title">项目材料</div>
|
||||
<el-button type="primary" :disabled="!attachmentRows.length" @click="handleBatchDownload"
|
||||
>批量下载</el-button
|
||||
>
|
||||
@@ -466,21 +479,18 @@
|
||||
<el-table-column label="附件类型" min-width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.fileType" placeholder="请选择" :disabled="dialogReadonly">
|
||||
<el-option label="项目立项报告" value="项目立项报告" />
|
||||
<el-option label="考察报告" value="考察报告" />
|
||||
<el-option label="立项成本测算表" value="立项成本测算表" />
|
||||
<el-option label="企业资质板附件" value="企业资质板附件" />
|
||||
<el-option label="其他" value="其他" />
|
||||
<el-option
|
||||
v-for="item in projectAttachmentTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="文件名"
|
||||
min-width="220"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="文件名" min-width="220" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.originalName || row.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件描述" min-width="240" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
@@ -519,13 +529,15 @@
|
||||
@change="handleAttachmentChange"
|
||||
/>
|
||||
|
||||
<div class="dialog-section-title project-apply-form__table-title">
|
||||
<div v-if="!isChangeDialog" class="dialog-section-title project-apply-form__table-title">
|
||||
变更记录
|
||||
<span class="project-apply-form__tip"
|
||||
>查看页面显示变更记录,变更提交后生成,可查看详情页面</span
|
||||
>
|
||||
</div>
|
||||
<el-table :data="changeRows" border class="project-apply-form__table">
|
||||
<el-table
|
||||
v-if="!isChangeDialog"
|
||||
:data="changeRows"
|
||||
border
|
||||
class="project-apply-form__table"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="changeDate" label="变更日期" min-width="140" align="center" />
|
||||
<el-table-column prop="changeType" label="变更类型" min-width="160" align="center" />
|
||||
@@ -553,19 +565,58 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template v-if="isChangeDialog">
|
||||
<div class="dialog-section-title">变更内容</div>
|
||||
<el-form-item prop="changeContent" class="project-apply-form__change-textarea">
|
||||
<el-input
|
||||
v-model="form.changeContent"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
placeholder="2000字以内"
|
||||
maxlength="2000"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="dialog-section-title">变更原因</div>
|
||||
<el-form-item prop="changeReason" class="project-apply-form__change-textarea">
|
||||
<el-input
|
||||
v-model="form.changeReason"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
placeholder="2000字以内"
|
||||
maxlength="2000"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="project-apply-dialog__footer">
|
||||
<el-button @click="projectBox = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="!dialogReadonly"
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="submitProject"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
<div
|
||||
class="project-apply-dialog__footer"
|
||||
:class="{ 'project-apply-dialog__footer--change': isChangeDialog }"
|
||||
>
|
||||
<template v-if="isChangeDialog">
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitChangeProject">
|
||||
提交
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="saveChangeProject">
|
||||
保存
|
||||
</el-button>
|
||||
<el-button @click="projectBox = false">关闭</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button @click="projectBox = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="!dialogReadonly"
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="submitProject"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -628,9 +679,11 @@ import {
|
||||
getDetail as getCustomerArchiveDetail,
|
||||
} from '@/api/vehicle/customer-archive';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { getDictionary } from '@/api/system/dict';
|
||||
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||
import { getDictionary as getBizDictionary } from '@/api/system/dictbiz';
|
||||
import { getList as getUserList } from '@/api/system/user';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { applyTableMenuWidth } from '@/utils/table-menu';
|
||||
import { downloadFileByUrl, downloadXls } from '@/utils/util';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -640,7 +693,6 @@ import {
|
||||
projectSourceOptions,
|
||||
projectTypeOptions,
|
||||
settlementModeOptions,
|
||||
transportTypeOptions,
|
||||
} from '@/option/business/common';
|
||||
import { config, option } from '@/option/business/project-apply';
|
||||
|
||||
@@ -655,6 +707,7 @@ const emptyForm = () => ({
|
||||
undertakeDeptName: '',
|
||||
projectSource: '商务洽谈',
|
||||
sourceRemark: '',
|
||||
changeType: '',
|
||||
customerNames: '',
|
||||
carrierNames: '',
|
||||
fundLimit: '',
|
||||
@@ -685,8 +738,38 @@ const emptyForm = () => ({
|
||||
profitRemark: '',
|
||||
riskPoint: '',
|
||||
emergencyPlan: '',
|
||||
changeContent: '',
|
||||
changeReason: '',
|
||||
});
|
||||
|
||||
const changeTypeOptions = [
|
||||
{ label: '项目变更', value: '项目变更' },
|
||||
{ label: '项目备案调整', value: '项目备案调整' },
|
||||
];
|
||||
|
||||
const normalProjectAttachmentTypeOptions = [
|
||||
'利润测算表',
|
||||
'单一来源供应商申请表/三方比价表',
|
||||
'合同模板',
|
||||
'项目操作说明',
|
||||
'项目分析报告',
|
||||
'项目考察报告',
|
||||
].map(item => ({ label: item, value: item }));
|
||||
|
||||
const majorProjectAttachmentTypeOptions = [
|
||||
'会议纪要',
|
||||
'评审表决票',
|
||||
'利润测算表',
|
||||
'单一来源供应商申请表/三方比价表',
|
||||
'项目操作说明',
|
||||
'项目分析报告',
|
||||
'项目考察报告',
|
||||
'合同模板',
|
||||
'上游尽职调查报告',
|
||||
'下游尽职调查报告',
|
||||
'业务承诺函',
|
||||
].map(item => ({ label: item, value: item }));
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const validateAmount = (rule, value, callback) => {
|
||||
@@ -719,14 +802,22 @@ export default {
|
||||
}
|
||||
callback();
|
||||
};
|
||||
const validateUser = (rule, value, callback) => {
|
||||
if (value || this.form[rule.nameProp]) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
callback(new Error(`请选择${rule.label}`));
|
||||
};
|
||||
return {
|
||||
api,
|
||||
config,
|
||||
projectTypeOptions,
|
||||
projectSourceOptions,
|
||||
transportTypeOptions,
|
||||
transportTypeOptions: [],
|
||||
businessTypeOptions,
|
||||
settlementModeOptions,
|
||||
changeTypeOptions,
|
||||
tableForm: {},
|
||||
tableOption: this.buildTableOption(),
|
||||
loading: true,
|
||||
@@ -746,6 +837,7 @@ export default {
|
||||
submitLoading: false,
|
||||
form: emptyForm(),
|
||||
formRules: {
|
||||
changeType: [{ required: true, message: '请选择变更类型', trigger: 'change' }],
|
||||
projectType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
|
||||
projectName: [
|
||||
{ required: true, message: '请输入项目名称', trigger: 'blur' },
|
||||
@@ -784,8 +876,30 @@ export default {
|
||||
projectScale: [{ label: '项目规模', validator: validateAmount, trigger: 'blur' }],
|
||||
estimatedProfit: [{ label: '预估利润', validator: validateAmount, trigger: 'blur' }],
|
||||
fundDemand: [{ label: '资金需求', validator: validateAmount, trigger: 'blur' }],
|
||||
handlerUserId: [{ required: true, message: '请选择项目经办人', trigger: 'change' }],
|
||||
principalUserId: [{ required: true, message: '请选择项目负责人', trigger: 'change' }],
|
||||
handlerUserId: [
|
||||
{
|
||||
label: '项目经办人',
|
||||
nameProp: 'handlerUserName',
|
||||
validator: validateUser,
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
principalUserId: [
|
||||
{
|
||||
label: '项目负责人',
|
||||
nameProp: 'principalUserName',
|
||||
validator: validateUser,
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
changeContent: [
|
||||
{ required: true, message: '请输入变更内容', trigger: 'blur' },
|
||||
{ max: 2000, message: '变更内容不能超过2000个字符', trigger: 'blur' },
|
||||
],
|
||||
changeReason: [
|
||||
{ required: true, message: '请输入变更原因', trigger: 'blur' },
|
||||
{ max: 2000, message: '变更原因不能超过2000个字符', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
deptOptions: [],
|
||||
cargoTypeOptions: [],
|
||||
@@ -852,29 +966,56 @@ export default {
|
||||
canCreate() {
|
||||
return this.hasPermission(`${this.config.permission}_add`) && !this.readonlyScope;
|
||||
},
|
||||
canMajorProjectSupplement() {
|
||||
return this.hasPermission(`${this.config.permission}_supplement`) && !this.readonlyScope;
|
||||
},
|
||||
isMajorProjectSupplementDialog() {
|
||||
return this.dialogType === 'majorSupplement';
|
||||
},
|
||||
isChangeDialog() {
|
||||
return this.dialogType === 'change';
|
||||
},
|
||||
isBasicInfoReadonly() {
|
||||
return this.dialogReadonly || this.isChangeDialog;
|
||||
},
|
||||
ids() {
|
||||
return this.selectionList.map(item => item.id).join(',');
|
||||
},
|
||||
projectDialogTitle() {
|
||||
if (this.isChangeDialog) {
|
||||
return '项目变更';
|
||||
}
|
||||
if (this.isMajorProjectSupplementDialog) {
|
||||
return '重大项目补录';
|
||||
}
|
||||
const text = { add: '新增', edit: '编辑', view: '查看' }[this.dialogType] || '新增';
|
||||
return `${text}${this.config.title}`;
|
||||
},
|
||||
projectAttachmentTypeOptions() {
|
||||
return this.form.projectType === '重大项目'
|
||||
? majorProjectAttachmentTypeOptions
|
||||
: normalProjectAttachmentTypeOptions;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.loadDeptOptions();
|
||||
this.loadCargoTypeOptions();
|
||||
this.loadTransportTypeOptions();
|
||||
},
|
||||
methods: {
|
||||
buildTableOption() {
|
||||
return {
|
||||
...option,
|
||||
dialogType: 'dialog',
|
||||
addBtn: false,
|
||||
viewBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
column: (option.column || []).map(column => ({ ...column, display: false })),
|
||||
};
|
||||
return applyTableMenuWidth(
|
||||
{
|
||||
...option,
|
||||
dialogType: 'dialog',
|
||||
addBtn: false,
|
||||
viewBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
column: (option.column || []).map(column => ({ ...column, display: false })),
|
||||
},
|
||||
4
|
||||
);
|
||||
},
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
|
||||
@@ -1029,9 +1170,17 @@ export default {
|
||||
this.selectionClear();
|
||||
},
|
||||
handleCustomOperation(operation, row) {
|
||||
if (operation.action === 'startChange') {
|
||||
this.openProjectDialog('change', row);
|
||||
return;
|
||||
}
|
||||
const run = value => {
|
||||
const args = operation.prompt ? [row.id, value] : [row.id];
|
||||
this.api[operation.action](...args).then(() => {
|
||||
this.api[operation.action](...args).then(res => {
|
||||
if (res.data?.success === false || res.data?.data === false) {
|
||||
this.$message.error(res.data?.msg || `${operation.label}失败,请联系管理员`);
|
||||
return;
|
||||
}
|
||||
this.$message.success(`${operation.label}成功`);
|
||||
this.onLoad(this.page, this.query);
|
||||
});
|
||||
@@ -1084,13 +1233,20 @@ export default {
|
||||
this.dialogType = type;
|
||||
this.dialogReadonly = type === 'view';
|
||||
this.projectBox = true;
|
||||
if (type === 'add') {
|
||||
this.applyProjectDetail(emptyForm());
|
||||
if (type === 'add' || type === 'majorSupplement') {
|
||||
this.applyProjectDetail({
|
||||
...emptyForm(),
|
||||
projectType: type === 'majorSupplement' ? '重大项目' : '',
|
||||
});
|
||||
this.fillDefaultUsers();
|
||||
return;
|
||||
}
|
||||
this.api.getDetail(row.id).then(res => {
|
||||
this.applyProjectDetail(res.data.data || {});
|
||||
const detail = res.data.data || {};
|
||||
this.applyProjectDetail({
|
||||
...detail,
|
||||
changeType: type === 'change' ? this.resolveChangeType(detail) : detail.changeType,
|
||||
});
|
||||
});
|
||||
},
|
||||
resetProjectDialog() {
|
||||
@@ -1113,16 +1269,23 @@ export default {
|
||||
: [],
|
||||
};
|
||||
const situation = this.parseSituation(row.situationRemark);
|
||||
const customerRows = this.parseJsonArray(row.customerJson);
|
||||
const carrierRows = this.parseJsonArray(row.carrierJson);
|
||||
this.form = {
|
||||
...form,
|
||||
...situation,
|
||||
customerNames: this.getCustomerRowNames(customerRows, 'customer') || form.customerNames,
|
||||
carrierNames: this.getCustomerRowNames(carrierRows, 'carrier') || form.carrierNames,
|
||||
};
|
||||
this.customerRows = this.parseJsonArray(row.customerJson);
|
||||
this.carrierRows = this.parseJsonArray(row.carrierJson);
|
||||
this.customerRows = customerRows;
|
||||
this.carrierRows = carrierRows;
|
||||
this.attachmentRows = this.parseJsonArray(row.attachmentsJson);
|
||||
this.changeRows = this.buildChangeRows(row);
|
||||
this.selectedCustomerId = this.customerRows[0]?.id || '';
|
||||
this.selectedCarrierIds = this.carrierRows.map(item => item.id).filter(Boolean);
|
||||
this.selectedCustomerId = this.getCustomerRowId(this.customerRows[0]);
|
||||
this.selectedCarrierIds = this.carrierRows
|
||||
.map(item => this.getCustomerRowId(item))
|
||||
.filter(Boolean);
|
||||
this.syncSelectedCustomerOptions();
|
||||
},
|
||||
fillDefaultUsers() {
|
||||
const userId = this.userInfo?.userId || this.userInfo?.id || '';
|
||||
@@ -1135,14 +1298,28 @@ export default {
|
||||
this.form.principalUserName = userName;
|
||||
}
|
||||
},
|
||||
resolveChangeType(row = {}) {
|
||||
if (row.changeType) return row.changeType;
|
||||
const node = row.currentNode || '';
|
||||
if (String(node).includes('备案')) return '项目备案调整';
|
||||
return '项目变更';
|
||||
},
|
||||
submitProject() {
|
||||
this.$refs.projectForm.validate(valid => {
|
||||
if (!valid) return;
|
||||
if (!valid) {
|
||||
this.handleValidateFail();
|
||||
return;
|
||||
}
|
||||
if (!this.validateAttachmentFileTypes()) return;
|
||||
this.submitLoading = true;
|
||||
this.api
|
||||
.submit(this.normalizeSubmitForm())
|
||||
.then(
|
||||
() => {
|
||||
res => {
|
||||
if (res.data?.success === false || res.data?.data === false) {
|
||||
this.$message.error(res.data?.msg || '保存失败,请联系管理员');
|
||||
return;
|
||||
}
|
||||
this.$message.success('操作成功!');
|
||||
this.projectBox = false;
|
||||
this.onLoad(this.page, this.query);
|
||||
@@ -1156,7 +1333,39 @@ export default {
|
||||
});
|
||||
});
|
||||
},
|
||||
normalizeSubmitForm() {
|
||||
saveChangeProject() {
|
||||
this.submitChangeForm(false);
|
||||
},
|
||||
submitChangeProject() {
|
||||
this.submitChangeForm(true);
|
||||
},
|
||||
submitChangeForm(needSubmit) {
|
||||
this.$refs.projectForm.validate(valid => {
|
||||
if (!valid) {
|
||||
this.handleValidateFail();
|
||||
return;
|
||||
}
|
||||
if (!this.validateAttachmentFileTypes()) return;
|
||||
this.submitLoading = true;
|
||||
const request = needSubmit ? this.api.submitChange : this.api.saveChange;
|
||||
request(this.normalizeSubmitForm({ includeChangeType: true }))
|
||||
.then(res => {
|
||||
if (res.data?.success === false || res.data?.data === false) {
|
||||
this.$message.error(
|
||||
res.data?.msg || `${needSubmit ? '提交' : '保存'}失败,请联系管理员`
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.$message.success(`${needSubmit ? '提交' : '保存'}成功!`);
|
||||
this.projectBox = false;
|
||||
this.onLoad(this.page, this.query);
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitLoading = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
normalizeSubmitForm(options = {}) {
|
||||
const [businessStartDate, businessEndDate] = this.form.businessDateRange || [];
|
||||
const submitRow = {
|
||||
...this.form,
|
||||
@@ -1173,6 +1382,9 @@ export default {
|
||||
}),
|
||||
};
|
||||
delete submitRow.businessDateRange;
|
||||
if (!options.includeChangeType) {
|
||||
delete submitRow.changeType;
|
||||
}
|
||||
['projectIntro', 'profitRemark', 'riskPoint', 'emergencyPlan'].forEach(
|
||||
key => delete submitRow[key]
|
||||
);
|
||||
@@ -1183,6 +1395,35 @@ export default {
|
||||
});
|
||||
return submitRow;
|
||||
},
|
||||
normalizeAttachmentFileTypes() {
|
||||
const values = this.projectAttachmentTypeOptions.map(item => item.value);
|
||||
this.attachmentRows = this.attachmentRows.map(row => ({
|
||||
...row,
|
||||
fileType: values.includes(row.fileType) ? row.fileType : '',
|
||||
}));
|
||||
},
|
||||
validateAttachmentFileTypes() {
|
||||
const values = this.projectAttachmentTypeOptions.map(item => item.value);
|
||||
const invalidIndex = this.attachmentRows.findIndex(row => !values.includes(row.fileType));
|
||||
if (invalidIndex === -1) return true;
|
||||
this.$message.warning(`请选择第${invalidIndex + 1}行项目材料的附件类型`);
|
||||
this.$nextTick(() => {
|
||||
const field = this.$el.querySelector('.project-apply-form__material-head');
|
||||
if (field && typeof field.scrollIntoView === 'function') {
|
||||
field.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
});
|
||||
return false;
|
||||
},
|
||||
handleValidateFail() {
|
||||
this.$message.warning('请完善表单必填项后再提交');
|
||||
this.$nextTick(() => {
|
||||
const field = this.$el.querySelector('.is-error');
|
||||
if (field && typeof field.scrollIntoView === 'function') {
|
||||
field.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
});
|
||||
},
|
||||
parseSituation(value) {
|
||||
if (!value) {
|
||||
return { projectIntro: '', profitRemark: '', riskPoint: '', emergencyPlan: '' };
|
||||
@@ -1212,15 +1453,63 @@ export default {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
getCustomerRowId(row = {}) {
|
||||
return row.id || row.customerId || row.carrierId || '';
|
||||
},
|
||||
getCustomerRowLabel(row = {}, type) {
|
||||
return (
|
||||
row[type === 'carrier' ? 'carrier' : 'customer'] ||
|
||||
row.fullName ||
|
||||
row.shortName ||
|
||||
row.customerName ||
|
||||
row.carrierName ||
|
||||
row.customerCode ||
|
||||
''
|
||||
);
|
||||
},
|
||||
getCustomerRowNames(rows = [], type) {
|
||||
return rows
|
||||
.map(row => this.getCustomerRowLabel(row, type))
|
||||
.filter(Boolean)
|
||||
.join('、');
|
||||
},
|
||||
buildCustomerOptionsFromRows(rows = [], type) {
|
||||
return rows
|
||||
.map(row => {
|
||||
const value = this.getCustomerRowId(row);
|
||||
const label = this.getCustomerRowLabel(row, type);
|
||||
return value && label ? { label, value, raw: row } : null;
|
||||
})
|
||||
.filter(Boolean);
|
||||
},
|
||||
mergeCustomerOptions(options = [], selectedOptions = []) {
|
||||
const result = [...selectedOptions];
|
||||
options.forEach(option => {
|
||||
const exists = result.some(item => String(item.value) === String(option.value));
|
||||
if (!exists) {
|
||||
result.push(option);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
syncSelectedCustomerOptions() {
|
||||
this.customerOptions = this.mergeCustomerOptions(
|
||||
this.customerOptions,
|
||||
this.buildCustomerOptionsFromRows(this.customerRows, 'customer')
|
||||
);
|
||||
this.carrierOptions = this.mergeCustomerOptions(
|
||||
this.carrierOptions,
|
||||
this.buildCustomerOptionsFromRows(this.carrierRows, 'carrier')
|
||||
);
|
||||
},
|
||||
buildChangeRows(row) {
|
||||
if (!row || (!row.changeContent && !row.changeReason)) return [];
|
||||
return [
|
||||
{
|
||||
changeDate: row.updateTime || row.createTime || '',
|
||||
changeType:
|
||||
row.approvalStatus && String(row.approvalStatus).includes('change')
|
||||
? '项目变更'
|
||||
: '项目调整备案',
|
||||
row.changeType ||
|
||||
(String(row.currentNode || '').includes('备案') ? '项目备案调整' : '项目变更'),
|
||||
handler: row.handlerUserName || '',
|
||||
content: row.changeContent || '',
|
||||
reason: row.changeReason || '',
|
||||
@@ -1239,6 +1528,10 @@ export default {
|
||||
this.form.undertakeDeptName = dept ? dept.rawLabel : '';
|
||||
this.$refs.projectForm?.validateField('undertakeDeptId');
|
||||
},
|
||||
handleProjectTypeChange() {
|
||||
this.normalizeAttachmentFileTypes();
|
||||
this.$refs.projectForm?.validateField('projectType');
|
||||
},
|
||||
loadDeptOptions() {
|
||||
getDeptTree().then(res => {
|
||||
this.deptOptions = this.flattenDept(res.data.data || []);
|
||||
@@ -1259,13 +1552,21 @@ export default {
|
||||
}, []);
|
||||
},
|
||||
loadCargoTypeOptions() {
|
||||
getDictionary({ code: 'type_of_goods' }).then(res => {
|
||||
getSystemDictionary({ code: 'type_of_goods' }).then(res => {
|
||||
this.cargoTypeOptions = (res.data.data || []).map(item => ({
|
||||
label: item.dictValue,
|
||||
value: item.dictKey,
|
||||
}));
|
||||
});
|
||||
},
|
||||
loadTransportTypeOptions() {
|
||||
getBizDictionary({ code: 'transport_type' }).then(res => {
|
||||
this.transportTypeOptions = (res.data.data || []).map(item => ({
|
||||
label: item.dictValue,
|
||||
value: item.dictKey,
|
||||
}));
|
||||
});
|
||||
},
|
||||
loadCustomerOptions(type) {
|
||||
const loadingKey = type === '客户' ? 'customerLoading' : 'carrierLoading';
|
||||
const optionsKey = type === '客户' ? 'customerOptions' : 'carrierOptions';
|
||||
@@ -1273,7 +1574,14 @@ export default {
|
||||
getCustomerArchiveList(1, 100, { customerType: type, status: 1 })
|
||||
.then(res => {
|
||||
const records = (res.data.data && res.data.data.records) || [];
|
||||
this[optionsKey] = records.map(item => this.mapCustomerOption(item));
|
||||
const selectedOptions = this.buildCustomerOptionsFromRows(
|
||||
type === '客户' ? this.customerRows : this.carrierRows,
|
||||
type === '客户' ? 'customer' : 'carrier'
|
||||
);
|
||||
this[optionsKey] = this.mergeCustomerOptions(
|
||||
records.map(item => this.mapCustomerOption(item)),
|
||||
selectedOptions
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
this[loadingKey] = false;
|
||||
@@ -1298,6 +1606,7 @@ export default {
|
||||
this.customerRows = [row];
|
||||
this.form.customerNames = row.customer;
|
||||
this.form.customerJson = JSON.stringify(this.customerRows);
|
||||
this.syncSelectedCustomerOptions();
|
||||
this.$refs.projectForm?.validateField('customerNames');
|
||||
});
|
||||
},
|
||||
@@ -1312,6 +1621,7 @@ export default {
|
||||
this.carrierRows = rows;
|
||||
this.form.carrierNames = rows.map(item => item.carrier).join('、');
|
||||
this.form.carrierJson = JSON.stringify(this.carrierRows);
|
||||
this.syncSelectedCustomerOptions();
|
||||
this.$refs.projectForm?.validateField('carrierNames');
|
||||
});
|
||||
},
|
||||
@@ -1353,9 +1663,10 @@ export default {
|
||||
handleAttachmentChange(list) {
|
||||
const userName = this.userInfo?.realName || this.userInfo?.userName || '';
|
||||
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
const values = this.projectAttachmentTypeOptions.map(item => item.value);
|
||||
this.attachmentRows = (list || []).map(item => ({
|
||||
...item,
|
||||
fileType: item.fileType || '其他',
|
||||
fileType: values.includes(item.fileType) ? item.fileType : '',
|
||||
description: item.description || '',
|
||||
uploadUserName: item.uploadUserName || userName,
|
||||
uploadTime: item.uploadTime || uploadTime,
|
||||
@@ -1377,7 +1688,7 @@ export default {
|
||||
this.$message.warning('附件地址为空');
|
||||
return;
|
||||
}
|
||||
downloadFileByUrl(url, row.name || '附件');
|
||||
downloadFileByUrl(url, row.originalName || row.name || '附件');
|
||||
},
|
||||
handleBatchDownload() {
|
||||
this.attachmentRows.forEach(row => this.downloadAttachment(row));
|
||||
@@ -1425,13 +1736,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.project-apply-page {
|
||||
&__scope {
|
||||
margin-left: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.project-apply-form {
|
||||
padding: 0 8px;
|
||||
|
||||
@@ -1523,6 +1827,15 @@ export default {
|
||||
&__upload {
|
||||
margin: -12px 0 24px;
|
||||
}
|
||||
|
||||
&__change-textarea {
|
||||
margin-bottom: 24px;
|
||||
|
||||
:deep(.el-form-item__content) {
|
||||
width: 100%;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global(.project-apply-dialog .el-dialog__body) {
|
||||
@@ -1535,6 +1848,11 @@ export default {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
|
||||
&--change {
|
||||
justify-content: flex-start;
|
||||
padding-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-apply-user-dialog {
|
||||
|
||||
Reference in New Issue
Block a user