Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-07-29 00:53:16 +08:00
39 changed files with 9180 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/common-cargo');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;

View File

@@ -0,0 +1,8 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/common-route');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;

103
src/api/business/common.js Normal file
View File

@@ -0,0 +1,103 @@
import request from '@/axios';
export const createCrudApi = baseUrl => ({
getList(current, size, params) {
return request({
url: `${baseUrl}/list`,
method: 'get',
params: {
...params,
current,
size,
},
});
},
getDetail(id) {
return request({
url: `${baseUrl}/detail`,
method: 'get',
params: {
id,
},
});
},
submit(row) {
return request({
url: `${baseUrl}/submit`,
method: 'post',
data: row,
});
},
remove(ids) {
return request({
url: `${baseUrl}/remove`,
method: 'post',
params: {
ids,
},
});
},
copy(id) {
return request({
url: `${baseUrl}/copy`,
method: 'post',
params: {
id,
},
});
},
enable(id) {
return request({
url: `${baseUrl}/enable`,
method: 'post',
params: {
id,
},
});
},
disable(id) {
return request({
url: `${baseUrl}/disable`,
method: 'post',
params: {
id,
},
});
},
cancel(id) {
return request({
url: `${baseUrl}/cancel`,
method: 'post',
params: {
id,
},
});
},
complete(id) {
return request({
url: `${baseUrl}/complete`,
method: 'post',
params: {
id,
},
});
},
reassign(id) {
return request({
url: `${baseUrl}/reassign`,
method: 'post',
params: {
id,
},
});
},
batchComplete(ids) {
return request({
url: `${baseUrl}/batch-complete`,
method: 'post',
params: {
ids,
},
});
},
});

View File

@@ -0,0 +1,78 @@
import { createCrudApi } from './common';
import request from '@/axios';
const baseUrl = '/blade-transport/contract-manage';
const api = createCrudApi(baseUrl);
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const copy = api.copy;
export const saveDraft = row =>
request({
url: `${baseUrl}/save-draft`,
method: 'post',
data: row,
});
export const toTemporary = id =>
request({
url: `${baseUrl}/to-temporary`,
method: 'post',
params: { id },
});
export const submitFormal = id =>
request({
url: `${baseUrl}/submit-formal`,
method: 'post',
params: { id },
});
export const approve = id =>
request({
url: `${baseUrl}/approve`,
method: 'post',
params: { id },
});
export const reject = id =>
request({
url: `${baseUrl}/reject`,
method: 'post',
params: { id },
});
export const withdraw = id =>
request({
url: `${baseUrl}/withdraw`,
method: 'post',
params: { id },
});
export const startChange = (id, reason) =>
request({
url: `${baseUrl}/start-change`,
method: 'post',
params: {
id,
changeContent: reason,
changeReason: reason,
},
});
export const terminate = (id, reason) =>
request({
url: `${baseUrl}/terminate`,
method: 'post',
params: { id, reason },
});
export const expireStats = params =>
request({
url: `${baseUrl}/expire-stats`,
method: 'get',
params,
});

View File

@@ -0,0 +1,11 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/process-config');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const copy = api.copy;
export const enable = api.enable;
export const disable = api.disable;

View File

@@ -0,0 +1,63 @@
import { createCrudApi } from './common';
import request from '@/axios';
const baseUrl = '/blade-transport/project-apply';
const api = createCrudApi(baseUrl);
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const saveDraft = row =>
request({
url: `${baseUrl}/save-draft`,
method: 'post',
data: row,
});
export const submitApproval = id =>
request({
url: `${baseUrl}/submit-approval`,
method: 'post',
params: { id },
});
export const approve = id =>
request({
url: `${baseUrl}/approve`,
method: 'post',
params: { id },
});
export const reject = id =>
request({
url: `${baseUrl}/reject`,
method: 'post',
params: { id },
});
export const withdraw = id =>
request({
url: `${baseUrl}/withdraw`,
method: 'post',
params: { id },
});
export const voidProject = (id, reason) =>
request({
url: `${baseUrl}/void`,
method: 'post',
params: { id, reason },
});
export const startChange = (id, reason) =>
request({
url: `${baseUrl}/start-change`,
method: 'post',
params: {
id,
changeContent: reason,
changeReason: reason,
},
});

View File

@@ -0,0 +1,9 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/shipping-template');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const copy = api.copy;

View File

@@ -0,0 +1,45 @@
import { createCrudApi } from './common';
import request from '@/axios';
const baseUrl = '/blade-transport/temporary-credit-limit';
const api = createCrudApi(baseUrl);
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const saveDraft = row =>
request({
url: `${baseUrl}/save-draft`,
method: 'post',
data: row,
});
export const submitApproval = id =>
request({
url: `${baseUrl}/submit-approval`,
method: 'post',
params: { id },
});
export const approve = id =>
request({
url: `${baseUrl}/approve`,
method: 'post',
params: { id },
});
export const reject = id =>
request({
url: `${baseUrl}/reject`,
method: 'post',
params: { id },
});
export const withdraw = id =>
request({
url: `${baseUrl}/withdraw`,
method: 'post',
params: { id },
});

View File

@@ -0,0 +1,11 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/transport-plan');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const copy = api.copy;
export const cancel = api.cancel;
export const complete = api.complete;

View File

@@ -0,0 +1,13 @@
import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/waybill-manage');
export const getList = api.getList;
export const getDetail = api.getDetail;
export const submit = api.submit;
export const remove = api.remove;
export const copy = api.copy;
export const cancel = api.cancel;
export const reassign = api.reassign;
export const complete = api.complete;
export const batchComplete = api.batchComplete;

View File

@@ -0,0 +1,179 @@
import {
auditColumns,
createCrudOption,
nonNegativeRule,
packageOptions,
priceUnitOptions,
selectRule,
textRule,
} from './common';
export const config = {
title: '常用货物',
permission: 'common_cargo',
exportUrl: '/blade-transport/common-cargo/export-common-cargo',
exportName: '常用货物',
importUrl: '/blade-transport/common-cargo/import-common-cargo',
templateUrl: '/blade-transport/common-cargo/export-template',
enableAllDept: true,
};
export const option = createCrudOption([
{
label: '组织',
prop: 'deptName',
search: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '一级货物类型',
prop: 'firstCargoTypeName',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('一级货物类型', 100, true),
},
{
label: '一级货物类型编码',
prop: 'firstCargoTypeCode',
hide: true,
editDisabled: true,
},
{
label: '二级货物类型',
prop: 'secondCargoTypeName',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('二级货物类型', 100, true),
},
{
label: '二级货物类型编码',
prop: 'secondCargoTypeCode',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('二级货物类型编码', 20, true),
},
{
label: '货物名称',
prop: 'cargoName',
search: true,
minWidth: 150,
rules: textRule('货物名称', 100, true),
},
{
label: '货物编号',
prop: 'cargoCode',
search: true,
minWidth: 120,
editDisabled: true,
rules: textRule('货物编号', 20, true),
},
{
label: '品牌',
prop: 'brand',
search: true,
minWidth: 120,
rules: textRule('品牌', 50),
},
{
label: '包装',
prop: 'packageType',
type: 'select',
dicData: packageOptions,
minWidth: 100,
},
{
label: '货值',
prop: 'cargoValue',
type: 'number',
precision: 2,
min: 0,
minWidth: 120,
rules: [nonNegativeRule('货值')],
},
{
label: '规格',
prop: 'specification',
minWidth: 120,
rules: textRule('规格', 50),
},
{
label: '计价单位',
prop: 'priceUnit',
type: 'select',
dicData: priceUnitOptions,
minWidth: 120,
},
{
label: '型号',
prop: 'model',
minWidth: 120,
rules: textRule('型号', 50),
},
{
label: '说明1',
prop: 'descriptionOne',
minWidth: 160,
rules: textRule('说明1', 100),
},
{
label: '尺寸',
prop: 'sizeText',
minWidth: 120,
rules: textRule('尺寸', 50),
},
{
label: '说明2',
prop: 'descriptionTwo',
minWidth: 160,
rules: textRule('说明2', 100),
},
{
label: '数据来源',
prop: 'dataSource',
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 200,
showWordLimit: true,
rules: textRule('备注', 200),
},
...auditColumns,
]);
export const excelOption = {
submitBtn: false,
emptyBtn: false,
column: [
{
label: '导入模板',
prop: 'excelTemplate',
formslot: true,
span: 24,
},
{
label: 'Excel文件',
prop: 'excelFile',
type: 'upload',
drag: true,
loadText: '模板上传中,请稍等',
span: 24,
propsHttp: {
res: 'data',
},
tip: '请上传 .xls,.xlsx 标准格式文件',
},
],
};

