1、调整导入运单
2、调整对账
This commit is contained in:
@@ -27,6 +27,12 @@ const listDicFormatter = res => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const projectNameDicFormatter = res => {
|
||||||
|
const list = listDicFormatter(res);
|
||||||
|
// 过滤掉 projectName 为空的记录
|
||||||
|
return list.filter(item => item && item.projectName && String(item.projectName).trim());
|
||||||
|
};
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
title: '合同管理',
|
title: '合同管理',
|
||||||
permission: 'contract_manage',
|
permission: 'contract_manage',
|
||||||
@@ -266,7 +272,7 @@ export const option = createCrudOption([
|
|||||||
order: 165,
|
order: 165,
|
||||||
dicUrl:
|
dicUrl:
|
||||||
'/blade-transport/project-apply/list?current=1&size=9999&approvalStatuses=approved,change_approved',
|
'/blade-transport/project-apply/list?current=1&size=9999&approvalStatuses=approved,change_approved',
|
||||||
dicFormatter: listDicFormatter,
|
dicFormatter: projectNameDicFormatter,
|
||||||
props: {
|
props: {
|
||||||
label: 'projectName',
|
label: 'projectName',
|
||||||
value: 'projectName',
|
value: 'projectName',
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ const listDicFormatter = res => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const projectNameDicFormatter = res => {
|
||||||
|
const list = listDicFormatter(res);
|
||||||
|
// 过滤掉 projectName 为空的记录
|
||||||
|
return list.filter(item => item && item.projectName && String(item.projectName).trim());
|
||||||
|
};
|
||||||
|
|
||||||
const userDicFormatter = res =>
|
const userDicFormatter = res =>
|
||||||
listDicFormatter(res).map(user => ({
|
listDicFormatter(res).map(user => ({
|
||||||
...user,
|
...user,
|
||||||
@@ -137,7 +143,7 @@ export const option = {
|
|||||||
searchType: 'select',
|
searchType: 'select',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
||||||
dicFormatter: listDicFormatter,
|
dicFormatter: projectNameDicFormatter,
|
||||||
props: {
|
props: {
|
||||||
label: 'projectName',
|
label: 'projectName',
|
||||||
value: 'projectName',
|
value: 'projectName',
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ const listDicFormatter = res => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const projectNameDicFormatter = res => {
|
||||||
|
const list = listDicFormatter(res);
|
||||||
|
// 过滤掉 projectName 为空的记录
|
||||||
|
return list.filter(item => item && item.projectName && String(item.projectName).trim());
|
||||||
|
};
|
||||||
|
|
||||||
const parseGoodsRows = value => {
|
const parseGoodsRows = value => {
|
||||||
if (!value) return [];
|
if (!value) return [];
|
||||||
if (Array.isArray(value)) return value;
|
if (Array.isArray(value)) return value;
|
||||||
@@ -209,7 +215,7 @@ export const config = {
|
|||||||
statusProp: 'businessStatus',
|
statusProp: 'businessStatus',
|
||||||
statusTextProp: 'businessStatusName',
|
statusTextProp: 'businessStatusName',
|
||||||
deleteStatus: ['draft', 'waiting_dispatch'],
|
deleteStatus: ['draft', 'waiting_dispatch'],
|
||||||
editStatus: ['draft', 'waiting_dispatch'],
|
editStatus: ['draft', 'waiting_dispatch', 'dispatching'],
|
||||||
detailButton: true,
|
detailButton: true,
|
||||||
detailSections: [
|
detailSections: [
|
||||||
{
|
{
|
||||||
@@ -364,7 +370,7 @@ export const option = {
|
|||||||
span: 6,
|
span: 6,
|
||||||
order: 400,
|
order: 400,
|
||||||
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
||||||
dicFormatter: listDicFormatter,
|
dicFormatter: projectNameDicFormatter,
|
||||||
props: {
|
props: {
|
||||||
label: 'projectName',
|
label: 'projectName',
|
||||||
value: 'projectName',
|
value: 'projectName',
|
||||||
|
|||||||
@@ -1257,6 +1257,7 @@ export default {
|
|||||||
dialogReadonly: false,
|
dialogReadonly: false,
|
||||||
crudDialogType: '',
|
crudDialogType: '',
|
||||||
standaloneFormKey: '',
|
standaloneFormKey: '',
|
||||||
|
copyingRow: null,
|
||||||
detailBox: false,
|
detailBox: false,
|
||||||
detailLoading: false,
|
detailLoading: false,
|
||||||
detailRow: {},
|
detailRow: {},
|
||||||
@@ -1427,7 +1428,7 @@ export default {
|
|||||||
String(item.value).toUpperCase() ===
|
String(item.value).toUpperCase() ===
|
||||||
String(this.shippingTemplateFreight.currency || '').toUpperCase()
|
String(this.shippingTemplateFreight.currency || '').toUpperCase()
|
||||||
);
|
);
|
||||||
return this.currencyName(option?.label || this.shippingTemplateFreight.currency);
|
return this.currencyUnit(option?.label || this.shippingTemplateFreight.currency);
|
||||||
},
|
},
|
||||||
roadFreightTotal() {
|
roadFreightTotal() {
|
||||||
const total = this.shippingTemplateFreight.freightItems.reduce(
|
const total = this.shippingTemplateFreight.freightItems.reduce(
|
||||||
@@ -1498,7 +1499,8 @@ export default {
|
|||||||
if (
|
if (
|
||||||
this.isStandaloneFormPage &&
|
this.isStandaloneFormPage &&
|
||||||
(to.query.mode !== from?.query?.mode ||
|
(to.query.mode !== from?.query?.mode ||
|
||||||
String(to.query.id || '') !== String(from?.query.id || ''))
|
String(to.query.id || '') !== String(from?.query.id || '') ||
|
||||||
|
to.query.copy !== from?.query?.copy)
|
||||||
)
|
)
|
||||||
this.$nextTick(() => this.initStandaloneFormPage());
|
this.$nextTick(() => this.initStandaloneFormPage());
|
||||||
},
|
},
|
||||||
@@ -1608,13 +1610,21 @@ export default {
|
|||||||
},
|
},
|
||||||
openBusinessForm(mode, row = {}) {
|
openBusinessForm(mode, row = {}) {
|
||||||
if (this.isStandaloneBusinessPage) {
|
if (this.isStandaloneBusinessPage) {
|
||||||
|
const query = {
|
||||||
|
mode,
|
||||||
|
...(mode === 'edit' && row.id ? { id: row.id } : {}),
|
||||||
|
name: `${mode === 'edit' ? '编辑' : '新增'}${this.config.title}`,
|
||||||
|
};
|
||||||
|
// 如果是复制模式,添加标识
|
||||||
|
console.log('openBusinessForm, mode:', mode, 'copyingRow:', this.copyingRow);
|
||||||
|
if (mode === 'add' && this.copyingRow) {
|
||||||
|
query.copy = Date.now().toString();
|
||||||
|
console.log('添加 copy 参数:', query.copy);
|
||||||
|
}
|
||||||
|
console.log('最终的 query:', query);
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/business/shipping-template/form',
|
path: '/business/shipping-template/form',
|
||||||
query: {
|
query,
|
||||||
mode,
|
|
||||||
...(mode === 'edit' && row.id ? { id: row.id } : {}),
|
|
||||||
name: `${mode === 'edit' ? '编辑' : '新增'}${this.config.title}`,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1624,10 +1634,29 @@ export default {
|
|||||||
if (!this.isStandaloneFormPage) return;
|
if (!this.isStandaloneFormPage) return;
|
||||||
const mode = this.$route.query.mode;
|
const mode = this.$route.query.mode;
|
||||||
const id = this.$route.query.id || '';
|
const id = this.$route.query.id || '';
|
||||||
const key = `${mode}:${id}`;
|
const copy = this.$route.query.copy || '';
|
||||||
|
const key = `${mode}:${id}:${copy}`;
|
||||||
|
console.log('initStandaloneFormPage 被调用, key:', key, 'standaloneFormKey:', this.standaloneFormKey);
|
||||||
if (this.standaloneFormKey === key) return;
|
if (this.standaloneFormKey === key) return;
|
||||||
this.standaloneFormKey = key;
|
this.standaloneFormKey = key;
|
||||||
|
|
||||||
|
// 检查是否是复制模式
|
||||||
|
if (mode === 'add' && copy) {
|
||||||
|
const copyData = sessionStorage.getItem('shipping-template-copy-data');
|
||||||
|
console.log('复制模式检测到,从 sessionStorage 读取数据:', copyData);
|
||||||
|
if (copyData) {
|
||||||
|
try {
|
||||||
|
this.copyingRow = JSON.parse(copyData);
|
||||||
|
console.log('解析后的 copyingRow:', this.copyingRow);
|
||||||
|
sessionStorage.removeItem('shipping-template-copy-data');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析复制数据失败', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mode === 'edit') this.form = { id };
|
if (mode === 'edit') this.form = { id };
|
||||||
|
console.log('调用 beforeOpen 前,copyingRow:', this.copyingRow);
|
||||||
this.beforeOpen(() => {}, mode);
|
this.beforeOpen(() => {}, mode);
|
||||||
},
|
},
|
||||||
parseJsonArray(value) {
|
parseJsonArray(value) {
|
||||||
@@ -1752,9 +1781,37 @@ export default {
|
|||||||
.catch(() => loading?.());
|
.catch(() => loading?.());
|
||||||
},
|
},
|
||||||
beforeOpen(done, type) {
|
beforeOpen(done, type) {
|
||||||
|
console.log('beforeOpen 被调用,type:', type, 'copyingRow:', this.copyingRow);
|
||||||
this.crudDialogType = type;
|
this.crudDialogType = type;
|
||||||
this.dialogReadonly = type === 'view';
|
this.dialogReadonly = type === 'view';
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
|
// 检查是否是复制模式
|
||||||
|
if (this.copyingRow) {
|
||||||
|
console.log('进入复制模式分支');
|
||||||
|
const copyData = { ...this.copyingRow };
|
||||||
|
this.copyingRow = null;
|
||||||
|
this.form = { ...(this.config.defaultForm || {}), ...copyData };
|
||||||
|
console.log('合并后的 form:', this.form);
|
||||||
|
// 删除模板编号,等待系统生成
|
||||||
|
delete this.form.templateCode;
|
||||||
|
this.applyFormDetail(this.form);
|
||||||
|
console.log('applyFormDetail 调用完成');
|
||||||
|
// 生成新的模板编号
|
||||||
|
if (typeof this.api.nextCode === 'function') {
|
||||||
|
this.api
|
||||||
|
.nextCode()
|
||||||
|
.then(res => {
|
||||||
|
this.form.templateCode = res?.data?.data || '';
|
||||||
|
console.log('生成的新模板编号:', this.form.templateCode);
|
||||||
|
})
|
||||||
|
.finally(() => done?.());
|
||||||
|
} else {
|
||||||
|
done?.();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('进入正常新增模式分支');
|
||||||
|
// 正常新增模式
|
||||||
this.form = { ...(this.config.defaultForm || {}) };
|
this.form = { ...(this.config.defaultForm || {}) };
|
||||||
this.selectedProjectId = '';
|
this.selectedProjectId = '';
|
||||||
this.contractOptions = [];
|
this.contractOptions = [];
|
||||||
@@ -1791,9 +1848,12 @@ export default {
|
|||||||
this.normalizeCargo(item)
|
this.normalizeCargo(item)
|
||||||
);
|
);
|
||||||
if (!this.transportCargoRows.length) this.transportCargoRows = [defaultCargo()];
|
if (!this.transportCargoRows.length) this.transportCargoRows = [defaultCargo()];
|
||||||
this.restoreCargoTypePaths();
|
// 先加载货物类型树,保证已有货物类型可以回显为级联路径,然后再恢复路径。
|
||||||
// 编辑时先加载货物类型树,保证已有货物类型可以回显为级联路径。
|
this.ensureCargoTypeOptions()
|
||||||
this.ensureCargoTypeOptions().catch(() => {});
|
.then(() => {
|
||||||
|
this.restoreCargoTypePaths();
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
|
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
|
||||||
this.shippingTemplateFreight = {
|
this.shippingTemplateFreight = {
|
||||||
...defaultFreight(),
|
...defaultFreight(),
|
||||||
@@ -1937,11 +1997,42 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleCopy(row) {
|
handleCopy(row) {
|
||||||
if (typeof this.api.copy !== 'function') return;
|
this.api
|
||||||
this.api.copy(row.id).then(() => {
|
.getDetail(row.id)
|
||||||
this.$message.success('复制成功');
|
.then(res => {
|
||||||
this.onLoad(this.page, this.query);
|
const detail = res?.data?.data || {};
|
||||||
});
|
console.log('获取到的详情数据:', detail);
|
||||||
|
// 删除不需要复制的字段
|
||||||
|
delete detail.id;
|
||||||
|
delete detail.templateCode; // 系统自动生成
|
||||||
|
delete detail.createTime;
|
||||||
|
delete detail.createUser;
|
||||||
|
delete detail.createUserName;
|
||||||
|
delete detail.createDept;
|
||||||
|
delete detail.updateTime;
|
||||||
|
delete detail.updateUser;
|
||||||
|
delete detail.updateUserName;
|
||||||
|
delete detail.status;
|
||||||
|
|
||||||
|
console.log('处理后的数据:', detail);
|
||||||
|
console.log('isStandaloneBusinessPage:', this.isStandaloneBusinessPage);
|
||||||
|
|
||||||
|
// 存储到组件状态(用于判断是否是复制模式)
|
||||||
|
this.copyingRow = detail;
|
||||||
|
console.log('已存储到 copyingRow');
|
||||||
|
|
||||||
|
// 如果是独立表单页模式,同时存储到 sessionStorage
|
||||||
|
if (this.isStandaloneBusinessPage) {
|
||||||
|
sessionStorage.setItem('shipping-template-copy-data', JSON.stringify(detail));
|
||||||
|
console.log('已存储到 sessionStorage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开新增表单
|
||||||
|
this.openBusinessForm('add', {});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.error('获取数据失败');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleCustomOperation(operation, row) {
|
handleCustomOperation(operation, row) {
|
||||||
if (operation.action === 'createFromTemplate') {
|
if (operation.action === 'createFromTemplate') {
|
||||||
@@ -2100,6 +2191,45 @@ export default {
|
|||||||
}[text.toUpperCase()] || text
|
}[text.toUpperCase()] || text
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
currencyUnit(value) {
|
||||||
|
const text = String(value || '');
|
||||||
|
// 如果格式是 "CNY - 人民币",提取货币代码部分
|
||||||
|
let code = text;
|
||||||
|
if (text.includes(' - ')) {
|
||||||
|
code = text.split(' - ')[0].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const upperCode = code.toUpperCase();
|
||||||
|
const unitMap = {
|
||||||
|
CNY: '元',
|
||||||
|
RMB: '元',
|
||||||
|
USD: '美元',
|
||||||
|
EUR: '欧元',
|
||||||
|
JPY: '日元',
|
||||||
|
GBP: '英镑',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果是已知的货币代码,返回对应的单位
|
||||||
|
if (unitMap[upperCode]) {
|
||||||
|
return unitMap[upperCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是中文货币名称,转换为单位
|
||||||
|
const nameMap = {
|
||||||
|
'人民币': '元',
|
||||||
|
'美元': '美元',
|
||||||
|
'欧元': '欧元',
|
||||||
|
'日元': '日元',
|
||||||
|
'英镑': '英镑',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (nameMap[code]) {
|
||||||
|
return nameMap[code];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回原值
|
||||||
|
return text;
|
||||||
|
},
|
||||||
loadFeeUnitOptions() {
|
loadFeeUnitOptions() {
|
||||||
getDictionary({ code: 'unit_fee' }).then(res => {
|
getDictionary({ code: 'unit_fee' }).then(res => {
|
||||||
this.feeUnitOptions = this.normalizeDictOptions(res?.data?.data || []);
|
this.feeUnitOptions = this.normalizeDictOptions(res?.data?.data || []);
|
||||||
@@ -2644,7 +2774,20 @@ export default {
|
|||||||
const pathMatch = this.cargoTypeFlatOptions.find(item => item.path?.join('/') === pathKey);
|
const pathMatch = this.cargoTypeFlatOptions.find(item => item.path?.join('/') === pathKey);
|
||||||
if (pathMatch) return pathMatch;
|
if (pathMatch) return pathMatch;
|
||||||
}
|
}
|
||||||
const codeCandidates = [row.secondCargoTypeCode, row.cargoTypeCode, row.firstCargoTypeCode]
|
|
||||||
|
// 优先通过二级类型编码查找(最准确)
|
||||||
|
if (row.secondCargoTypeCode) {
|
||||||
|
const secondMatch = this.cargoTypeFlatOptions.find(
|
||||||
|
item => String(item.cargoCode || item.code || '').trim() === String(row.secondCargoTypeCode).trim()
|
||||||
|
);
|
||||||
|
if (secondMatch) {
|
||||||
|
console.log('通过 secondCargoTypeCode 找到货物类型:', secondMatch);
|
||||||
|
return secondMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他候选编码
|
||||||
|
const codeCandidates = [row.cargoTypeCode, row.firstCargoTypeCode]
|
||||||
.map(value => String(value || '').trim())
|
.map(value => String(value || '').trim())
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
const nameCandidates = [
|
const nameCandidates = [
|
||||||
@@ -2655,6 +2798,7 @@ export default {
|
|||||||
]
|
]
|
||||||
.map(value => String(value || '').trim())
|
.map(value => String(value || '').trim())
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.cargoTypeFlatOptions.find(item =>
|
this.cargoTypeFlatOptions.find(item =>
|
||||||
codeCandidates.some(
|
codeCandidates.some(
|
||||||
@@ -2671,13 +2815,19 @@ export default {
|
|||||||
return matched?.path ? this.cargoPath(matched.path) : [];
|
return matched?.path ? this.cargoPath(matched.path) : [];
|
||||||
},
|
},
|
||||||
restoreCargoTypePaths() {
|
restoreCargoTypePaths() {
|
||||||
|
console.log('restoreCargoTypePaths 被调用');
|
||||||
|
console.log('transportCargoRows:', this.transportCargoRows);
|
||||||
|
console.log('cargoTypeFlatOptions 长度:', this.cargoTypeFlatOptions.length);
|
||||||
if (!this.transportCargoRows.length || !this.cargoTypeFlatOptions.length) return;
|
if (!this.transportCargoRows.length || !this.cargoTypeFlatOptions.length) return;
|
||||||
this.transportCargoRows.forEach(row => {
|
this.transportCargoRows.forEach((row, index) => {
|
||||||
|
console.log(`处理第 ${index + 1} 行货物:`, row);
|
||||||
const path = this.resolveCargoTypePath(row);
|
const path = this.resolveCargoTypePath(row);
|
||||||
|
console.log(`解析出的 path:`, path);
|
||||||
if (!path.length) return;
|
if (!path.length) return;
|
||||||
const item = this.cargoTypeFlatOptions.find(
|
const item = this.cargoTypeFlatOptions.find(
|
||||||
option => option.path?.join('/') === path.join('/')
|
option => option.path?.join('/') === path.join('/')
|
||||||
);
|
);
|
||||||
|
console.log(`匹配到的 item:`, item);
|
||||||
row.cargoTypePath = path;
|
row.cargoTypePath = path;
|
||||||
row.cargoType =
|
row.cargoType =
|
||||||
item?.cargoName ||
|
item?.cargoName ||
|
||||||
@@ -2691,12 +2841,22 @@ export default {
|
|||||||
row.secondCargoTypeCode ||
|
row.secondCargoTypeCode ||
|
||||||
row.firstCargoTypeCode ||
|
row.firstCargoTypeCode ||
|
||||||
'';
|
'';
|
||||||
|
console.log(`设置后的 row.cargoTypePath:`, row.cargoTypePath);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
normalizeCargo(row = {}) {
|
normalizeCargo(row = {}) {
|
||||||
const cargoTypePath = this.resolveCargoTypePath(row);
|
console.log('normalizeCargo 输入:', row);
|
||||||
|
// 如果原始数据中有完整的 cargoTypePath 数组,直接使用
|
||||||
|
let cargoTypePath = [];
|
||||||
|
if (Array.isArray(row.cargoTypePath) && row.cargoTypePath.length > 0) {
|
||||||
|
cargoTypePath = this.cargoPath(row.cargoTypePath);
|
||||||
|
console.log('使用原始的 cargoTypePath:', cargoTypePath);
|
||||||
|
} else {
|
||||||
|
cargoTypePath = this.resolveCargoTypePath(row);
|
||||||
|
console.log('解析的 cargoTypePath:', cargoTypePath);
|
||||||
|
}
|
||||||
const cargoType = this.findCargoTypeOption({ ...row, cargoTypePath });
|
const cargoType = this.findCargoTypeOption({ ...row, cargoTypePath });
|
||||||
return {
|
const result = {
|
||||||
...defaultCargo(),
|
...defaultCargo(),
|
||||||
...row,
|
...row,
|
||||||
cargoTypePath,
|
cargoTypePath,
|
||||||
@@ -2714,6 +2874,8 @@ export default {
|
|||||||
'',
|
'',
|
||||||
cargoName: row.cargoName || row.goodsName || '',
|
cargoName: row.cargoName || row.goodsName || '',
|
||||||
};
|
};
|
||||||
|
console.log('normalizeCargo 输出:', result);
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
handleCargoTypeChange(row, value) {
|
handleCargoTypeChange(row, value) {
|
||||||
const path = this.cargoPath(value);
|
const path = this.cargoPath(value);
|
||||||
@@ -2740,26 +2902,47 @@ export default {
|
|||||||
.catch(() => callback([]));
|
.catch(() => callback([]));
|
||||||
},
|
},
|
||||||
async selectCargoSuggestion(row, item = {}) {
|
async selectCargoSuggestion(row, item = {}) {
|
||||||
const cargoTypeOption = this.findCargoTypeOption(item);
|
console.log('selectCargoSuggestion 被调用,item:', item);
|
||||||
|
|
||||||
const selectedCargo = {
|
const selectedCargo = {
|
||||||
...row,
|
...row,
|
||||||
...item,
|
...item,
|
||||||
cargoName: item.cargoName || item.name || item.label || item.value || row.cargoName || '',
|
cargoName: item.cargoName || item.name || item.label || item.value || row.cargoName || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 确保货物类型树已加载
|
||||||
try {
|
try {
|
||||||
await this.ensureCargoTypeOptions();
|
await this.ensureCargoTypeOptions();
|
||||||
|
console.log('货物类型树已加载,共', this.cargoTypeFlatOptions.length, '个选项');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.warn('货物类型树加载失败', error);
|
||||||
// 货物类型树加载失败时仍保留货物名称,提交时会给出货物类型必填提示。
|
// 货物类型树加载失败时仍保留货物名称,提交时会给出货物类型必填提示。
|
||||||
}
|
}
|
||||||
// 货物名称返回了类型信息时,以货物自身的类型覆盖当前行原有类型。
|
|
||||||
// 这样从一个类型切换到另一个类型时,级联选择器不会继续显示旧值。
|
// 从常用货物返回的数据中查找货物类型
|
||||||
const matchedCargoType = this.findCargoTypeOption(item) || cargoTypeOption;
|
const matchedCargoType = this.findCargoTypeOption(item);
|
||||||
|
console.log('匹配到的货物类型:', matchedCargoType);
|
||||||
|
|
||||||
if (matchedCargoType?.path?.length) {
|
if (matchedCargoType?.path?.length) {
|
||||||
selectedCargo.cargoTypePath = this.cargoPath(matchedCargoType.path);
|
// 找到匹配的货物类型,回填到当前行
|
||||||
|
const fullPath = matchedCargoType.path;
|
||||||
|
selectedCargo.cargoTypePath = this.cargoPath(fullPath);
|
||||||
selectedCargo.cargoType = matchedCargoType.cargoName || selectedCargo.cargoType;
|
selectedCargo.cargoType = matchedCargoType.cargoName || selectedCargo.cargoType;
|
||||||
selectedCargo.cargoTypeCode =
|
selectedCargo.cargoTypeCode =
|
||||||
matchedCargoType.cargoCode || matchedCargoType.code || matchedCargoType.id || '';
|
matchedCargoType.cargoCode || matchedCargoType.code || matchedCargoType.id || '';
|
||||||
|
|
||||||
|
console.log('货物名称选择后反选货物类型:', {
|
||||||
|
cargoName: selectedCargo.cargoName,
|
||||||
|
cargoType: selectedCargo.cargoType,
|
||||||
|
cargoTypePath: selectedCargo.cargoTypePath,
|
||||||
|
fullPath: fullPath,
|
||||||
|
matchedCargoType: matchedCargoType,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('未找到匹配的货物类型,item数据:', item);
|
||||||
|
console.warn('当前 cargoTypeFlatOptions 前5项:', this.cargoTypeFlatOptions.slice(0, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(row, this.normalizeCargo(selectedCargo));
|
Object.assign(row, this.normalizeCargo(selectedCargo));
|
||||||
row.value = undefined;
|
row.value = undefined;
|
||||||
this.syncFreightItems();
|
this.syncFreightItems();
|
||||||
|
|||||||
@@ -316,6 +316,25 @@
|
|||||||
empty-text="暂无货物信息"
|
empty-text="暂无货物信息"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="70" align="center" fixed="left" />
|
<el-table-column type="index" label="序号" width="70" align="center" fixed="left" />
|
||||||
|
<el-table-column min-width="220" align="center">
|
||||||
|
<template #header>
|
||||||
|
<span class="transport-plan-page__required-column">货物类型</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-cascader
|
||||||
|
v-model="row.cargoTypePath"
|
||||||
|
:options="transportCargoTypeOptions"
|
||||||
|
:props="transportCargoTypeCascaderProps"
|
||||||
|
:placeholder="row.cargoType || '请选择'"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
:filter-method="filterBillingCargoType"
|
||||||
|
@visible-change="visible => visible && ensureBillingCargoTypeOptions()"
|
||||||
|
@change="value => handleTransportCargoTypeChange(row, value)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="货物名称" min-width="240" align="center">
|
<el-table-column label="货物名称" min-width="240" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
@@ -334,31 +353,11 @@
|
|||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<div class="transport-plan-page__cargo-autocomplete-item">
|
<div class="transport-plan-page__cargo-autocomplete-item">
|
||||||
<span>{{ formatBillingCargoTypeLabel(item) }}</span>
|
<span>{{ formatBillingCargoTypeLabel(item) }}</span>
|
||||||
<small v-if="item.cargoCode">{{ item.cargoCode }}</small>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column min-width="220" align="center">
|
|
||||||
<template #header>
|
|
||||||
<span class="transport-plan-page__required-column">货物类型</span>
|
|
||||||
</template>
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-cascader
|
|
||||||
v-model="row.cargoTypePath"
|
|
||||||
:options="transportCargoTypeOptions"
|
|
||||||
:props="transportCargoTypeCascaderProps"
|
|
||||||
:placeholder="row.cargoType || '请选择'"
|
|
||||||
clearable
|
|
||||||
filterable
|
|
||||||
:disabled="dialogReadonly"
|
|
||||||
:filter-method="filterBillingCargoType"
|
|
||||||
@visible-change="visible => visible && ensureBillingCargoTypeOptions()"
|
|
||||||
@change="value => handleTransportCargoTypeChange(row, value)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="数量" min-width="120" align="center">
|
<el-table-column label="数量" min-width="120" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -1494,10 +1493,12 @@
|
|||||||
v-model="dispatchItemForm.departureName"
|
v-model="dispatchItemForm.departureName"
|
||||||
:placeholder="dispatchStationNamePlaceholder"
|
:placeholder="dispatchStationNamePlaceholder"
|
||||||
:suffix-icon="dispatchStationMode ? Search : undefined"
|
:suffix-icon="dispatchStationMode ? Search : undefined"
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="dispatchItemForm.departureAddress"
|
v-model="dispatchItemForm.departureAddress"
|
||||||
:placeholder="dispatchAddressDetailPlaceholder"
|
:placeholder="dispatchAddressDetailPlaceholder"
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
<template v-if="!dispatchStationMode" #suffix>
|
<template v-if="!dispatchStationMode" #suffix>
|
||||||
<el-link
|
<el-link
|
||||||
@@ -1509,9 +1510,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<span class="transport-plan-page__route-label">联系人</span>
|
<span class="transport-plan-page__route-label">联系人</span>
|
||||||
<el-input v-model="dispatchItemForm.departureContact" placeholder="请输入" />
|
<el-input v-model="dispatchItemForm.departureContact" placeholder="请输入" disabled />
|
||||||
<span class="transport-plan-page__route-label">联系方式</span>
|
<span class="transport-plan-page__route-label">联系方式</span>
|
||||||
<el-input v-model="dispatchItemForm.departurePhone" placeholder="请输入" />
|
<el-input v-model="dispatchItemForm.departurePhone" placeholder="请输入" disabled />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收货地址" required>
|
<el-form-item label="收货地址" required>
|
||||||
@@ -1520,10 +1521,12 @@
|
|||||||
v-model="dispatchItemForm.arrivalName"
|
v-model="dispatchItemForm.arrivalName"
|
||||||
:placeholder="dispatchStationNamePlaceholder"
|
:placeholder="dispatchStationNamePlaceholder"
|
||||||
:suffix-icon="dispatchStationMode ? Search : undefined"
|
:suffix-icon="dispatchStationMode ? Search : undefined"
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="dispatchItemForm.arrivalAddress"
|
v-model="dispatchItemForm.arrivalAddress"
|
||||||
:placeholder="dispatchAddressDetailPlaceholder"
|
:placeholder="dispatchAddressDetailPlaceholder"
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
<template v-if="!dispatchStationMode" #suffix>
|
<template v-if="!dispatchStationMode" #suffix>
|
||||||
<el-link
|
<el-link
|
||||||
@@ -1535,9 +1538,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<span class="transport-plan-page__route-label">联系人</span>
|
<span class="transport-plan-page__route-label">联系人</span>
|
||||||
<el-input v-model="dispatchItemForm.arrivalContact" placeholder="请输入" />
|
<el-input v-model="dispatchItemForm.arrivalContact" placeholder="请输入" disabled />
|
||||||
<span class="transport-plan-page__route-label">联系方式</span>
|
<span class="transport-plan-page__route-label">联系方式</span>
|
||||||
<el-input v-model="dispatchItemForm.arrivalPhone" placeholder="请输入" />
|
<el-input v-model="dispatchItemForm.arrivalPhone" placeholder="请输入" disabled />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
@@ -4849,10 +4852,7 @@ export default {
|
|||||||
fetchTaskCargoSuggestions(queryString, callback, path = []) {
|
fetchTaskCargoSuggestions(queryString, callback, path = []) {
|
||||||
const keyword = String(queryString || '').trim();
|
const keyword = String(queryString || '').trim();
|
||||||
const normalizedPath = this.normalizeBillingCargoTypePath(path);
|
const normalizedPath = this.normalizeBillingCargoTypePath(path);
|
||||||
if (!keyword && !normalizedPath.length) {
|
// 移除空查询时返回空数组的限制,允许点击时显示货物列表
|
||||||
callback([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let loadingKey = '';
|
let loadingKey = '';
|
||||||
this.ensureBillingCargoTypeOptions()
|
this.ensureBillingCargoTypeOptions()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -4884,11 +4884,42 @@ export default {
|
|||||||
if (loadingKey) this.setTaskCargoLoadingByKey(loadingKey, false);
|
if (loadingKey) this.setTaskCargoLoadingByKey(loadingKey, false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleTaskCargoRowSelect(row, item = {}) {
|
async handleTaskCargoRowSelect(row, item = {}) {
|
||||||
const value = this.formatBillingCargoTypeLabel(item);
|
const value = this.formatBillingCargoTypeLabel(item);
|
||||||
row.cargoName = value;
|
row.cargoName = value;
|
||||||
row.specification = item.specification || item.spec || row.specification || '';
|
row.specification = item.specification || item.spec || row.specification || '';
|
||||||
row.model = item.model || item.modelName || row.model || '';
|
row.model = item.model || item.modelName || row.model || '';
|
||||||
|
|
||||||
|
// 确保货物类型树已加载
|
||||||
|
try {
|
||||||
|
await this.ensureBillingCargoTypeOptions();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('货物类型树加载失败', error);
|
||||||
|
this.syncTransportCargoJson();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从常用货物返回的数据中查找货物类型并反选
|
||||||
|
const matchedCargoType = this.findBillingCargoTypeOption(item);
|
||||||
|
|
||||||
|
if (matchedCargoType?.path?.length) {
|
||||||
|
// 找到匹配的货物类型,回填到当前行
|
||||||
|
const fullPath = this.normalizeBillingCargoTypePath(matchedCargoType.path);
|
||||||
|
row.cargoTypePath = fullPath;
|
||||||
|
row.cargoType = matchedCargoType.cargoName || row.cargoType || '';
|
||||||
|
row.cargoTypeCode =
|
||||||
|
matchedCargoType.cargoCode || matchedCargoType.code || matchedCargoType.id || '';
|
||||||
|
|
||||||
|
console.log('货物名称选择后反选货物类型:', {
|
||||||
|
cargoName: row.cargoName,
|
||||||
|
cargoType: row.cargoType,
|
||||||
|
cargoTypePath: row.cargoTypePath,
|
||||||
|
matchedCargoType: matchedCargoType,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('未找到匹配的货物类型,item数据:', item);
|
||||||
|
}
|
||||||
|
|
||||||
this.syncTransportCargoJson();
|
this.syncTransportCargoJson();
|
||||||
},
|
},
|
||||||
loadTaskQuantityUnitOptions() {
|
loadTaskQuantityUnitOptions() {
|
||||||
@@ -6179,6 +6210,49 @@ export default {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
findBillingCargoTypeOption(row = {}) {
|
||||||
|
const path = this.normalizeBillingCargoTypePath(row.cargoTypePath);
|
||||||
|
if (path.length) {
|
||||||
|
const pathKey = path.join('/');
|
||||||
|
const pathMatch = this.billingCargoTypeFlatOptions.find(item => item.path?.join('/') === pathKey);
|
||||||
|
if (pathMatch) return pathMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先通过二级类型编码查找(最准确)
|
||||||
|
if (row.secondCargoTypeCode) {
|
||||||
|
const secondMatch = this.billingCargoTypeFlatOptions.find(
|
||||||
|
item => String(item.cargoCode || item.code || '').trim() === String(row.secondCargoTypeCode).trim()
|
||||||
|
);
|
||||||
|
if (secondMatch) {
|
||||||
|
console.log('通过 secondCargoTypeCode 找到货物类型:', secondMatch);
|
||||||
|
return secondMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他候选编码
|
||||||
|
const codeCandidates = [row.cargoTypeCode, row.firstCargoTypeCode]
|
||||||
|
.map(value => String(value || '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const nameCandidates = [
|
||||||
|
row.secondCargoTypeName,
|
||||||
|
row.cargoType,
|
||||||
|
row.goodsType,
|
||||||
|
row.firstCargoTypeName,
|
||||||
|
]
|
||||||
|
.map(value => String(value || '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
return (
|
||||||
|
this.billingCargoTypeFlatOptions.find(item =>
|
||||||
|
codeCandidates.some(
|
||||||
|
code => code === String(item.cargoCode || item.code || item.id || '').trim()
|
||||||
|
)
|
||||||
|
) ||
|
||||||
|
this.billingCargoTypeFlatOptions.find(item =>
|
||||||
|
nameCandidates.some(name => name === String(item.cargoName || '').trim())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
resolveCommonCargoTypePath(row = {}) {
|
resolveCommonCargoTypePath(row = {}) {
|
||||||
const path = this.normalizeBillingCargoTypePath(row.cargoTypePath);
|
const path = this.normalizeBillingCargoTypePath(row.cargoTypePath);
|
||||||
if (path.length) return path;
|
if (path.length) return path;
|
||||||
|
|||||||
@@ -247,6 +247,9 @@
|
|||||||
>
|
>
|
||||||
{{ row[column.prop] }}
|
{{ row[column.prop] }}
|
||||||
</el-link>
|
</el-link>
|
||||||
|
<span v-else-if="column.money && column.prop === 'unitPrice'">
|
||||||
|
{{ formatUnitPrice(row) }}
|
||||||
|
</span>
|
||||||
<span v-else-if="column.money">
|
<span v-else-if="column.money">
|
||||||
{{ formatMoney(row[column.prop], row.currency || form.currency) }}
|
{{ formatMoney(row[column.prop], row.currency || form.currency) }}
|
||||||
</span>
|
</span>
|
||||||
@@ -259,6 +262,12 @@
|
|||||||
<span v-else-if="column.prop === 'transportType'">
|
<span v-else-if="column.prop === 'transportType'">
|
||||||
{{ transportTypeName(row[column.prop]) }}
|
{{ transportTypeName(row[column.prop]) }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else-if="column.prop === 'cargoName'">
|
||||||
|
{{ formatCargoNames(row) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="column.prop === 'cargoType'">
|
||||||
|
{{ formatCargoTypes(row) }}
|
||||||
|
</span>
|
||||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -1078,6 +1087,7 @@ export default {
|
|||||||
adjustRows: [],
|
adjustRows: [],
|
||||||
pendingAdjustments: {},
|
pendingAdjustments: {},
|
||||||
sourceFeeSnapshots: {},
|
sourceFeeSnapshots: {},
|
||||||
|
detailFeeCache: {}, // 缓存每个明细的费用明细数据(用于拼接货物名称和类型)
|
||||||
adjustChangeRecordVisible: false,
|
adjustChangeRecordVisible: false,
|
||||||
adjustChangeRecord: null,
|
adjustChangeRecord: null,
|
||||||
adjustChangeRecordDetailRows: [],
|
adjustChangeRecordDetailRows: [],
|
||||||
@@ -1169,6 +1179,19 @@ export default {
|
|||||||
});
|
});
|
||||||
return Array.from(names);
|
return Array.from(names);
|
||||||
},
|
},
|
||||||
|
// 按 preSettlementDetailId 分组的明细数据(用于拼接货物名称和类型)
|
||||||
|
groupedDetails() {
|
||||||
|
const groups = {};
|
||||||
|
this.details.forEach(detail => {
|
||||||
|
// 优先使用 sourceDetailId,如果没有则使用 preSettlementDetailId
|
||||||
|
const groupKey = detail.sourceDetailId || detail.preSettlementDetailId || detail.id;
|
||||||
|
if (!groups[groupKey]) {
|
||||||
|
groups[groupKey] = [];
|
||||||
|
}
|
||||||
|
groups[groupKey].push(detail);
|
||||||
|
});
|
||||||
|
return groups;
|
||||||
|
},
|
||||||
filteredDetails() {
|
filteredDetails() {
|
||||||
return this.details.filter(row =>
|
return this.details.filter(row =>
|
||||||
Object.entries(this.appliedDetailQuery).every(([field, keyword]) => {
|
Object.entries(this.appliedDetailQuery).every(([field, keyword]) => {
|
||||||
@@ -1322,6 +1345,7 @@ export default {
|
|||||||
this.adjustRows = [];
|
this.adjustRows = [];
|
||||||
this.pendingAdjustments = {};
|
this.pendingAdjustments = {};
|
||||||
this.sourceFeeSnapshots = {};
|
this.sourceFeeSnapshots = {};
|
||||||
|
this.detailFeeCache = {};
|
||||||
this.adjustDialog.activeTab = 'adjust';
|
this.adjustDialog.activeTab = 'adjust';
|
||||||
this.adjustDialog.detailId = '';
|
this.adjustDialog.detailId = '';
|
||||||
this.adjustDialog.sourceDetailId = '';
|
this.adjustDialog.sourceDetailId = '';
|
||||||
@@ -1371,6 +1395,8 @@ export default {
|
|||||||
partyB: detail.payeeName,
|
partyB: detail.payeeName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 预加载所有明细的费用明细数据,用于拼接货物名称和类型
|
||||||
|
await this.loadAllDetailFees();
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
@@ -1917,6 +1943,30 @@ export default {
|
|||||||
this.normalizeAdjustRow(item, data.feeItemNames || [])
|
this.normalizeAdjustRow(item, data.feeItemNames || [])
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
// 批量加载所有明细的费用明细数据,用于拼接货物名称和类型
|
||||||
|
async loadAllDetailFees() {
|
||||||
|
if (!this.details.length) return;
|
||||||
|
|
||||||
|
// 并发加载所有明细的费用数据
|
||||||
|
await Promise.all(
|
||||||
|
this.details.map(async detail => {
|
||||||
|
if (!detail.id) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await getDetailFees(detail.id);
|
||||||
|
const feeRows = response.data?.data || response.data || [];
|
||||||
|
|
||||||
|
// 缓存费用明细数据
|
||||||
|
if (Array.isArray(feeRows) && feeRows.length > 0) {
|
||||||
|
this.detailFeeCache[detail.id] = feeRows;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 加载失败时使用明细本身的数据
|
||||||
|
console.warn(`加载明细 ${detail.id} 的费用数据失败:`, error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
// 明细列表只有汇总金额,费用项级别的原始金额需要按来源明细单独拉取并缓存为调整基准。
|
// 明细列表只有汇总金额,费用项级别的原始金额需要按来源明细单独拉取并缓存为调整基准。
|
||||||
async ensureSourceFeeSnapshots() {
|
async ensureSourceFeeSnapshots() {
|
||||||
const targets = this.details.filter(row => {
|
const targets = this.details.filter(row => {
|
||||||
@@ -2461,6 +2511,65 @@ export default {
|
|||||||
if (!Number.isFinite(quantity)) return '-';
|
if (!Number.isFinite(quantity)) return '-';
|
||||||
return `${quantity.toFixed(2)}${row.quantityUnit ? ` ${row.quantityUnit}` : ''}`;
|
return `${quantity.toFixed(2)}${row.quantityUnit ? ` ${row.quantityUnit}` : ''}`;
|
||||||
},
|
},
|
||||||
|
// 拼接同一运单的货物名称
|
||||||
|
formatCargoNames(row) {
|
||||||
|
const detailId = row.id;
|
||||||
|
const feeRows = this.detailFeeCache[detailId] || [];
|
||||||
|
|
||||||
|
// 如果没有缓存数据或只有一条,返回原始值
|
||||||
|
if (feeRows.length <= 1) {
|
||||||
|
return this.displayValue(row.cargoName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有货物名称并去重
|
||||||
|
const names = feeRows
|
||||||
|
.map(item => item.cargoName)
|
||||||
|
.filter(name => name && String(name).trim())
|
||||||
|
.filter((name, index, arr) => arr.indexOf(name) === index);
|
||||||
|
|
||||||
|
return names.length > 0 ? names.join('、') : this.displayValue(row.cargoName);
|
||||||
|
},
|
||||||
|
// 拼接同一运单的货物类型
|
||||||
|
formatCargoTypes(row) {
|
||||||
|
const detailId = row.id;
|
||||||
|
const feeRows = this.detailFeeCache[detailId] || [];
|
||||||
|
|
||||||
|
// 如果没有缓存数据或只有一条,返回原始值
|
||||||
|
if (feeRows.length <= 1) {
|
||||||
|
return this.displayValue(row.cargoType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有货物类型并去重
|
||||||
|
const types = feeRows
|
||||||
|
.map(item => item.cargoType)
|
||||||
|
.filter(type => type && String(type).trim())
|
||||||
|
.filter((type, index, arr) => arr.indexOf(type) === index);
|
||||||
|
|
||||||
|
return types.length > 0 ? types.join('、') : this.displayValue(row.cargoType);
|
||||||
|
},
|
||||||
|
// 格式化运输单价,如果多个货物的单价不一样则显示'-'
|
||||||
|
formatUnitPrice(row) {
|
||||||
|
const detailId = row.id;
|
||||||
|
const feeRows = this.detailFeeCache[detailId] || [];
|
||||||
|
|
||||||
|
// 如果没有缓存数据或只有一条,返回原始值
|
||||||
|
if (feeRows.length <= 1) {
|
||||||
|
return this.formatMoney(row.unitPrice, row.currency || this.form.currency);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查所有货物的运输单价是否一致
|
||||||
|
const prices = feeRows
|
||||||
|
.map(item => Number(item.unitPrice || 0))
|
||||||
|
.filter((price, index, arr) => arr.indexOf(price) === index);
|
||||||
|
|
||||||
|
// 如果单价不一致,返回'-'
|
||||||
|
if (prices.length > 1) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单价一致,返回该单价
|
||||||
|
return this.formatMoney(prices[0], row.currency || this.form.currency);
|
||||||
|
},
|
||||||
displayValue(value) {
|
displayValue(value) {
|
||||||
return value === undefined || value === null || value === '' ? '-' : value;
|
return value === undefined || value === null || value === '' ? '-' : value;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -523,23 +523,62 @@
|
|||||||
<el-button type="primary" plain @click="openFeeAdjustment('补款')">补款</el-button>
|
<el-button type="primary" plain @click="openFeeAdjustment('补款')">补款</el-button>
|
||||||
<el-button type="primary" plain @click="openFeeAdjustment('扣款')">扣款</el-button>
|
<el-button type="primary" plain @click="openFeeAdjustment('扣款')">扣款</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="completionSummaryRows" border>
|
<el-table
|
||||||
|
:data="completionSummaryRows"
|
||||||
|
border
|
||||||
|
show-summary
|
||||||
|
:summary-method="getCompletionSummarySums"
|
||||||
|
>
|
||||||
<el-table-column type="index" label="序号" width="72" align="center" />
|
<el-table-column type="index" label="序号" width="72" align="center" />
|
||||||
<el-table-column prop="name" label="费用项目" min-width="150" align="center" />
|
<el-table-column prop="name" label="费用项目" min-width="150" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="{ 'completion-dialog__negative': row._feeKind === '扣款' }">{{ row.name }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="原金额(元)" min-width="160" align="right">
|
<el-table-column label="原金额(元)" min-width="160" align="right">
|
||||||
<template #default="{ row }">{{ formatCompletionMoney(row.originalAmount) }}</template>
|
<template #default="{ row }">{{ formatCompletionMoney(row.originalAmount) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="调整金额(元)" min-width="160" align="right">
|
<el-table-column label="调整金额(元)" min-width="160" align="right">
|
||||||
<template #default="{ row }"
|
<template #default="{ row }">
|
||||||
><span :class="{ 'completion-dialog__negative': row.adjustAmount < 0 }">{{
|
<el-input-number
|
||||||
|
v-if="editable && row.manualFlag === 1"
|
||||||
|
v-model="row.adjustAmount"
|
||||||
|
:class="{ 'completion-dialog__negative-input': row._feeKind === '扣款' }"
|
||||||
|
:precision="2"
|
||||||
|
:step="0.01"
|
||||||
|
:controls="false"
|
||||||
|
:value-on-clear="0"
|
||||||
|
@change="recalculateCompletionFee(row)"
|
||||||
|
/>
|
||||||
|
<span v-else :class="{ 'completion-dialog__negative': Number(row.adjustAmount) < 0 }">{{
|
||||||
formatCompletionMoney(row.adjustAmount)
|
formatCompletionMoney(row.adjustAmount)
|
||||||
}}</span></template
|
}}</span>
|
||||||
>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="调整后金额(元)" min-width="180" align="right">
|
<el-table-column label="调整后金额(元)" min-width="180" align="right">
|
||||||
<template #default="{ row }">{{ formatCompletionMoney(row.afterAmount) }}</template>
|
<template #default="{ row }">
|
||||||
|
<span :class="{ 'completion-dialog__negative': Number(row.afterAmount) < 0 }">{{
|
||||||
|
formatCompletionMoney(row.afterAmount)
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="remark" label="备注" min-width="220">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-input
|
||||||
|
v-if="editable"
|
||||||
|
v-model="row.remark"
|
||||||
|
maxlength="200"
|
||||||
|
show-word-limit
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ displayValue(row.remark) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-if="editable" label="操作" width="90" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-link v-if="row.manualFlag === 1" type="danger" @click="removeCompletionFee(row)">删除</el-link>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="remark" label="备注" min-width="220" />
|
|
||||||
</el-table>
|
</el-table>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -565,6 +604,7 @@ import * as api from '@/api/settlement/transportReconciliation';
|
|||||||
import * as formalSettlementApi from '@/api/settlement/formalSettlement';
|
import * as formalSettlementApi from '@/api/settlement/formalSettlement';
|
||||||
import { getDictionary } from '@/api/system/dictbiz';
|
import { getDictionary } from '@/api/system/dictbiz';
|
||||||
import { Search } from '@element-plus/icons-vue';
|
import { Search } from '@element-plus/icons-vue';
|
||||||
|
import { h } from 'vue';
|
||||||
import { downloadXls } from '@/utils/util';
|
import { downloadXls } from '@/utils/util';
|
||||||
import { transportReconciliationFormFields } from '@/option/settlement/transportReconciliationForm';
|
import { transportReconciliationFormFields } from '@/option/settlement/transportReconciliationForm';
|
||||||
import {
|
import {
|
||||||
@@ -610,6 +650,7 @@ export default {
|
|||||||
adjustDialog: { visible: false, saving: false, rows: [], reason: '' },
|
adjustDialog: { visible: false, saving: false, rows: [], reason: '' },
|
||||||
manualMatchDialog: { visible: false, loading: false, row: null },
|
manualMatchDialog: { visible: false, loading: false, row: null },
|
||||||
completionDialog: { visible: false, loading: false },
|
completionDialog: { visible: false, loading: false },
|
||||||
|
completionSummaryRowsData: null,
|
||||||
externalEditing: {},
|
externalEditing: {},
|
||||||
externalEditSnapshots: {},
|
externalEditSnapshots: {},
|
||||||
matchingStarted: false,
|
matchingStarted: false,
|
||||||
@@ -728,9 +769,17 @@ export default {
|
|||||||
return [...names];
|
return [...names];
|
||||||
},
|
},
|
||||||
duplicateRows() {
|
duplicateRows() {
|
||||||
return this.externalDetails.filter(
|
const duplicateKeys = new Set();
|
||||||
row => row.suspectedDuplicate || row.matchStatus === 'suspected_duplicate'
|
const duplicateRows = [];
|
||||||
|
this.externalDetails.forEach(row => {
|
||||||
|
const key = this.externalDuplicateKey(row);
|
||||||
|
if (duplicateKeys.has(key)) duplicateRows.push(row);
|
||||||
|
else duplicateKeys.add(key);
|
||||||
|
});
|
||||||
|
const duplicateKeySet = new Set(
|
||||||
|
duplicateRows.map(row => this.externalDuplicateKey(row))
|
||||||
);
|
);
|
||||||
|
return this.externalDetails.filter(row => duplicateKeySet.has(this.externalDuplicateKey(row)));
|
||||||
},
|
},
|
||||||
canStartMatch() {
|
canStartMatch() {
|
||||||
return Boolean(this.form.formalSettlementId && this.externalDetails.length);
|
return Boolean(this.form.formalSettlementId && this.externalDetails.length);
|
||||||
@@ -767,6 +816,11 @@ export default {
|
|||||||
return this.form.reconciliationModeName || labels[this.form.reconciliationMode] || '-';
|
return this.form.reconciliationModeName || labels[this.form.reconciliationMode] || '-';
|
||||||
},
|
},
|
||||||
completionSummaryRows() {
|
completionSummaryRows() {
|
||||||
|
if (Array.isArray(this.completionSummaryRowsData)) return this.completionSummaryRowsData;
|
||||||
|
return this.buildCompletionSummaryRows;
|
||||||
|
},
|
||||||
|
|
||||||
|
buildCompletionSummaryRows() {
|
||||||
const source =
|
const source =
|
||||||
this.form.feeSummary ||
|
this.form.feeSummary ||
|
||||||
this.form.feeSummaries ||
|
this.form.feeSummaries ||
|
||||||
@@ -796,10 +850,14 @@ export default {
|
|||||||
: originalAmount;
|
: originalAmount;
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
|
feeType: '',
|
||||||
|
feeItem: name,
|
||||||
originalAmount,
|
originalAmount,
|
||||||
adjustAmount: afterAmount - originalAmount,
|
adjustAmount: afterAmount - originalAmount,
|
||||||
afterAmount,
|
afterAmount,
|
||||||
remark: '',
|
remark: '',
|
||||||
|
manualFlag: 0,
|
||||||
|
_feeKind: '',
|
||||||
_index: index,
|
_index: index,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -851,6 +909,7 @@ export default {
|
|||||||
this.externalDetails = [];
|
this.externalDetails = [];
|
||||||
this.externalEditing = {};
|
this.externalEditing = {};
|
||||||
this.externalEditSnapshots = {};
|
this.externalEditSnapshots = {};
|
||||||
|
this.completionSummaryRowsData = null;
|
||||||
this.matchingStarted = false;
|
this.matchingStarted = false;
|
||||||
this.externalTab = 'all';
|
this.externalTab = 'all';
|
||||||
this.internalQuery = { documentNo: '', vehicleNo: '', batchNo: '', cargoName: '' };
|
this.internalQuery = { documentNo: '', vehicleNo: '', batchNo: '', cargoName: '' };
|
||||||
@@ -880,6 +939,7 @@ export default {
|
|||||||
: data.payeeName) ||
|
: data.payeeName) ||
|
||||||
'',
|
'',
|
||||||
};
|
};
|
||||||
|
this.completionSummaryRowsData = null;
|
||||||
const internalRows = data.internalDetails || data.internalBillDetails || data.internals || [];
|
const internalRows = data.internalDetails || data.internalBillDetails || data.internals || [];
|
||||||
this.internalDetails = internalRows.map(row => this.normalizeInternalRow(row));
|
this.internalDetails = internalRows.map(row => this.normalizeInternalRow(row));
|
||||||
const externalRows = data.externalDetails || data.externalBillDetails || data.externals || [];
|
const externalRows = data.externalDetails || data.externalBillDetails || data.externals || [];
|
||||||
@@ -908,6 +968,52 @@ export default {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
externalDuplicateKey(row) {
|
||||||
|
const feeItems = row.feeItems || this.parseFeeItems(row.feeItemsJson);
|
||||||
|
const normalized = value => {
|
||||||
|
if (value === null || value === undefined || value === '') return '';
|
||||||
|
if (typeof value === 'number') return Number(value).toString();
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
return JSON.stringify(
|
||||||
|
Object.keys(value)
|
||||||
|
.sort()
|
||||||
|
.reduce((result, key) => {
|
||||||
|
result[key] = normalized(value[key]);
|
||||||
|
return result;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const text = String(value).trim().replace(/\s+/g, '').toLowerCase();
|
||||||
|
return /^-?\d+(\.\d+)?$/.test(text) ? Number(text).toString() : text;
|
||||||
|
};
|
||||||
|
const normalizeDate = value => {
|
||||||
|
if (!value) return '';
|
||||||
|
const date = this.$dayjs(value);
|
||||||
|
return date.isValid() ? date.format('YYYY-MM-DDTHH:mm:ss') : value;
|
||||||
|
};
|
||||||
|
return [
|
||||||
|
row.vehicleNo,
|
||||||
|
row.departureAddress,
|
||||||
|
row.arrivalAddress,
|
||||||
|
normalizeDate(row.actualDepartureTime),
|
||||||
|
normalizeDate(row.actualCompletionTime),
|
||||||
|
row.transportType,
|
||||||
|
row.cargoName,
|
||||||
|
row.cargoType,
|
||||||
|
row.specification,
|
||||||
|
row.model,
|
||||||
|
row.transportQuantity,
|
||||||
|
row.quantityUnit,
|
||||||
|
row.mileage,
|
||||||
|
row.batchNo,
|
||||||
|
row.unitPrice,
|
||||||
|
row.freightAmount,
|
||||||
|
feeItems,
|
||||||
|
row.settlementAmount,
|
||||||
|
]
|
||||||
|
.map(normalized)
|
||||||
|
.join('|');
|
||||||
|
},
|
||||||
normalizeInternalRow(row) {
|
normalizeInternalRow(row) {
|
||||||
const feeItems =
|
const feeItems =
|
||||||
row.feeItems && typeof row.feeItems === 'object' && Object.keys(row.feeItems).length
|
row.feeItems && typeof row.feeItems === 'object' && Object.keys(row.feeItems).length
|
||||||
@@ -1027,6 +1133,7 @@ export default {
|
|||||||
if (formalSettlementChanged) {
|
if (formalSettlementChanged) {
|
||||||
this.externalDetails = [];
|
this.externalDetails = [];
|
||||||
this.matchingStarted = false;
|
this.matchingStarted = false;
|
||||||
|
this.completionSummaryRowsData = null;
|
||||||
}
|
}
|
||||||
await this.loadFormalInternalPreview(selected.id);
|
await this.loadFormalInternalPreview(selected.id);
|
||||||
this.formalDialog.visible = false;
|
this.formalDialog.visible = false;
|
||||||
@@ -1174,6 +1281,7 @@ export default {
|
|||||||
this.externalDetails = (data.externalDetails || []).map((row, index) =>
|
this.externalDetails = (data.externalDetails || []).map((row, index) =>
|
||||||
this.normalizeExternalRow(row, index)
|
this.normalizeExternalRow(row, index)
|
||||||
);
|
);
|
||||||
|
this.completionSummaryRowsData = null;
|
||||||
this.matchingStarted = true;
|
this.matchingStarted = true;
|
||||||
this.$message.success('匹配完成');
|
this.$message.success('匹配完成');
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1206,10 +1314,22 @@ export default {
|
|||||||
) {
|
) {
|
||||||
return this.$message.warning('差异单数、差异货量和差异金额必须全部为0才可完成对账');
|
return this.$message.warning('差异单数、差异货量和差异金额必须全部为0才可完成对账');
|
||||||
}
|
}
|
||||||
|
this.completionSummaryRowsData = this.buildCompletionSummaryRows.map(row => ({ ...row }));
|
||||||
this.completionDialog.visible = true;
|
this.completionDialog.visible = true;
|
||||||
},
|
},
|
||||||
async confirmCompletion() {
|
async confirmCompletion() {
|
||||||
if (this.completionDialog.loading) return;
|
if (this.completionDialog.loading) return;
|
||||||
|
for (const row of this.completionSummaryRows) {
|
||||||
|
const adjustAmount = Number(row.adjustAmount || 0);
|
||||||
|
if (row.manualFlag === 1 && row._feeKind === '补款' && adjustAmount <= 0) {
|
||||||
|
return this.$message.warning('补款调整金额必须大于0');
|
||||||
|
}
|
||||||
|
if (row.manualFlag === 1 && row._feeKind === '扣款' && adjustAmount >= 0) {
|
||||||
|
return this.$message.warning('扣款调整金额必须小于0');
|
||||||
|
}
|
||||||
|
if (String(row.remark || '').length > 200) return this.$message.warning('备注不能超过200个字');
|
||||||
|
this.recalculateCompletionFee(row);
|
||||||
|
}
|
||||||
this.completionDialog.loading = true;
|
this.completionDialog.loading = true;
|
||||||
try {
|
try {
|
||||||
this.actionLoading = true;
|
this.actionLoading = true;
|
||||||
@@ -1220,6 +1340,16 @@ export default {
|
|||||||
remark: this.form.remark,
|
remark: this.form.remark,
|
||||||
internalDetails: this.serializeInternalRows(),
|
internalDetails: this.serializeInternalRows(),
|
||||||
externalDetails: this.serializeExternalRows(),
|
externalDetails: this.serializeExternalRows(),
|
||||||
|
feeSummary: this.completionSummaryRows.map(row => ({
|
||||||
|
id: row.id || undefined,
|
||||||
|
feeType: row.feeType,
|
||||||
|
feeItem: row.feeItem || row.name,
|
||||||
|
originalAmount: Number(row.originalAmount || 0),
|
||||||
|
adjustAmount: Number(row.adjustAmount || 0),
|
||||||
|
settlementAmount: Number(row.afterAmount || 0),
|
||||||
|
remark: row.remark || '',
|
||||||
|
manualFlag: Number(row.manualFlag || 0),
|
||||||
|
})),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
this.form = { ...this.form, ...data };
|
this.form = { ...this.form, ...data };
|
||||||
@@ -1237,7 +1367,55 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openFeeAdjustment(type) {
|
openFeeAdjustment(type) {
|
||||||
this.$message.info(`${type}请在结算明细调整中维护`);
|
if (!Array.isArray(this.completionSummaryRowsData)) {
|
||||||
|
this.completionSummaryRowsData = this.buildCompletionSummaryRows.map(row => ({ ...row }));
|
||||||
|
}
|
||||||
|
this.completionSummaryRowsData.push({
|
||||||
|
id: null,
|
||||||
|
name: type,
|
||||||
|
feeType: '其他费用',
|
||||||
|
feeItem: type,
|
||||||
|
originalAmount: 0,
|
||||||
|
adjustAmount: 0,
|
||||||
|
afterAmount: 0,
|
||||||
|
remark: '',
|
||||||
|
manualFlag: 1,
|
||||||
|
_feeKind: type,
|
||||||
|
_index: this.completionSummaryRowsData.length,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeCompletionFee(row) {
|
||||||
|
if (row.manualFlag !== 1 || !Array.isArray(this.completionSummaryRowsData)) return;
|
||||||
|
const index = this.completionSummaryRowsData.indexOf(row);
|
||||||
|
if (index >= 0) this.completionSummaryRowsData.splice(index, 1);
|
||||||
|
},
|
||||||
|
recalculateCompletionFee(row) {
|
||||||
|
row.originalAmount = row.manualFlag === 1 ? 0 : Number(row.originalAmount || 0);
|
||||||
|
row.afterAmount = Number(row.originalAmount || 0) + Number(row.adjustAmount || 0);
|
||||||
|
},
|
||||||
|
getCompletionSummarySums({ columns, data }) {
|
||||||
|
return columns.map((column, index) => {
|
||||||
|
if (index === 0) return '合计';
|
||||||
|
const amountPropertyByIndex = {
|
||||||
|
2: 'originalAmount',
|
||||||
|
3: 'adjustAmount',
|
||||||
|
4: 'afterAmount',
|
||||||
|
};
|
||||||
|
const property = column.property || amountPropertyByIndex[index];
|
||||||
|
if (property === 'originalAmount' || property === 'adjustAmount' || property === 'afterAmount') {
|
||||||
|
const total = data.reduce((sum, row) => {
|
||||||
|
const value = property === 'afterAmount' ? row.afterAmount : row[property];
|
||||||
|
return sum + Number(value || 0);
|
||||||
|
}, 0);
|
||||||
|
const text = this.formatCompletionMoney(total);
|
||||||
|
const negativeAmount =
|
||||||
|
(property === 'adjustAmount' || property === 'afterAmount') && total < 0;
|
||||||
|
return negativeAmount
|
||||||
|
? h('span', { class: 'completion-dialog__negative', style: { color: '#f56c6c' } }, text)
|
||||||
|
: text;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
},
|
},
|
||||||
sumFeeAmount(rows, name) {
|
sumFeeAmount(rows, name) {
|
||||||
return rows.reduce((sum, row) => {
|
return rows.reduce((sum, row) => {
|
||||||
@@ -1254,11 +1432,16 @@ export default {
|
|||||||
item.afterAmount ?? item.adjustedAmount ?? item.settlementAmount ?? item.totalAmount ?? originalAmount
|
item.afterAmount ?? item.adjustedAmount ?? item.settlementAmount ?? item.totalAmount ?? originalAmount
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
id: item.id,
|
||||||
|
feeType: item.feeType || '',
|
||||||
|
feeItem: item.feeItem || item.name || item.feeItemName || '',
|
||||||
name: item.name || item.feeItem || item.feeItemName || `费用${index + 1}`,
|
name: item.name || item.feeItem || item.feeItemName || `费用${index + 1}`,
|
||||||
originalAmount,
|
originalAmount,
|
||||||
adjustAmount: Number(item.adjustAmount ?? item.adjustmentAmount ?? afterAmount - originalAmount),
|
adjustAmount: Number(item.adjustAmount ?? item.adjustmentAmount ?? afterAmount - originalAmount),
|
||||||
afterAmount,
|
afterAmount,
|
||||||
remark: item.remark || item.adjustRemark || '',
|
remark: item.remark || item.adjustRemark || '',
|
||||||
|
manualFlag: Number(item.manualFlag || 0),
|
||||||
|
_feeKind: item.feeItem === '补款' || item.feeItem === '扣款' ? item.feeItem : '',
|
||||||
_index: index,
|
_index: index,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -1781,6 +1964,9 @@ export default {
|
|||||||
.completion-dialog__negative {
|
.completion-dialog__negative {
|
||||||
color: #f56c6c;
|
color: #f56c6c;
|
||||||
}
|
}
|
||||||
|
.completion-dialog__negative-input :deep(input) {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
.completion-dialog__footer {
|
.completion-dialog__footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user