Files
tms-erp-web/src/option/business/contract-manage.js
T
gxwebsoft f7eea88945 feat(login): 更换登录验证码为图形字符验证码
- 配置文件 website.js 中将 captchaType 从 'behavior' 改为 'image'
- 修改 userlogin.vue,图形验证码图片由输入框内联改为输入框旁独立显示
- 重写 login.scss 样式,实现验证码图片区域带边框和高亮效果
- 确保验证码图片点击可刷新,且支持从后端接口获取数据
- 登录页仍默认显示 IAM 登录,需切换「账号密码登录」显示验证码区域

feat(contract-manage): 优化所属组织搜索栏为树形下拉选择框

- 引入并应用 organization-search mixin 统一管理所属组织搜索
- contract-manage.js、driver.js、transport-ship.js、transport-vehicle.js 中所属组织搜索改为 searchslot 模式
- contract-manage.vue 中新增 renderOrganizationSearch 方法,渲染基于 ElTreeSelect 的树形下拉组件
- 组织树数据加载时自动排除「外部组织」节点,保持搜索选项清晰
- 所有相关所属组织搜索统一样式与交互,提升用户体验

feat(system): 用户和部门视图样式及操作改进

- user.vue 和 userinfo.vue 中 el-tabs 组件添加 border-card 类型,提升标签页视觉效果
- dept.vue 中添加查看、编辑、删除操作入口,绑定对应方法,通过权限控制显示权限按钮
- dept.vue 菜单宽度、对话框宽度及行为配置优化

style(login): 调整登录样式及验证码布局细节

- 调整 .login-code-wrap 及内部元素的 flex 布局,输入框与验证码图片并排显示
- 设置验证码图片容器尺寸、边框及 hover 高亮样式
- 确保验证码图片撑满容器并禁止用户选中

refactor(mixins): 新增 organization-search 统一搜索 mixin

- 实现组织树数据加载、排除外部节点、归一化及扁平化处理
- 提供 renderOrganizationSearch 方法用于渲染统一树形选择搜索框
- 减少重复代码,方便各页面快速接入和统一维护

chore(vehicle): 车辆页面引入 organization-search mixin

- 在车辆视图 vehicle.vue 中混入 organization-search,增强所属组织搜索功能一致性
2026-08-28 15:41:01 +08:00

677 lines
15 KiB
JavaScript