View File

@@ -0,0 +1,131 @@
import { auditColumns, createCrudOption, phoneRule, textRule } from './common';
export const config = {
title: '常用线路',
permission: 'common_route',
exportUrl: '/blade-transport/common-route/export-common-route',
exportName: '常用线路',
enableAllDept: true,
};
export const option = createCrudOption([
{
label: '组织',
prop: 'deptName',
search: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '线路编号',
prop: 'routeCode',
search: true,
minWidth: 120,
addDisplay: false,
editDisabled: true,
},
{
label: '线路名称',
prop: 'routeName',
search: true,
minWidth: 150,
rules: textRule('线路名称', 100, true),
},
{
label: '发货地',
prop: 'departureName',
search: true,
minWidth: 140,
rules: textRule('发货地', 100, true),
},
{
label: '发货地址',
prop: 'departureAddress',
search: true,
minWidth: 220,
rules: textRule('发货地址', 255, true),
},
{
label: '发货经度',
prop: 'departureLongitude',
type: 'number',
precision: 6,
minWidth: 120,
hide: true,
},
{
label: '发货纬度',
prop: 'departureLatitude',
type: 'number',
precision: 6,
minWidth: 120,
hide: true,
},
{
label: '发货联系人',
prop: 'departureContact',
minWidth: 120,
rules: textRule('发货联系人', 50),
},
{
label: '发货联系方式',
prop: 'departurePhone',
minWidth: 140,
rules: [phoneRule('发货联系方式'), ...textRule('发货联系方式', 50)],
},
{
label: '收货地',
prop: 'arrivalName',
search: true,
minWidth: 140,
rules: textRule('收货地', 100, true),
},
{
label: '收货地址',
prop: 'arrivalAddress',
search: true,
minWidth: 220,
rules: textRule('收货地址', 255, true),
},
{
label: '收货经度',
prop: 'arrivalLongitude',
type: 'number',
precision: 6,
minWidth: 120,
hide: true,
},
{
label: '收货纬度',
prop: 'arrivalLatitude',
type: 'number',
precision: 6,
minWidth: 120,
hide: true,
},
{
label: '收货联系人',
prop: 'arrivalContact',
minWidth: 120,
rules: textRule('收货联系人', 50),
},
{
label: '收货联系方式',
prop: 'arrivalPhone',
minWidth: 140,
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 500,
showWordLimit: true,
rules: textRule('备注', 500),
},
...auditColumns,
]);

View File

@@ -0,0 +1,244 @@
export const transportTypeOptions = [
{ label: '公路整车', value: '公路整车' },
{ label: '公路零担', value: '公路零担' },
{ label: '铁路运输', value: '铁路运输' },
{ label: '水路运输', value: '水路运输' },
{ label: '跨境海运', value: '跨境海运' },
{ label: '航空运输', value: '航空运输' },
];
export const packageOptions = [
{ label: '袋装', value: '袋装' },
{ label: '散装', value: '散装' },
{ label: '桶装', value: '桶装' },
{ label: '箱装', value: '箱装' },
{ label: '托盘', value: '托盘' },
];
export const priceUnitOptions = [
{ label: '元/吨', value: '元/吨' },
{ label: '元/立方米', value: '元/立方米' },
{ label: '元/件', value: '元/件' },
{ label: '元/车', value: '元/车' },
];
export const templateTypeOptions = [
{ label: '运输计划', value: '运输计划' },
{ label: '常规运单', value: '常规运单' },
];
export const processStatusOptions = [
{ label: '草稿', value: 0 },
{ label: '启用', value: 1 },
{ label: '停用', value: 2 },
];
export const planStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '待调度', value: 'waiting_dispatch' },
{ label: '调度中', value: 'dispatching' },
{ label: '已完成', value: 'completed' },
{ label: '已取消', value: 'cancelled' },
];
export const waybillStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '待执行', value: 'pending' },
{ label: '进行中', value: 'processing' },
{ label: '已完成', value: 'completed' },
{ label: '已取消', value: 'cancelled' },
];
export const dataSourceOptions = [
{ label: '手工创建', value: '手工创建' },
{ label: '批量导入', value: '批量导入' },
{ label: '模板生成', value: '模板生成' },
{ label: '计划调度', value: '计划调度' },
];
export const projectTypeOptions = [
{ label: '普通项目', value: '普通项目' },
{ label: '重大项目', value: '重大项目' },
];
export const projectSourceOptions = [
{ label: '商务洽谈', value: '商务洽谈' },
{ label: '招投标', value: '招投标' },
{ label: '客户委托', value: '客户委托' },
{ label: '其它', value: '其它' },
];
export const projectApprovalStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '审批中', value: 'reviewing' },
{ label: '已撤回', value: 'withdrawn' },
{ label: '审批通过', value: 'approved' },
{ label: '已驳回', value: 'rejected' },
{ label: '变更审批中', value: 'change_reviewing' },
{ label: '变更驳回', value: 'change_rejected' },
{ label: '变更审批通过', value: 'change_approved' },
{ label: '已作废', value: 'voided' },
];
export const approvalStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '审批中', value: 'reviewing' },
{ label: '已撤回', value: 'withdrawn' },
{ label: '审批通过', value: 'approved' },
{ label: '已驳回', value: 'rejected' },
];
export const effectiveTypeOptions = [
{ label: '临时', value: 'temporary' },
{ label: '正式', value: 'formal' },
];
export const businessTypeOptions = [
{ label: '一类规模业务', value: '一类规模业务' },
{ label: '二类规模业务', value: '二类规模业务' },
{ label: '普通业务', value: '普通业务' },
];
export const settlementModeOptions = [
{ label: '先票后款', value: '先票后款' },
{ label: '先款后票', value: '先款后票' },
{ label: '月结', value: '月结' },
];
export const contractCategoryOptions = [
{ label: '客户合同', value: '客户合同' },
{ label: '承运商合同', value: '承运商合同' },
{ label: '补充协议', value: '补充协议' },
];
export const signTypeOptions = [
{ label: '新签', value: '新签' },
{ label: '续签', value: '续签' },
];
export const contractStageOptions = [
{ label: '草稿', value: 'draft' },
{ label: '临时合同', value: 'temporary' },
{ label: '正式合同', value: 'formal' },
{ label: '已终止', value: 'terminated' },
];
export const contractApprovalStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '审批中', value: 'reviewing' },
{ label: '已驳回', value: 'rejected' },
{ label: '审批通过', value: 'approved' },
{ label: '变更审批中', value: 'change_reviewing' },
{ label: '变更驳回', value: 'change_rejected' },
{ label: '变更审批通过', value: 'change_approved' },
];
export const nodeOptions = [
{ label: '接单', value: '接单' },
{ label: '到场', value: '到场' },
{ label: '装货', value: '装货' },
{ label: '发货', value: '发货' },
{ label: '在途', value: '在途' },
{ label: '到货', value: '到货' },
{ label: '卸货', value: '卸货' },
{ label: '签收', value: '签收' },
{ label: '回单', value: '回单' },
];
export const textRule = (label, max, required = false) => {
const rules = [];
if (required) {
rules.push({ required: true, message: `请输入${label}`, trigger: 'blur' });
}
if (max) {
rules.push({ max, message: `${label}不能超过${max}个字符`, trigger: 'blur' });
}
return rules;
};
export const selectRule = label => [{ required: true, message: `请选择${label}`, trigger: 'change' }];
export const nonNegativeRule = label => ({
validator: (rule, value, callback) => {
if (value !== undefined && value !== null && value !== '' && Number(value) < 0) {
callback(new Error(`${label}不能小于0`));
return;
}
callback();
},
trigger: 'blur',
});
export const phoneRule = label => ({
pattern: /^(1\d{10}|0\d{2,3}-?\d{7,8})$/,
message: `${label}格式不正确`,
trigger: 'blur',
});
export const createCrudOption = columns => ({
height: 'auto',
calcHeight: 32,
dialogWidth: 980,
labelPosition: 'right',
labelWidth: 'auto',
tip: false,
searchBtnText: '查询',
emptyBtnText: '重置',
saveBtnText: '提交',
updateBtnText: '提交',
searchShow: true,
searchMenuSpan: 24,
searchIcon: true,
searchIndex: 8,
searchMenuPosition: 'right',
border: true,
index: true,
indexLabel: '序号',
indexWidth: 70,
selection: true,
addBtn: false,
viewBtn: false,
editBtn: false,
delBtn: false,
dialogClickModal: false,
menuFixed: 'right',
menuWidth: 240,
column: columns,
});
export const auditColumns = [
{
label: '创建人',
prop: 'createUserName',
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '更新人',
prop: 'updateUserName',
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '创建时间',
prop: 'createTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 160,
addDisplay: false,
editDisplay: false,
},
{
label: '更新时间',
prop: 'updateTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 160,
addDisplay: false,
editDisplay: false,
},
];

