1、基础数据修复bug
2、客商模块修复bug
This commit is contained in:
@@ -40,6 +40,16 @@ export const submitApproval = id => {
|
||||
});
|
||||
};
|
||||
|
||||
export const withdrawApproval = id => {
|
||||
return request({
|
||||
url: '/blade-transport/customer-archive/withdraw-approval',
|
||||
method: 'post',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const approve = id => {
|
||||
return request({
|
||||
url: '/blade-transport/customer-archive/approve',
|
||||
|
||||
@@ -85,6 +85,9 @@ const MIME_MAP = {
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
ppt: 'application/vnd.ms-powerpoint',
|
||||
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
eml: 'message/rfc822',
|
||||
msg: 'application/vnd.ms-outlook',
|
||||
zip: 'application/zip',
|
||||
txt: 'text/plain',
|
||||
};
|
||||
|
||||
|
||||
@@ -56,10 +56,10 @@ export const getCargoTypeOption = ctx => ({
|
||||
type: 'radio',
|
||||
dataType: 'number',
|
||||
dicData: typeLevelDic,
|
||||
search: true,
|
||||
searchSpan: 6,
|
||||
search: false,
|
||||
value: 2,
|
||||
span: 24,
|
||||
order: 100,
|
||||
hide: true,
|
||||
minWidth: 120,
|
||||
editDisabled: true,
|
||||
@@ -70,20 +70,34 @@ export const getCargoTypeOption = ctx => ({
|
||||
label: '货物类型',
|
||||
prop: 'cargoName',
|
||||
minWidth: 150,
|
||||
search: true,
|
||||
searchPlaceholder: '请输入',
|
||||
searchSpan: 6,
|
||||
searchOrder: 2,
|
||||
order: 70,
|
||||
placeholder: '请输入',
|
||||
maxlength: 50,
|
||||
showWordLimit: true,
|
||||
showOverflowTooltip: true,
|
||||
rules: [{ validator: validateCargoName, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入货物类型名称', trigger: 'blur' },
|
||||
{ validator: validateCargoName, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '货物类型编码',
|
||||
prop: 'cargoCode',
|
||||
minWidth: 140,
|
||||
search: true,
|
||||
searchPlaceholder: '请输入',
|
||||
searchSpan: 6,
|
||||
searchOrder: 1,
|
||||
maxlength: 4,
|
||||
order: 60,
|
||||
placeholder: '请输入',
|
||||
editDisabled: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入货物类型编码', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
const form = ctx.form || {};
|
||||
@@ -115,6 +129,8 @@ export const getCargoTypeOption = ctx => ({
|
||||
hide: true,
|
||||
display: false,
|
||||
span: 12,
|
||||
order: 90,
|
||||
placeholder: '请输入',
|
||||
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
@@ -128,16 +144,19 @@ export const getCargoTypeOption = ctx => ({
|
||||
minWidth: 160,
|
||||
},
|
||||
{
|
||||
label: '上级货物编码',
|
||||
label: '上级货物类型编码',
|
||||
prop: 'parentCargoCode',
|
||||
slot: true,
|
||||
readonly: true,
|
||||
editDisabled: true,
|
||||
addDisabled: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
span: 12,
|
||||
order: 80,
|
||||
minWidth: 160,
|
||||
placeholder: '请输入',
|
||||
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
@@ -156,6 +175,7 @@ export const getCargoTypeOption = ctx => ({
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
minWidth: 180,
|
||||
placeholder: '请输入',
|
||||
maxlength: 200,
|
||||
showWordLimit: true,
|
||||
overHidden: true,
|
||||
|
||||
@@ -27,18 +27,154 @@ export const createOption = () => ({
|
||||
delBtn: false,
|
||||
addBtn: false,
|
||||
dialogClickModal: false,
|
||||
menuWidth: 160,
|
||||
menuFixed: 'right',
|
||||
menuWidth: 220,
|
||||
column: [
|
||||
{
|
||||
label: '地址名称',
|
||||
prop: 'addressName',
|
||||
search: true,
|
||||
searchOrder: 8,
|
||||
span: 24,
|
||||
minWidth: 150,
|
||||
showOverflowTooltip: true,
|
||||
placeholder: '请输入',
|
||||
maxlength: 100,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入地址名称', trigger: 'blur' },
|
||||
{ max: 100, message: '地址名称不能超过100个字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '地址编号',
|
||||
prop: 'addressCode',
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '类型',
|
||||
prop: 'addressType',
|
||||
type: 'select',
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 7,
|
||||
span: 24,
|
||||
minWidth: 140,
|
||||
dicData: addressTypeOptions,
|
||||
rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '站点编码',
|
||||
prop: 'siteCodeDisplay',
|
||||
search: false,
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
formslot: true,
|
||||
type: 'textarea',
|
||||
minRows: 3,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
showOverflowTooltip: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' },
|
||||
{ max: 255, message: '详细地址不能超过255个字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划',
|
||||
prop: 'regionName',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
display: false,
|
||||
minWidth: 150,
|
||||
rules: [{ required: true, message: '请选择行政区划', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '联系人',
|
||||
prop: 'contactName',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
minWidth: 110,
|
||||
placeholder: '请输入',
|
||||
maxlength: 50,
|
||||
rules: [{ max: 50, message: '联系人不能超过50个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '联系方式',
|
||||
prop: 'contactPhone',
|
||||
search: true,
|
||||
searchOrder: 1,
|
||||
minWidth: 130,
|
||||
placeholder: '请输入',
|
||||
maxlength: 20,
|
||||
rules: [{ max: 20, message: '联系方式不能超过20个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
minWidth: 160,
|
||||
overHidden: true,
|
||||
showOverflowTooltip: true,
|
||||
placeholder: '请输入',
|
||||
maxlength: 200,
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '更新时间',
|
||||
prop: 'updateTime',
|
||||
type: 'datetime',
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
width: 180,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
type: 'datetime',
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
width: 180,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '港口',
|
||||
prop: 'portId',
|
||||
@@ -75,133 +211,24 @@ export const createOption = () => ({
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请选择机场标准名称', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '地址名称',
|
||||
prop: 'addressName',
|
||||
search: true,
|
||||
span: 24,
|
||||
minWidth: 150,
|
||||
maxlength: 100,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入地址名称', trigger: 'blur' },
|
||||
{ max: 100, message: '地址名称不能超过100个字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '地址编号',
|
||||
prop: 'addressCode',
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '站点编码',
|
||||
prop: 'siteCodeDisplay',
|
||||
search: false,
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '站点编码',
|
||||
prop: 'siteCode',
|
||||
search: true,
|
||||
searchOrder: 6,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划',
|
||||
prop: 'regionName',
|
||||
search: true,
|
||||
display: false,
|
||||
minWidth: 150,
|
||||
rules: [{ required: true, message: '请选择行政区划', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
search: true,
|
||||
formslot: true,
|
||||
type: 'textarea',
|
||||
minRows: 3,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
rules: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' },
|
||||
{ max: 255, message: '详细地址不能超过255个字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptId',
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
hide: true,
|
||||
display: false,
|
||||
dicData: [],
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '联系人',
|
||||
prop: 'contactName',
|
||||
search: true,
|
||||
minWidth: 110,
|
||||
maxlength: 50,
|
||||
rules: [{ max: 50, message: '联系人不能超过50个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '联系方式',
|
||||
prop: 'contactPhone',
|
||||
search: true,
|
||||
minWidth: 130,
|
||||
maxlength: 20,
|
||||
rules: [{ max: 20, message: '联系方式不能超过20个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
hide: true,
|
||||
maxlength: 200,
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '更新人',
|
||||
prop: 'updateUserName',
|
||||
minWidth: 120,
|
||||
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,
|
||||
},
|
||||
{
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -6,6 +6,15 @@ import {
|
||||
textRule,
|
||||
} from './common';
|
||||
|
||||
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: 'common_cargo',
|
||||
@@ -17,12 +26,29 @@ export const config = {
|
||||
};
|
||||
|
||||
export const option = createCrudOption([
|
||||
{
|
||||
label: '货物名称',
|
||||
prop: 'cargoName',
|
||||
minWidth: 150,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('货物名称', 100, true),
|
||||
},
|
||||
{
|
||||
label: '货物编号',
|
||||
prop: 'cargoCode',
|
||||
formslot: true,
|
||||
minWidth: 120,
|
||||
maxlength: 20,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入货物编号', trigger: 'blur' },
|
||||
{ max: 20, message: '货物编号不能超过20个字符', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '一级货物类型',
|
||||
prop: 'firstCargoTypeName',
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
minWidth: 150,
|
||||
editDisabled: true,
|
||||
rules: [{ required: true, message: '请选择一级货物类型', trigger: 'change' }],
|
||||
@@ -39,8 +65,6 @@ export const option = createCrudOption([
|
||||
label: '二级货物类型',
|
||||
prop: 'secondCargoTypeName',
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
minWidth: 150,
|
||||
editDisabled: true,
|
||||
rules: [{ required: true, message: '请选择二级货物类型', trigger: 'change' }],
|
||||
@@ -48,47 +72,118 @@ export const option = createCrudOption([
|
||||
{
|
||||
label: '二级货物类型编码',
|
||||
prop: 'secondCargoTypeCode',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisabled: true,
|
||||
},
|
||||
// 搜索字段与表格、表单字段独立,避免筛选配置影响数据展示和编辑布局。
|
||||
{
|
||||
label: '货物名称',
|
||||
prop: 'cargoName',
|
||||
prop: 'searchCargoName',
|
||||
searchProp: 'cargoName',
|
||||
search: true,
|
||||
searchOrder: 1,
|
||||
minWidth: 150,
|
||||
rules: textRule('货物名称', 100, true),
|
||||
searchOrder: 5,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '货物编号',
|
||||
prop: 'cargoCode',
|
||||
formslot: true,
|
||||
prop: 'searchCargoCode',
|
||||
searchProp: 'cargoCode',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '一级货物类型',
|
||||
prop: 'searchFirstCargoTypeName',
|
||||
searchProp: 'firstCargoTypeName',
|
||||
type: 'select',
|
||||
searchType: 'select',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
searchPlaceholder: '请选择',
|
||||
dicUrl: '/blade-system/cargo-type/list?current=1&size=9999&typeLevel=1',
|
||||
dicFormatter: listDicFormatter,
|
||||
props: {
|
||||
label: 'cargoName',
|
||||
value: 'cargoName',
|
||||
},
|
||||
filterable: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '二级货物类型',
|
||||
prop: 'searchSecondCargoTypeName',
|
||||
searchProp: 'secondCargoTypeName',
|
||||
type: 'select',
|
||||
searchType: 'select',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
minWidth: 120,
|
||||
maxlength: 20,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请输入货物编号', trigger: 'blur' },
|
||||
{ max: 20, message: '货物编号不能超过20个字符', trigger: 'blur' },
|
||||
],
|
||||
searchPlaceholder: '请选择',
|
||||
dicUrl: '/blade-system/cargo-type/list?current=1&size=9999&typeLevel=2',
|
||||
dicFormatter: listDicFormatter,
|
||||
props: {
|
||||
label: 'cargoName',
|
||||
value: 'cargoName',
|
||||
},
|
||||
filterable: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
prop: 'searchDeptId',
|
||||
searchProp: 'deptId',
|
||||
type: 'select',
|
||||
searchType: 'select',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
searchOrder: 1,
|
||||
searchPlaceholder: '请选择',
|
||||
dicData: [],
|
||||
props: {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
},
|
||||
filterable: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '包装品牌',
|
||||
prop: 'packageBrand',
|
||||
slot: true,
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '品牌',
|
||||
prop: 'brand',
|
||||
search: false,
|
||||
hide: true,
|
||||
minWidth: 120,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('品牌', 50),
|
||||
},
|
||||
{
|
||||
@@ -96,10 +191,25 @@ export const option = createCrudOption([
|
||||
prop: 'packageType',
|
||||
type: 'select',
|
||||
dicData: packageOptions,
|
||||
hide: true,
|
||||
minWidth: 100,
|
||||
},
|
||||
{
|
||||
label: '货值',
|
||||
label: '规格',
|
||||
prop: 'specification',
|
||||
minWidth: 120,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('规格', 50),
|
||||
},
|
||||
{
|
||||
label: '型号',
|
||||
prop: 'model',
|
||||
minWidth: 120,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('型号', 50),
|
||||
},
|
||||
{
|
||||
label: '单价',
|
||||
prop: 'cargoValue',
|
||||
formslot: true,
|
||||
minWidth: 120,
|
||||
@@ -129,29 +239,26 @@ export const option = createCrudOption([
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
label: '规格',
|
||||
prop: 'specification',
|
||||
minWidth: 120,
|
||||
rules: textRule('规格', 50),
|
||||
},
|
||||
{
|
||||
label: '型号',
|
||||
prop: 'model',
|
||||
minWidth: 120,
|
||||
rules: textRule('型号', 50),
|
||||
},
|
||||
{
|
||||
label: '说明',
|
||||
prop: 'descriptionOne',
|
||||
minWidth: 160,
|
||||
rules: textRule('说明', 100),
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'dataSource',
|
||||
label: '尺寸',
|
||||
prop: 'sizeText',
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: textRule('尺寸', 100),
|
||||
},
|
||||
{
|
||||
label: '其他说明1',
|
||||
prop: 'descriptionOne',
|
||||
minWidth: 160,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('其他说明1', 100),
|
||||
},
|
||||
{
|
||||
label: '其他说明2',
|
||||
prop: 'descriptionTwo',
|
||||
minWidth: 160,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('其他说明2', 100),
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
@@ -159,12 +266,25 @@ export const option = createCrudOption([
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
hide: true,
|
||||
maxlength: 200,
|
||||
showWordLimit: true,
|
||||
placeholder: '请输入',
|
||||
rules: textRule('备注', 200),
|
||||
},
|
||||
...auditColumns,
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
...auditColumns
|
||||
.filter(column => ['updateTime', 'createTime'].includes(column.prop))
|
||||
.sort(
|
||||
(first, second) =>
|
||||
['updateTime', 'createTime'].indexOf(first.prop) -
|
||||
['updateTime', 'createTime'].indexOf(second.prop)
|
||||
),
|
||||
]);
|
||||
|
||||
export const excelOption = {
|
||||
|
||||
@@ -5,6 +5,8 @@ export const config = {
|
||||
permission: 'common_route',
|
||||
exportUrl: '/blade-transport/common-route/export-common-route',
|
||||
exportName: '常用线路',
|
||||
importUrl: '/blade-transport/common-route/import-common-route',
|
||||
templateUrl: '/blade-transport/common-route/export-template',
|
||||
enableAllDept: false,
|
||||
};
|
||||
|
||||
@@ -12,17 +14,14 @@ export const option = createCrudOption([
|
||||
{
|
||||
label: '线路名称',
|
||||
prop: 'routeName',
|
||||
search: true,
|
||||
searchOrder: 1,
|
||||
span: 24,
|
||||
span: 12,
|
||||
minWidth: 150,
|
||||
overHidden: true,
|
||||
rules: textRule('线路名称', 100, true),
|
||||
},
|
||||
{
|
||||
label: '线路编号',
|
||||
prop: 'routeCode',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
minWidth: 120,
|
||||
addDisplay: false,
|
||||
editDisabled: true,
|
||||
@@ -30,8 +29,6 @@ export const option = createCrudOption([
|
||||
{
|
||||
label: '发货地',
|
||||
prop: 'departureName',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
minWidth: 140,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
@@ -40,10 +37,9 @@ export const option = createCrudOption([
|
||||
label: '发货地址',
|
||||
prop: 'departureAddress',
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: true,
|
||||
rules: textRule('发货地址', 255, true),
|
||||
},
|
||||
{
|
||||
@@ -53,6 +49,8 @@ export const option = createCrudOption([
|
||||
precision: 6,
|
||||
minWidth: 120,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '发货纬度',
|
||||
@@ -61,6 +59,8 @@ export const option = createCrudOption([
|
||||
precision: 6,
|
||||
minWidth: 120,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '发货联系人',
|
||||
@@ -77,8 +77,6 @@ export const option = createCrudOption([
|
||||
{
|
||||
label: '收货地',
|
||||
prop: 'arrivalName',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
minWidth: 140,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
@@ -87,10 +85,9 @@ export const option = createCrudOption([
|
||||
label: '收货地址',
|
||||
prop: 'arrivalAddress',
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 6,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: true,
|
||||
rules: textRule('收货地址', 255, true),
|
||||
},
|
||||
{
|
||||
@@ -100,6 +97,8 @@ export const option = createCrudOption([
|
||||
precision: 6,
|
||||
minWidth: 120,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '收货纬度',
|
||||
@@ -108,6 +107,8 @@ export const option = createCrudOption([
|
||||
precision: 6,
|
||||
minWidth: 120,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '收货联系人',
|
||||
@@ -121,25 +122,160 @@ export const option = createCrudOption([
|
||||
minWidth: 140,
|
||||
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
search: true,
|
||||
searchOrder: 7,
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
hide: true,
|
||||
minWidth: 180,
|
||||
maxlength: 500,
|
||||
showWordLimit: true,
|
||||
rules: textRule('备注', 500),
|
||||
},
|
||||
...auditColumns,
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
// 搜索字段独立于表格和表单字段,避免筛选配置影响数据展示和编辑布局。
|
||||
{
|
||||
label: '线路名称',
|
||||
prop: 'searchRouteName',
|
||||
searchProp: 'routeName',
|
||||
search: true,
|
||||
searchOrder: 7,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '线路编号',
|
||||
prop: 'searchRouteCode',
|
||||
searchProp: 'routeCode',
|
||||
search: true,
|
||||
searchOrder: 6,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '发货地',
|
||||
prop: 'searchDepartureName',
|
||||
searchProp: 'departureName',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '发货地址',
|
||||
prop: 'searchDepartureAddress',
|
||||
searchProp: 'departureAddress',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '收货地',
|
||||
prop: 'searchArrivalName',
|
||||
searchProp: 'arrivalName',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '收货地址',
|
||||
prop: 'searchArrivalAddress',
|
||||
searchProp: 'arrivalAddress',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'searchDeptId',
|
||||
searchProp: 'deptId',
|
||||
search: true,
|
||||
searchOrder: 1,
|
||||
searchType: 'cascader',
|
||||
searchPlaceholder: '请选择',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
dicData: [],
|
||||
props: {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
children: 'children',
|
||||
},
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
showAllLevels: false,
|
||||
filterable: true,
|
||||
},
|
||||
...auditColumns
|
||||
.filter(column => column.prop !== 'createUserName')
|
||||
.map(column =>
|
||||
['createTime', 'updateTime'].includes(column.prop) ? { ...column, minWidth: 190 } : column
|
||||
)
|
||||
.sort(
|
||||
(first, second) =>
|
||||
['updateUserName', 'updateTime', 'createTime'].indexOf(first.prop) -
|
||||
['updateUserName', 'updateTime', 'createTime'].indexOf(second.prop)
|
||||
),
|
||||
]);
|
||||
|
||||
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 标准格式文件',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -241,7 +241,7 @@ export const option = createCrudOption([
|
||||
prop: 'partyA',
|
||||
type: 'select',
|
||||
order: 160,
|
||||
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved',
|
||||
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved&status=1',
|
||||
dicFormatter: listDicFormatter,
|
||||
props: {
|
||||
label: 'fullName',
|
||||
@@ -256,7 +256,7 @@ export const option = createCrudOption([
|
||||
prop: 'partyB',
|
||||
type: 'select',
|
||||
order: 150,
|
||||
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved',
|
||||
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved&status=1',
|
||||
dicFormatter: listDicFormatter,
|
||||
props: {
|
||||
label: 'fullName',
|
||||
|
||||
@@ -13,7 +13,7 @@ export const config = {
|
||||
permission: 'process_config',
|
||||
exportUrl: '/blade-transport/process-config/export-process-config',
|
||||
exportName: '过程配置',
|
||||
enableAllDept: false,
|
||||
enableAllDept: true,
|
||||
actions: ['copy', 'enable', 'disable'],
|
||||
statusProp: 'status',
|
||||
statusTextProp: 'statusName',
|
||||
@@ -29,21 +29,13 @@ export const option = applyTableMenuWidth({
|
||||
span: 24,
|
||||
hide: true,
|
||||
},
|
||||
{
|
||||
label: '配置编号',
|
||||
prop: 'configCode',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
minWidth: 130,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
editDisabled: true,
|
||||
},
|
||||
{
|
||||
label: '配置名称',
|
||||
prop: 'configName',
|
||||
search: true,
|
||||
searchOrder: 6,
|
||||
searchSpan: 6,
|
||||
searchPlaceholder: '请输入',
|
||||
span: 12,
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
@@ -51,13 +43,16 @@ export const option = applyTableMenuWidth({
|
||||
rules: textRule('配置名称', 100, true),
|
||||
},
|
||||
{
|
||||
label: '项目ID集合',
|
||||
prop: 'projectIds',
|
||||
hide: true,
|
||||
display: false,
|
||||
label: '配置编号',
|
||||
prop: 'configCode',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
searchSpan: 6,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 130,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: textRule('项目ID集合', 1000, true),
|
||||
editDisabled: true,
|
||||
},
|
||||
{
|
||||
label: '项目',
|
||||
@@ -65,7 +60,9 @@ export const option = applyTableMenuWidth({
|
||||
formslot: true,
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
searchType: 'select',
|
||||
searchType: 'input',
|
||||
searchSpan: 6,
|
||||
searchPlaceholder: '请输入',
|
||||
type: 'textarea',
|
||||
minRows: 2,
|
||||
span: 12,
|
||||
@@ -77,48 +74,98 @@ export const option = applyTableMenuWidth({
|
||||
rules: textRule('项目', 1000, true),
|
||||
},
|
||||
{
|
||||
label: '包含过程节点',
|
||||
label: '过程节点',
|
||||
prop: 'includedNodes',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
type: 'select',
|
||||
multiple: true,
|
||||
dicData: nodeOptions,
|
||||
minWidth: 180,
|
||||
rules: selectRule('包含过程节点'),
|
||||
minWidth: 260,
|
||||
overHidden: false,
|
||||
slot: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: selectRule('过程节点'),
|
||||
},
|
||||
{
|
||||
label: '默认完成运输天数',
|
||||
label: '默认运输完成天数',
|
||||
prop: 'defaultFinishDays',
|
||||
formslot: true,
|
||||
type: 'number',
|
||||
min: 1,
|
||||
min: 0,
|
||||
max: 999,
|
||||
span: 12,
|
||||
minWidth: 170,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
minWidth: 180,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
maxlength: 500,
|
||||
showWordLimit: true,
|
||||
rules: textRule('备注', 500),
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
minWidth: 150,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
...auditColumns
|
||||
.filter(column => ['updateTime', 'createTime'].includes(column.prop))
|
||||
.map(column => ({ ...column, minWidth: 190 }))
|
||||
.sort(
|
||||
(first, second) =>
|
||||
['updateTime', 'createTime'].indexOf(first.prop) -
|
||||
['updateTime', 'createTime'].indexOf(second.prop)
|
||||
),
|
||||
{
|
||||
label: '项目ID集合',
|
||||
prop: 'projectIds',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: textRule('项目ID集合', 1000, true),
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 1,
|
||||
searchSpan: 6,
|
||||
searchPlaceholder: '请选择',
|
||||
dicData: processStatusOptions,
|
||||
slot: true,
|
||||
minWidth: 100,
|
||||
hide: true,
|
||||
fixed: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
prop: 'deptName',
|
||||
prop: 'searchDeptId',
|
||||
searchProp: 'deptId',
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
minWidth: 150,
|
||||
searchSpan: 6,
|
||||
searchPlaceholder: '请选择',
|
||||
hide: true,
|
||||
display: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
dicData: [],
|
||||
filterable: true,
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
@@ -127,22 +174,9 @@ export const option = applyTableMenuWidth({
|
||||
span: 24,
|
||||
hide: true,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
maxlength: 500,
|
||||
showWordLimit: true,
|
||||
rules: textRule('备注', 500),
|
||||
},
|
||||
...auditColumns,
|
||||
]),
|
||||
saveBtnText: '保存',
|
||||
updateBtnText: '保存',
|
||||
dialogTop: '10px',
|
||||
dialogWidth: '96%',
|
||||
searchSpan: 8,
|
||||
}, 5);
|
||||
|
||||
@@ -267,6 +267,19 @@
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
// 统一 CRUD 顶部新增按钮为蓝底白字,保留其他工具按钮的描边样式
|
||||
.avue-crud__header .el-button--primary.is-plain:has(.el-icon-plus) {
|
||||
--el-button-bg-color: #409eff;
|
||||
--el-button-border-color: #409eff;
|
||||
--el-button-hover-bg-color: #66b1ff;
|
||||
--el-button-hover-border-color: #66b1ff;
|
||||
--el-button-active-bg-color: #337ecc;
|
||||
--el-button-active-border-color: #337ecc;
|
||||
--el-button-text-color: #fff;
|
||||
--el-button-hover-text-color: #fff;
|
||||
--el-button-active-text-color: #fff;
|
||||
}
|
||||
|
||||
// 统一分页为按钮样式并靠右展示
|
||||
.avue-crud__pagination,
|
||||
.empty-pagination {
|
||||
@@ -462,16 +475,24 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// 全站统一:操作列最多一行展示 4 个按钮,第 5 个开始自动换行
|
||||
.avue-crud .el-table td .cell.avue-crud__menu {
|
||||
display: inline-grid;
|
||||
grid-template-columns: repeat(4, max-content);
|
||||
gap: 4px;
|
||||
// 全站统一:Avue 操作列文字链接保持间距并支持自动换行
|
||||
.avue-crud .avue-crud__menu {
|
||||
display: inline-flex !important;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
// 全站统一:手写表格操作列中的文字链接保持间距并支持自动换行
|
||||
.el-table .el-table__body .cell:not(.avue-crud__menu):has(> .el-link) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.avue-crud__menu > .el-button,
|
||||
.avue-crud__menu > .el-dropdown {
|
||||
margin: 0;
|
||||
|
||||
@@ -47,7 +47,12 @@ const decorateFailExcel = async (blob, businessName, failDetailDecorator) => {
|
||||
*/
|
||||
export const openImportDialog = (vm, businessName, onSuccess, options = {}) => {
|
||||
const { failDetailDecorator } = options;
|
||||
const column = vm.findColumn(vm.excelOption.column, 'excelFile');
|
||||
const excelOption = vm.excelOption || vm.excelOptionConfig;
|
||||
const column = vm.findColumn(excelOption?.column || [], 'excelFile');
|
||||
if (!column) {
|
||||
vm.$message.error('导入配置异常,请稍后重试');
|
||||
return;
|
||||
}
|
||||
column.httpRequest = (option, uploadColumn) =>
|
||||
handleImportExcel(vm, option, uploadColumn, businessName, onSuccess, { failDetailDecorator });
|
||||
vm.excelBox = true;
|
||||
|
||||
@@ -250,7 +250,7 @@ export default {
|
||||
viewBtn: true,
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
menuWidth: 160,
|
||||
menuWidth: 320,
|
||||
dialogWidth: 600,
|
||||
dialogClickModal: false,
|
||||
column: [
|
||||
@@ -466,7 +466,7 @@ export default {
|
||||
});
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
add(row).then(
|
||||
add(this.withTenantId(row)).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({
|
||||
@@ -482,7 +482,7 @@ export default {
|
||||
);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
update(row).then(
|
||||
update(this.withTenantId(row)).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({
|
||||
@@ -497,6 +497,12 @@ export default {
|
||||
}
|
||||
);
|
||||
},
|
||||
withTenantId(row) {
|
||||
return {
|
||||
...row,
|
||||
tenantId: row.tenantId || this.userInfo.tenantId || website.tenantId,
|
||||
};
|
||||
},
|
||||
rowDel(row) {
|
||||
this.$confirm('确定将选择数据删除?', {
|
||||
confirmButtonText: '确定',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:table-loading="loading"
|
||||
:data="data"
|
||||
v-model:page="page"
|
||||
v-model:form="form"
|
||||
v-model="form"
|
||||
ref="crud"
|
||||
:permission="permissionList"
|
||||
:before-open="beforeOpen"
|
||||
@@ -22,7 +22,7 @@
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button type="primary" v-if="permission.cargo_type_add" @click="$refs.crud.rowAdd()">
|
||||
<el-icon class="el-icon--left"><Plus /></el-icon>新增
|
||||
<el-icon class="el-icon--left"><Plus /></el-icon>新建货物类型
|
||||
</el-button>
|
||||
<el-button type="primary" plain v-if="permission.cargo_type_import" @click="handleImport"
|
||||
><el-icon class="el-icon--left"><Upload /></el-icon>批量导入</el-button
|
||||
@@ -67,7 +67,7 @@
|
||||
:remote-method="loadParentOptions"
|
||||
:loading="parentLoading"
|
||||
:disabled="dialogType === 'view' || form.typeLevel !== 2"
|
||||
placeholder="请输入名称或编码搜索"
|
||||
placeholder="请输入"
|
||||
style="width: 100%"
|
||||
@change="handleParentChange"
|
||||
>
|
||||
@@ -348,6 +348,11 @@ export default {
|
||||
const parent = this.parentOptions.find(item => String(item.id) === String(value));
|
||||
this.form.parentCargoName = parent ? parent.cargoName : '';
|
||||
this.form.parentCargoCode = parent ? parent.cargoCode || parent.code || '' : '';
|
||||
if (parent) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.crud?.clearValidate?.(['parentId', 'parentCargoCode']);
|
||||
});
|
||||
}
|
||||
if (!parent) {
|
||||
this.form.cargoCode = '';
|
||||
return;
|
||||
@@ -540,7 +545,10 @@ export default {
|
||||
});
|
||||
},
|
||||
buildExportParams() {
|
||||
return { ...this.query };
|
||||
return {
|
||||
...this.query,
|
||||
...(this.ids ? { ids: this.ids } : {}),
|
||||
};
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出货物类型数据?', '提示', {
|
||||
@@ -564,16 +572,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
NProgress.start();
|
||||
// 直接下载工程内置的标准导入模板(public 目录静态资源),表头与可正常导入的模板一致,
|
||||
// 含一级(19 类)及全部二级示例,便于用户参照填写层级关系与编码规则
|
||||
const templateUrl = `${import.meta.env.BASE_URL}cargo-type-import-template.xlsx`;
|
||||
fetch(templateUrl)
|
||||
exportBlob('/blade-system/cargo-type/export-template', {}, { feedback: true })
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('模板文件不存在');
|
||||
return res.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
downloadXls(blob, '货物类型导入模板.xlsx');
|
||||
downloadXls(res.data, '货物类型导入模板.xlsx');
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('模板下载失败,请稍后重试');
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('common_address_add')"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>新增
|
||||
>新建常用地址
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -188,7 +187,6 @@
|
||||
/>
|
||||
<el-input
|
||||
v-model="form.detailAddress"
|
||||
readonly
|
||||
maxlength="255"
|
||||
placeholder="点击后弹出地图组件"
|
||||
suffix-icon="el-icon-location"
|
||||
@@ -389,10 +387,96 @@ export default {
|
||||
column.rules = rules;
|
||||
}
|
||||
},
|
||||
setColumnSpan(prop, span) {
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (column) {
|
||||
column.span = span;
|
||||
}
|
||||
},
|
||||
setColumnRow(prop, row) {
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (column) {
|
||||
column.row = row;
|
||||
}
|
||||
},
|
||||
setColumnOrder(prop, order) {
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (column) {
|
||||
column.order = order;
|
||||
}
|
||||
},
|
||||
syncSourceFormLayout(addressType) {
|
||||
const isPortTerminal = addressType === '港口/码头';
|
||||
const isRailwayStation = addressType === '铁路车站';
|
||||
const isAirport = addressType === '空港机场';
|
||||
const isRegularAddress = addressType === '常规地址';
|
||||
this.setColumnSpan(
|
||||
'addressName',
|
||||
isRegularAddress || isPortTerminal || isRailwayStation || isAirport ? 12 : 24
|
||||
);
|
||||
this.setColumnRow('addressName', true);
|
||||
this.setColumnSpan('stationId', isRailwayStation ? 12 : 24);
|
||||
this.setColumnSpan('airportId', isAirport ? 12 : 24);
|
||||
this.setColumnRow('stationId', isRailwayStation);
|
||||
this.setColumnRow('airportId', isAirport);
|
||||
const formOrders = {
|
||||
addressType: 100,
|
||||
addressName: 70,
|
||||
contactName: 60,
|
||||
contactPhone: 50,
|
||||
detailAddress: 40,
|
||||
remark: 30,
|
||||
};
|
||||
if (isPortTerminal) {
|
||||
Object.assign(formOrders, {
|
||||
addressType: 80,
|
||||
portId: 70,
|
||||
terminalId: 60,
|
||||
addressName: 50,
|
||||
contactName: 40,
|
||||
contactPhone: 30,
|
||||
detailAddress: 20,
|
||||
remark: 10,
|
||||
});
|
||||
} else if (isRailwayStation) {
|
||||
Object.assign(formOrders, {
|
||||
addressType: 80,
|
||||
stationId: 70,
|
||||
addressName: 60,
|
||||
contactName: 50,
|
||||
contactPhone: 40,
|
||||
detailAddress: 30,
|
||||
remark: 20,
|
||||
});
|
||||
} else if (isAirport) {
|
||||
Object.assign(formOrders, {
|
||||
addressType: 80,
|
||||
airportId: 70,
|
||||
addressName: 60,
|
||||
contactName: 50,
|
||||
contactPhone: 40,
|
||||
detailAddress: 30,
|
||||
remark: 20,
|
||||
});
|
||||
}
|
||||
[
|
||||
'addressType',
|
||||
'portId',
|
||||
'terminalId',
|
||||
'stationId',
|
||||
'airportId',
|
||||
'addressName',
|
||||
'contactName',
|
||||
'contactPhone',
|
||||
'detailAddress',
|
||||
'remark',
|
||||
].forEach(prop => this.setColumnOrder(prop, formOrders[prop]));
|
||||
},
|
||||
syncSourceColumnDisplay(addressType) {
|
||||
const isPortTerminal = addressType === '港口/码头';
|
||||
const isRailwayStation = addressType === '铁路车站';
|
||||
const isAirport = addressType === '空港机场';
|
||||
this.syncSourceFormLayout(addressType);
|
||||
this.setColumnDisplay('portId', isPortTerminal);
|
||||
this.setColumnDisplay('terminalId', isPortTerminal);
|
||||
this.setColumnDisplay('stationId', isRailwayStation);
|
||||
@@ -1183,6 +1267,17 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.common-address-page :deep(.avue-crud__dialog .avue-form__row),
|
||||
.common-address-page :deep(.avue-crud__dialog .el-row) {
|
||||
margin-right: -16px;
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
.common-address-page :deep(.avue-crud__dialog .el-col) {
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.common-address-page {
|
||||
&__map-address {
|
||||
display: flex;
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('common_cargo_add')"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>新增
|
||||
>新建常用货物
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -113,7 +112,7 @@
|
||||
clearable
|
||||
maxlength="20"
|
||||
show-word-limit
|
||||
placeholder="请输入货物编号"
|
||||
placeholder="请输入"
|
||||
:disabled="dialogReadonly || dialogType === 'edit'"
|
||||
@input="handleCargoCodeInput"
|
||||
/>
|
||||
@@ -144,6 +143,10 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #packageBrand="{ row }">
|
||||
{{ [row.packageType, row.brand].filter(Boolean).join(' / ') || '-' }}
|
||||
</template>
|
||||
|
||||
<template #menu="{ row, index }">
|
||||
<el-link
|
||||
type="primary"
|
||||
@@ -192,6 +195,7 @@
|
||||
import * as api from '@/api/business/common-cargo';
|
||||
import { getList as getCargoTypeList } from '@/api/base/cargo-type';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { config, excelOption, option } from '@/option/business/common-cargo';
|
||||
import { priceUnitOptions } from '@/option/business/common';
|
||||
import { getToken } from '@/utils/auth';
|
||||
@@ -221,6 +225,7 @@ export default {
|
||||
secondCargoTypeLoading: false,
|
||||
firstCargoTypeOptions: [],
|
||||
secondCargoTypeOptions: [],
|
||||
deptOptions: [],
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
@@ -247,6 +252,9 @@ export default {
|
||||
return this.selectionList.map(item => item.id).join(',');
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initDeptTree();
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
|
||||
@@ -256,6 +264,28 @@ export default {
|
||||
if (Array.isArray(data)) return data;
|
||||
return (data && data.records) || [];
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
this.deptOptions = this.flattenDept(res.data.data || []);
|
||||
const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
|
||||
if (deptColumn) {
|
||||
deptColumn.dicData = this.deptOptions;
|
||||
}
|
||||
});
|
||||
},
|
||||
flattenDept(tree, level = 0) {
|
||||
const result = [];
|
||||
tree.forEach(item => {
|
||||
result.push({
|
||||
label: `${' '.repeat(level)}${item.title || item.deptName || item.name}`,
|
||||
value: item.id,
|
||||
});
|
||||
if (item.children && item.children.length) {
|
||||
result.push(...this.flattenDept(item.children, level + 1));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
normalizeCargoTypeOptions(list = []) {
|
||||
return list
|
||||
.map(item => ({
|
||||
@@ -319,11 +349,12 @@ export default {
|
||||
const second = this.secondCargoTypeOptions.find(item => item.cargoCode === value);
|
||||
this.form.secondCargoTypeName = second ? second.cargoName : '';
|
||||
this.form.secondCargoTypeCode = second ? second.cargoCode : '';
|
||||
this.form.cargoCode = second ? String(second.cargoCode).slice(0, 4) : '';
|
||||
this.syncCargoCodePrefix();
|
||||
},
|
||||
getCargoCodePrefix() {
|
||||
return this.form.secondCargoTypeCode && this.form.firstCargoTypeCode
|
||||
? this.form.firstCargoTypeCode
|
||||
return this.form.secondCargoTypeCode
|
||||
? String(this.form.secondCargoTypeCode).slice(0, 4)
|
||||
: '';
|
||||
},
|
||||
syncCargoCodePrefix() {
|
||||
@@ -383,13 +414,13 @@ export default {
|
||||
return false;
|
||||
}
|
||||
const cargoCode = String(row.cargoCode || '');
|
||||
const prefix = row.firstCargoTypeCode;
|
||||
const prefix = String(row.secondCargoTypeCode || '').slice(0, 4);
|
||||
if (!cargoCode || cargoCode === prefix) {
|
||||
this.$message.warning('请输入货物编号');
|
||||
return false;
|
||||
}
|
||||
if (!cargoCode.startsWith(prefix)) {
|
||||
this.$message.warning('货物编号需拼接一级货物类型编号在前面');
|
||||
this.$message.warning('货物编号需拼接二级货物类型编号在前面');
|
||||
return false;
|
||||
}
|
||||
if (cargoCode.length > 20) {
|
||||
|
||||
@@ -24,10 +24,25 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('common_route_add')"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>新增
|
||||
>新建路线
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-upload"
|
||||
plain
|
||||
v-if="config.importUrl && hasPermission('common_route_import')"
|
||||
@click="handleImport"
|
||||
>批量导入
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="config.templateUrl && hasPermission('common_route_template')"
|
||||
@click="handleTemplate"
|
||||
>下载模板
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -57,10 +72,10 @@
|
||||
/>
|
||||
<el-input
|
||||
v-model="form.departureAddress"
|
||||
readonly
|
||||
placeholder="请输入并选择地址"
|
||||
suffix-icon="el-icon-location"
|
||||
:disabled="dialogReadonly"
|
||||
@click="openRouteMapDialog('departure')"
|
||||
/>
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
@@ -84,10 +99,10 @@
|
||||
/>
|
||||
<el-input
|
||||
v-model="form.arrivalAddress"
|
||||
readonly
|
||||
placeholder="请输入并选择地址"
|
||||
suffix-icon="el-icon-location"
|
||||
:disabled="dialogReadonly"
|
||||
@click="openRouteMapDialog('arrival')"
|
||||
/>
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
@@ -133,6 +148,16 @@
|
||||
@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>
|
||||
|
||||
<el-dialog
|
||||
title="选择常用地址"
|
||||
append-to-body
|
||||
@@ -238,6 +263,48 @@
|
||||
<el-button @click="addressDialogVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="地图选择地址"
|
||||
append-to-body
|
||||
v-model="routeMapVisible"
|
||||
width="920px"
|
||||
@opened="initRouteAmap"
|
||||
>
|
||||
<div class="common-route-page__map-toolbar">
|
||||
<el-input
|
||||
v-model="routeMapKeyword"
|
||||
clearable
|
||||
placeholder="输入地址关键词"
|
||||
@keyup.enter="searchRouteMapKeyword"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Search"
|
||||
:loading="routeMapLoading"
|
||||
@click="searchRouteMapKeyword"
|
||||
>
|
||||
搜索
|
||||
</el-button>
|
||||
</div>
|
||||
<div ref="routeAmap" class="common-route-page__map"></div>
|
||||
<div class="common-route-page__map-info">
|
||||
<span>{{ routeMapStatus }}</span>
|
||||
<span v-if="routeMapSelected.regionName"
|
||||
>发货/收货地:{{ routeMapSelected.regionName }}</span
|
||||
>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="routeMapVisible = false">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!routeMapSelected.longitude"
|
||||
@click="confirmRouteMapPick"
|
||||
>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
@@ -247,18 +314,24 @@ import { getList as getCommonAddressList } from '@/api/base/common-address';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { addressTypeOptions } from '@/option/base/common-address';
|
||||
import { config, option } from '@/option/business/common-route';
|
||||
import { config, excelOption, option } from '@/option/business/common-route';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { List } from '@element-plus/icons-vue';
|
||||
import { List, Search } from '@element-plus/icons-vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
|
||||
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
|
||||
let amapLoader;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
List,
|
||||
Search,
|
||||
config,
|
||||
option,
|
||||
form: {},
|
||||
@@ -266,12 +339,24 @@ export default {
|
||||
loading: true,
|
||||
data: [],
|
||||
dialogReadonly: false,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
excelOptionConfig: excelOption,
|
||||
addressTypeOptions,
|
||||
addressDialogVisible: false,
|
||||
addressTarget: '',
|
||||
addressQuery: {},
|
||||
addressData: [],
|
||||
addressLoading: false,
|
||||
routeMapVisible: false,
|
||||
routeMapTarget: '',
|
||||
routeMapLoading: false,
|
||||
routeMapKeyword: '',
|
||||
routeMapStatus: '可搜索地址或点击地图选点',
|
||||
routeMapSelected: {},
|
||||
routeAmap: null,
|
||||
routeAmapMarker: null,
|
||||
routeAmapGeocoder: null,
|
||||
deptOptions: [],
|
||||
page: {
|
||||
pageSize: 10,
|
||||
@@ -313,9 +398,22 @@ export default {
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
this.deptOptions = this.flattenDept(res.data.data || []);
|
||||
const deptTree = res.data.data || [];
|
||||
this.deptOptions = this.flattenDept(deptTree);
|
||||
const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
|
||||
if (deptColumn) {
|
||||
deptColumn.dicData = this.buildDeptTree(deptTree);
|
||||
}
|
||||
});
|
||||
},
|
||||
buildDeptTree(tree) {
|
||||
return tree.map(item => ({
|
||||
label: item.title || item.deptName || item.name,
|
||||
value: item.id,
|
||||
children:
|
||||
item.children && item.children.length ? this.buildDeptTree(item.children) : undefined,
|
||||
}));
|
||||
},
|
||||
flattenDept(tree, level = 0) {
|
||||
const result = [];
|
||||
tree.forEach(item => {
|
||||
@@ -400,6 +498,246 @@ export default {
|
||||
this.form[`${prefix}Contact`] = address.contactName || this.form[`${prefix}Contact`] || '';
|
||||
this.form[`${prefix}Phone`] = address.contactPhone || this.form[`${prefix}Phone`] || '';
|
||||
},
|
||||
openRouteMapDialog(target) {
|
||||
if (this.dialogReadonly) return;
|
||||
const prefix = target === 'departure' ? 'departure' : 'arrival';
|
||||
this.routeMapTarget = prefix;
|
||||
this.routeMapKeyword = this.form[`${prefix}Address`] || this.form[`${prefix}Name`] || '';
|
||||
this.routeMapSelected = this.buildRouteMapSelection({
|
||||
lng: this.form[`${prefix}Longitude`],
|
||||
lat: this.form[`${prefix}Latitude`],
|
||||
address: this.form[`${prefix}Address`],
|
||||
regionName: this.form[`${prefix}Name`],
|
||||
});
|
||||
this.routeMapStatus = this.routeMapSelected.longitude
|
||||
? '已加载当前选点,可重新选点'
|
||||
: '可搜索地址或点击地图选点';
|
||||
this.routeMapVisible = true;
|
||||
},
|
||||
loadAmap() {
|
||||
if (window.AMap && window.AMap.Map) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!amapLoader) {
|
||||
amapLoader = new Promise((resolve, reject) => {
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: AMAP_SECURITY_CODE,
|
||||
};
|
||||
const script = document.createElement('script');
|
||||
script.src = `https://webapi.amap.com/maps?v=2.0&key=${AMAP_KEY}`;
|
||||
script.async = true;
|
||||
script.onload = resolve;
|
||||
script.onerror = () => reject(new Error('高德地图组件加载失败'));
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
return amapLoader;
|
||||
},
|
||||
initRouteAmap() {
|
||||
this.loadAmap()
|
||||
.then(() => {
|
||||
this.$nextTick(() => {
|
||||
if (!this.routeAmap) {
|
||||
const center = this.toLngLat(
|
||||
this.routeMapSelected.longitude || 116.40769,
|
||||
this.routeMapSelected.latitude || 39.89945
|
||||
);
|
||||
this.routeAmap = new window.AMap.Map(this.$refs.routeAmap, {
|
||||
center,
|
||||
zoom: this.routeMapSelected.longitude ? 14 : 11,
|
||||
});
|
||||
window.AMap.plugin(['AMap.ToolBar', 'AMap.Geocoder'], () => {
|
||||
this.routeAmap.addControl(new window.AMap.ToolBar());
|
||||
if (!this.routeAmapGeocoder) {
|
||||
this.routeAmapGeocoder = new window.AMap.Geocoder();
|
||||
}
|
||||
});
|
||||
this.routeAmap.on('click', event => this.pickRouteMapPoint(event.lnglat));
|
||||
} else if (typeof this.routeAmap.resize === 'function') {
|
||||
this.routeAmap.resize();
|
||||
}
|
||||
if (this.routeMapSelected.longitude) {
|
||||
this.renderRouteMapMarker(
|
||||
this.toLngLat(this.routeMapSelected.longitude, this.routeMapSelected.latitude)
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('高德地图组件加载失败,请稍后重试或重新打开弹窗');
|
||||
this.routeMapVisible = false;
|
||||
});
|
||||
},
|
||||
searchRouteMapKeyword() {
|
||||
const keyword = String(this.routeMapKeyword || '').trim();
|
||||
if (!keyword) {
|
||||
this.$message.warning('请输入地址关键词');
|
||||
return;
|
||||
}
|
||||
this.loadAmap()
|
||||
.then(() => {
|
||||
this.routeMapLoading = true;
|
||||
return this.ensureRouteAmapGeocoder();
|
||||
})
|
||||
.then(() => this.runAmapGeocode('location', keyword))
|
||||
.then(result => {
|
||||
const point = this.resolveMapPoint(result);
|
||||
if (!point) {
|
||||
this.routeMapStatus = '未找到匹配地址';
|
||||
this.$message.warning('地图搜索无匹配地址');
|
||||
return;
|
||||
}
|
||||
this.pickRouteMapPoint(point, keyword);
|
||||
})
|
||||
.catch(() => {
|
||||
this.routeMapStatus = '地图搜索失败';
|
||||
this.$message.error('地图搜索失败,请稍后重试');
|
||||
})
|
||||
.finally(() => {
|
||||
this.routeMapLoading = false;
|
||||
});
|
||||
},
|
||||
pickRouteMapPoint(lnglat, keyword) {
|
||||
const longitude = this.getPointLng(lnglat);
|
||||
const latitude = this.getPointLat(lnglat);
|
||||
if (longitude === undefined || latitude === undefined) {
|
||||
this.$message.warning('选点坐标无效');
|
||||
return;
|
||||
}
|
||||
const point = this.toLngLat(longitude, latitude);
|
||||
this.renderRouteMapMarker(point);
|
||||
this.routeMapSelected = this.buildRouteMapSelection({
|
||||
lng: longitude,
|
||||
lat: latitude,
|
||||
address: keyword,
|
||||
});
|
||||
this.routeMapStatus = '正在反查地址...';
|
||||
this.ensureRouteAmapGeocoder()
|
||||
.then(() => this.runAmapGeocode('address', point))
|
||||
.then(result => {
|
||||
const address = this.resolveMapAddress(result);
|
||||
this.routeMapSelected = {
|
||||
...this.routeMapSelected,
|
||||
detailAddress: address.detailAddress || this.routeMapSelected.detailAddress,
|
||||
regionName: address.regionName || this.routeMapSelected.regionName,
|
||||
};
|
||||
this.routeMapKeyword = this.routeMapSelected.detailAddress || this.routeMapKeyword;
|
||||
this.routeMapStatus = this.routeMapSelected.detailAddress || '已选点,可确认回填';
|
||||
})
|
||||
.catch(() => {
|
||||
this.routeMapStatus = '反查地址失败';
|
||||
this.$message.error('反查地址失败,请重新选点');
|
||||
});
|
||||
},
|
||||
renderRouteMapMarker(point) {
|
||||
if (!this.routeAmap || !window.AMap) return;
|
||||
if (this.routeAmapMarker) {
|
||||
this.routeAmapMarker.setMap(null);
|
||||
}
|
||||
this.routeAmapMarker = new window.AMap.Marker({ position: point });
|
||||
this.routeAmapMarker.setMap(this.routeAmap);
|
||||
this.routeAmap.setCenter(point);
|
||||
},
|
||||
confirmRouteMapPick() {
|
||||
if (!this.routeMapSelected.longitude) {
|
||||
this.$message.warning('请先搜索或点击地图完成选点');
|
||||
return;
|
||||
}
|
||||
const prefix = this.routeMapTarget;
|
||||
this.form[`${prefix}Address`] =
|
||||
this.routeMapSelected.detailAddress || this.form[`${prefix}Address`];
|
||||
this.form[`${prefix}Name`] = this.routeMapSelected.regionName || this.form[`${prefix}Name`];
|
||||
this.form[`${prefix}Longitude`] = this.routeMapSelected.longitude;
|
||||
this.form[`${prefix}Latitude`] = this.routeMapSelected.latitude;
|
||||
this.routeMapVisible = false;
|
||||
this.$refs.crud?.validateField?.(`${prefix}Address`);
|
||||
},
|
||||
buildRouteMapSelection({ lng, lat, address, regionName }) {
|
||||
return {
|
||||
longitude: this.formatCoordinate(lng),
|
||||
latitude: this.formatCoordinate(lat),
|
||||
detailAddress: address || '',
|
||||
regionName: regionName || '',
|
||||
};
|
||||
},
|
||||
formatCoordinate(value) {
|
||||
if (value === undefined || value === null || value === '') return '';
|
||||
const numberValue = Number(value);
|
||||
return Number.isFinite(numberValue) ? numberValue.toFixed(6) : '';
|
||||
},
|
||||
toLngLat(lng, lat) {
|
||||
return new window.AMap.LngLat(Number(lng), Number(lat));
|
||||
},
|
||||
getPointLng(point) {
|
||||
if (!point) return undefined;
|
||||
if (typeof point.getLng === 'function') return point.getLng();
|
||||
return point.lng ?? point.lon;
|
||||
},
|
||||
getPointLat(point) {
|
||||
if (!point) return undefined;
|
||||
if (typeof point.getLat === 'function') return point.getLat();
|
||||
return point.lat;
|
||||
},
|
||||
ensureRouteAmapGeocoder() {
|
||||
if (this.routeAmapGeocoder) return Promise.resolve(this.routeAmapGeocoder);
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!window.AMap || !window.AMap.plugin) {
|
||||
reject(new Error('高德地图组件未就绪'));
|
||||
return;
|
||||
}
|
||||
window.AMap.plugin(['AMap.Geocoder'], () => {
|
||||
try {
|
||||
this.routeAmapGeocoder = new window.AMap.Geocoder();
|
||||
resolve(this.routeAmapGeocoder);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
runAmapGeocode(action, input) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = window.setTimeout(() => {
|
||||
reject(new Error('高德地图请求超时'));
|
||||
}, 10000);
|
||||
const done = (status, result) => {
|
||||
window.clearTimeout(timer);
|
||||
if (status === 'complete' && result) {
|
||||
resolve(result);
|
||||
return;
|
||||
}
|
||||
reject(new Error('高德地图请求失败'));
|
||||
};
|
||||
try {
|
||||
if (action === 'location') {
|
||||
this.routeAmapGeocoder.getLocation(input, done);
|
||||
} else {
|
||||
this.routeAmapGeocoder.getAddress(input, done);
|
||||
}
|
||||
} catch (error) {
|
||||
window.clearTimeout(timer);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
resolveMapPoint(result) {
|
||||
if (!result) return null;
|
||||
const geocode = Array.isArray(result.geocodes) ? result.geocodes[0] : null;
|
||||
if (geocode && geocode.location) return geocode.location;
|
||||
if (result.location) return result.location;
|
||||
if (result.lnglat) return result.lnglat;
|
||||
if (result.getLng || result.lng || result.lon) return result;
|
||||
return null;
|
||||
},
|
||||
resolveMapAddress(result = {}) {
|
||||
const regeocode = result.regeocode || {};
|
||||
const component = regeocode.addressComponent || {};
|
||||
const city = Array.isArray(component.city) ? '' : component.city;
|
||||
return {
|
||||
detailAddress: regeocode.formattedAddress || '',
|
||||
regionName: [component.province, city, component.district].filter(Boolean).join(''),
|
||||
};
|
||||
},
|
||||
normalizeRow(row) {
|
||||
const submitRow = { ...row };
|
||||
Object.keys(submitRow).forEach(key => {
|
||||
@@ -609,6 +947,27 @@ export default {
|
||||
});
|
||||
});
|
||||
},
|
||||
handleTemplate() {
|
||||
NProgress.start();
|
||||
exportBlob(
|
||||
config.templateUrl,
|
||||
{
|
||||
[this.website.tokenHeader]: getToken(),
|
||||
},
|
||||
{ feedback: true }
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `${config.title}模板.xlsx`);
|
||||
})
|
||||
.finally(() => {
|
||||
NProgress.done();
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
const column = this.excelOptionConfig.column.find(item => item.prop === 'excelFile');
|
||||
column.action = config.importUrl;
|
||||
openImportDialog(this, config.title, () => this.onLoad(this.page, this.query));
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -650,5 +1009,31 @@ export default {
|
||||
justify-content: flex-end;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
&__map-toolbar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__map {
|
||||
width: 100%;
|
||||
height: 420px;
|
||||
border: 1px solid #eff1f7;
|
||||
}
|
||||
|
||||
&__map-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 10px;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="actionButtonLikeSearch ? undefined : 'el-icon-plus'"
|
||||
:plain="!actionButtonLikeSearch"
|
||||
v-if="canCreate"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>{{ config.createText || '新增' }}
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('process_config_add')"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
>新增
|
||||
>新建过程配置
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -53,13 +52,23 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<template #includedNodes="{ row }">
|
||||
<span class="process-config-page__node-value">
|
||||
{{ formatProcessNodes(row.includedNodes) }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #basicInfo-form>
|
||||
<div class="process-config-page__section">
|
||||
<div class="dialog-section-title">基本信息</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-col :span="8">
|
||||
<div class="process-config-page__field">
|
||||
<span class="process-config-page__field-label">配置名称</span>
|
||||
<span
|
||||
class="process-config-page__field-label process-config-page__field-label--required"
|
||||
>
|
||||
配置名称
|
||||
</span>
|
||||
<el-input
|
||||
v-model="form.configName"
|
||||
:disabled="dialogReadonly"
|
||||
@@ -68,9 +77,13 @@
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="8">
|
||||
<div class="process-config-page__field">
|
||||
<span class="process-config-page__field-label">项目</span>
|
||||
<span
|
||||
class="process-config-page__field-label process-config-page__field-label--required"
|
||||
>
|
||||
项目
|
||||
</span>
|
||||
<el-select
|
||||
v-model="selectedProjectId"
|
||||
clearable
|
||||
@@ -92,33 +105,33 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="8">
|
||||
<div class="process-config-page__field">
|
||||
<span class="process-config-page__field-label">默认后台完成运输天数</span>
|
||||
<span class="process-config-page__field-label">运输完成时限</span>
|
||||
<div class="process-config-page__finish-days">
|
||||
<span>默认</span>
|
||||
<el-input
|
||||
v-model="form.defaultFinishDays"
|
||||
:disabled="dialogReadonly"
|
||||
maxlength="3"
|
||||
placeholder="X"
|
||||
placeholder="请输入"
|
||||
@input="handleFinishDaysInput"
|
||||
/>
|
||||
<span>天后台完成运输</span>
|
||||
<span>天后完成运输</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="24">
|
||||
<div class="process-config-page__field">
|
||||
<span class="process-config-page__field-label">备注</span>
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
:disabled="dialogReadonly"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
placeholder="请输入"
|
||||
show-word-limit
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:disabled="dialogReadonly"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -196,7 +209,7 @@
|
||||
<el-radio-group
|
||||
v-model="row.confirmMode"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
@change="handleReturnConfirmChange(row)"
|
||||
>
|
||||
<el-radio label="yes">是</el-radio>
|
||||
<el-radio label="no_confirm_complete">无需确认完成</el-radio>
|
||||
@@ -390,6 +403,7 @@
|
||||
<script>
|
||||
import * as api from '@/api/business/process-config';
|
||||
import { getList as getProjectList } from '@/api/business/project-apply';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { config, option } from '@/option/business/process-config';
|
||||
import { getToken } from '@/utils/auth';
|
||||
@@ -513,11 +527,35 @@ export default {
|
||||
created() {
|
||||
this.resetNodeRows();
|
||||
this.loadProjectOptions('');
|
||||
this.initDeptOptions();
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
|
||||
},
|
||||
handleReturnConfirmChange(row) {
|
||||
row.confirmInternal = row.confirmMode === 'yes';
|
||||
this.syncNodeFields();
|
||||
},
|
||||
initDeptOptions() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
|
||||
if (deptColumn) {
|
||||
deptColumn.dicData = this.flattenDept(res.data.data || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
flattenDept(tree, level = 0) {
|
||||
return tree.flatMap(item => [
|
||||
{
|
||||
label: `${' '.repeat(level)}${item.title || item.deptName || item.name}`,
|
||||
value: item.id,
|
||||
},
|
||||
...(item.children && item.children.length
|
||||
? this.flattenDept(item.children, level + 1)
|
||||
: []),
|
||||
]);
|
||||
},
|
||||
displayStatus(status) {
|
||||
const statusMap = {
|
||||
0: '草稿',
|
||||
@@ -526,6 +564,13 @@ export default {
|
||||
};
|
||||
return statusMap[status] || status || '未知';
|
||||
},
|
||||
formatProcessNodes(nodes) {
|
||||
return String(nodes || '')
|
||||
.split(/[,,]/)
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean)
|
||||
.join('-');
|
||||
},
|
||||
statusTagType(status) {
|
||||
if (status === 1) return 'success';
|
||||
if (status === 2) return 'info';
|
||||
@@ -558,7 +603,7 @@ export default {
|
||||
voucherTypes: [],
|
||||
frequencyDays: '1',
|
||||
timeStart: '00:00',
|
||||
timeEnd: '24:00',
|
||||
timeEnd: '23:59',
|
||||
supportCargo: false,
|
||||
supportVoucher: false,
|
||||
voucherOptions: [],
|
||||
@@ -705,7 +750,7 @@ export default {
|
||||
result.push(`打卡定位:${node.location ? '是' : '否'}`);
|
||||
if (node.punch) {
|
||||
result.push(`打卡频次:每${node.frequencyDays || 1}天打卡1次`);
|
||||
result.push(`打卡时段:${node.timeStart || '00:00'}-${node.timeEnd || '24:00'}`);
|
||||
result.push(`打卡时段:${node.timeStart || '00:00'}-${node.timeEnd || '23:59'}`);
|
||||
}
|
||||
} else {
|
||||
result.push(`打卡操作:${node.punch ? '是' : '否'}`);
|
||||
@@ -744,9 +789,15 @@ export default {
|
||||
this.$message.warning('项目不能为空');
|
||||
return false;
|
||||
}
|
||||
if (row.defaultFinishDays && !/^[1-9]\d{0,2}$/.test(String(row.defaultFinishDays))) {
|
||||
this.$message.warning('请输入正整数');
|
||||
return false;
|
||||
if (row.defaultFinishDays !== undefined && row.defaultFinishDays !== '') {
|
||||
if (!Number.isInteger(Number(row.defaultFinishDays)) || Number(row.defaultFinishDays) < 0) {
|
||||
this.$message.warning('完成天数不能小于0');
|
||||
return false;
|
||||
}
|
||||
if (Number(row.defaultFinishDays) > 999) {
|
||||
this.$message.warning('完成天数不能超过999');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (row.remark && row.remark.length > 500) {
|
||||
this.$message.warning('备注不能超过500个字符');
|
||||
@@ -774,43 +825,61 @@ export default {
|
||||
loading();
|
||||
}
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
this.syncNodeFields();
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateRow(submitRow)) {
|
||||
this.stopSubmitLoading(loading);
|
||||
return;
|
||||
needsDuplicateVoucherConfirm() {
|
||||
const signNode = this.nodeRows.find(item => item.key === 'sign');
|
||||
const returnNode = this.nodeRows.find(item => item.key === 'return');
|
||||
const hasSignVoucher =
|
||||
signNode &&
|
||||
signNode.enabled &&
|
||||
signNode.uploadVoucher &&
|
||||
signNode.voucherTypes.includes('签收单');
|
||||
const hasReturnVoucher =
|
||||
returnNode &&
|
||||
returnNode.enabled &&
|
||||
returnNode.uploadVoucher &&
|
||||
returnNode.voucherTypes.includes('签收单');
|
||||
return hasSignVoucher && hasReturnVoucher;
|
||||
},
|
||||
confirmDuplicateVoucher() {
|
||||
if (!this.needsDuplicateVoucherConfirm()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
api.submit(submitRow).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
window.console.log(error);
|
||||
this.stopSubmitLoading(loading);
|
||||
return this.$confirm(
|
||||
'签收与回单同时勾选了上传凭证,司机将需重复上传凭证,是否确认?',
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
submitRow(row, done, loading) {
|
||||
this.syncNodeFields();
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateRow(submitRow)) {
|
||||
this.stopSubmitLoading(loading);
|
||||
return;
|
||||
}
|
||||
api.submit(submitRow).then(
|
||||
() => {
|
||||
this.confirmDuplicateVoucher()
|
||||
.then(() => api.submit(submitRow))
|
||||
.then(() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
window.console.log(error);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error !== 'cancel' && error !== 'close') {
|
||||
window.console.log(error);
|
||||
}
|
||||
this.stopSubmitLoading(loading);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
this.submitRow(row, done, loading);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
this.submitRow(row, done, loading);
|
||||
},
|
||||
rowDel(row) {
|
||||
this.$confirm('确定将选择数据删除?', {
|
||||
@@ -914,7 +983,11 @@ export default {
|
||||
onLoad(page, params = {}) {
|
||||
this.loading = true;
|
||||
api
|
||||
.getList(page.currentPage, page.pageSize, { ...params, ...this.query, allDept: 0 })
|
||||
.getList(page.currentPage, page.pageSize, {
|
||||
...params,
|
||||
...this.query,
|
||||
allDept: this.isAdmin ? 1 : 0,
|
||||
})
|
||||
.then(res => {
|
||||
const result = res.data.data || {};
|
||||
this.page.total = result.total || 0;
|
||||
@@ -928,7 +1001,7 @@ export default {
|
||||
buildExportParams() {
|
||||
return {
|
||||
...this.query,
|
||||
allDept: 0,
|
||||
allDept: this.isAdmin ? 1 : 0,
|
||||
ids: this.ids,
|
||||
[this.website.tokenHeader]: getToken(),
|
||||
};
|
||||
@@ -1004,6 +1077,17 @@ export default {
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
|
||||
&--required::before {
|
||||
margin-right: 4px;
|
||||
color: #f56c6c;
|
||||
content: '*';
|
||||
}
|
||||
}
|
||||
|
||||
&__node-value {
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&__finish-days {
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="canMajorProjectSupplement"
|
||||
@click="openProjectDialog('majorSupplement')"
|
||||
>
|
||||
@@ -29,7 +28,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="canCreate"
|
||||
@click="openProjectDialog('add')"
|
||||
>
|
||||
@@ -1568,7 +1566,11 @@ export default {
|
||||
const loadingKey = type === '客户' ? 'customerLoading' : 'carrierLoading';
|
||||
const optionsKey = type === '客户' ? 'customerOptions' : 'carrierOptions';
|
||||
this[loadingKey] = true;
|
||||
getCustomerArchiveList(1, 100, { customerType: type, status: 1 })
|
||||
getCustomerArchiveList(1, 100, {
|
||||
customerType: type,
|
||||
status: 1,
|
||||
...(type === '客户' ? { approvalStatus: 'approved' } : {}),
|
||||
})
|
||||
.then(res => {
|
||||
const records = (res.data.data && res.data.data.records) || [];
|
||||
const selectedOptions = this.buildCustomerOptionsFromRows(
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('driver_add')"
|
||||
@click="openDriver()"
|
||||
>新增
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('transport_ship_add')"
|
||||
@click="openShip()"
|
||||
>
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('transport_vehicle_add')"
|
||||
@click="openVehicle()"
|
||||
>新增
|
||||
|
||||
@@ -20,35 +20,10 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_add')"
|
||||
@click="openConfig()"
|
||||
>新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-upload"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_import')"
|
||||
@click="handleImport"
|
||||
>批量导入
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_template')"
|
||||
@click="handleTemplate"
|
||||
>下载模板
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_export')"
|
||||
@click="handleExport"
|
||||
>批量导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
@@ -71,28 +46,28 @@
|
||||
<template #menu="{ row }">
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="hasPermission('credit_score_quantification_edit')"
|
||||
@click="openConfig(row)"
|
||||
v-if="hasPermission('credit_score_quantification_status') && row.status === 1"
|
||||
@click="handleStatus(row)"
|
||||
>
|
||||
编辑
|
||||
停用
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="hasPermission('credit_score_quantification_publish') && row.status === 3"
|
||||
v-if="hasPermission('credit_score_quantification_publish') && row.status !== 1"
|
||||
@click="handlePublish(row)"
|
||||
>
|
||||
发布
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="hasPermission('credit_score_quantification_status') && row.status !== 3"
|
||||
@click="handleStatus(row)"
|
||||
v-if="hasPermission('credit_score_quantification_edit') && row.status !== 1"
|
||||
@click="openConfig(row)"
|
||||
>
|
||||
{{ row.status === 1 ? '停用' : '启用' }}
|
||||
编辑
|
||||
</el-link>
|
||||
<el-link
|
||||
type="danger"
|
||||
v-if="hasPermission('credit_score_quantification_delete') && row.status === 3"
|
||||
v-if="hasPermission('credit_score_quantification_delete')"
|
||||
@click="rowDel(row)"
|
||||
>
|
||||
删除
|
||||
@@ -100,16 +75,6 @@
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog title="评分量化表数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form :option="excelOption" 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>
|
||||
|
||||
<el-dialog
|
||||
:title="readonly ? '查看评分量化表' : configForm.id ? '编辑评分量化表' : '新增评分量化表'"
|
||||
append-to-body
|
||||
@@ -128,10 +93,21 @@
|
||||
:disabled="readonly"
|
||||
>
|
||||
<el-form-item label="评定表名称" required>
|
||||
<el-input v-model="configForm.name" maxlength="30" show-word-limit />
|
||||
<el-input
|
||||
v-model="configForm.name"
|
||||
class="score-config__name-input"
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="configForm.remark" type="textarea" maxlength="500" show-word-limit />
|
||||
<el-input
|
||||
v-model="configForm.remark"
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -160,16 +136,6 @@
|
||||
<el-table :data="configForm.standards" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="信用等级" prop="creditLevel" width="120" align="center" />
|
||||
<el-table-column label="得分率" width="160" align="center">
|
||||
<template #default="{ row }"
|
||||
>{{ row.scoreRateLower }}% - {{ row.scoreRateUpper }}%</template
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="最大资金使用额度(万元)" width="210" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.creditLimitLower }} - {{ row.creditLimitUpper }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标准说明" prop="standardDescription" min-width="320" />
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
@@ -192,7 +158,7 @@
|
||||
append-to-body
|
||||
v-model="categoryBox"
|
||||
width="82%"
|
||||
class="score-dialog"
|
||||
class="score-dialog category-dialog"
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<div class="category-detail">
|
||||
@@ -383,14 +349,8 @@ import {
|
||||
publish,
|
||||
changeStatus,
|
||||
} from '@/api/vehicle/credit-score-quantification';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
const createTimeRangeMap = {
|
||||
createTimeRange: ['createTimeStart', 'createTimeEnd'],
|
||||
@@ -413,9 +373,7 @@ export default {
|
||||
categoryBox: false,
|
||||
itemBox: false,
|
||||
standardBox: false,
|
||||
excelBox: false,
|
||||
readonly: false,
|
||||
excelForm: {},
|
||||
configForm: this.emptyConfig(),
|
||||
currentCategory: { items: [] },
|
||||
currentItemIndex: -1,
|
||||
@@ -455,7 +413,7 @@ export default {
|
||||
menuWidth: 160,
|
||||
column: [
|
||||
{
|
||||
label: '评定表名称',
|
||||
label: '评分表名称',
|
||||
prop: 'name',
|
||||
slot: true,
|
||||
minWidth: 180,
|
||||
@@ -464,23 +422,10 @@ export default {
|
||||
rules: [{ required: true, message: '请输入评定表名称', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
minWidth: 260,
|
||||
overHidden: true,
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
search: true,
|
||||
slot: true,
|
||||
dataType: 'number',
|
||||
dicData: [
|
||||
{ label: '正常', value: 1 },
|
||||
{ label: '停用', value: 2 },
|
||||
{ label: '草稿', value: 3 },
|
||||
],
|
||||
label: '创建人',
|
||||
prop: 'createUserName',
|
||||
minWidth: 120,
|
||||
display: false,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
@@ -489,6 +434,22 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
minWidth: 160,
|
||||
display: false,
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
search: true,
|
||||
slot: true,
|
||||
dataType: 'number',
|
||||
searchValue: '',
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '正常', value: 1 },
|
||||
{ label: '停用', value: 2 },
|
||||
],
|
||||
clearable: true,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
@@ -502,33 +463,6 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
{
|
||||
label: '模板上传',
|
||||
prop: 'excelFile',
|
||||
type: 'upload',
|
||||
drag: true,
|
||||
loadText: '模板上传中,请稍等',
|
||||
span: 24,
|
||||
propsHttp: {
|
||||
res: 'data',
|
||||
},
|
||||
tip: '请上传 .xls,.xlsx 标准格式文件',
|
||||
action:
|
||||
'/blade-transport/credit-score-quantification/import-credit-score-quantification',
|
||||
},
|
||||
{
|
||||
label: '模板下载',
|
||||
prop: 'excelTemplate',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -786,7 +720,13 @@ export default {
|
||||
this.standardBox = false;
|
||||
},
|
||||
removeStandard(index) {
|
||||
this.configForm.standards.splice(index, 1);
|
||||
this.$confirm('确定删除该评估标准?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
this.configForm.standards.splice(index, 1);
|
||||
});
|
||||
},
|
||||
isBlankValue(value) {
|
||||
return value === undefined || value === null || value === '';
|
||||
@@ -947,7 +887,7 @@ export default {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
this.$confirm('仅草稿状态量表可删除,确定删除所选数据?', {
|
||||
this.$confirm('确定删除所选评分量化表?', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
@@ -1024,49 +964,9 @@ export default {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
openImportDialog(this, '评分量化表');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出评分量化表数据?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob(
|
||||
'/blade-transport/credit-score-quantification/export-credit-score-quantification',
|
||||
this.buildExportParams(),
|
||||
{ feedback: true }
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `评分量化表${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
.finally(() => {
|
||||
NProgress.done();
|
||||
});
|
||||
});
|
||||
},
|
||||
buildExportParams() {
|
||||
return {
|
||||
...this.buildQuery(),
|
||||
ids: this.ids,
|
||||
[this.website.tokenHeader]: getToken(),
|
||||
};
|
||||
},
|
||||
buildQuery(params = {}) {
|
||||
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/credit-score-quantification/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`,
|
||||
{ feedback: true }
|
||||
).then(res => {
|
||||
downloadXls(res.data, '评分量化表模板.xlsx');
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1074,6 +974,10 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.score-config {
|
||||
padding: 4px 12px 12px;
|
||||
|
||||
&__name-input {
|
||||
width: min(420px, 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.base-form {
|
||||
@@ -1111,10 +1015,14 @@ export default {
|
||||
.category-line {
|
||||
margin: 0 0 24px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
font-weight: 400;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
:deep(.category-dialog .el-dialog__title) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.score-item-form {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('customer_archive_add')"
|
||||
@click="openArchive()"
|
||||
>新增
|
||||
@@ -87,6 +86,16 @@
|
||||
>
|
||||
提交
|
||||
</el-link>
|
||||
<el-link
|
||||
type="warning"
|
||||
v-if="
|
||||
hasPermission('customer_archive_submit') &&
|
||||
['draft', 'reviewing'].includes(row.approvalStatus)
|
||||
"
|
||||
@click="handleWithdrawApproval(row)"
|
||||
>
|
||||
撤回
|
||||
</el-link>
|
||||
<el-link
|
||||
type="success"
|
||||
v-if="hasPermission('customer_archive_approve') && row.approvalStatus === 'reviewing'"
|
||||
@@ -153,7 +162,12 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客商性质" prop="customerNature">
|
||||
<el-select v-model="archiveForm.customerNature" filterable clearable>
|
||||
<el-select
|
||||
v-model="archiveForm.customerNature"
|
||||
placeholder="请输入"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerNatureOptions"
|
||||
:key="item.value"
|
||||
@@ -167,6 +181,7 @@
|
||||
<el-form-item label="统一社会信用代码" prop="unifiedCreditCode">
|
||||
<el-input
|
||||
v-model="archiveForm.unifiedCreditCode"
|
||||
placeholder="请输入"
|
||||
maxlength="18"
|
||||
show-word-limit
|
||||
@input="
|
||||
@@ -179,12 +194,22 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客商名称" prop="fullName">
|
||||
<el-input v-model="archiveForm.fullName" maxlength="100" show-word-limit />
|
||||
<el-input
|
||||
v-model="archiveForm.fullName"
|
||||
placeholder="请输入"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客商类型" prop="customerType">
|
||||
<el-select v-model="archiveForm.customerType" filterable clearable>
|
||||
<el-select
|
||||
v-model="archiveForm.customerType"
|
||||
placeholder="请输入"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerTypeOptions"
|
||||
:key="item.value"
|
||||
@@ -200,7 +225,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="经营范围" prop="businessScope">
|
||||
<el-form-item label="经营范围" prop="businessScope" required>
|
||||
<el-select v-model="archiveForm.businessScope" multiple filterable clearable>
|
||||
<el-option
|
||||
v-for="item in businessScopeOptions"
|
||||
@@ -237,11 +262,16 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="客户简称" prop="shortName">
|
||||
<el-input v-model="archiveForm.shortName" maxlength="20" show-word-limit />
|
||||
<el-input
|
||||
v-model="archiveForm.shortName"
|
||||
placeholder="请输入"
|
||||
maxlength="20"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="地址" prop="registeredDetailAddress">
|
||||
<el-form-item label="地址" prop="registeredDetailAddress" required>
|
||||
<div class="archive-form__address">
|
||||
<el-cascader
|
||||
ref="registeredRegionCascader"
|
||||
@@ -333,13 +363,13 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="申请总资金使用额度(万元)" prop="applyCreditLimit">
|
||||
<el-input
|
||||
v-model="archiveForm.applyCreditLimit"
|
||||
maxlength="18"
|
||||
@input="value => handleDecimalInput('applyCreditLimit', value)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="申请总资金使用额度(万元)" prop="applyCreditLimit">
|
||||
<el-input
|
||||
v-model="archiveForm.applyCreditLimit"
|
||||
maxlength="18"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
@@ -559,7 +589,7 @@
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
title="支持 JPG、PNG、PDF、Word、Excel、PPT,单文件大小不超过 10MB。"
|
||||
title="支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件大小限制500M"
|
||||
class="archive-rule-alert"
|
||||
/>
|
||||
<el-alert
|
||||
@@ -586,8 +616,8 @@
|
||||
v-model="row.files"
|
||||
:readonly="readonly"
|
||||
:multiple="false"
|
||||
accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
|
||||
:max-size="10"
|
||||
accept=".pdf,.bmp,.jpeg,.png,.jpg,.doc,.docx,.ppt,.pptx,.xlsx,.xls,.eml,.msg,.zip"
|
||||
:max-size="500"
|
||||
button-text="上传文件"
|
||||
:show-tip="false"
|
||||
@success="file => handleQualificationUploadSuccess(file, row)"
|
||||
@@ -658,13 +688,13 @@
|
||||
label-width="110px"
|
||||
class="contact-form"
|
||||
>
|
||||
<el-form-item label="联系人姓名" prop="contactName">
|
||||
<el-form-item label="联系人姓名" prop="contactName" class="contact-form__compact-field">
|
||||
<el-input v-model="contactForm.contactName" maxlength="30" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="contactPhone">
|
||||
<el-form-item label="手机号" prop="contactPhone" class="contact-form__compact-field">
|
||||
<el-input v-model="contactForm.contactPhone" maxlength="11" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-form-item label="邮箱" prop="email" class="contact-form__compact-field">
|
||||
<el-input v-model="contactForm.email" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地址" prop="detailAddress">
|
||||
@@ -685,13 +715,15 @@
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-form-item label="备注" prop="remark" class="contact-form__compact-field">
|
||||
<el-input v-model="contactForm.remark" maxlength="200" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="saveContact">保存</el-button>
|
||||
<el-button @click="contactBox = false">返回</el-button>
|
||||
<div class="contact-dialog__footer-actions">
|
||||
<el-button type="primary" @click="saveContact">保存</el-button>
|
||||
<el-button @click="contactBox = false">返回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -778,8 +810,10 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="saveReceipt">保存</el-button>
|
||||
<el-button @click="receiptBox = false">返回</el-button>
|
||||
<div class="receipt-dialog__footer-actions">
|
||||
<el-button type="primary" @click="saveReceipt">保存</el-button>
|
||||
<el-button @click="receiptBox = false">返回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -809,24 +843,24 @@
|
||||
<el-input v-model="invoiceForm.registeredPhone" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="注册地址" prop="registeredRegionName">
|
||||
<div class="invoice-form__address">
|
||||
<el-input
|
||||
v-model="invoiceForm.registeredRegionName"
|
||||
readonly
|
||||
maxlength="100"
|
||||
placeholder="点击后弹出地图组件"
|
||||
suffix-icon="el-icon-location"
|
||||
@click="handleInvoiceRegisteredMapPick"
|
||||
/>
|
||||
<el-input
|
||||
v-model="invoiceForm.registeredDetailAddress"
|
||||
readonly
|
||||
maxlength="255"
|
||||
placeholder="点击后弹出地图组件"
|
||||
suffix-icon="el-icon-location"
|
||||
@click="handleInvoiceRegisteredMapPick"
|
||||
/>
|
||||
</div>
|
||||
<el-input
|
||||
v-model="invoiceForm.registeredRegionName"
|
||||
readonly
|
||||
maxlength="100"
|
||||
placeholder="点击后弹出地图组件"
|
||||
suffix-icon="el-icon-location"
|
||||
@click="handleInvoiceRegisteredMapPick"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址" prop="registeredDetailAddress">
|
||||
<el-input
|
||||
v-model="invoiceForm.registeredDetailAddress"
|
||||
readonly
|
||||
maxlength="255"
|
||||
placeholder="点击后弹出地图组件"
|
||||
suffix-icon="el-icon-location"
|
||||
@click="handleInvoiceRegisteredMapPick"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -880,8 +914,10 @@
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="saveInvoice">保存</el-button>
|
||||
<el-button @click="invoiceBox = false">返回</el-button>
|
||||
<div class="invoice-dialog__footer-actions">
|
||||
<el-button type="primary" @click="saveInvoice">保存</el-button>
|
||||
<el-button @click="invoiceBox = false">返回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -1097,7 +1133,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" align="center" v-if="!readonly">
|
||||
<template #default="{ $index }">
|
||||
<el-link type="primary" @click="scoreAttachmentFiles.splice($index, 1)">
|
||||
<el-link type="primary" @click="deleteScoreAttachment($index)">
|
||||
删除
|
||||
</el-link>
|
||||
</template>
|
||||
@@ -1120,6 +1156,7 @@ import {
|
||||
getDetail,
|
||||
submit,
|
||||
submitApproval,
|
||||
withdrawApproval,
|
||||
approve,
|
||||
reject,
|
||||
changeStatus,
|
||||
@@ -1187,11 +1224,11 @@ export default {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateInvoiceRegisteredAddress = (rule, value, callback) => {
|
||||
const regionName = (this.invoiceForm.registeredRegionName || '').trim();
|
||||
const detailAddress = (this.invoiceForm.registeredDetailAddress || '').trim();
|
||||
const validateRegisteredAddress = (rule, value, callback) => {
|
||||
const regionName = (this.archiveForm.registeredRegionName || '').trim();
|
||||
const detailAddress = String(value || '').trim();
|
||||
if (!regionName) {
|
||||
callback(new Error('请选择注册地址'));
|
||||
callback(new Error('请选择省市区'));
|
||||
} else if (!detailAddress) {
|
||||
callback(new Error('请输入详细地址'));
|
||||
} else if (detailAddress.length > 255) {
|
||||
@@ -1203,6 +1240,7 @@ export default {
|
||||
return {
|
||||
form: {},
|
||||
query: {},
|
||||
deptSearchInitialized: false,
|
||||
loading: true,
|
||||
data: [],
|
||||
page: {
|
||||
@@ -1312,8 +1350,18 @@ export default {
|
||||
maxCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||
applyCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||
businessEndDate: [{ validator: validateBusinessEndDate, trigger: 'change' }],
|
||||
registeredDetailAddress: [{ max: 255, message: '详细地址最多255个字符', trigger: 'blur' }],
|
||||
businessScope: [{ type: 'array', message: '请选择经营范围', trigger: 'change' }],
|
||||
registeredDetailAddress: [
|
||||
{ validator: validateRegisteredAddress, trigger: ['change', 'blur'] },
|
||||
],
|
||||
businessScope: [
|
||||
{
|
||||
required: true,
|
||||
type: 'array',
|
||||
min: 1,
|
||||
message: '请选择经营范围',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
remark: [{ max: 500, message: '备注最多500个字符', trigger: 'blur' }],
|
||||
},
|
||||
contactRules: {
|
||||
@@ -1339,7 +1387,11 @@ export default {
|
||||
registeredPhone: [{ required: true, message: '请输入注册电话', trigger: 'blur' }],
|
||||
bankName: [{ required: true, message: '请输入开户行名称', trigger: 'blur' }],
|
||||
registeredRegionName: [
|
||||
{ required: true, validator: validateInvoiceRegisteredAddress, trigger: 'blur' },
|
||||
{ required: true, message: '请选择注册地址', trigger: 'blur' },
|
||||
],
|
||||
registeredDetailAddress: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' },
|
||||
{ max: 255, message: '详细地址最多255个字符', trigger: 'blur' },
|
||||
],
|
||||
bankAccount: [{ required: true, message: '请输入银行账号', trigger: 'blur' }],
|
||||
receiverDetailAddress: [
|
||||
@@ -1376,6 +1428,7 @@ export default {
|
||||
slot: true,
|
||||
search: true,
|
||||
searchOrder: 10,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
@@ -1383,6 +1436,7 @@ export default {
|
||||
prop: 'shortName',
|
||||
search: true,
|
||||
searchOrder: 2,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
@@ -1390,6 +1444,7 @@ export default {
|
||||
prop: 'fullName',
|
||||
search: true,
|
||||
searchOrder: 9,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 220,
|
||||
overHidden: true,
|
||||
},
|
||||
@@ -1399,8 +1454,10 @@ export default {
|
||||
search: true,
|
||||
searchType: 'select',
|
||||
searchOrder: 7,
|
||||
searchValue: '',
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 140,
|
||||
dicData: this.customerTypeOptions,
|
||||
dicData: [{ label: '全部', value: '' }],
|
||||
},
|
||||
{
|
||||
label: '客户性质',
|
||||
@@ -1408,8 +1465,11 @@ export default {
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
searchValue: '',
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 120,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '有限公司', value: '有限公司' },
|
||||
{ label: '个体工商户', value: '个体工商户' },
|
||||
],
|
||||
@@ -1419,6 +1479,7 @@ export default {
|
||||
prop: 'unifiedCreditCode',
|
||||
search: true,
|
||||
searchOrder: 3,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 190,
|
||||
},
|
||||
{
|
||||
@@ -1427,8 +1488,9 @@ export default {
|
||||
search: true,
|
||||
searchType: 'select',
|
||||
searchOrder: 1,
|
||||
searchValue: '',
|
||||
minWidth: 180,
|
||||
dicData: [],
|
||||
dicData: [{ label: '全部', value: '' }],
|
||||
},
|
||||
{
|
||||
label: '准入标准',
|
||||
@@ -1439,8 +1501,8 @@ export default {
|
||||
searchOrder: 8,
|
||||
minWidth: 120,
|
||||
dicData: [
|
||||
{ label: '临时客商', value: 'temporary' },
|
||||
{ label: '正式客商', value: 'formal' },
|
||||
{ label: '临时', value: 'temporary' },
|
||||
{ label: '正式', value: 'formal' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -1450,8 +1512,10 @@ export default {
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 4,
|
||||
searchValue: '',
|
||||
minWidth: 130,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '草稿', value: 'draft' },
|
||||
{ label: '审核中', value: 'reviewing' },
|
||||
{ label: '审核通过', value: 'approved' },
|
||||
@@ -1475,9 +1539,11 @@ export default {
|
||||
type: 'select',
|
||||
search: true,
|
||||
searchOrder: 6,
|
||||
searchValue: '',
|
||||
dataType: 'number',
|
||||
minWidth: 100,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '停用', value: 2 },
|
||||
],
|
||||
@@ -1743,15 +1809,38 @@ export default {
|
||||
};
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
this.deptTree = this.normalizeDeptTree(res.data.data || []);
|
||||
this.deptOptions = this.flattenDept(this.deptTree);
|
||||
const deptColumn = this.findColumn(this.option.column, 'deptName');
|
||||
deptColumn.dicData = this.deptOptions.map(item => ({
|
||||
label: item.label,
|
||||
value: item.rawLabel,
|
||||
}));
|
||||
});
|
||||
getDeptTree(this.userInfo.tenantId)
|
||||
.then(res => {
|
||||
this.deptTree = this.normalizeDeptTree(res.data.data || []);
|
||||
this.deptOptions = this.flattenDept(this.deptTree);
|
||||
const deptColumn = this.findColumn(this.option.column, 'deptName');
|
||||
deptColumn.dicData = [
|
||||
{ label: '全部', value: '' },
|
||||
...this.deptOptions.map(item => ({
|
||||
label: item.label,
|
||||
value: item.rawLabel,
|
||||
})),
|
||||
];
|
||||
this.applyDefaultDeptSearch(deptColumn);
|
||||
})
|
||||
.finally(() => {
|
||||
this.deptSearchInitialized = true;
|
||||
this.$nextTick(() => this.onLoad(this.page, this.query));
|
||||
});
|
||||
},
|
||||
applyDefaultDeptSearch(deptColumn) {
|
||||
if (this.isAdmin) return;
|
||||
const currentDeptId = this.userInfo.deptId || this.userInfo.dept_id;
|
||||
const currentDept = this.deptOptions.find(
|
||||
item => String(item.value) === String(currentDeptId)
|
||||
);
|
||||
const deptName = currentDept?.rawLabel || this.userInfo.deptName || this.userInfo.dept_name;
|
||||
if (!deptName) return;
|
||||
deptColumn.searchValue = deptName;
|
||||
this.query = { ...this.query, deptName };
|
||||
if (this.$refs.crud?.searchForm) {
|
||||
this.$refs.crud.searchForm.deptName = deptName;
|
||||
}
|
||||
},
|
||||
initRegionOptions() {
|
||||
getLazyTree().then(res => {
|
||||
@@ -1834,10 +1923,12 @@ export default {
|
||||
handleRegisteredRegionChange(value) {
|
||||
if (!value || !value.length) {
|
||||
this.archiveForm.registeredRegionName = '';
|
||||
this.$refs.archiveForm?.validateField('registeredDetailAddress');
|
||||
return;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.archiveForm.registeredRegionName = this.getRegisteredRegionLabels(value).join('');
|
||||
this.$refs.archiveForm?.validateField('registeredDetailAddress');
|
||||
});
|
||||
},
|
||||
initBusinessDictionaries() {
|
||||
@@ -1847,12 +1938,12 @@ export default {
|
||||
['有限公司', '个体工商户'],
|
||||
options => {
|
||||
const customerNatureColumn = this.findColumn(this.option.column, 'customerNature');
|
||||
customerNatureColumn.dicData = options;
|
||||
customerNatureColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
||||
}
|
||||
);
|
||||
this.loadDictOptions('customer_type', 'customerTypeOptions', ['客户', '承运商'], options => {
|
||||
const customerTypeColumn = this.findColumn(this.option.column, 'customerType');
|
||||
customerTypeColumn.dicData = options;
|
||||
const customerTypeColumn = this.findColumn(this.option.column, 'customerType');
|
||||
customerTypeColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
||||
});
|
||||
this.loadDictOptions('scope_of_business', 'businessScopeOptions');
|
||||
this.loadDictOptions('bank_list', 'bankListOptions');
|
||||
@@ -2040,8 +2131,16 @@ export default {
|
||||
});
|
||||
},
|
||||
deleteContact(index) {
|
||||
this.archiveForm.contacts.splice(index, 1);
|
||||
this.handleDetailCurrentChange('contact', this.contactPage.currentPage);
|
||||
this.$confirm('确定删除该联系人?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
this.archiveForm.contacts.splice(index, 1);
|
||||
this.handleDetailCurrentChange('contact', this.contactPage.currentPage);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
handleContactMapPick() {
|
||||
this.contactMapTarget = 'contact';
|
||||
@@ -2368,8 +2467,16 @@ export default {
|
||||
});
|
||||
},
|
||||
deleteReceipt(index) {
|
||||
this.archiveForm.receiptAccounts.splice(index, 1);
|
||||
this.handleDetailCurrentChange('receipt', this.receiptPage.currentPage);
|
||||
this.$confirm('确定删除该收款信息?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
this.archiveForm.receiptAccounts.splice(index, 1);
|
||||
this.handleDetailCurrentChange('receipt', this.receiptPage.currentPage);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
normalizeInvoice(invoice = {}) {
|
||||
const registeredDetailAddress =
|
||||
@@ -2423,8 +2530,27 @@ export default {
|
||||
});
|
||||
},
|
||||
deleteInvoice(index) {
|
||||
this.archiveForm.invoices.splice(index, 1);
|
||||
this.handleDetailCurrentChange('invoice', this.invoicePage.currentPage);
|
||||
this.$confirm('确定删除该发票信息?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
this.archiveForm.invoices.splice(index, 1);
|
||||
this.handleDetailCurrentChange('invoice', this.invoicePage.currentPage);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
deleteScoreAttachment(index) {
|
||||
this.$confirm('确定删除该评分证明材料?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
this.scoreAttachmentFiles.splice(index, 1);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
parseAttachments(value) {
|
||||
if (!value) return [];
|
||||
@@ -2578,6 +2704,7 @@ export default {
|
||||
const latestScore = this.getLatestCreditScore(archive.scores || []);
|
||||
archive.customerLevel = latestScore?.creditLevel || archive.customerLevel || '';
|
||||
archive.maxCreditLimit = latestScore?.maxCreditLimit || archive.maxCreditLimit || '';
|
||||
archive.applyCreditLimit = archive.maxCreditLimit;
|
||||
return archive;
|
||||
},
|
||||
syncArchiveCreditFromScores() {
|
||||
@@ -3172,6 +3299,18 @@ export default {
|
||||
});
|
||||
});
|
||||
},
|
||||
handleWithdrawApproval(row) {
|
||||
this.$confirm('是否确认撤回该客商审批?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => withdrawApproval(row.id))
|
||||
.then(() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '已撤回至草稿状态!' });
|
||||
});
|
||||
},
|
||||
handleApprove(row) {
|
||||
this.$confirm('是否确认审核通过?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -3211,7 +3350,7 @@ export default {
|
||||
});
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
this.query = this.isAdmin ? {} : { deptName: this.getCurrentDeptName() };
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
searchChange(params, done) {
|
||||
@@ -3237,6 +3376,7 @@ export default {
|
||||
this.onLoad(this.page, this.query);
|
||||
},
|
||||
onLoad(page, params = {}) {
|
||||
if (!this.deptSearchInitialized) return;
|
||||
this.loading = true;
|
||||
getList(page.currentPage, page.pageSize, this.buildQuery(params))
|
||||
.then(res => {
|
||||
@@ -3279,6 +3419,13 @@ export default {
|
||||
buildQuery(params = {}) {
|
||||
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
|
||||
},
|
||||
getCurrentDeptName() {
|
||||
const currentDeptId = this.userInfo.deptId || this.userInfo.dept_id;
|
||||
const currentDept = this.deptOptions.find(
|
||||
item => String(item.value) === String(currentDeptId)
|
||||
);
|
||||
return currentDept?.rawLabel || this.userInfo.deptName || this.userInfo.dept_name || '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -3579,6 +3726,37 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.contact-form__compact-field {
|
||||
:deep(.el-input) {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-dialog__footer-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.receipt-form {
|
||||
:deep(.el-input),
|
||||
:deep(.el-select) {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.receipt-dialog__footer-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.invoice-dialog__footer-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.contact-form__map-toolbar {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
||||
Reference in New Issue
Block a user