import {
auditColumns,
contractApprovalStatusOptions,
contractCategoryOptions,
contractStageOptions,
createCrudOption,
effectiveTypeOptions,
selectRule,
signTypeOptions,
textRule,
} from './common';
const contractSettlementModeOptions = [
{ label: '现结', value: '现结' },
{ label: '日结', value: '日结' },
{ label: '周结', value: '周结' },
{ label: '月结', value: '月结' },
{ label: '按固定天数周期', value: '按固定天数周期' },
];
const listDicFormatter = res => {
const data = res?.data || res;
if (Array.isArray(data)) return data;
if (Array.isArray(data?.records)) return data.records;
if (Array.isArray(data?.data)) return data.data;
if (Array.isArray(data?.data?.records)) return data.data.records;
return [];
};
export const config = {
title: '合同管理',
permission: 'contract_manage',
exportUrl: '/blade-transport/contract-manage/export-contract-manage',
exportName: '合同管理',
defaultForm: {
contractCategory: '客户合同',
},
projectPlaceholder: '请选择',
organizationPlaceholder: '请选择',
enableAllDept: true,
allDeptReadonly: false,
batchDelete: false,
enableProjectSelect: true,
projectQueryParams: {
approvalStatuses: 'approved,change_approved',
},
actions: ['copy'],
statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName',
detailSections: [
{
title: '基本信息',
fields: [
['contractNo', '合同编号'],
['contractName', '合同名称'],
['projectName', '所属项目'],
['organizationName', '所属组织'],
['contractCategory', '合同类别'],
['signType', '签约类型'],
['partyA', '甲方'],
['partyB', '乙方'],
['handlerUserName', '经办人'],
['signDate', '签订日期'],
['contractFormat', '合同格式'],
['legalSealFlag', '是否需要加盖法人章'],
['copyCount', '一式(份)'],
['paymentDays', '回款账期(天)'],
['remark', '备注', 2],
],
},
{
title: '合同期限',
fields: [
['startDate', '开始日期'],
['endDate', '结束日期'],
['temporaryStartDate', '临时效力起'],
['temporaryEndDate', '临时效力止'],
['effectiveType', '生效类型'],
['contractStage', '合同阶段'],
['approvalStatus', '审核状态'],
['currentNode', '当前节点'],
['currentProcessor', '当前处理人'],
],
},
{
title: '计费与结算',
fields: [
['feeGenerationMode', '费用生成模式'],
['billingPlanJson', '计费方案', 2],
['settlementMode', '结算类型'],
['settlementRuleJson', '结算规则', 2],
['paymentRatioJson', '付款比例设置', 2],
],
},
],
editLabelStatusMap: {
change_rejected: '编辑变更内容',
},
deleteStatus: ['draft'],
deleteStage: ['draft'],
editStatus: ['draft', 'rejected', 'change_rejected'],
operations: [
{
action: 'flow',
label: '查看流程',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_view',
},
{
action: 'withdraw',
label: '撤回',
statusProp: 'approvalStatus',
status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_withdraw',
},
{
action: 'approve',
label: '通过',
statusProp: 'approvalStatus',
status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_approve',
},
{
action: 'reject',
label: '驳回',
statusProp: 'approvalStatus',
status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_reject',
},
{
action: 'approve',
label: '通过',
statusProp: 'approvalStatus',
status: ['change_reviewing'],
stage: ['formal'],
permission: 'contract_manage_approve',
},
{
action: 'reject',
label: '驳回',
statusProp: 'approvalStatus',
status: ['change_reviewing'],
stage: ['formal'],
permission: 'contract_manage_reject',
},
{
action: 'submitFormal',
label: '转正式合同',
statusProp: 'approvalStatus',
status: ['approved'],
stage: ['temporary'],
permission: 'contract_manage_formal',
confirmMessage: '确定将该临时合同提交正式合同审批吗?',
successMessage: '已提交正式合同审批',
},
{
action: 'submitFormal',
label: '重新提交转正',
statusProp: 'approvalStatus',
status: ['rejected'],
stage: ['temporary'],
permission: 'contract_manage_formal',
},
{
action: 'startChange',
label: '变更',
statusProp: 'approvalStatus',
status: ['approved'],
stage: ['formal'],
permission: 'contract_manage_change',
prompt: '请输入变更内容与原因',
},
{
action: 'startChange',
label: '变更',
statusProp: 'approvalStatus',
status: ['change_approved'],
stage: ['formal'],
permission: 'contract_manage_change',
prompt: '请输入变更内容与原因',
},
{
action: 'attachmentUpload',
label: '附件上传',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
stage: ['formal'],
permission: 'contract_manage_edit',
},
{
action: 'flow',
label: '查看流程',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
stage: ['formal', 'terminated'],
permission: 'contract_manage_view',
},
{
action: 'withdraw',
label: '撤回变更',
statusProp: 'approvalStatus',
status: ['change_reviewing'],
stage: ['formal'],
permission: 'contract_manage_withdraw',
},
{
action: 'startChange',
label: '重新提交变更',
statusProp: 'approvalStatus',
status: ['change_rejected'],
stage: ['formal'],
permission: 'contract_manage_change',
prompt: '请输入变更内容与原因',
},
],
};
export const option = createCrudOption([
{
label: '',
prop: 'basicInfoTitle',
formslot: true,
span: 24,
order: 200,
hide: true,
labelWidth: 0,
},
{
label: '合同编号',
prop: 'contractNo',
search: true,
searchOrder: 6,
searchPlaceholder: '请输入',
order: 185,
disabled: true,
placeholder: '不填写,则系统自动生成',
minWidth: 200,
},
{
label: '合同名称',
prop: 'contractName',
align: 'left',
headerAlign: 'left',
search: true,
searchOrder: 7,
searchPlaceholder: '请输入',
order: 180,
slot: true,
overHidden: true,
minWidth: 240,
rules: textRule('合同名称', 100, true),
},
{
label: '所属项目',
prop: 'projectName',
search: true,
searchOrder: 8,
searchType: 'select',
searchPlaceholder: '请选择',
formslot: true,
order: 165,
dicUrl:
'/blade-transport/project-apply/list?current=1&size=9999&approvalStatuses=approved,change_approved',
dicFormatter: listDicFormatter,
props: {
label: 'projectName',
value: 'projectName',
},
filterable: true,
minWidth: 160,
rules: selectRule('所属项目'),
},
{
label: '所属项目ID',
prop: 'projectId',
hide: true,
display: false,
},
{
label: '所属组织',
prop: 'organizationName',
search: true,
searchOrder: 3,
searchslot: true,
searchPlaceholder: '请选择 所属组织',
formslot: true,
order: 120,
dicData: [],
minWidth: 150,
rules: selectRule('所属组织'),
},
{
label: '合同类别',
prop: 'contractCategory',
type: 'select',
search: true,
searchOrder: 9,
searchPlaceholder: '请选择',
order: 170,
dicData: contractCategoryOptions,
minWidth: 130,
rules: selectRule('合同类别'),
},
{
label: '签约类型',
prop: 'signType',
type: 'select',
search: true,
searchOrder: 10,
searchPlaceholder: '请选择',
span: 8,
order: 190,
dicData: signTypeOptions,
minWidth: 120,
rules: selectRule('签约类型'),
},
{
label: '生效类型',
prop: 'effectiveType',
type: 'select',
search: true,
searchOrder: 5,
searchPlaceholder: '请选择',
dicData: effectiveTypeOptions,
hide: true,
display: false,
},
{
label: '甲方',
prop: 'partyA',
type: 'select',
formslot: true,
disabled: true,
order: 160,
filterable: true,
minWidth: 160,
rules: selectRule('甲方'),
},
{
label: '乙方',
prop: 'partyB',
type: 'select',
formslot: true,
disabled: true,
order: 150,
filterable: true,
minWidth: 160,
rules: selectRule('乙方'),
},
{
label: '合同期限',
prop: 'contractPeriod',
formslot: true,
order: 130,
hide: true,
rules: [{ required: true, message: '请选择合同期限', trigger: 'change' }],
},
{
label: '开始日期',
prop: 'startDate',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '结束日期',
prop: 'endDate',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '临时效力起',
prop: 'temporaryStartDate',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '临时效力止',
prop: 'temporaryEndDate',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '经办人',
prop: 'handlerUserName',
order: 110,
disabled: true,
minWidth: 120,
rules: textRule('经办人', 50, true),
},
{
label: '签订日期',
prop: 'signDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
hide: true,
order: 100,
minWidth: 130,
rules: [{ required: true, message: '请选择签订日期', trigger: 'change' }],
},
{
label: '结算类型',
prop: 'settlementMode',
type: 'select',
dicData: contractSettlementModeOptions,
hide: true,
order: 90,
minWidth: 120,
rules: selectRule('结算类型'),
},
{
label: '合同格式',
prop: 'contractFormat',
labelWidth: '72px',
type: 'select',
dicData: [
{ label: '电子合同', value: '电子合同' },
{ label: '纸质合同', value: '纸质合同' },
],
hide: true,
order: 80,
minWidth: 120,
rules: selectRule('合同格式'),
},
{
label: '是否需要加盖法人章',
prop: 'legalSealFlag',
labelWidth: '72px',
type: 'select',
dicData: [
{ label: '否', value: 0 },
{ label: '是', value: 1 },
],
value: 0,
hide: true,
order: 70,
minWidth: 100,
rules: selectRule('是否需要加盖法人章'),
},
{
label: '一式(份)',
prop: 'copyCount',
labelWidth: '72px',
formslot: true,
hide: true,
order: 60,
minWidth: 110,
},
{
label: '回款账期(天)',
prop: 'paymentDays',
formslot: true,
hide: true,
order: 50,
minWidth: 130,
},
{
label: '创建时间',
prop: 'createTime',
sortable: true,
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 190,
addDisplay: false,
editDisplay: false,
},
{
label: '合同阶段',
prop: 'contractStage',
type: 'select',
search: true,
searchOrder: 2,
searchPlaceholder: '请选择',
slot: true,
dicData: contractStageOptions,
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '审核状态',
prop: 'approvalStatus',
type: 'select',
search: true,
searchOrder: 4,
searchPlaceholder: '请选择',
slot: true,
dicData: contractApprovalStatusOptions,
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '当前节点',
prop: 'currentNode',
minWidth: 140,
addDisplay: false,
editDisplay: false,
},
{
label: '当前处理人',
prop: 'currentProcessor',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '费用生成模式',
prop: 'billingEnabled',
type: 'switch',
dicData: [
{ label: '关闭', value: 0 },
{ label: '开启', value: 1 },
],
value: 1,
hide: true,
display: false,
minWidth: 110,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
span: 24,
minRows: 2,
hide: true,
order: 40,
maxlength: 2000,
showWordLimit: true,
rules: textRule('备注', 2000),
},
{
label: '',
prop: 'contractFileTitle',
formslot: true,
span: 24,
order: 30,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'contractFileJson',
formslot: true,
span: 24,
className: 'contract-file-form-item',
order: 20,
hide: true,
},
{
label: '',
prop: 'billingInfoTitle',
formslot: true,
span: 24,
order: 10,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'billingPlanJson',
formslot: true,
span: 24,
order: 0,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'settlementRuleTitle',
formslot: true,
span: 24,
order: -10,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'settlementRuleJson',
formslot: true,
span: 24,
order: -20,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'paymentRatioTitle',
formslot: true,
span: 24,
order: -30,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'paymentRatioJson',
formslot: true,
span: 24,
order: -40,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'attachmentTitle',
formslot: true,
span: 24,
order: -50,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'attachmentsJson',
formslot: true,
span: 24,
order: -60,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'changeRecordTitle',
formslot: true,
span: 24,
order: -70,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'changeRecordJson',
formslot: true,
span: 24,
order: -80,
hide: true,
labelWidth: 0,
},
...auditColumns
.filter(column => column.prop !== 'createTime')
.map(column => ({ ...column, hide: true })),
]);
option.span = 8;
option.dialogWidth = 1480;
option.dialogTop = '4vh';
option.dialogCloseBtn = true;
option.menuWidth = 320;
option.dialogCustomClass = 'contract-manage-dialog';