View File

@@ -0,0 +1,333 @@
import {
auditColumns,
contractApprovalStatusOptions,
contractCategoryOptions,
contractStageOptions,
createCrudOption,
selectRule,
settlementModeOptions,
signTypeOptions,
textRule,
} from './common';
export const config = {
title: '合同管理',
permission: 'contract_manage',
exportUrl: '/blade-transport/contract-manage/export-contract-manage',
exportName: '合同管理',
enableAllDept: true,
actions: ['copy'],
statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName',
deleteStatus: ['draft'],
editStatus: ['draft', 'rejected', 'change_rejected'],
operations: [
{
action: 'toTemporary',
label: '转临时',
statusProp: 'approvalStatus',
status: ['draft'],
stage: ['draft'],
permission: 'contract_manage_temp',
},
{
action: 'submitFormal',
label: '转正式',
statusProp: 'approvalStatus',
status: ['draft', 'rejected', 'approved'],
stage: ['temporary'],
permission: 'contract_manage_formal',
},
{
action: 'withdraw',
label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
permission: 'contract_manage_withdraw',
},
{
action: 'approve',
label: '审批通过',
type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
permission: 'contract_manage_approve',
},
{
action: 'reject',
label: '审批驳回',
type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
permission: 'contract_manage_reject',
},
{
action: 'startChange',
label: '发起变更',
icon: 'el-icon-edit-outline',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
stage: ['formal'],
permission: 'contract_manage_change',
prompt: '请输入变更内容与原因',
},
{
action: 'terminate',
label: '终止',
type: 'danger',
icon: 'el-icon-close',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
stage: ['formal'],
permission: 'contract_manage_terminate',
prompt: '请输入终止原因',
},
],
};
export const option = createCrudOption([
{
label: '合同编号',
prop: 'contractNo',
search: true,
minWidth: 160,
addDisplay: false,
editDisabled: true,
},
{
label: '合同名称',
prop: 'contractName',
search: true,
minWidth: 180,
rules: textRule('合同名称', 100, true),
},
{
label: '所属项目',
prop: 'projectName',
search: true,
minWidth: 160,
},
{
label: '所属项目ID',
prop: 'projectId',
hide: true,
},
{
label: '所属组织',
prop: 'organizationName',
search: true,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '合同类别',
prop: 'contractCategory',
type: 'select',
search: true,
dicData: contractCategoryOptions,
minWidth: 130,
rules: selectRule('合同类别'),
},
{
label: '签约类型',
prop: 'signType',
type: 'select',
search: true,
dicData: signTypeOptions,
minWidth: 120,
},
{
label: '甲方',
prop: 'partyA',
minWidth: 160,
},
{
label: '乙方',
prop: 'partyB',
minWidth: 160,
},
{
label: '开始日期',
prop: 'startDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '结束日期',
prop: 'endDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '临时效力起',
prop: 'temporaryStartDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '临时效力止',
prop: 'temporaryEndDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '经办人',
prop: 'handlerUserName',
minWidth: 120,
},
{
label: '签订日期',
prop: 'signDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '结算方式',
prop: 'settlementMode',
type: 'select',
dicData: settlementModeOptions,
minWidth: 120,
},
{
label: '合同格式',
prop: 'contractFormat',
type: 'select',
dicData: [
{ label: '电子合同', value: '电子合同' },
{ label: '纸质合同', value: '纸质合同' },
],
minWidth: 120,
},
{
label: '法人章',
prop: 'legalSealFlag',
type: 'switch',
dicData: [
{ label: '否', value: 0 },
{ label: '是', value: 1 },
],
value: 0,
minWidth: 100,
},
{
label: '一式份数',
prop: 'copyCount',
type: 'number',
minWidth: 110,
},
{
label: '回款账期(天)',
prop: 'paymentDays',
type: 'number',
minWidth: 130,
},
{
label: '合同阶段',
prop: 'contractStage',
type: 'select',
search: true,
slot: true,
dicData: contractStageOptions,
minWidth: 120,
addDisplay: false,
editDisplay: false,
fixed: 'right',
},
{
label: '审核状态',
prop: 'approvalStatus',
type: 'select',
search: true,
slot: true,
dicData: contractApprovalStatusOptions,
minWidth: 130,
addDisplay: false,
editDisplay: false,
fixed: 'right',
},
{
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: 0,
minWidth: 110,
},
{
label: '合同主文件JSON',
prop: 'contractFileJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '其它附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '计费方案JSON',
prop: 'billingPlanJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '结算生成规则JSON',
prop: 'settlementRuleJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '对账配置JSON',
prop: 'reconciliationJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
span: 24,
hide: true,
maxlength: 2000,
showWordLimit: true,
rules: textRule('备注', 2000),
},
...auditColumns,
]);

View File

