Merge remote-tracking branch 'refs/remotes/origin/master' into feature/bfi-api-rate

# Conflicts:
#	pnpm-lock.yaml
#	src/axios.js
#	src/views/settlement/formal-settlement.vue
#	src/views/vehicle/customer-archive.vue
This commit is contained in:
刘泉佳
2026-10-01 13:46:44 +08:00
139 changed files with 10731 additions and 2593 deletions
@@ -136,6 +136,7 @@ export default {
syncLoading: { type: Boolean, default: false },
page: { type: Object, required: true },
hasPermission: { type: Function, required: true },
mkEnabled: { type: Boolean, default: false },
},
emits: [
'create',
@@ -195,7 +196,10 @@ export default {
actions.push({ type: 'delete', label: '删除', danger: true });
if (this.hasPermission('formal_settlement_submit') && this.isEditable(row))
actions.push({ type: 'submit', label: '提交' });
if (this.hasPermission('formal_settlement_approve') && row.approvalStatus === 'reviewing') {
if (this.mkEnabled && this.hasPermission('formal_settlement_approve') && row.approvalStatus === 'reviewing') {
actions.push({ type: 'mkAudit', label: '流程' });
}
if (!this.mkEnabled && this.hasPermission('formal_settlement_approve') && row.approvalStatus === 'reviewing') {
actions.push({ type: 'approve', label: '通过' });
actions.push({ type: 'return', label: '驳回', danger: true });
}
@@ -966,6 +966,7 @@ import {
import { downloadFileByUrl } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import * as XLSX from 'xlsx';
import { isAdministrator } from '@/utils/auth';
export default {
name: 'PreSettlementEditor',
@@ -1164,10 +1165,7 @@ export default {
return !this.readonly && ['draft', 'returned'].includes(this.form.approvalStatus);
},
isAdmin() {
const authority = this.userInfo?.authority;
return Array.isArray(authority)
? authority.includes('admin')
: String(authority || '').includes('admin');
return isAdministrator(this.userInfo);
},
canAdjustDetail() {
return this.editable && this.hasPermission('pre_settlement_adjust');
@@ -1611,12 +1609,13 @@ export default {
await this.loadDetail();
await this.persistPendingAdjustments();
if (shouldSubmit) {
const previousApprovalStatus = this.form.approvalStatus || '';
await submit({ id: this.form.id });
await submitMkApprovalFlow({
bizType: 'pre-settlement',
formInstanceId: this.form.id,
bizId: this.form.id,
subjectName: this.form.preSettlementNo || this.form.contractName || '',
approvalStatus: this.form.approvalStatus || '',
approvalStatus: previousApprovalStatus,
});
this.$message.success('审批流程已发起');
this.visible = false;
@@ -127,6 +127,13 @@
</div>
<el-button @click="resetInternalQuery">重置</el-button>
<el-button type="primary" @click="internalFilterTick++">查询</el-button>
<el-button
type="primary"
plain
:disabled="!filteredInternalRows.length"
@click="exportInternalDetails"
>导出</el-button
>
</div>
<el-table
:data="filteredInternalRows"
@@ -616,6 +623,7 @@
<script>
import { mapGetters } from 'vuex';
import * as XLSX from 'xlsx';
import * as api from '@/api/settlement/transportReconciliation';
import * as formalSettlementApi from '@/api/settlement/formalSettlement';
import { getDictionary } from '@/api/system/dictbiz';
@@ -1807,6 +1815,63 @@ export default {
formatNumber(value) {
return Number(value || 0).toFixed(2);
},
formatExportMoney(value) {
if (value === null || value === undefined || value === '' || Number(value) === -1) {
return '';
}
return Number(value || 0).toFixed(2);
},
formatInternalExportCell(row, column) {
if (column.prop === 'matchResult') return this.matchName(row.matchResult);
if (column.prop === 'updateResult') return this.updateName(row.updateResult);
if (column.prop === 'matchedExternalLineNo') {
return this.hasMatchedExternal(row)
? this.formatMatchedExternalLineNo(row.matchedExternalLineNo)
: '';
}
if (column.prop === 'transportType') return this.transportTypeLabel(row.transportType);
if (column.prop === 'transportQuantity') {
return row.transportQuantity === null ||
row.transportQuantity === undefined ||
row.transportQuantity === ''
? ''
: Number(row.transportQuantity || 0).toFixed(2);
}
if (column.feeItemName) {
return this.formatExportMoney(this.getFeeItemAmount(row, column.feeItemName));
}
if (column.prop === 'mileage') {
return Number(row.mileage) === -1 ? '' : this.formatExportMoney(row.mileage);
}
if (column.prop === 'actualDepartureTime' || column.prop === 'actualCompletionTime') {
const text = this.formatDate(row[column.prop]);
return text === '-' ? '' : text;
}
if (column.money || column.number) return this.formatExportMoney(row[column.prop]);
const value = row[column.prop];
return value === null || value === undefined || value === '' ? '' : value;
},
exportInternalDetails() {
if (!this.filteredInternalRows.length) {
this.$message.warning('暂无可导出的内部账单明细');
return;
}
const rows = this.filteredInternalRows.map((row, index) => {
const result = { 序号: index + 1 };
this.internalTableColumns.forEach(column => {
result[column.label] = this.formatInternalExportCell(row, column);
});
return result;
});
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet(rows), '内部账单明细');
XLSX.writeFile(
workbook,
`${this.form.reconciliationNo || '运输对账'}内部账单明细${this.$dayjs().format(
'YYYY-MM-DD HH-mm-ss'
)}.xlsx`
);
},
},
};
</script>
+34 -3
View File
@@ -65,6 +65,7 @@
:page="page"
:has-permission="hasPermissionFn"
:sync-loading="syncLoading"
:mk-enabled="mkEnabled"
@create="openCreate"
@payment="openPaymentDialog"
@sync="handleSync"
@@ -84,6 +85,7 @@
:page="page"
:has-permission="hasPermissionFn"
:sync-loading="syncLoading"
:mk-enabled="mkEnabled"
@create="openCreate"
@payment="openPaymentDialog"
@sync="handleSync"
@@ -184,7 +186,8 @@ import organizationSearch from '@/mixins/organization-search';
import { formalSettlementTableColumns } from '@/option/settlement/formalSettlementTable';
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
import FormalSettlementTablePanel from './components/formal-settlement-table-panel.vue';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { submitMkApprovalFlow, loadMkEnabled } from '@/utils/mk-approval';
import { getMKApprovalUrl } from '@/api/system/business-process';
const emptyQuery = () => ({
formalSettlementNo: '',
@@ -227,6 +230,7 @@ export default {
rows: [],
form: { appliedAmount: 0, remark: '' },
},
mkEnabled: false,
};
},
computed: {
@@ -250,6 +254,13 @@ export default {
this.loadOrganizationOptions();
this.loadTable();
this.openRouteDetail();
loadMkEnabled()
.then(enabled => {
this.mkEnabled = !!enabled;
})
.catch(() => {
this.mkEnabled = false;
});
},
methods: {
hasPermission(code) {
@@ -293,6 +304,7 @@ export default {
edit: () => this.openEdit(row),
delete: () => this.handleDelete(row),
submit: () => this.handleSubmit(row),
mkAudit: () => this.handleMkAudit(row),
approve: () => this.handleApprove(row),
return: () => this.handleReturn(row),
void: () => this.handleVoid(row),
@@ -340,16 +352,35 @@ export default {
},
async handleSubmit(row) {
await this.$confirm('提交后来源预结算将保持锁定,确认提交?', '提示', { type: 'warning' });
const previousApprovalStatus = row.approvalStatus || '';
await api.submit({ id: row.id });
await submitMkApprovalFlow({
bizType: 'formal-settlement',
formInstanceId: row.id,
bizId: row.id,
subjectName: row.formalSettlementNo || '',
approvalStatus: row.approvalStatus || '',
approvalStatus: previousApprovalStatus,
});
this.$message.success('提交成功');
this.loadTable();
},
handleMkAudit(row) {
if (!row?.id) {
this.$message.warning('正式结算单ID为空,无法打开审核页');
return;
}
getMKApprovalUrl({ bizId: String(row.id) })
.then(res => {
const url = res?.data?.data;
if (!url) {
this.$message.error('获取审核跳转地址失败');
return;
}
window.open(url, '_blank');
})
.catch(() => {
this.$message.error('获取审核跳转地址失败');
});
},
async handleApprove(row) {
await this.$confirm(
'审核通过后正式结算生效,金额只能通过结算调整单处理,确认通过?',
+68 -32
View File
@@ -172,21 +172,43 @@
删除
</el-link>
<el-link
v-if="hasPermission('pre_settlement_view') && row.approvalStatus !== 'draft'"
v-if="
hasPermission('pre_settlement_submit') &&
['draft', 'returned'].includes(row.approvalStatus)
"
type="primary"
@click="openFlow(row)"
@click="handleSubmit(row)"
>
提交
</el-link>
<el-link
v-if="
mkEnabled &&
hasPermission('pre_settlement_approve') &&
row.approvalStatus === 'reviewing'
"
type="primary"
@click="handleMkAudit(row)"
>
流程
</el-link>
<el-link
v-if="hasPermission('pre_settlement_approve') && row.approvalStatus === 'reviewing'"
v-if="
!mkEnabled &&
hasPermission('pre_settlement_approve') &&
row.approvalStatus === 'reviewing'
"
type="primary"
@click="handleApprove(row)"
>
通过
</el-link>
<el-link
v-if="hasPermission('pre_settlement_approve') && row.approvalStatus === 'reviewing'"
v-if="
!mkEnabled &&
hasPermission('pre_settlement_approve') &&
row.approvalStatus === 'reviewing'
"
type="danger"
@click="handleReturn(row)"
>
@@ -259,23 +281,6 @@
</el-button>
</template>
</el-dialog>
<el-dialog v-model="flowDialog.visible" title="审批流程" width="620px" append-to-body>
<el-descriptions :column="1" border>
<el-descriptions-item label="预结算单号">
{{ flowDialog.row.preSettlementNo || '-' }}
</el-descriptions-item>
<el-descriptions-item label="审核状态">
{{ flowDialog.row.approvalStatusName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="当前节点">
{{ flowDialog.row.currentNode || '-' }}
</el-descriptions-item>
<el-descriptions-item label="当前处理人">
{{ flowDialog.row.currentProcessor || '-' }}
</el-descriptions-item>
</el-descriptions>
</el-dialog>
</basic-container>
</template>
@@ -290,6 +295,7 @@ import {
getPrintTemplates,
remove,
returnBill,
submit,
voidBill,
} from '@/api/settlement/preSettlement';
import { preSettlementSearchFields } from '@/option/settlement/preSettlementSearch';
@@ -297,7 +303,10 @@ import organizationSearch from '@/mixins/organization-search';
import { preSettlementTableColumns } from '@/option/settlement/preSettlementTable';
import { createSettlementTransfer } from '@/utils/settlement-transfer';
import { downloadFile } from '@/utils/util';
import { getMKApprovalUrl } from '@/api/system/business-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
import PreSettlementEditor from './components/pre-settlement-editor.vue';
import { isAdministrator } from '@/utils/auth';
const emptyQuery = () => ({
preSettlementNo: '',
@@ -345,19 +354,13 @@ export default {
templates: [],
template: '',
},
flowDialog: {
visible: false,
row: {},
},
mkEnabled: false,
};
},
computed: {
...mapGetters(['permission', 'userInfo']),
isAdmin() {
const authority = this.userInfo?.authority;
return Array.isArray(authority)
? authority.includes('admin')
: String(authority || '').includes('admin');
return isAdministrator(this.userInfo);
},
visibleSearchFields() {
return this.searchExpanded ? this.searchFields : this.searchFields.slice(0, 4);
@@ -372,6 +375,13 @@ export default {
this.loadOrganizationOptions();
this.loadTable();
this.openRouteDetail();
loadMkEnabled()
.then(enabled => {
this.mkEnabled = !!enabled;
})
.catch(() => {
this.mkEnabled = false;
});
},
methods: {
hasPermission(code) {
@@ -628,9 +638,35 @@ export default {
const { data } = await exportList(params);
downloadFile(data, `预结算单${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
},
openFlow(row) {
this.flowDialog.row = row;
this.flowDialog.visible = true;
async handleSubmit(row) {
const previousApprovalStatus = row.approvalStatus || '';
await submit({ id: row.id });
await submitMkApprovalFlow({
bizType: 'pre-settlement',
bizId: row.id,
subjectName: row.preSettlementNo || '',
approvalStatus: previousApprovalStatus,
});
this.$message.success('提交成功');
this.loadTable();
},
handleMkAudit(row) {
if (!row?.id) {
this.$message.warning('预结算单ID为空,无法打开审核页');
return;
}
getMKApprovalUrl({ bizId: String(row.id) })
.then(res => {
const url = res?.data?.data;
if (!url) {
this.$message.error('获取审核跳转地址失败');
return;
}
window.open(url, '_blank');
})
.catch(() => {
this.$message.error('获取审核跳转地址失败');
});
},
async handleApprove(row) {
await this.$confirm('确认审批通过该预结算单?', '提示', { type: 'warning' });
@@ -172,6 +172,7 @@ import { settlementAdjustmentSearchFields } from '@/option/settlement/settlement
import organizationSearch from '@/mixins/organization-search';
import { settlementAdjustmentTableColumns } from '@/option/settlement/settlementAdjustmentTable';
import SettlementAdjustmentEditor from './components/settlement-adjustment-editor.vue';
import { isAdministrator } from '@/utils/auth';
const emptyQuery = () => ({
adjustmentNo: '',
@@ -207,7 +208,7 @@ export default {
return this.searchExpanded ? this.searchFields : this.searchFields.slice(0, 4);
},
isAdmin() {
return String(this.userInfo?.authority || '').includes('admin');
return isAdministrator(this.userInfo);
},
},
created() {