@@ -0,0 +1,103 @@
import { auditColumns, createCrudOption, nodeOptions, processStatusOptions, selectRule, textRule } from './common';
export const config = {
title: '过程配置',
permission: 'process_config',
exportUrl: '/blade-transport/process-config/export-process-config',
exportName: '过程配置',
enableAllDept: true,
actions: ['copy', 'enable', 'disable'],
statusProp: 'status',
statusTextProp: 'statusName',
deleteStatus: [0, 2],
};
export const option = createCrudOption([
{
label: '配置编号',
prop: 'configCode',
search: true,
minWidth: 130,
addDisplay: false,
editDisabled: true,
},
{
label: '配置名称',
prop: 'configName',
search: true,
minWidth: 150,
rules: textRule('配置名称', 100, true),
},
{
label: '项目ID集合',
prop: 'projectIds',
hide: true,
rules: textRule('项目ID集合', 1000, true),
},
{
label: '项目',
prop: 'projectNames',
search: true,
type: 'textarea',
minRows: 2,
minWidth: 180,
rules: textRule('项目', 1000, true),
},
{
label: '包含过程节点',
prop: 'includedNodes',
search: true,
type: 'select',
multiple: true,
dicData: nodeOptions,
minWidth: 180,
rules: selectRule('包含过程节点'),
},
{
label: '默认完成运输天数',
prop: 'defaultFinishDays',
type: 'number',
min: 1,
max: 999,
minWidth: 150,
},
{
label: '状态',
prop: 'status',
type: 'select',
search: true,
dicData: processStatusOptions,
slot: true,
minWidth: 100,
addDisplay: false,
editDisplay: false,
},
{
label: '所属组织',
prop: 'deptName',
search: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '节点配置JSON',
prop: 'nodeConfigJson',
type: 'textarea',
minRows: 6,
span: 24,
hide: true,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 500,
showWordLimit: true,
rules: textRule('备注', 500),
},
...auditColumns,
]);

View File

@@ -0,0 +1,359 @@
import {
auditColumns,
businessTypeOptions,
createCrudOption,
effectiveTypeOptions,
nonNegativeRule,
projectApprovalStatusOptions,
projectSourceOptions,
projectTypeOptions,
selectRule,
settlementModeOptions,
textRule,
transportTypeOptions,
} from './common';
const amountRules = label => [
{ required: true, message: `请输入${label}`, trigger: 'blur' },
nonNegativeRule(label),
];
export const config = {
title: '项目管理',
permission: 'project_apply',
exportUrl: '/blade-transport/project-apply/export-project-apply',
exportName: '项目立项',
enableAllDept: true,
statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName',
deleteStatus: ['draft', 'withdrawn', 'rejected'],
editStatus: ['draft', 'withdrawn', 'rejected', 'change_rejected'],
operations: [
{
action: 'submitApproval',
label: '提交审批',
icon: 'el-icon-position',
statusProp: 'approvalStatus',
status: ['draft', 'withdrawn', 'rejected'],
permission: 'project_apply_submit',
},
{
action: 'withdraw',
label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus',
status: ['reviewing'],
permission: 'project_apply_withdraw',
},
{
action: 'approve',
label: '审批通过',
type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
permission: 'project_apply_approve',
},
{
action: 'reject',
label: '审批驳回',
type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'],
permission: 'project_apply_reject',
},
{
action: 'startChange',
label: '发起变更',
icon: 'el-icon-edit-outline',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
permission: 'project_apply_change',
prompt: '请输入变更内容与原因',
},
{
action: 'voidProject',
label: '作废',
type: 'danger',
icon: 'el-icon-delete',
statusProp: 'approvalStatus',
status: ['approved', 'change_approved'],
permission: 'project_apply_void',
prompt: '请输入作废原因',
},
],
};
export const option = createCrudOption([
{
label: '立项申请单号',
prop: 'applyNo',
search: true,
minWidth: 160,
addDisplay: false,
editDisabled: true,
},
{
label: '项目编号',
prop: 'projectCode',
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '项目名称',
prop: 'projectName',
search: true,
minWidth: 180,
maxlength: 50,
rules: textRule('项目名称', 50, true),
},
{
label: '项目简称',
prop: 'projectShortName',
minWidth: 140,
maxlength: 20,
rules: textRule('项目简称', 20, true),
},
{
label: '项目类型',
prop: 'projectType',
type: 'select',
search: true,
dicData: projectTypeOptions,
minWidth: 120,
rules: selectRule('项目类型'),
},
{
label: '业务部门',
prop: 'businessDeptName',
minWidth: 150,
rules: textRule('业务部门', 50, true),
},
{
label: '承办部门',
prop: 'undertakeDeptName',
search: true,
minWidth: 150,
rules: textRule('承办部门', 50, true),
},
{
label: '承办部门ID',
prop: 'undertakeDeptId',
hide: true,
},
{
label: '项目负责人',
prop: 'principalUserName',
search: true,
minWidth: 130,
rules: textRule('项目负责人', 50, true),
},
{
label: '项目经办人',
prop: 'handlerUserName',
minWidth: 130,
rules: textRule('项目经办人', 50, true),
},
{
label: '项目由来',
prop: 'projectSource',
type: 'select',
dicData: projectSourceOptions,
value: '商务洽谈',
minWidth: 120,
},
{
label: '项目资金使用额度(万元)',
prop: 'fundLimit',
type: 'number',
precision: 2,
minWidth: 190,
rules: amountRules('项目资金使用额度'),
},
{
label: '项目应收账款额度(万元)',
prop: 'receivableLimit',
type: 'number',
precision: 2,
minWidth: 200,
rules: amountRules('项目应收账款额度'),
},
{
label: '应收账款回款期限(天)',
prop: 'receivableDays',
type: 'number',
minWidth: 190,
rules: [{ required: true, message: '请输入应收账款回款期限', trigger: 'blur' }],
},
{
label: '回款账期(天)',
prop: 'paymentDays',
type: 'number',
minWidth: 140,
rules: [{ required: true, message: '请输入回款账期', trigger: 'blur' }],
},
{
label: '客户名称',
prop: 'customerNames',
search: true,
minWidth: 180,
rules: textRule('客户名称', 255, true),
},
{
label: '下游承运商',
prop: 'carrierNames',
minWidth: 180,
rules: textRule('下游承运商', 255, true),
},
{
label: '货物类型',
prop: 'cargoType',
minWidth: 120,
},
{
label: '预估货物数量',
prop: 'cargoQuantity',
minWidth: 150,
maxlength: 100,
},
{
label: '业务周期开始',
prop: 'businessStartDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '业务周期结束',
prop: 'businessEndDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 130,
},
{
label: '运输线路',
prop: 'transportRoute',
minWidth: 180,
maxlength: 100,
},
{
label: '运输类型',
prop: 'transportType',
type: 'select',
dicData: transportTypeOptions,
minWidth: 120,
},
{
label: '业务类型',
prop: 'businessType',
type: 'select',
dicData: businessTypeOptions,
minWidth: 130,
},
{
label: '项目规模(万元)',
prop: 'projectScale',
type: 'number',
precision: 2,
minWidth: 150,
rules: [nonNegativeRule('项目规模')],
},
{
label: '预计利润(万元)',
prop: 'estimatedProfit',
type: 'number',
precision: 2,
minWidth: 150,
rules: [nonNegativeRule('预计利润')],
},
{
label: '资金需求(万元)',
prop: 'fundDemand',
type: 'number',
precision: 2,
minWidth: 150,
rules: [nonNegativeRule('资金需求')],
},
{
label: '结算方式',
prop: 'settlementMode',
type: 'select',
dicData: settlementModeOptions,
minWidth: 120,
},
{
label: '审批状态',
prop: 'approvalStatus',
type: 'select',
search: true,
slot: true,
dicData: projectApprovalStatusOptions,
minWidth: 130,
addDisplay: false,
editDisplay: false,
fixed: 'right',
},
{
label: '当前节点',
prop: 'currentNode',
minWidth: 140,
addDisplay: false,
editDisplay: false,
},
{
label: '当前处理人',
prop: 'currentProcessor',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '生效类型',
prop: 'effectiveType',
type: 'select',
search: true,
dicData: effectiveTypeOptions,
value: 'temporary',
minWidth: 110,
},
{
label: '审核通过时间',
prop: 'approvedTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 170,
addDisplay: false,
editDisplay: false,
},
{
label: '项目由来说明',
prop: 'sourceRemark',
type: 'textarea',
span: 24,
hide: true,
maxlength: 300,
showWordLimit: true,
},
{
label: '项目情况说明',
prop: 'situationRemark',
type: 'textarea',
span: 24,
hide: true,
maxlength: 1000,
showWordLimit: true,
},
{
label: '项目附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
span: 24,
hide: true,
},
...auditColumns,
]);

View File

@@ -0,0 +1,167 @@
import {
auditColumns,
createCrudOption,
templateTypeOptions,
transportTypeOptions,
selectRule,
textRule,
} from './common';
export const config = {
title: '发货模板',
permission: 'shipping_template',
exportUrl: '/blade-transport/shipping-template/export-shipping-template',
exportName: '发货模板',
enableAllDept: true,
actions: ['copy'],
};
export const option = createCrudOption([
{
label: '模板编号',
prop: 'templateCode',
search: true,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '模板名称',
prop: 'templateName',
search: true,
minWidth: 150,
rules: textRule('模板名称', 50, true),
},
{
label: '模板类型',
prop: 'templateType',
type: 'select',
search: true,
dicData: templateTypeOptions,
minWidth: 120,
value: '运输计划',
rules: selectRule('模板类型'),
},
{
label: '项目',
prop: 'projectName',
search: true,
minWidth: 150,
rules: textRule('项目', 100, true),
},
{
label: '项目ID',
prop: 'projectId',
hide: true,
},
{
label: '客户合同',
prop: 'contractName',
minWidth: 160,
rules: textRule('客户合同', 100, true),
},
{
label: '客户合同ID',
prop: 'contractId',
hide: true,
},
{
label: '运输类型',
prop: 'transportType',
type: 'select',
dicData: transportTypeOptions,
minWidth: 130,
rules: selectRule('运输类型'),
},
{
label: '发货地',
prop: 'departureName',
minWidth: 140,
rules: textRule('发货地', 100, true),
},
{
label: '发货地址',
prop: 'departureAddress',
minWidth: 220,
rules: textRule('发货地址', 255, true),
},
{
label: '发货联系人',
prop: 'departureContact',
minWidth: 120,
rules: textRule('发货联系人', 20),
},
{
label: '发货联系方式',
prop: 'departurePhone',
minWidth: 140,
rules: textRule('发货联系方式', 20),
},
{
label: '收货地',
prop: 'arrivalName',
minWidth: 140,
rules: textRule('收货地', 100, true),
},
{
label: '收货地址',
prop: 'arrivalAddress',
minWidth: 220,
rules: textRule('收货地址', 255, true),
},
{
label: '收货联系人',
prop: 'arrivalContact',
minWidth: 120,
rules: textRule('收货联系人', 20),
},
{
label: '收货联系方式',
prop: 'arrivalPhone',
minWidth: 140,
rules: textRule('收货联系方式', 20),
},
{
label: '货物信息JSON',
prop: 'goodsJson',
type: 'textarea',
minRows: 5,
span: 24,
hide: true,
},
{
label: '运费信息JSON',
prop: 'freightJson',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
},
{
label: '附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
minRows: 3,
span: 24,
hide: true,
},
{
label: '所属组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 200,
showWordLimit: true,
rules: textRule('备注', 200),
},
...auditColumns,
]);

View File

@@ -0,0 +1,191 @@
import { approvalStatusOptions, auditColumns, createCrudOption, nonNegativeRule, textRule } from './common';
export const config = {
title: '临时额度管理',
permission: 'temporary_credit_limit',
exportUrl: '/blade-transport/temporary-credit-limit/export-temporary-credit-limit',
exportName: '临时额度申请',
enableAllDept: true,
statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName',
deleteStatus: ['draft', 'withdrawn', 'rejected'],
editStatus: ['draft', 'withdrawn', 'rejected'],
operations: [
{
action: 'submitApproval',
label: '提交审批',
statusProp: 'approvalStatus',
status: ['draft', 'withdrawn', 'rejected'],
permission: 'temporary_credit_limit_submit',
},
{
action: 'withdraw',
label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus',
status: ['reviewing'],
permission: 'temporary_credit_limit_withdraw',
},
{
action: 'approve',
label: '审批通过',
type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus',
status: ['reviewing'],
permission: 'temporary_credit_limit_approve',
},
{
action: 'reject',
label: '审批驳回',
type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus',
status: ['reviewing'],
permission: 'temporary_credit_limit_reject',
},
],
};
export const option = createCrudOption([
{
label: '申请单号',
prop: 'applicationNo',
search: true,
minWidth: 160,
addDisplay: false,
editDisabled: true,
},
{
label: '项目名称',
prop: 'projectName',
search: true,
minWidth: 180,
rules: textRule('项目名称', 100, true),
},
{
label: '项目ID',
prop: 'projectId',
hide: true,
},
{
label: '项目编号',
prop: 'projectCode',
minWidth: 150,
rules: textRule('项目编号', 50, true),
},
{
label: '承办部门',
prop: 'undertakeDeptName',
minWidth: 150,
rules: textRule('承办部门', 50, true),
},
{
label: '项目资金使用额度(万元)',
prop: 'projectFundLimit',
type: 'number',
precision: 2,
minWidth: 200,
editDisabled: true,
rules: [nonNegativeRule('项目资金使用额度')],
},
{
label: '已使用项目资金额度(万元)',
prop: 'usedFundLimit',
type: 'number',
precision: 2,
minWidth: 220,
value: 0,
editDisabled: true,
rules: [nonNegativeRule('已使用项目资金额度')],
},
{
label: '剩余项目资金使用额度(万元)',
prop: 'remainingFundLimit',
type: 'number',
precision: 2,
minWidth: 230,
editDisabled: true,
rules: [nonNegativeRule('剩余项目资金使用额度')],
},
{
label: '申请临时额度(万元)',
prop: 'applyLimit',
type: 'number',
precision: 2,
minWidth: 180,
rules: [
{ required: true, message: '请输入申请临时额度', trigger: 'blur' },
nonNegativeRule('申请临时额度'),
],
},
{
label: '申请有效期至',
prop: 'validUntil',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
minWidth: 140,
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
},
{
label: '申请部门',
prop: 'applyDeptName',
search: true,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '申请人',
prop: 'applicantName',
search: true,
minWidth: 120,
addDisplay: false,
editDisabled: true,
},
{
label: '审批状态',
prop: 'approvalStatus',
type: 'select',
search: true,
slot: true,
dicData: approvalStatusOptions,
minWidth: 130,
addDisplay: false,
editDisplay: false,
fixed: 'right',
},
{
label: '当前节点',
prop: 'currentNode',
minWidth: 140,
addDisplay: false,
editDisplay: false,
},
{
label: '当前处理人',
prop: 'currentProcessor',
minWidth: 130,
addDisplay: false,
editDisplay: false,
},
{
label: '附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
span: 24,
hide: true,
maxlength: 500,
showWordLimit: true,
rules: textRule('备注', 500),
},
...auditColumns,
]);

View File

@@ -0,0 +1,175 @@
import {
auditColumns,
createCrudOption,
dataSourceOptions,
planStatusOptions,
selectRule,
textRule,
transportTypeOptions,
} from './common';
export const config = {
title: '运输计划',
permission: 'transport_plan',
exportUrl: '/blade-transport/transport-plan/export-transport-plan',
exportName: '运输计划',
enableAllDept: true,
actions: ['copy', 'cancel', 'complete'],
statusProp: 'businessStatus',
statusTextProp: 'businessStatusName',
deleteStatus: ['draft'],
editStatus: ['draft', 'waiting_dispatch'],
};
export const option = createCrudOption([
{
label: '计划单号',
prop: 'planNo',
search: true,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '计划名称',
prop: 'planName',
search: true,
minWidth: 150,
rules: textRule('计划名称', 50, true),
},
{
label: '项目',
prop: 'projectName',
minWidth: 150,
rules: textRule('项目', 100, true),
},
{
label: '项目ID',
prop: 'projectId',
hide: true,
},
{
label: '客户合同',
prop: 'contractName',
minWidth: 160,
rules: textRule('客户合同', 100, true),
},
{
label: '客户合同ID',
prop: 'contractId',
hide: true,
},
{
label: '客户名称',
prop: 'customerName',
search: true,
minWidth: 150,
},
{
label: '运输类型',
prop: 'transportType',
type: 'select',
search: true,
dicData: transportTypeOptions,
minWidth: 130,
rules: selectRule('运输类型'),
},
{
label: '计划开始日期',
prop: 'planStartDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
search: true,
minWidth: 130,
},
{
label: '计划结束日期',
prop: 'planEndDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
search: true,
minWidth: 130,
},
{
label: '发货地',
prop: 'departureName',
minWidth: 140,
rules: textRule('发货地', 100, true),
},
{
label: '发货地址',
prop: 'departureAddress',
search: true,
minWidth: 220,
rules: textRule('发货地址', 255, true),
},
{
label: '收货地',
prop: 'arrivalName',
minWidth: 140,
rules: textRule('收货地', 100, true),
},
{
label: '收货地址',
prop: 'arrivalAddress',
search: true,
minWidth: 220,
rules: textRule('收货地址', 255, true),
},
{
label: '货物信息JSON',
prop: 'goodsJson',
type: 'textarea',
minRows: 5,
span: 24,
hide: true,
},
{
label: '附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
minRows: 3,
span: 24,
hide: true,
},
{
label: '数据来源',
prop: 'dataSource',
type: 'select',
search: true,
dicData: dataSourceOptions,
minWidth: 120,
},
{
label: '业务状态',
prop: 'businessStatus',
type: 'select',
slot: true,
search: true,
dicData: planStatusOptions,
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '所属组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 200,
showWordLimit: true,
rules: textRule('备注', 200),
},
...auditColumns,
]);

View File

@@ -0,0 +1,254 @@
import {
auditColumns,
createCrudOption,
dataSourceOptions,
selectRule,
textRule,
transportTypeOptions,
waybillStatusOptions,
} from './common';
export const config = {
title: '运单管理',
permission: 'waybill_manage',
exportUrl: '/blade-transport/waybill-manage/export-waybill-manage',
exportName: '运单管理',
enableAllDept: true,
actions: ['copy', 'cancel', 'reassign', 'complete', 'batchComplete'],
statusProp: 'businessStatus',
statusTextProp: 'businessStatusName',
deleteStatus: ['draft'],
editStatus: ['draft', 'pending'],
};
export const option = createCrudOption([
{
label: '运单号',
prop: 'waybillNo',
search: true,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '项目',
prop: 'projectName',
search: true,
minWidth: 150,
rules: textRule('项目', 100, true),
},
{
label: '项目ID',
prop: 'projectId',
hide: true,
},
{
label: '客户合同',
prop: 'contractName',
minWidth: 160,
rules: textRule('客户合同', 100, true),
},
{
label: '客户合同ID',
prop: 'contractId',
hide: true,
},
{
label: '客户名称',
prop: 'customerName',
search: true,
minWidth: 150,
},
{
label: '运输类型',
prop: 'transportType',
type: 'select',
search: true,
dicData: transportTypeOptions,
minWidth: 130,
rules: selectRule('运输类型'),
},
{
label: '货物名称',
prop: 'cargoName',
search: true,
minWidth: 150,
rules: textRule('货物名称', 100, true),
},
{
label: '货物类型',
prop: 'cargoType',
search: true,
minWidth: 130,
rules: textRule('货物类型', 100, true),
},
{
label: '发货地址',
prop: 'departureAddress',
search: true,
minWidth: 220,
rules: textRule('发货地址', 255, true),
},
{
label: '收货地址',
prop: 'arrivalAddress',
search: true,
minWidth: 220,
rules: textRule('收货地址', 255, true),
},
{
label: '承运商名称',
prop: 'carrierName',
search: true,
minWidth: 150,
},
{
label: '司机姓名',
prop: 'driverName',
search: true,
minWidth: 120,
},
{
label: '车/船/航班/班列号',
prop: 'vehicleNo',
search: true,
minWidth: 170,
},
{
label: '原始单号',
prop: 'originalNo',
search: true,
minWidth: 140,
},
{
label: '业务状态',
prop: 'businessStatus',
type: 'select',
slot: true,
search: true,
dicData: waybillStatusOptions,
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{
label: '数据来源',
prop: 'dataSource',
type: 'select',
search: true,
dicData: dataSourceOptions,
minWidth: 120,
},
{
label: '开始日期',
prop: 'startDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
search: true,
minWidth: 130,
},
{
label: '结束日期',
prop: 'endDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
search: true,
minWidth: 130,
},
{
label: '计划名称',
prop: 'planName',
search: true,
minWidth: 150,
},
{
label: '多联总单',
prop: 'masterNo',
search: true,
minWidth: 140,
},
{
label: '配载单号',
prop: 'loadingNo',
search: true,
minWidth: 140,
},
{
label: '运单批次号',
prop: 'batchNo',
search: true,
minWidth: 140,
},
{
label: '关联单号',
prop: 'relationNo',
search: true,
minWidth: 140,
},
{
label: '当前过程节点',
prop: 'currentProcessNode',
minWidth: 140,
},
{
label: '货物信息JSON',
prop: 'goodsJson',
type: 'textarea',
minRows: 5,
span: 24,
hide: true,
},
{
label: '承运信息JSON',
prop: 'carrierJson',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
},
{
label: '过程配置JSON',
prop: 'processJson',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
},
{
label: '运费信息JSON',
prop: 'freightJson',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
},
{
label: '附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
minRows: 3,
span: 24,
hide: true,
},
{
label: '所属组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 4,
span: 24,
hide: true,
maxlength: 500,
showWordLimit: true,
rules: textRule('备注', 500),
},
...auditColumns,
]);

View File

@@ -0,0 +1,21 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" :crud-excel-option="excelOption" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/common-cargo';
import { config, excelOption, option } from '@/option/business/common-cargo';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
excelOption,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/common-route';
import { config, option } from '@/option/business/common-route';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,673 @@
<template>
<basic-container class="business-crud-page">
<avue-crud
:option="option"
:table-loading="loading"
:data="data"
v-model:page="page"
v-model="form"
ref="crud"
:permission="permissionList"
:before-open="beforeOpen"
@row-save="rowSave"
@row-update="rowUpdate"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad"
>
<template #menu-left>
<el-button
type="primary"
icon="el-icon-plus"
plain
v-if="canCreate"
@click="$refs.crud.rowAdd()"
>新增
</el-button>
<el-button
type="primary"
icon="el-icon-upload"
plain
v-if="config.importUrl && hasPermission(`${config.permission}_import`) && !readonlyScope"
@click="handleImport"
>批量导入
</el-button>
<el-button
type="primary"
icon="el-icon-download"
plain
v-if="config.templateUrl && hasPermission(`${config.permission}_template`)"
@click="handleTemplate"
>下载模板
</el-button>
<el-button
type="primary"
icon="el-icon-download"
plain
v-if="config.exportUrl && hasPermission(`${config.permission}_export`)"
@click="handleExport"
>批量导出
</el-button>
<el-button
type="success"
icon="el-icon-check"
plain
v-if="canBatchComplete"
@click="handleBatchComplete"
>批量完成
</el-button>
<el-button
type="danger"
icon="el-icon-delete"
plain
v-if="hasPermission(`${config.permission}_delete`) && !readonlyScope"
@click="handleDelete"
>批量删除
</el-button>
<el-switch
v-if="config.enableAllDept && canViewAllDept"
v-model="allDept"
class="business-crud-page__scope"
active-text="全部组织"
inactive-text="当前组织"
:active-value="1"
:inactive-value="0"
@change="handleScopeChange"
/>
</template>
<template #status="{ row }">
<el-tag :type="statusTagType(row.status)">
{{ displayStatus(row, 'status') }}
</el-tag>
</template>
<template #businessStatus="{ row }">
<el-tag :type="statusTagType(row.businessStatus)">
{{ displayStatus(row, 'businessStatus') }}
</el-tag>
</template>
<template #approvalStatus="{ row }">
<el-tag :type="statusTagType(row.approvalStatus)">
{{ displayStatus(row, 'approvalStatus') }}
</el-tag>
</template>
<template #contractStage="{ row }">
<el-tag :type="stageTagType(row.contractStage)">
{{ displayStatus(row, 'contractStage') }}
</el-tag>
</template>
<template #menu="{ row, index }">
<el-button
type="primary"
text
icon="el-icon-view"
v-if="hasPermission(`${config.permission}_view`)"
@click="$refs.crud.rowView(row, index)"
>
查看
</el-button>
<el-button
type="primary"
text
icon="el-icon-edit"
v-if="canEdit(row)"
@click="$refs.crud.rowEdit(row, index)"
>
编辑
</el-button>
<el-button type="primary" text icon="el-icon-copy-document" v-if="canCopy(row)" @click="handleCopy(row)">
复制
</el-button>
<el-button type="primary" text icon="el-icon-video-play" v-if="canEnable(row)" @click="handleAction('enable', row)">
启用
</el-button>
<el-button type="primary" text icon="el-icon-video-pause" v-if="canDisable(row)" @click="handleAction('disable', row)">
停用
</el-button>
<el-button type="primary" text icon="el-icon-refresh" v-if="canReassign(row)" @click="handleAction('reassign', row)">
重新派单
</el-button>
<el-button type="primary" text icon="el-icon-close" v-if="canCancel(row)" @click="handleAction('cancel', row)">
取消
</el-button>
<el-button type="primary" text icon="el-icon-check" v-if="canComplete(row)" @click="handleAction('complete', row)">
完成
</el-button>
<el-button
v-for="operation in customOperations(row)"
:key="operation.action"
:type="operation.type || 'primary'"
text
:icon="operation.icon || 'el-icon-position'"
@click="handleCustomOperation(operation, row)"
>
{{ operation.label }}
</el-button>
<el-button type="primary" text icon="el-icon-delete" v-if="canDelete(row)" @click="rowDel(row)">
删除
</el-button>
</template>
</avue-crud>
<empty-pagination
:page="page"
@size-change="sizeChange"
@current-change="currentChange"
@load="onLoad(page, query)"
/>
<el-dialog :title="`${config.title}导入`" append-to-body v-model="excelBox" width="555px">
<avue-form :option="excelOptionConfig" v-model="excelForm">
<template #excelTemplate>
<el-button type="primary" @click="handleTemplate">
点击下载<i class="el-icon-download el-icon--right"></i>
</el-button>
</template>
</avue-form>
</el-dialog>
</basic-container>
</template>
<script>
import { exportBlob } from '@/api/common';
import { getToken } from '@/utils/auth';
import { openImportDialog } from '@/utils/import-excel';
import { downloadXls } from '@/utils/util';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
export default {
name: 'BusinessCrudPage',
props: {
api: {
type: Object,
required: true,
},
config: {
type: Object,
required: true,
},
crudOption: {
type: Object,
required: true,
},
crudExcelOption: {
type: Object,
default: () => ({ column: [] }),
},
},
data() {
return {
form: {},
query: {},
loading: true,
data: [],
allDept: 0,
dialogReadonly: false,
option: this.cloneOption(this.crudOption),
excelBox: false,
excelForm: {},
excelOptionConfig: this.cloneOption(this.crudExcelOption),
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
currentPage: 1,
total: 0,
},
selectionList: [],
};
},
computed: {
...mapGetters(['permission', 'userInfo']),
permissionList() {
return {
addBtn: this.canCreate,
};
},
isAdmin() {
const authority = this.userInfo && this.userInfo.authority;
return Array.isArray(authority) ? authority.includes('admin') : String(authority || '').includes('admin');
},
canViewAllDept() {
return this.isAdmin;
},
readonlyScope() {
return this.config.enableAllDept && this.allDept === 1;
},
canCreate() {
return this.hasPermission(`${this.config.permission}_add`) && !this.readonlyScope;
},
canBatchComplete() {
return (
this.hasAction('batchComplete') &&
this.hasPermission(`${this.config.permission}_batch_complete`) &&
!this.readonlyScope
);
},
ids() {
return this.selectionList.map(item => item.id).join(',');
},
},
methods: {
cloneOption(option) {
return {
...option,
column: (option.column || []).map(column => ({ ...column })),
};
},
hasPermission(code) {
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
},
hasAction(action) {
return (this.config.actions || []).includes(action);
},
statusValue(row) {
return row[this.config.statusProp || 'status'];
},
inStatus(row, statusList) {
if (!statusList || !statusList.length) {
return true;
}
return statusList.includes(this.statusValue(row));
},
canEdit(row) {
return (
this.hasPermission(`${this.config.permission}_edit`) &&
!this.readonlyScope &&
!row.readonly &&
this.inStatus(row, this.config.editStatus)
);
},
canDelete(row) {
return (
this.hasPermission(`${this.config.permission}_delete`) &&
!this.readonlyScope &&
!row.readonly &&
this.inStatus(row, this.config.deleteStatus)
);
},
canCopy(row) {
return this.hasAction('copy') && this.hasPermission(`${this.config.permission}_copy`) && !this.readonlyScope && !row.readonly;
},
canEnable(row) {
return (
this.hasAction('enable') &&
this.hasPermission(`${this.config.permission}_enable`) &&
!this.readonlyScope &&
!row.readonly &&
[0, 2].includes(row.status)
);
},
canDisable(row) {
return (
this.hasAction('disable') &&
this.hasPermission(`${this.config.permission}_disable`) &&
!this.readonlyScope &&
!row.readonly &&
row.status === 1
);
},
canCancel(row) {
if (!this.hasAction('cancel') || !this.hasPermission(`${this.config.permission}_cancel`) || this.readonlyScope || row.readonly) {
return false;
}
const status = this.statusValue(row);
return this.config.permission === 'transport_plan'
? ['waiting_dispatch', 'dispatching'].includes(status)
: ['pending', 'processing'].includes(status);
},
canComplete(row) {
if (!this.hasAction('complete') || !this.hasPermission(`${this.config.permission}_complete`) || this.readonlyScope || row.readonly) {
return false;
}
const status = this.statusValue(row);
return this.config.permission === 'transport_plan' ? status === 'dispatching' : status === 'processing';
},
canReassign(row) {
return (
this.hasAction('reassign') &&
this.hasPermission(`${this.config.permission}_reassign`) &&
!this.readonlyScope &&
!row.readonly &&
this.statusValue(row) === 'pending'
);
},
customOperations(row) {
return (this.config.operations || []).filter(operation => this.canOperation(operation, row));
},
canOperation(operation, row) {
const permission = operation.permission || `${this.config.permission}_${operation.action}`;
if (!this.hasPermission(permission) || this.readonlyScope || row.readonly) {
return false;
}
const prop = operation.statusProp || this.config.statusProp || 'status';
const statusList = operation.status || [];
if (statusList.length && !statusList.includes(row[prop])) {
return false;
}
if (operation.stage && !operation.stage.includes(row.contractStage)) {
return false;
}
return true;
},
displayStatus(row, prop) {
const textProp = prop === this.config.statusProp ? this.config.statusTextProp : '';
if (textProp && row[textProp]) {
return row[textProp];
}
const column = this.findColumn(this.option.column, prop);
const item = column && (column.dicData || []).find(dic => dic.value === row[prop]);
return item ? item.label : row[prop] || '未知';
},
statusTagType(status) {
if ([1, 'pending', 'waiting_dispatch', 'processing', 'dispatching', 'approved', 'change_approved'].includes(status)) {
return 'success';
}
if ([2, 'cancelled', 'withdrawn', 'draft'].includes(status)) {
return 'info';
}
if (['rejected', 'change_rejected'].includes(status)) {
return 'danger';
}
if (status === 'completed') {
return 'primary';
}
return 'warning';
},
stageTagType(stage) {
if (stage === 'formal') {
return 'success';
}
if (stage === 'temporary') {
return 'warning';
}
if (stage === 'terminated') {
return 'danger';
}
return 'info';
},
normalizeRow(row) {
const submitRow = { ...row };
Object.keys(submitRow).forEach(key => {
if (typeof submitRow[key] === 'string') {
submitRow[key] = submitRow[key].trim();
}
});
return submitRow;
},
stopSubmitLoading(loading) {
if (typeof loading === 'function') {
loading();
}
},
rowSave(row, done, loading) {
this.api.submit(this.normalizeRow(row)).then(
() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
},
error => {
window.console.log(error);
this.stopSubmitLoading(loading);
}
);
},
rowUpdate(row, index, done, loading) {
this.api.submit(this.normalizeRow(row)).then(
() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
},
error => {
window.console.log(error);
this.stopSubmitLoading(loading);
}
);
},
rowDel(row) {
this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.api.remove(row.id))
.then(res => {
this.afterRemove(res.data.data);
});
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning('请选择至少一条数据');
return;
}
const selection = this.selectionList.filter(item => this.canDelete(item));
if (!selection.length) {
this.$message.warning('所选数据当前状态不可删除');
return;
}
this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.api.remove(selection.map(item => item.id).join(',')))
.then(res => {
this.afterRemove(res.data.data);
});
},
afterRemove(result = {}) {
this.onLoad(this.page);
const successCount = result.successCount || 0;
const skippedCount = result.skippedCount || 0;
if (skippedCount) {
this.$message.warning(`成功删除${successCount}条,因业务引用跳过${skippedCount}`);
} else {
this.$message({ type: 'success', message: '删除成功!' });
}
this.selectionClear();
},
beforeOpen(done, type) {
this.dialogReadonly = type === 'view';
if (type === 'add') {
this.form = {
...(this.config.defaultForm || {}),
...this.form,
};
done();
return;
}
if (['edit', 'view'].includes(type)) {
this.api.getDetail(this.form.id).then(res => {
this.form = res.data.data || {};
done();
});
return;
}
done();
},
searchReset() {
this.query = {};
this.page.currentPage = 1;
this.onLoad(this.page);
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
selectionChange(list) {
this.selectionList = list;
},
selectionClear() {
this.selectionList = [];
if (this.$refs.crud) {
this.$refs.crud.toggleSelection();
}
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
refreshChange() {
this.onLoad(this.page, this.query);
},
handleScopeChange() {
if (!this.canViewAllDept) {
this.allDept = 0;
}
this.page.currentPage = 1;
this.onLoad(this.page);
},
onLoad(page, params = {}) {
this.loading = true;
this.api
.getList(page.currentPage, page.pageSize, { ...params, ...this.query, allDept: this.allDept })
.then(res => {
const result = res.data.data;
this.page.total = result.total;
this.data = result.records;
this.selectionClear();
})
.finally(() => {
this.loading = false;
});
},
buildExportParams() {
return {
...this.query,
allDept: this.allDept,
ids: this.ids,
[this.website.tokenHeader]: getToken(),
};
},
handleExport() {
this.$confirm(`是否导出${this.config.exportName || this.config.title}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
NProgress.start();
exportBlob(this.config.exportUrl, this.buildExportParams())
.then(res => {
downloadXls(res.data, `${this.config.exportName || this.config.title}${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
})
.finally(() => {
NProgress.done();
});
});
},
handleTemplate() {
NProgress.start();
exportBlob(this.config.templateUrl, {
[this.website.tokenHeader]: getToken(),
})
.then(res => {
downloadXls(res.data, `${this.config.title}模板.xlsx`);
})
.finally(() => {
NProgress.done();
});
},
handleImport() {
const column = this.findColumn(this.excelOptionConfig.column, 'excelFile');
column.action = this.config.importUrl;
openImportDialog(this, this.config.title, () => this.onLoad(this.page, this.query));
},
handleCopy(row) {
this.$confirm(`确定复制该${this.config.title}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.api.copy(row.id))
.then(() => {
this.$message.success('复制成功');
this.onLoad(this.page, this.query);
});
},
handleAction(action, row) {
const actionName = {
enable: '启用',
disable: '停用',
cancel: '取消',
complete: '完成',
reassign: '重新派单',
}[action];
this.$confirm(`确定${actionName}${this.config.title}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.api[action](row.id))
.then(() => {
this.$message.success(`${actionName}成功`);
this.onLoad(this.page, this.query);
});
},
handleCustomOperation(operation, row) {
const run = value => {
const args = operation.prompt ? [row.id, value] : [row.id];
this.api[operation.action](...args).then(() => {
this.$message.success(`${operation.label}成功`);
this.onLoad(this.page, this.query);
});
};
if (operation.prompt) {
this.$prompt(operation.prompt, operation.label, {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /\S+/,
inputErrorMessage: operation.promptError || '请输入内容',
}).then(({ value }) => run(value));
return;
}
this.$confirm(operation.confirm || `确定${operation.label}${this.config.title}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => run());
},
handleBatchComplete() {
if (!this.selectionList.length) {
this.$message.warning('请选择至少一条数据');
return;
}
this.$confirm('确定完成选中的运单?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.api.batchComplete(this.ids))
.then(res => {
const result = res.data.data || {};
this.$message.success(`成功完成${result.successCount || 0}条,跳过${result.skippedCount || 0}`);
this.onLoad(this.page, this.query);
});
},
},
};
</script>
<style lang="scss" scoped>
.business-crud-page {
&__scope {
margin-left: 12px;
vertical-align: middle;
}
}
</style>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/contract-manage';
import { config, option } from '@/option/business/contract-manage';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/process-config';
import { config, option } from '@/option/business/process-config';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/project-apply';
import { config, option } from '@/option/business/project-apply';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/shipping-template';
import { config, option } from '@/option/business/shipping-template';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/temporary-credit-limit';
import { config, option } from '@/option/business/temporary-credit-limit';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/transport-plan';
import { config, option } from '@/option/business/transport-plan';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<business-crud-page :api="api" :config="config" :crud-option="option" />
</template>
<script>
import BusinessCrudPage from './components/business-crud-page.vue';
import * as api from '@/api/business/waybill-manage';
import { config, option } from '@/option/business/waybill-manage';
export default {
components: { BusinessCrudPage },
data() {
return {
api,
config,
option,
};
},
};
</script>