Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 884de893db | |||
| cc73d544ff | |||
| 10fecb5a54 | |||
| a554ccf38e | |||
| a748e52551 | |||
| e89e78b527 | |||
| 2a03991297 | |||
| 58aaf79445 | |||
| f067518c0e | |||
| 11460f3378 | |||
| 7f543937fb |
@@ -1,5 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
|
pnpm-lock.yaml
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
/tests/e2e/videos/
|
/tests/e2e/videos/
|
||||||
|
|||||||
+5
-2
@@ -6,7 +6,8 @@
|
|||||||
"prod": "vite --mode production",
|
"prod": "vite --mode production",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"build:prod": "vite build --mode production",
|
"build:prod": "vite build --mode production",
|
||||||
"serve": "vite preview --host"
|
"serve": "vite preview --host",
|
||||||
|
"typecheck": "vue-tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
@@ -46,9 +47,11 @@
|
|||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"sass": "^1.85.1",
|
"sass": "^1.85.1",
|
||||||
"terser": "^5.31.1",
|
"terser": "^5.31.1",
|
||||||
|
"typescript": "^7.0.2",
|
||||||
"unplugin-auto-import": "^0.11.2",
|
"unplugin-auto-import": "^0.11.2",
|
||||||
"vite": "^5.4.19",
|
"vite": "^5.4.19",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-vue-setup-extend": "^0.4.0"
|
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||||
|
"vue-tsc": "^3.3.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
-4259
File diff suppressed because it is too large
Load Diff
@@ -58,3 +58,14 @@ export const changeStatus = (id, status) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBfiExchangeRate = (currencyCode, effectdate) => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-transport/bfi/exchange-rate',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
currencyCode,
|
||||||
|
effectdate,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const baseUrl = '/blade-transport/invoice-receipt';
|
|||||||
export const getList = (current, size, params) =>
|
export const getList = (current, size, params) =>
|
||||||
request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } });
|
request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } });
|
||||||
export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
|
export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
|
||||||
export const getInvoicePool = keyword =>
|
export const queryInvoicePool = params =>
|
||||||
request({ url: `${baseUrl}/invoice-pool`, method: 'get', params: { keyword } });
|
request({ url: `${baseUrl}/invoice-pool`, method: 'get', params });
|
||||||
export const getSettlementCandidates = (keyword, receiptId) =>
|
export const getSettlementCandidates = (keyword, receiptId) =>
|
||||||
request({
|
request({
|
||||||
url: `${baseUrl}/settlement-candidates`,
|
url: `${baseUrl}/settlement-candidates`,
|
||||||
@@ -27,6 +27,8 @@ export const returnBill = data => request({ url: `${baseUrl}/return`, method: 'p
|
|||||||
export const voidBill = data => request({ url: `${baseUrl}/void`, method: 'post', data });
|
export const voidBill = data => request({ url: `${baseUrl}/void`, method: 'post', data });
|
||||||
export const syncKingdee = id =>
|
export const syncKingdee = id =>
|
||||||
request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } });
|
request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } });
|
||||||
|
export const pushKingdee = ids =>
|
||||||
|
request({ url: `${baseUrl}/push-kingdee`, method: 'post', data: ids });
|
||||||
|
|
||||||
export const approvalStatusOptions = [
|
export const approvalStatusOptions = [
|
||||||
{ label: '草稿', value: 'draft' },
|
{ label: '草稿', value: 'draft' },
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export const syncKingdee = id =>
|
|||||||
request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } });
|
request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } });
|
||||||
export const syncKingdeeBatch = ids =>
|
export const syncKingdeeBatch = ids =>
|
||||||
request({ url: `${baseUrl}/sync-kingdee-batch`, method: 'post', data: ids });
|
request({ url: `${baseUrl}/sync-kingdee-batch`, method: 'post', data: ids });
|
||||||
|
export const syncKingdeeResult = () =>
|
||||||
|
request({ url: `${baseUrl}/sync-kingdee-result`, method: 'post' });
|
||||||
|
|
||||||
export const paymentTypeOptions = [
|
export const paymentTypeOptions = [
|
||||||
{ label: '项目预付', value: 'project_advance' },
|
{ label: '项目预付', value: 'project_advance' },
|
||||||
@@ -36,5 +38,8 @@ export const approvalStatusOptions = [
|
|||||||
export const kingdeeStatusOptions = [
|
export const kingdeeStatusOptions = [
|
||||||
{ label: '未生成', value: 'unsynced' },
|
{ label: '未生成', value: 'unsynced' },
|
||||||
{ label: '已生成', value: 'synced' },
|
{ label: '已生成', value: 'synced' },
|
||||||
|
{ label: '付款中', value: 'paying' },
|
||||||
|
{ label: '已付款', value: 'paid' },
|
||||||
|
{ label: '已关闭', value: 'closed' },
|
||||||
{ label: '生成失败', value: 'failed' },
|
{ label: '生成失败', value: 'failed' },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -48,3 +48,5 @@ export const applyPayments = data =>
|
|||||||
request({ url: `${baseUrl}/apply-payments`, method: 'post', data });
|
request({ url: `${baseUrl}/apply-payments`, method: 'post', data });
|
||||||
export const claimInvoices = data =>
|
export const claimInvoices = data =>
|
||||||
request({ url: `${baseUrl}/claim-invoices`, method: 'post', data });
|
request({ url: `${baseUrl}/claim-invoices`, method: 'post', data });
|
||||||
|
export const queryInvoicePool = params =>
|
||||||
|
request({ url: `${baseUrl}/invoice-pool`, method: 'get', params });
|
||||||
|
|||||||
@@ -113,6 +113,26 @@ export const getScoreTemplate = quantificationId => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const queryKingdeeCustomer = creditCode => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-transport/bfi/customer/query-by-credit-code',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
creditCode,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const syncKingdee = id => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-transport/customer-archive/sync-kingdee',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const recognizeBusinessLicenseOcr = imageUrl => {
|
export const recognizeBusinessLicenseOcr = imageUrl => {
|
||||||
return request({
|
return request({
|
||||||
url: '/blade-transport/baidu-ocr/recognize-url',
|
url: '/blade-transport/baidu-ocr/recognize-url',
|
||||||
|
|||||||
@@ -223,6 +223,14 @@ axios.interceptors.response.use(
|
|||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
|
// 网络级失败(HTTP 状态 >500、网关错误、超时、断网等 validateStatus 放行之外的响应)
|
||||||
|
// 原为静默 reject,接口报错页面无任何感知;统一补错误提示,取消请求与刷新令牌请求除外
|
||||||
|
if (!axios.isCancel(error) && !isRefreshTokenRequest(error?.config)) {
|
||||||
|
ElMessage({
|
||||||
|
message: error?.response?.data?.msg || '请求失败,请稍后重试',
|
||||||
|
type: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
return Promise.reject(new Error(error));
|
return Promise.reject(new Error(error));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,296 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="visible" :title="title" width="92%" append-to-body destroy-on-close @open="handleOpen">
|
||||||
|
<el-form :model="query" inline label-width="90px" @submit.prevent>
|
||||||
|
<el-form-item label="发票号码">
|
||||||
|
<el-input v-model="query.invoiceNo" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开票日期">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="query.invoiceDateRange"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="销方税号">
|
||||||
|
<el-input
|
||||||
|
v-model="query.salerTaxNo"
|
||||||
|
clearable
|
||||||
|
style="width: 180px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="购方税号">
|
||||||
|
<el-input
|
||||||
|
v-model="query.buyerTaxNo"
|
||||||
|
clearable
|
||||||
|
style="width: 180px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="发票类型">
|
||||||
|
<el-select
|
||||||
|
v-model="query.invoiceType"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="不限"
|
||||||
|
style="width: 230px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in invoiceTypeOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="单据使用状态">
|
||||||
|
<el-select v-model="query.expenseStatus" clearable placeholder="不限" style="width: 130px">
|
||||||
|
<el-option
|
||||||
|
v-for="option in expenseStatusOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button :disabled="loading" @click="resetQuery">重置</el-button>
|
||||||
|
<el-button type="primary" :disabled="loading" @click="handleQuery">查询</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-table
|
||||||
|
ref="poolTable"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="rows"
|
||||||
|
:row-key="rowKey"
|
||||||
|
border
|
||||||
|
height="520"
|
||||||
|
:highlight-current-row="!multiple"
|
||||||
|
@selection-change="selection => (selected = selection)"
|
||||||
|
@row-dblclick="handleRowDblclick"
|
||||||
|
>
|
||||||
|
<el-table-column v-if="multiple" type="selection" width="52" fixed="left" align="center" reserve-selection />
|
||||||
|
<el-table-column v-else width="52" align="center" fixed="left">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-radio
|
||||||
|
:model-value="current && current.invoiceNo"
|
||||||
|
:value="row.invoiceNo"
|
||||||
|
@change="current = row"
|
||||||
|
>
|
||||||
|
<span></span>
|
||||||
|
</el-radio>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="invoiceNo" label="发票号码" min-width="180" />
|
||||||
|
<el-table-column prop="invoiceDate" label="开票日期" min-width="120" />
|
||||||
|
<el-table-column prop="invoiceType" label="发票类型" min-width="140" />
|
||||||
|
<el-table-column prop="issuerName" label="开票单位" min-width="180" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="receiverName" label="受票单位" min-width="180" show-overflow-tooltip />
|
||||||
|
<el-table-column label="金额(含税)" min-width="130" align="right">
|
||||||
|
<template #default="{ row }">{{ formatMoney(row.invoiceAmount) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="税率" min-width="90" align="center">
|
||||||
|
<template #default="{ row }">{{ formatRate(row.taxRate) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="税额" min-width="120" align="right">
|
||||||
|
<template #default="{ row }">{{ formatMoney(row.taxAmount) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="kingdeeBillNo" label="金蝶单据号" min-width="210" show-overflow-tooltip />
|
||||||
|
<el-table-column label="认领状态" min-width="100" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.claimed" type="danger" size="small">已认领</el-tag>
|
||||||
|
<el-tag v-else type="info" size="small">未认领</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="登记状态" min-width="100" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.registered" type="warning" size="small">已登记</el-tag>
|
||||||
|
<el-tag v-else type="info" size="small">未登记</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-if="!multiple" label="操作" width="90" fixed="right" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-link type="primary" @click.stop="confirmRows([row])">选择</el-link>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="kingdee-pool-dialog__pager">
|
||||||
|
<span class="kingdee-pool-dialog__pager-info">第 {{ page.current }} 页</span>
|
||||||
|
<el-button :disabled="page.current <= 1 || loading" @click="prevPage">上一页</el-button>
|
||||||
|
<el-button :disabled="!page.hasMore || loading" @click="nextPage">下一页</el-button>
|
||||||
|
<el-select v-model="page.size" style="width: 110px" @change="handleSizeChange">
|
||||||
|
<el-option v-for="n in [10, 20, 50, 100]" :key="n" :label="`${n}条/页`" :value="n" />
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirm">{{ confirmText }}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'KingdeeInvoicePoolDialog',
|
||||||
|
props: {
|
||||||
|
modelValue: { type: Boolean, required: true },
|
||||||
|
title: { type: String, default: '查询金蝶票据池' },
|
||||||
|
confirmText: { type: String, default: '确定' },
|
||||||
|
multiple: { type: Boolean, default: false },
|
||||||
|
initialInvoiceNo: { type: String, default: '' },
|
||||||
|
queryApi: { type: Function, required: true },
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue', 'confirm'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
// 与后端 BfiConstant.INVOICE_TYPE_NAMES 对齐:value 为发票类型编码,label 为中文名
|
||||||
|
// 选票场景只开放数电票(普票/专票)
|
||||||
|
invoiceTypeOptions: [
|
||||||
|
{ value: '26', label: '数电发票(普通发票)' },
|
||||||
|
{ value: '27', label: '数电发票(增值税专用发票)' },
|
||||||
|
],
|
||||||
|
expenseStatusOptions: [
|
||||||
|
{ value: '1', label: '未用' },
|
||||||
|
{ value: '30', label: '在用' },
|
||||||
|
{ value: '60', label: '已用' },
|
||||||
|
{ value: '65', label: '已入账' },
|
||||||
|
],
|
||||||
|
rows: [],
|
||||||
|
selected: [],
|
||||||
|
current: null,
|
||||||
|
page: { current: 1, size: 10, hasMore: false },
|
||||||
|
query: this.emptyQuery(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
visible: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
emptyQuery() {
|
||||||
|
return {
|
||||||
|
invoiceNo: '',
|
||||||
|
// 默认查近一个月,随请求传后端并在页面回显
|
||||||
|
invoiceDateRange: [this.$dayjs().subtract(1, 'month').format('YYYY-MM-DD'), this.$dayjs().format('YYYY-MM-DD')],
|
||||||
|
salerTaxNo: '',
|
||||||
|
buyerTaxNo: '',
|
||||||
|
invoiceType: '',
|
||||||
|
// 单据使用状态默认"未用"
|
||||||
|
expenseStatus: '1',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 远程实时查询的票未入本地镜像,id 恒空,用发票号码兜底作为行主键
|
||||||
|
rowKey(row) {
|
||||||
|
return row.invoiceNo || row.id;
|
||||||
|
},
|
||||||
|
handleOpen() {
|
||||||
|
this.query = this.emptyQuery();
|
||||||
|
this.query.invoiceNo = this.initialInvoiceNo || '';
|
||||||
|
this.current = null;
|
||||||
|
this.selected = [];
|
||||||
|
this.$refs.poolTable?.clearSelection();
|
||||||
|
this.page.current = 1;
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
this.page.current = 1;
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
handleSizeChange() {
|
||||||
|
this.page.current = 1;
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
prevPage() {
|
||||||
|
this.page.current -= 1;
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
nextPage() {
|
||||||
|
this.page.current += 1;
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
resetQuery() {
|
||||||
|
this.query = this.emptyQuery();
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
unwrap(response) {
|
||||||
|
const body = response?.data || response || {};
|
||||||
|
return body?.data || body;
|
||||||
|
},
|
||||||
|
async load() {
|
||||||
|
this.loading = true;
|
||||||
|
// 请求前快照页码:prev/next 会先改写 current,远程失败时回滚避免停留在错页
|
||||||
|
const lastRequested = this.page.current;
|
||||||
|
try {
|
||||||
|
const range = this.query.invoiceDateRange || [];
|
||||||
|
const data = this.unwrap(
|
||||||
|
await this.queryApi({
|
||||||
|
current: this.page.current,
|
||||||
|
size: this.page.size,
|
||||||
|
invoiceNo: this.query.invoiceNo || undefined,
|
||||||
|
invoiceDateStart: range[0] || undefined,
|
||||||
|
invoiceDateEnd: range[1] || undefined,
|
||||||
|
salerTaxNo: this.query.salerTaxNo || undefined,
|
||||||
|
buyerTaxNo: this.query.buyerTaxNo || undefined,
|
||||||
|
invoiceType: this.query.invoiceType || undefined,
|
||||||
|
expenseStatus: this.query.expenseStatus || undefined,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.rows = data.records || [];
|
||||||
|
this.page.hasMore = !!data.hasMore;
|
||||||
|
} catch (error) {
|
||||||
|
if (this.page.current !== lastRequested) {
|
||||||
|
this.page.current = lastRequested;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleRowDblclick(row) {
|
||||||
|
if (!this.multiple) {
|
||||||
|
this.confirmRows([row]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
const picked = this.multiple ? this.selected : this.current ? [this.current] : [];
|
||||||
|
this.confirmRows(picked);
|
||||||
|
},
|
||||||
|
confirmRows(rows) {
|
||||||
|
if (!rows.length) {
|
||||||
|
this.$message.warning(this.multiple ? '请至少选择一条发票' : '请选择一张发票');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('confirm', rows);
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
formatMoney(value) {
|
||||||
|
const number = Number(value);
|
||||||
|
return Number.isFinite(number) ? number.toFixed(2) : '-';
|
||||||
|
},
|
||||||
|
formatRate(value) {
|
||||||
|
const number = Number(value);
|
||||||
|
return Number.isFinite(number) ? `${number}%` : '-';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.kingdee-pool-dialog__pager {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -497,6 +497,7 @@ const emptyLine = () => ({
|
|||||||
localId: ++localId,
|
localId: ++localId,
|
||||||
goodsCategory: '',
|
goodsCategory: '',
|
||||||
goodsName: '',
|
goodsName: '',
|
||||||
|
taxClassificationCode: '',
|
||||||
unit: '吨',
|
unit: '吨',
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
unitPriceNoTax: 0,
|
unitPriceNoTax: 0,
|
||||||
@@ -724,9 +725,11 @@ export default {
|
|||||||
const item = this.findInvoiceItem(line);
|
const item = this.findInvoiceItem(line);
|
||||||
if (item) {
|
if (item) {
|
||||||
line.taxRate = Number(item.defaultTaxRate || 0);
|
line.taxRate = Number(item.defaultTaxRate || 0);
|
||||||
|
line.taxClassificationCode = item.taxClassificationCode || '';
|
||||||
} else if (clearInvalid) {
|
} else if (clearInvalid) {
|
||||||
line.goodsName = '';
|
line.goodsName = '';
|
||||||
line.taxRate = 0;
|
line.taxRate = 0;
|
||||||
|
line.taxClassificationCode = '';
|
||||||
}
|
}
|
||||||
this.recalculateLine(line);
|
this.recalculateLine(line);
|
||||||
},
|
},
|
||||||
@@ -734,6 +737,7 @@ export default {
|
|||||||
const names = this.invoiceItemNames(line.goodsCategory);
|
const names = this.invoiceItemNames(line.goodsCategory);
|
||||||
if (!names.some(item => item.shortName === line.goodsName)) line.goodsName = '';
|
if (!names.some(item => item.shortName === line.goodsName)) line.goodsName = '';
|
||||||
line.taxRate = 0;
|
line.taxRate = 0;
|
||||||
|
line.taxClassificationCode = this.findInvoiceItem(line)?.taxClassificationCode || '';
|
||||||
if (names.length === 1) {
|
if (names.length === 1) {
|
||||||
line.goodsName = names[0].shortName;
|
line.goodsName = names[0].shortName;
|
||||||
this.handleGoodsNameChange(line);
|
this.handleGoodsNameChange(line);
|
||||||
@@ -743,9 +747,11 @@ export default {
|
|||||||
const item = this.findInvoiceItem(line);
|
const item = this.findInvoiceItem(line);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
line.taxRate = 0;
|
line.taxRate = 0;
|
||||||
|
line.taxClassificationCode = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
line.taxRate = Number(item.defaultTaxRate || 0);
|
line.taxRate = Number(item.defaultTaxRate || 0);
|
||||||
|
line.taxClassificationCode = item.taxClassificationCode || '';
|
||||||
this.recalculateLine(line);
|
this.recalculateLine(line);
|
||||||
},
|
},
|
||||||
validateSettlements(rule, value, callback) {
|
validateSettlements(rule, value, callback) {
|
||||||
@@ -1141,6 +1147,7 @@ export default {
|
|||||||
lines: sheet.lines.map(line => ({
|
lines: sheet.lines.map(line => ({
|
||||||
goodsCategory: line.goodsCategory,
|
goodsCategory: line.goodsCategory,
|
||||||
goodsName: line.goodsName,
|
goodsName: line.goodsName,
|
||||||
|
taxClassificationCode: line.taxClassificationCode,
|
||||||
unit: line.unit,
|
unit: line.unit,
|
||||||
quantity: line.quantity,
|
quantity: line.quantity,
|
||||||
unitPriceNoTax: line.unitPriceNoTax,
|
unitPriceNoTax: line.unitPriceNoTax,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="开票金额">
|
<el-form-item label="开票金额">
|
||||||
<el-input
|
<el-input
|
||||||
:model-value="form.kingdeeInvoicePoolId ? formatMoney(form.invoiceAmount) : ''"
|
:model-value="form.invoiceNo ? formatMoney(form.invoiceAmount) : ''"
|
||||||
disabled
|
disabled
|
||||||
placeholder="从金蝶票据池带出"
|
placeholder="从金蝶票据池带出"
|
||||||
/>
|
/>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="税额">
|
<el-form-item label="税额">
|
||||||
<el-input
|
<el-input
|
||||||
:model-value="form.kingdeeInvoicePoolId ? formatMoney(form.taxAmount) : ''"
|
:model-value="form.invoiceNo ? formatMoney(form.taxAmount) : ''"
|
||||||
disabled
|
disabled
|
||||||
placeholder="从金蝶票据池带出"
|
placeholder="从金蝶票据池带出"
|
||||||
/>
|
/>
|
||||||
@@ -149,62 +149,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-dialog v-model="invoiceDialog.visible" title="查询金蝶票据池" width="86%" append-to-body>
|
<kingdee-invoice-pool-dialog
|
||||||
<div class="receipt-form-page__dialog-search">
|
v-model="invoiceDialog.visible"
|
||||||
<el-input
|
title="查询金蝶票据池"
|
||||||
v-model="invoiceDialog.keyword"
|
:initial-invoice-no="form.invoiceNo"
|
||||||
clearable
|
:query-api="apiQueryInvoicePool"
|
||||||
placeholder="发票号码、开票单位或受票单位"
|
@confirm="handleInvoicePicked"
|
||||||
@keyup.enter="loadInvoicePool"
|
/>
|
||||||
/>
|
|
||||||
<el-button type="primary" @click="loadInvoicePool">查询</el-button>
|
|
||||||
</div>
|
|
||||||
<el-table
|
|
||||||
v-loading="invoiceDialog.loading"
|
|
||||||
:data="invoiceDialog.rows"
|
|
||||||
border
|
|
||||||
empty-text="暂无票据数据"
|
|
||||||
highlight-current-row
|
|
||||||
@current-change="invoiceDialog.current = $event"
|
|
||||||
@row-dblclick="confirmInvoice"
|
|
||||||
>
|
|
||||||
<el-table-column prop="invoiceNo" label="发票号码" min-width="180" />
|
|
||||||
<el-table-column prop="invoiceDate" label="开票日期" min-width="120" />
|
|
||||||
<el-table-column prop="invoiceType" label="发票类型" min-width="130" />
|
|
||||||
<el-table-column prop="issuerName" label="开票单位" min-width="170" />
|
|
||||||
<el-table-column prop="receiverName" label="受票单位" min-width="170" />
|
|
||||||
<el-table-column label="开票金额" min-width="130" align="right">
|
|
||||||
<template #default="{ row }">{{ formatMoney(row.invoiceAmount) }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="税率" min-width="100" align="center">
|
|
||||||
<template #default="{ row }">{{ formatRate(row.taxRate) }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="税额" min-width="120" align="right">
|
|
||||||
<template #default="{ row }">{{ formatMoney(row.taxAmount) }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="kingdeeBillNo" label="金蝶单据号" min-width="150" />
|
|
||||||
<el-table-column label="操作" width="100" fixed="right" align="center">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-link type="primary" @click.stop="confirmInvoice(row)">选择</el-link>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div class="receipt-form-page__dialog-pagination">
|
|
||||||
<el-pagination
|
|
||||||
v-model:current-page="invoiceDialog.page.current"
|
|
||||||
v-model:page-size="invoiceDialog.page.size"
|
|
||||||
:total="invoiceDialog.page.total"
|
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
@current-change="refreshInvoicePoolPage"
|
|
||||||
@size-change="handleInvoicePoolSizeChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<el-button @click="invoiceDialog.visible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmInvoice()">确定</el-button>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="settlementDialog.visible"
|
v-model="settlementDialog.visible"
|
||||||
@@ -259,80 +210,11 @@
|
|||||||
import { Search } from '@element-plus/icons-vue';
|
import { Search } from '@element-plus/icons-vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import * as api from '@/api/payment/invoiceReceipt';
|
import * as api from '@/api/payment/invoiceReceipt';
|
||||||
import { getList as getCustomerList } from '@/api/vehicle/customer-archive';
|
import KingdeeInvoicePoolDialog from '@/components/kingdee-invoice-pool-dialog/main.vue';
|
||||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||||
|
|
||||||
const mockInvoiceTypes = ['增值税专用发票', '增值税普通发票'];
|
|
||||||
const mockTaxRates = [3, 6, 9, 13];
|
|
||||||
const mockBankNames = ['中国工商银行', '中国农业银行', '中国银行', '中国建设银行', '招商银行'];
|
|
||||||
|
|
||||||
const randomDigits = length =>
|
|
||||||
Array.from({ length }, () => Math.floor(Math.random() * 10)).join('');
|
|
||||||
|
|
||||||
const formatMockDate = date => {
|
|
||||||
const year = date.getFullYear();
|
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
||||||
const day = String(date.getDate()).padStart(2, '0');
|
|
||||||
return `${year}-${month}-${day}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const customerName = customer =>
|
|
||||||
customer.fullName || customer.shortName || customer.customerCode || `客商${customer.id}`;
|
|
||||||
|
|
||||||
const customerEmail = (customer, index) => {
|
|
||||||
const prefix = String(customer.customerCode || customer.id || `customer${index + 1}`)
|
|
||||||
.replace(/[^a-zA-Z0-9_-]/g, '')
|
|
||||||
.toLowerCase();
|
|
||||||
return `finance@${prefix || `customer${index + 1}`}.example.com`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createInvoicePoolMockRows = (customers, counterpartyName, departmentEmail) => {
|
|
||||||
const rows = [];
|
|
||||||
const baseId = Date.now();
|
|
||||||
customers.forEach((customer, customerIndex) => {
|
|
||||||
const name = customerName(customer);
|
|
||||||
['issuer', 'receiver'].forEach((role, roleIndex) => {
|
|
||||||
const count = 3 + Math.floor(Math.random() * 5);
|
|
||||||
for (let index = 0; index < count; index += 1) {
|
|
||||||
const rowIndex = rows.length;
|
|
||||||
const invoiceDateValue = new Date();
|
|
||||||
invoiceDateValue.setDate(invoiceDateValue.getDate() - Math.floor(Math.random() * 90));
|
|
||||||
const invoiceDate = formatMockDate(invoiceDateValue);
|
|
||||||
const taxRate = mockTaxRates[(customerIndex + roleIndex + index) % mockTaxRates.length];
|
|
||||||
const invoiceAmount = Math.floor(10000 + Math.random() * 190000);
|
|
||||||
const taxAmount = Number(
|
|
||||||
((invoiceAmount * Number(taxRate)) / (100 + Number(taxRate))).toFixed(2)
|
|
||||||
);
|
|
||||||
const bankName = mockBankNames[(customerIndex + index) % mockBankNames.length];
|
|
||||||
rows.push({
|
|
||||||
id: baseId + rowIndex,
|
|
||||||
invoiceNo: `25${randomDigits(18)}`,
|
|
||||||
invoiceDate,
|
|
||||||
invoiceType: mockInvoiceTypes[(customerIndex + index) % mockInvoiceTypes.length],
|
|
||||||
taxRate,
|
|
||||||
invoiceAmount,
|
|
||||||
taxAmount,
|
|
||||||
receiverName: role === 'receiver' ? name : counterpartyName,
|
|
||||||
issuerName: role === 'issuer' ? name : counterpartyName,
|
|
||||||
bankName,
|
|
||||||
bankAccount: randomDigits(19),
|
|
||||||
issuingBank: `${bankName}营业部`,
|
|
||||||
phone: customer.contactPhone || '',
|
|
||||||
customerEmails: customerEmail(customer, customerIndex),
|
|
||||||
departmentEmails: departmentEmail || '',
|
|
||||||
attachmentsJson: '[]',
|
|
||||||
kingdeeBillNo: `KD-FP-${invoiceDate.replaceAll('-', '')}${randomDigits(5)}`,
|
|
||||||
kingdeeStatus: 'unsynced',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return rows;
|
|
||||||
};
|
|
||||||
|
|
||||||
const emptyForm = () => ({
|
const emptyForm = () => ({
|
||||||
id: null,
|
id: null,
|
||||||
kingdeeInvoicePoolId: null,
|
|
||||||
invoiceNo: '',
|
invoiceNo: '',
|
||||||
invoiceDate: '',
|
invoiceDate: '',
|
||||||
invoiceType: '',
|
invoiceType: '',
|
||||||
@@ -361,24 +243,17 @@ const emptyForm = () => ({
|
|||||||
export default {
|
export default {
|
||||||
name: 'InvoiceReceiptForm',
|
name: 'InvoiceReceiptForm',
|
||||||
components: {
|
components: {
|
||||||
|
KingdeeInvoicePoolDialog,
|
||||||
VehicleAttachmentTable,
|
VehicleAttachmentTable,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
Search,
|
Search,
|
||||||
form: emptyForm(),
|
form: emptyForm(),
|
||||||
invoicePoolMockRows: [],
|
|
||||||
invoicePoolMockLoaded: false,
|
|
||||||
customerEmailOptions: [],
|
customerEmailOptions: [],
|
||||||
departmentEmailOptions: [],
|
departmentEmailOptions: [],
|
||||||
invoiceDialog: {
|
invoiceDialog: {
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
|
||||||
keyword: '',
|
|
||||||
sourceRows: [],
|
|
||||||
rows: [],
|
|
||||||
current: null,
|
|
||||||
page: { current: 1, size: 10, total: 0 },
|
|
||||||
},
|
},
|
||||||
settlementDialog: {
|
settlementDialog: {
|
||||||
visible: false,
|
visible: false,
|
||||||
@@ -421,6 +296,12 @@ export default {
|
|||||||
this.initialize();
|
this.initialize();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
apiQueryInvoicePool(params) {
|
||||||
|
return api.queryInvoicePool(params);
|
||||||
|
},
|
||||||
|
handleInvoicePicked(rows) {
|
||||||
|
this.confirmInvoice(rows[0]);
|
||||||
|
},
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.permission?.[code] !== false;
|
return this.permission?.[code] !== false;
|
||||||
},
|
},
|
||||||
@@ -466,7 +347,7 @@ export default {
|
|||||||
if (this.settlementIds.length) await this.loadReferenceInformation();
|
if (this.settlementIds.length) await this.loadReferenceInformation();
|
||||||
},
|
},
|
||||||
validateInvoice(rule, value, callback) {
|
validateInvoice(rule, value, callback) {
|
||||||
if (!value || !this.form.kingdeeInvoicePoolId) {
|
if (!value) {
|
||||||
callback(new Error('请选择金蝶票据池发票'));
|
callback(new Error('请选择金蝶票据池发票'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -492,99 +373,17 @@ export default {
|
|||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
async openInvoiceDialog() {
|
openInvoiceDialog() {
|
||||||
this.invoiceDialog.visible = true;
|
this.invoiceDialog.visible = true;
|
||||||
this.invoiceDialog.keyword = this.form.invoiceNo || '';
|
|
||||||
await this.loadInvoicePool();
|
|
||||||
},
|
|
||||||
async loadInvoicePool() {
|
|
||||||
this.invoiceDialog.loading = true;
|
|
||||||
this.invoiceDialog.page.current = 1;
|
|
||||||
this.invoiceDialog.current = null;
|
|
||||||
try {
|
|
||||||
if (!this.recordId) {
|
|
||||||
if (!this.invoicePoolMockLoaded) await this.loadInvoicePoolMockRows();
|
|
||||||
this.invoiceDialog.sourceRows = this.filterInvoicePoolMockRows(
|
|
||||||
this.invoiceDialog.keyword
|
|
||||||
);
|
|
||||||
this.refreshInvoicePoolPage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const data = this.unwrapData(await api.getInvoicePool(this.invoiceDialog.keyword));
|
|
||||||
this.invoiceDialog.sourceRows = Array.isArray(data) ? data : data?.records || [];
|
|
||||||
this.refreshInvoicePoolPage();
|
|
||||||
} finally {
|
|
||||||
this.invoiceDialog.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async loadInvoicePoolMockRows() {
|
|
||||||
const pageSize = 500;
|
|
||||||
const firstData = this.unwrapData(await getCustomerList(1, pageSize, {}));
|
|
||||||
const firstRows = Array.isArray(firstData) ? firstData : firstData?.records || [];
|
|
||||||
const total = Number(firstData?.total || firstRows.length);
|
|
||||||
const pageCount = Math.ceil(total / pageSize);
|
|
||||||
const remainingPages = await Promise.all(
|
|
||||||
Array.from({ length: Math.max(pageCount - 1, 0) }, (_, index) =>
|
|
||||||
getCustomerList(index + 2, pageSize, {})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const customers = [
|
|
||||||
...firstRows,
|
|
||||||
...remainingPages.flatMap(response => {
|
|
||||||
const data = this.unwrapData(response);
|
|
||||||
return Array.isArray(data) ? data : data?.records || [];
|
|
||||||
}),
|
|
||||||
].filter(
|
|
||||||
(customer, index, rows) =>
|
|
||||||
rows.findIndex(item => String(item.id) === String(customer.id)) === index
|
|
||||||
);
|
|
||||||
const userInfo = this.$store.getters.userInfo || {};
|
|
||||||
const counterpartyName = userInfo.deptName || userInfo.dept_name || '本企业';
|
|
||||||
this.invoicePoolMockRows = createInvoicePoolMockRows(
|
|
||||||
customers,
|
|
||||||
counterpartyName,
|
|
||||||
userInfo.email || ''
|
|
||||||
);
|
|
||||||
this.invoicePoolMockLoaded = true;
|
|
||||||
},
|
|
||||||
refreshInvoicePoolPage() {
|
|
||||||
const page = this.invoiceDialog.page;
|
|
||||||
const total = this.invoiceDialog.sourceRows.length;
|
|
||||||
const maxPage = Math.max(Math.ceil(total / page.size), 1);
|
|
||||||
if (page.current > maxPage) page.current = maxPage;
|
|
||||||
const start = (page.current - 1) * page.size;
|
|
||||||
page.total = total;
|
|
||||||
this.invoiceDialog.current = null;
|
|
||||||
this.invoiceDialog.rows = this.invoiceDialog.sourceRows.slice(start, start + page.size);
|
|
||||||
},
|
|
||||||
handleInvoicePoolSizeChange() {
|
|
||||||
this.invoiceDialog.page.current = 1;
|
|
||||||
this.refreshInvoicePoolPage();
|
|
||||||
},
|
|
||||||
filterInvoicePoolMockRows(keyword) {
|
|
||||||
const normalizedKeyword = String(keyword || '')
|
|
||||||
.trim()
|
|
||||||
.toLowerCase();
|
|
||||||
if (!normalizedKeyword) return this.invoicePoolMockRows.map(item => ({ ...item }));
|
|
||||||
return this.invoicePoolMockRows
|
|
||||||
.filter(item =>
|
|
||||||
[item.invoiceNo, item.issuerName, item.receiverName].some(value =>
|
|
||||||
String(value || '')
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(normalizedKeyword)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map(item => ({ ...item }));
|
|
||||||
},
|
},
|
||||||
confirmInvoice(row, options = {}) {
|
confirmInvoice(row, options = {}) {
|
||||||
const selected = row?.id ? row : this.invoiceDialog.current;
|
const selected = row;
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
this.$message.warning('请选择一张金蝶票据池发票');
|
this.$message.warning('请选择一张金蝶票据池发票');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const preserveUserInput = options.preserveUserInput === true;
|
const preserveUserInput = options.preserveUserInput === true;
|
||||||
Object.assign(this.form, {
|
Object.assign(this.form, {
|
||||||
kingdeeInvoicePoolId: selected.id,
|
|
||||||
invoiceNo: selected.invoiceNo,
|
invoiceNo: selected.invoiceNo,
|
||||||
invoiceDate: selected.invoiceDate,
|
invoiceDate: selected.invoiceDate,
|
||||||
invoiceType: selected.invoiceType,
|
invoiceType: selected.invoiceType,
|
||||||
@@ -708,7 +507,6 @@ export default {
|
|||||||
payload() {
|
payload() {
|
||||||
return {
|
return {
|
||||||
id: this.form.id,
|
id: this.form.id,
|
||||||
kingdeeInvoicePoolId: this.form.kingdeeInvoicePoolId,
|
|
||||||
invoiceNo: this.form.invoiceNo,
|
invoiceNo: this.form.invoiceNo,
|
||||||
invoiceDate: this.form.invoiceDate,
|
invoiceDate: this.form.invoiceDate,
|
||||||
invoiceType: this.form.invoiceType,
|
invoiceType: this.form.invoiceType,
|
||||||
@@ -758,13 +556,12 @@ export default {
|
|||||||
this.$message.warning('请先选择金蝶票据池发票');
|
this.$message.warning('请先选择金蝶票据池发票');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = this.recordId
|
const data = this.unwrapData(
|
||||||
? this.unwrapData(await api.getInvoicePool(this.form.invoiceNo))
|
await api.queryInvoicePool({ current: 1, size: 1, invoiceNo: this.form.invoiceNo })
|
||||||
: this.filterInvoicePoolMockRows(this.form.invoiceNo);
|
);
|
||||||
const rows = Array.isArray(data) ? data : data?.records || [];
|
const invoice = (data.records || []).find(item => item.invoiceNo === this.form.invoiceNo);
|
||||||
const invoice = rows.find(item => item.invoiceNo === this.form.invoiceNo);
|
|
||||||
if (!invoice) {
|
if (!invoice) {
|
||||||
this.$message.warning('金蝶票据池中未查询到该发票');
|
this.$message.warning('金蝶票池未查询到该发票');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.confirmInvoice(invoice, { preserveUserInput: true })) return;
|
if (!this.confirmInvoice(invoice, { preserveUserInput: true })) return;
|
||||||
@@ -827,11 +624,6 @@ export default {
|
|||||||
.receipt-form-page__dialog-search .el-input {
|
.receipt-form-page__dialog-search .el-input {
|
||||||
width: 360px;
|
width: 360px;
|
||||||
}
|
}
|
||||||
.receipt-form-page__dialog-pagination {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
.receipt-form-page :deep(.el-table) {
|
.receipt-form-page :deep(.el-table) {
|
||||||
--el-table-border-color: #eff1f7;
|
--el-table-border-color: #eff1f7;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,13 @@
|
|||||||
@click="handleBatchSync"
|
@click="handleBatchSync"
|
||||||
>批量同步</el-button
|
>批量同步</el-button
|
||||||
>
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="hasPermission('invoice_receipt_sync')"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
@click="handlePushKingdee"
|
||||||
|
>推送金蝶收票单</el-button
|
||||||
|
>
|
||||||
<el-button v-if="hasPermission('invoice_receipt_add')" type="primary" @click="openCreate"
|
<el-button v-if="hasPermission('invoice_receipt_add')" type="primary" @click="openCreate"
|
||||||
>新增</el-button
|
>新增</el-button
|
||||||
>
|
>
|
||||||
@@ -373,6 +380,19 @@ export default {
|
|||||||
this.$message.success(`已同步${rows.length}条收票登记`);
|
this.$message.success(`已同步${rows.length}条收票登记`);
|
||||||
this.loadTable();
|
this.loadTable();
|
||||||
},
|
},
|
||||||
|
async handlePushKingdee() {
|
||||||
|
const rows = this.selection.filter(row => row.approvalStatus === 'approved');
|
||||||
|
if (!rows.length) {
|
||||||
|
this.$message.warning('请选择至少一条审批通过的收票登记');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.$confirm(`确认将选中的 ${rows.length} 条收票登记推送金蝶收票单?`, '提示', {
|
||||||
|
type: 'warning',
|
||||||
|
});
|
||||||
|
const summary = this.unwrapData(await api.pushKingdee(rows.map(row => row.id)));
|
||||||
|
this.$alert(summary || '推送完成', '推送结果', { confirmButtonText: '知道了' });
|
||||||
|
this.loadTable();
|
||||||
|
},
|
||||||
async handleExport() {
|
async handleExport() {
|
||||||
const data = this.unwrapData(await api.getList(1, 100000, this.query));
|
const data = this.unwrapData(await api.getList(1, 100000, this.query));
|
||||||
const exportRows = (data.records || []).map(item => ({
|
const exportRows = (data.records || []).map(item => ({
|
||||||
|
|||||||
@@ -84,6 +84,13 @@
|
|||||||
@click="handleSync"
|
@click="handleSync"
|
||||||
>批量同步</el-button
|
>批量同步</el-button
|
||||||
>
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="hasPermission('payment_application_sync')"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
@click="handleSyncResult"
|
||||||
|
>同步付款结果</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="hasPermission('payment_application_add')"
|
v-if="hasPermission('payment_application_add')"
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -396,8 +403,22 @@ export default {
|
|||||||
this.$message.warning('请选择至少一条审批通过的付款申请');
|
this.$message.warning('请选择至少一条审批通过的付款申请');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await api.syncKingdeeBatch(rows.map(row => row.id));
|
const data = this.unwrapData(await api.syncKingdeeBatch(rows.map(row => row.id))) || [];
|
||||||
this.$message.success(`已同步${rows.length}条付款申请`);
|
const failedList = data.filter(item => String(item).includes('同步失败'));
|
||||||
|
if (failedList.length) {
|
||||||
|
this.$message({
|
||||||
|
type: 'warning',
|
||||||
|
message: `同步完成:成功${data.length - failedList.length}条,失败${failedList.length}条。${failedList.join(';')}`,
|
||||||
|
duration: 8000,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$message.success(`已同步${data.length}条付款申请`);
|
||||||
|
}
|
||||||
|
this.loadTable();
|
||||||
|
},
|
||||||
|
async handleSyncResult() {
|
||||||
|
const data = this.unwrapData(await api.syncKingdeeResult());
|
||||||
|
this.$message.success(data || '金蝶付款结果回写完成');
|
||||||
this.loadTable();
|
this.loadTable();
|
||||||
},
|
},
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
type="date"
|
type="date"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
@change="fetchBfiExchangeRate"
|
||||||
/>
|
/>
|
||||||
<el-select
|
<el-select
|
||||||
v-else-if="field.type === 'project' && editable"
|
v-else-if="field.type === 'project' && editable"
|
||||||
@@ -411,66 +412,15 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</section-card>
|
</section-card>
|
||||||
|
|
||||||
<el-dialog
|
<kingdee-invoice-pool-dialog
|
||||||
v-model="invoiceClaimDialog.visible"
|
v-model="invoiceClaimDialog.visible"
|
||||||
title="查询可认领发票"
|
title="查询可认领发票"
|
||||||
width="92%"
|
confirm-text="确认认领"
|
||||||
append-to-body
|
multiple
|
||||||
destroy-on-close
|
:initial-invoice-no="String(invoiceClaimNo || '').trim()"
|
||||||
>
|
:query-api="invoicePoolQueryApi"
|
||||||
<el-table
|
@confirm="handleInvoiceClaimConfirm"
|
||||||
ref="invoiceClaimTable"
|
/>
|
||||||
v-loading="invoiceClaimDialog.loading"
|
|
||||||
:data="invoiceClaimPagedRows"
|
|
||||||
row-key="invoiceNo"
|
|
||||||
border
|
|
||||||
height="520"
|
|
||||||
@selection-change="invoiceClaimDialog.selected = $event"
|
|
||||||
>
|
|
||||||
<el-table-column
|
|
||||||
type="selection"
|
|
||||||
width="52"
|
|
||||||
fixed="left"
|
|
||||||
align="center"
|
|
||||||
reserve-selection
|
|
||||||
/>
|
|
||||||
<el-table-column type="index" label="序号" width="64" align="center" />
|
|
||||||
<el-table-column prop="invoiceNo" label="发票号" min-width="180" align="center" />
|
|
||||||
<el-table-column prop="invoiceDate" label="开票日期" min-width="130" align="center" />
|
|
||||||
<el-table-column prop="invoiceType" label="发票类型" min-width="150" align="center" />
|
|
||||||
<el-table-column prop="issuerName" label="开票单位" min-width="180" align="center" />
|
|
||||||
<el-table-column prop="receiverName" label="受票单位" min-width="180" align="center" />
|
|
||||||
<el-table-column
|
|
||||||
prop="invoiceAmount"
|
|
||||||
label="发票金额(含税)"
|
|
||||||
min-width="160"
|
|
||||||
align="right"
|
|
||||||
>
|
|
||||||
<template #default="{ row }">{{ formatMoney(row.invoiceAmount) }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="matchedAmount" label="认领金额" min-width="140" align="right">
|
|
||||||
<template #default="{ row }">{{ formatMoney(row.matchedAmount) }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div class="formal-editor__pagination">
|
|
||||||
<el-pagination
|
|
||||||
v-model:current-page="invoiceClaimDialog.page.current"
|
|
||||||
v-model:page-size="invoiceClaimDialog.page.size"
|
|
||||||
:total="invoiceClaimDialog.page.total"
|
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<el-button @click="invoiceClaimDialog.visible = false">取消</el-button>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
:loading="invoiceClaimDialog.confirming"
|
|
||||||
@click="confirmInvoiceClaims"
|
|
||||||
>确认认领</el-button
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<section-card
|
<section-card
|
||||||
v-if="readonly"
|
v-if="readonly"
|
||||||
@@ -940,6 +890,7 @@ import {
|
|||||||
getNextNo,
|
getNextNo,
|
||||||
getReceiptClaims,
|
getReceiptClaims,
|
||||||
claimInvoices as claimInvoicesApi,
|
claimInvoices as claimInvoicesApi,
|
||||||
|
queryInvoicePool,
|
||||||
save,
|
save,
|
||||||
} from '@/api/settlement/formalSettlement';
|
} from '@/api/settlement/formalSettlement';
|
||||||
import {
|
import {
|
||||||
@@ -947,6 +898,7 @@ import {
|
|||||||
getDetailFees as getPreSettlementDetailFees,
|
getDetailFees as getPreSettlementDetailFees,
|
||||||
} from '@/api/settlement/preSettlement';
|
} from '@/api/settlement/preSettlement';
|
||||||
import { calculateAdjustedFee, getFeeDetail } from '@/api/settlement/receivable-payable-detail';
|
import { calculateAdjustedFee, getFeeDetail } from '@/api/settlement/receivable-payable-detail';
|
||||||
|
import { getBfiExchangeRate } from '@/api/base/currency';
|
||||||
import {
|
import {
|
||||||
createFormalSettlementForm,
|
createFormalSettlementForm,
|
||||||
formalSettlementFormFields,
|
formalSettlementFormFields,
|
||||||
@@ -963,11 +915,12 @@ import { h } from 'vue';
|
|||||||
import { InfoFilled } from '@element-plus/icons-vue';
|
import { InfoFilled } from '@element-plus/icons-vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { downloadFileByUrl } from '@/utils/util';
|
import { downloadFileByUrl } from '@/utils/util';
|
||||||
|
import KingdeeInvoicePoolDialog from '@/components/kingdee-invoice-pool-dialog/main.vue';
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormalSettlementEditor',
|
name: 'FormalSettlementEditor',
|
||||||
components: { InfoFilled },
|
components: { InfoFilled, KingdeeInvoicePoolDialog },
|
||||||
props: {
|
props: {
|
||||||
modelValue: Boolean,
|
modelValue: Boolean,
|
||||||
recordId: [String, Number],
|
recordId: [String, Number],
|
||||||
@@ -999,11 +952,8 @@ export default {
|
|||||||
invoiceClaimLoading: false,
|
invoiceClaimLoading: false,
|
||||||
invoiceClaimDialog: {
|
invoiceClaimDialog: {
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
|
||||||
confirming: false,
|
|
||||||
rows: [],
|
|
||||||
selected: [],
|
selected: [],
|
||||||
page: { current: 1, size: 10, total: 0 },
|
confirming: false,
|
||||||
},
|
},
|
||||||
attachmentUploadFiles: [],
|
attachmentUploadFiles: [],
|
||||||
attachmentTypeOptions: [],
|
attachmentTypeOptions: [],
|
||||||
@@ -1146,11 +1096,6 @@ export default {
|
|||||||
});
|
});
|
||||||
return Array.from(names);
|
return Array.from(names);
|
||||||
},
|
},
|
||||||
invoiceClaimPagedRows() {
|
|
||||||
const { current, size } = this.invoiceClaimDialog.page;
|
|
||||||
const start = (current - 1) * size;
|
|
||||||
return this.invoiceClaimDialog.rows.slice(start, start + size);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -1229,7 +1174,6 @@ export default {
|
|||||||
this.invoices = [];
|
this.invoices = [];
|
||||||
this.invoiceClaimNo = '';
|
this.invoiceClaimNo = '';
|
||||||
this.invoiceClaimDialog.visible = false;
|
this.invoiceClaimDialog.visible = false;
|
||||||
this.invoiceClaimDialog.rows = [];
|
|
||||||
this.invoiceClaimDialog.selected = [];
|
this.invoiceClaimDialog.selected = [];
|
||||||
this.attachmentUploadFiles = [];
|
this.attachmentUploadFiles = [];
|
||||||
this.billingRuleDialog = {
|
this.billingRuleDialog = {
|
||||||
@@ -1250,6 +1194,7 @@ export default {
|
|||||||
if (this.initialData) await this.applyInitialData();
|
if (this.initialData) await this.applyInitialData();
|
||||||
Object.assign(this.form, newRecordAudit);
|
Object.assign(this.form, newRecordAudit);
|
||||||
await this.refreshFormalSettlementNo();
|
await this.refreshFormalSettlementNo();
|
||||||
|
await this.fetchBfiExchangeRate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
@@ -1482,6 +1427,7 @@ export default {
|
|||||||
(settlementType === 'receivable' ? contract.partyA : contract.partyB),
|
(settlementType === 'receivable' ? contract.partyA : contract.partyB),
|
||||||
settlementType,
|
settlementType,
|
||||||
settlementTypeName: settlementType === 'receivable' ? '应收' : '应付',
|
settlementTypeName: settlementType === 'receivable' ? '应收' : '应付',
|
||||||
|
currency: contract.settlementCurrency || 'RMB',
|
||||||
});
|
});
|
||||||
this.sources = [];
|
this.sources = [];
|
||||||
this.details = [];
|
this.details = [];
|
||||||
@@ -1489,6 +1435,23 @@ export default {
|
|||||||
this.form.sourcePreSettlementIds = [];
|
this.form.sourcePreSettlementIds = [];
|
||||||
this.form.sourceDetailIds = [];
|
this.form.sourceDetailIds = [];
|
||||||
if (refreshSettlementNo) this.refreshFormalSettlementNo();
|
if (refreshSettlementNo) this.refreshFormalSettlementNo();
|
||||||
|
if (this.form.currency !== 'RMB') this.fetchBfiExchangeRate();
|
||||||
|
},
|
||||||
|
async fetchBfiExchangeRate() {
|
||||||
|
const currency = this.form.currency;
|
||||||
|
if (!currency || currency === 'RMB') return;
|
||||||
|
if (!this.form.exchangeRateDate) return;
|
||||||
|
try {
|
||||||
|
const { data } = await getBfiExchangeRate(currency, this.form.exchangeRateDate);
|
||||||
|
const rateData = data?.data;
|
||||||
|
if (rateData?.excval != null) {
|
||||||
|
this.form.exchangeRate = Number(rateData.excval);
|
||||||
|
} else {
|
||||||
|
this.$message.warning(`未查询到 ${currency} 的BFI汇率数据`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.$message.warning('查询BFI汇率失败,请手动输入结算汇率');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
openCandidateDialog() {
|
openCandidateDialog() {
|
||||||
this.candidate.visible = true;
|
this.candidate.visible = true;
|
||||||
@@ -2202,79 +2165,19 @@ export default {
|
|||||||
this.adjust.saving = false;
|
this.adjust.saving = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
claimInvoices() {
|
|
||||||
this.invoiceClaimLoading = true;
|
|
||||||
try {
|
|
||||||
const keyword = String(this.invoiceClaimNo || '').trim();
|
|
||||||
const defaultNo = `MOCK${this.$dayjs().format('YYYYMMDD')}`;
|
|
||||||
const baseNo = (keyword || defaultNo).slice(0, 29);
|
|
||||||
const numbers = [baseNo, `${baseNo}-02`, `${baseNo}-03`];
|
|
||||||
const invoiceAmounts = [1000, 2000, 3000];
|
|
||||||
const availableAmounts = [1000, 1000, 3000];
|
|
||||||
const preferredMatchedAmounts = [1000, 1000, 2000];
|
|
||||||
let remainingAmount = Math.max(
|
|
||||||
Number(this.form.settlementAmount || this.summaryTotal || 0) -
|
|
||||||
this.invoices.reduce((total, item) => total + Number(item.matchedAmount || 0), 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const existingNumbers = new Set(this.invoices.map(item => String(item.invoiceNo)));
|
|
||||||
const mockRows = numbers
|
|
||||||
.map((invoiceNo, index) => {
|
|
||||||
const matchedAmount = Math.min(
|
|
||||||
preferredMatchedAmounts[index],
|
|
||||||
availableAmounts[index],
|
|
||||||
remainingAmount
|
|
||||||
);
|
|
||||||
remainingAmount = Number((remainingAmount - matchedAmount).toFixed(2));
|
|
||||||
return {
|
|
||||||
invoiceNo,
|
|
||||||
invoiceDate: this.$dayjs().subtract(index, 'day').format('YYYY-MM-DD'),
|
|
||||||
invoiceType: index === 1 ? '增值税普通发票' : '增值税专用发票',
|
|
||||||
taxRate: [3, 6, 9][index],
|
|
||||||
invoiceAmount: invoiceAmounts[index],
|
|
||||||
availableInvoiceAmount: availableAmounts[index],
|
|
||||||
matchedAmount,
|
|
||||||
attachmentJson: '',
|
|
||||||
mockData: true,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter(item => !existingNumbers.has(item.invoiceNo));
|
|
||||||
if (!mockRows.length) {
|
|
||||||
this.$message.warning('当前发票号码的Mock数据已认领');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.invoices = [...this.invoices, ...mockRows];
|
|
||||||
this.$message.success(`已生成${mockRows.length}条Mock发票数据`);
|
|
||||||
} finally {
|
|
||||||
this.invoiceClaimLoading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openInvoiceClaimDialog() {
|
openInvoiceClaimDialog() {
|
||||||
const stamp = Date.now();
|
|
||||||
this.invoiceClaimDialog.loading = true;
|
|
||||||
this.invoiceClaimDialog.rows = Array.from({ length: 80 }, (_, index) => {
|
|
||||||
const amount = Math.floor(1000 + Math.random() * 49000);
|
|
||||||
return {
|
|
||||||
invoiceNo: `MOCK${stamp}${String(index + 1).padStart(3, '0')}`.slice(0, 32),
|
|
||||||
invoiceDate: this.$dayjs()
|
|
||||||
.subtract(Math.floor(Math.random() * 90), 'day')
|
|
||||||
.format('YYYY-MM-DD'),
|
|
||||||
invoiceType: index % 2 ? '增值税普通发票' : '增值税专用发票',
|
|
||||||
issuerName: this.form.payerName || 'Mock开票单位',
|
|
||||||
receiverName: this.form.payeeName || 'Mock受票单位',
|
|
||||||
invoiceAmount: amount,
|
|
||||||
availableInvoiceAmount: amount,
|
|
||||||
matchedAmount: amount,
|
|
||||||
taxRate: [3, 6, 9, 13][index % 4],
|
|
||||||
attachmentJson: '',
|
|
||||||
mockData: true,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
this.invoiceClaimDialog.selected = [];
|
|
||||||
this.invoiceClaimDialog.page.current = 1;
|
|
||||||
this.invoiceClaimDialog.page.total = 80;
|
|
||||||
this.invoiceClaimDialog.visible = true;
|
this.invoiceClaimDialog.visible = true;
|
||||||
this.invoiceClaimDialog.loading = false;
|
},
|
||||||
|
invoicePoolQueryApi(params) {
|
||||||
|
return queryInvoicePool(params);
|
||||||
|
},
|
||||||
|
async handleInvoiceClaimConfirm(rows) {
|
||||||
|
// 统一票池行附件字段为复数 attachmentsJson,认领请求契约是单数 attachmentJson,中转处归一
|
||||||
|
this.invoiceClaimDialog.selected = rows.map(row => ({
|
||||||
|
...row,
|
||||||
|
attachmentJson: row.attachmentJson || row.attachmentsJson,
|
||||||
|
}));
|
||||||
|
await this.confirmInvoiceClaims();
|
||||||
},
|
},
|
||||||
async confirmInvoiceClaims() {
|
async confirmInvoiceClaims() {
|
||||||
if (!this.invoiceClaimDialog.selected.length) {
|
if (!this.invoiceClaimDialog.selected.length) {
|
||||||
@@ -2300,7 +2203,11 @@ export default {
|
|||||||
if (Number(this.form.settlementAmount || 0) > 0) {
|
if (Number(this.form.settlementAmount || 0) > 0) {
|
||||||
remaining = Math.max(0, remaining - matchedAmount);
|
remaining = Math.max(0, remaining - matchedAmount);
|
||||||
}
|
}
|
||||||
return { ...row, matchedAmount };
|
return {
|
||||||
|
...row,
|
||||||
|
invoiceType: row.invoiceTypeName || row.invoiceType || '',
|
||||||
|
matchedAmount,
|
||||||
|
};
|
||||||
})
|
})
|
||||||
.filter(row => row.matchedAmount > 0);
|
.filter(row => row.matchedAmount > 0);
|
||||||
if (!invoices.length) {
|
if (!invoices.length) {
|
||||||
@@ -2388,12 +2295,12 @@ export default {
|
|||||||
},
|
},
|
||||||
viewInvoiceAttachment(row) {
|
viewInvoiceAttachment(row) {
|
||||||
const url = this.invoiceAttachmentUrl(row);
|
const url = this.invoiceAttachmentUrl(row);
|
||||||
if (!url) return this.$message.warning('当前Mock发票暂无可查看附件');
|
if (!url) return this.$message.warning('当前发票暂无可查看附件');
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
},
|
},
|
||||||
downloadInvoiceAttachment(row) {
|
downloadInvoiceAttachment(row) {
|
||||||
const url = this.invoiceAttachmentUrl(row);
|
const url = this.invoiceAttachmentUrl(row);
|
||||||
if (!url) return this.$message.warning('当前Mock发票暂无可下载附件');
|
if (!url) return this.$message.warning('当前发票暂无可下载附件');
|
||||||
downloadFileByUrl(url, this.invoiceAttachmentName(row));
|
downloadFileByUrl(url, this.invoiceAttachmentName(row));
|
||||||
},
|
},
|
||||||
buildSavePayload() {
|
buildSavePayload() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
:disabled="!editable || form.currency === 'RMB'"
|
:disabled="!editable || form.currency === 'RMB'"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@change="recalculateLocalAmount"
|
@change="handleExchangeRateDateChange"
|
||||||
/>
|
/>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-else-if="field.type === 'number'"
|
v-else-if="field.type === 'number'"
|
||||||
@@ -934,6 +934,7 @@ import {
|
|||||||
submit,
|
submit,
|
||||||
} from '@/api/settlement/preSettlement';
|
} from '@/api/settlement/preSettlement';
|
||||||
import { calculateAdjustedFee, getFeeDetail } from '@/api/settlement/receivable-payable-detail';
|
import { calculateAdjustedFee, getFeeDetail } from '@/api/settlement/receivable-payable-detail';
|
||||||
|
import { getBfiExchangeRate } from '@/api/base/currency';
|
||||||
import { getDictionary } from '@/api/system/dictbiz';
|
import { getDictionary } from '@/api/system/dictbiz';
|
||||||
import {
|
import {
|
||||||
emptyPreSettlementForm,
|
emptyPreSettlementForm,
|
||||||
@@ -1242,7 +1243,11 @@ export default {
|
|||||||
await this.loadFeeCategoryOptions();
|
await this.loadFeeCategoryOptions();
|
||||||
await this.loadTransportTypeOptions();
|
await this.loadTransportTypeOptions();
|
||||||
if (this.recordId) await this.loadDetail();
|
if (this.recordId) await this.loadDetail();
|
||||||
else if (this.initialData) await this.applyInitialData();
|
else if (this.initialData) {
|
||||||
|
await this.applyInitialData();
|
||||||
|
this.form.exchangeRateDate = this.$dayjs().format('YYYY-MM-DD');
|
||||||
|
await this.fetchBfiExchangeRate();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async applyInitialData() {
|
async applyInitialData() {
|
||||||
const rows = Array.isArray(this.initialData?.rows) ? this.initialData.rows : [];
|
const rows = Array.isArray(this.initialData?.rows) ? this.initialData.rows : [];
|
||||||
@@ -1527,7 +1532,12 @@ export default {
|
|||||||
this.form.settlementType = contract.settlementType || 'payable';
|
this.form.settlementType = contract.settlementType || 'payable';
|
||||||
this.form.payerName = contract.partyA;
|
this.form.payerName = contract.partyA;
|
||||||
this.form.payeeName = contract.partyB;
|
this.form.payeeName = contract.partyB;
|
||||||
|
this.form.currency = contract.settlementCurrency || 'RMB';
|
||||||
this.summaryFees = [];
|
this.summaryFees = [];
|
||||||
|
if (this.form.currency !== 'RMB') {
|
||||||
|
this.form.exchangeRateDate = this.$dayjs().format('YYYY-MM-DD');
|
||||||
|
this.fetchBfiExchangeRate();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async saveDraft(shouldSubmit) {
|
async saveDraft(shouldSubmit) {
|
||||||
await this.$refs.formRef?.validate();
|
await this.$refs.formRef?.validate();
|
||||||
@@ -1794,6 +1804,26 @@ export default {
|
|||||||
.toFixed(2)
|
.toFixed(2)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
handleExchangeRateDateChange() {
|
||||||
|
this.fetchBfiExchangeRate();
|
||||||
|
this.recalculateLocalAmount();
|
||||||
|
},
|
||||||
|
async fetchBfiExchangeRate() {
|
||||||
|
if (!this.form.currency || this.form.currency === 'RMB') return;
|
||||||
|
if (!this.form.exchangeRateDate) return;
|
||||||
|
try {
|
||||||
|
const { data } = await getBfiExchangeRate(this.form.currency, this.form.exchangeRateDate);
|
||||||
|
const rateData = data?.data;
|
||||||
|
if (rateData?.excval != null) {
|
||||||
|
this.form.exchangeRate = Number(rateData.excval);
|
||||||
|
this.recalculateLocalAmount();
|
||||||
|
} else {
|
||||||
|
this.$message.warning(`未查询到 ${this.form.currency} 的BFI汇率数据`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.$message.warning('查询BFI汇率失败,请手动输入结算汇率');
|
||||||
|
}
|
||||||
|
},
|
||||||
recalculateLocalAmount() {
|
recalculateLocalAmount() {
|
||||||
const rate = this.form.currency === 'RMB' ? 1 : Number(this.form.exchangeRate || 0);
|
const rate = this.form.currency === 'RMB' ? 1 : Number(this.form.exchangeRate || 0);
|
||||||
this.form.localSettlementAmount = (Number(this.form.settlementAmount || 0) * rate).toFixed(2);
|
this.form.localSettlementAmount = (Number(this.form.settlementAmount || 0) * rate).toFixed(2);
|
||||||
|
|||||||
@@ -109,6 +109,12 @@
|
|||||||
{{ row.status === 1 ? '启用' : '停用' }}
|
{{ row.status === 1 ? '启用' : '停用' }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
|
<template #kingdeeStatus="{ row }">
|
||||||
|
<el-tag v-if="row.kingdeeStatus === 'synced'" type="success">已推送</el-tag>
|
||||||
|
<el-tag v-else-if="row.kingdeeStatus === 'exist'" type="primary">金蝶已有</el-tag>
|
||||||
|
<el-tag v-else-if="row.kingdeeStatus === 'failed'" type="danger">推送失败</el-tag>
|
||||||
|
<el-tag v-else type="info">未推送</el-tag>
|
||||||
|
</template>
|
||||||
<template #menu="{ row }">
|
<template #menu="{ row }">
|
||||||
<el-link
|
<el-link
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -165,6 +171,17 @@
|
|||||||
>
|
>
|
||||||
{{ row.status === 1 ? '停用' : '启用' }}
|
{{ row.status === 1 ? '停用' : '启用' }}
|
||||||
</el-link>
|
</el-link>
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
v-if="
|
||||||
|
hasPermission('customer_archive_sync') &&
|
||||||
|
row.approvalStatus === 'approved' &&
|
||||||
|
row.kingdeeStatus === 'failed'
|
||||||
|
"
|
||||||
|
@click="handleSyncKingdee(row)"
|
||||||
|
>
|
||||||
|
同步金蝶
|
||||||
|
</el-link>
|
||||||
<el-link
|
<el-link
|
||||||
type="danger"
|
type="danger"
|
||||||
v-if="hasPermission('customer_archive_delete') && row.approvalStatus === 'draft'"
|
v-if="hasPermission('customer_archive_delete') && row.approvalStatus === 'draft'"
|
||||||
@@ -266,6 +283,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
maxlength="18"
|
maxlength="18"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
|
:disabled="kingdeeLocked && Boolean(archiveForm.id)"
|
||||||
@input="
|
@input="
|
||||||
archiveForm.unifiedCreditCode = String(
|
archiveForm.unifiedCreditCode = String(
|
||||||
archiveForm.unifiedCreditCode || ''
|
archiveForm.unifiedCreditCode || ''
|
||||||
@@ -281,6 +299,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
maxlength="100"
|
maxlength="100"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
|
:disabled="kingdeeLocked"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -304,12 +323,22 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="企业法人" prop="legalPerson">
|
<el-form-item label="企业法人" prop="legalPerson">
|
||||||
<el-input v-model="archiveForm.legalPerson" maxlength="10" show-word-limit />
|
<el-input
|
||||||
|
v-model="archiveForm.legalPerson"
|
||||||
|
maxlength="10"
|
||||||
|
show-word-limit
|
||||||
|
:disabled="kingdeeLocked"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="经营范围" prop="businessScope" required>
|
<el-form-item label="经营范围" prop="businessScope" required>
|
||||||
<el-select v-model="archiveForm.businessScope" multiple filterable clearable>
|
<el-select
|
||||||
|
v-model="archiveForm.businessScope"
|
||||||
|
multiple
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in businessScopeOptions"
|
v-for="item in businessScopeOptions"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
@@ -446,6 +475,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="archiveForm.registeredCapital"
|
v-model="archiveForm.registeredCapital"
|
||||||
maxlength="18"
|
maxlength="18"
|
||||||
|
:disabled="kingdeeLocked"
|
||||||
@input="value => handleDecimalInput('registeredCapital', value)"
|
@input="value => handleDecimalInput('registeredCapital', value)"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -1492,6 +1522,8 @@ import {
|
|||||||
remove,
|
remove,
|
||||||
getScoreTemplate,
|
getScoreTemplate,
|
||||||
recognizeBusinessLicenseOcr,
|
recognizeBusinessLicenseOcr,
|
||||||
|
queryKingdeeCustomer,
|
||||||
|
syncKingdee,
|
||||||
} from '@/api/vehicle/customer-archive';
|
} from '@/api/vehicle/customer-archive';
|
||||||
import {
|
import {
|
||||||
getList as getCreditScoreQuantificationList,
|
getList as getCreditScoreQuantificationList,
|
||||||
@@ -1565,23 +1597,13 @@ export default {
|
|||||||
const code = String(value || '')
|
const code = String(value || '')
|
||||||
.trim()
|
.trim()
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
const charset = '0123456789ABCDEFGHJKLMNPQRTUWXY';
|
|
||||||
const weights = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
|
|
||||||
if (!code) {
|
if (!code) {
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (code.length !== 18 || ![...code].every(char => charset.includes(char))) {
|
const error = this.unifiedCreditCodeError(code);
|
||||||
callback(new Error('统一社会信用代码必须为18位有效字符'));
|
if (error) {
|
||||||
return;
|
callback(new Error(error));
|
||||||
}
|
|
||||||
const sum = [...code.slice(0, 17)].reduce(
|
|
||||||
(total, char, index) => total + charset.indexOf(char) * weights[index],
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const checkCode = charset[(31 - (sum % 31)) % 31];
|
|
||||||
if (code[17] !== checkCode) {
|
|
||||||
callback(new Error('统一社会信用代码校验码错误'));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
@@ -1621,6 +1643,8 @@ export default {
|
|||||||
originalAccessType: '',
|
originalAccessType: '',
|
||||||
activeTab: 'scores',
|
activeTab: 'scores',
|
||||||
archiveForm: this.emptyArchive(),
|
archiveForm: this.emptyArchive(),
|
||||||
|
kingdeeBlocked: false,
|
||||||
|
kingdeeQueryTimer: null,
|
||||||
currentScore: { details: [] },
|
currentScore: { details: [] },
|
||||||
scoreRecordIndex: -1,
|
scoreRecordIndex: -1,
|
||||||
scoreAttachmentFiles: [],
|
scoreAttachmentFiles: [],
|
||||||
@@ -1967,6 +1991,12 @@ export default {
|
|||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '金蝶同步状态',
|
||||||
|
prop: 'kingdeeStatus',
|
||||||
|
slot: true,
|
||||||
|
minWidth: 110,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
prop: 'status',
|
prop: 'status',
|
||||||
@@ -2004,6 +2034,9 @@ export default {
|
|||||||
const authority = this.userInfo.authority || '';
|
const authority = this.userInfo.authority || '';
|
||||||
return authority.includes('admin');
|
return authority.includes('admin');
|
||||||
},
|
},
|
||||||
|
kingdeeLocked() {
|
||||||
|
return this.archiveForm.kingdeeStatus === 'exist';
|
||||||
|
},
|
||||||
permissionList() {
|
permissionList() {
|
||||||
return {
|
return {
|
||||||
addBtn: false,
|
addBtn: false,
|
||||||
@@ -2179,6 +2212,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
'archiveForm.unifiedCreditCode'(val) {
|
||||||
|
this.handleKingdeeCreditCodeChange(val);
|
||||||
|
},
|
||||||
'archiveForm.registeredDetailAddress'() {
|
'archiveForm.registeredDetailAddress'() {
|
||||||
this.$nextTick(() => this.checkOverflow('registeredDetailInput', 'registeredDetailOverflow'));
|
this.$nextTick(() => this.checkOverflow('registeredDetailInput', 'registeredDetailOverflow'));
|
||||||
},
|
},
|
||||||
@@ -2190,6 +2226,119 @@ export default {
|
|||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.isAdmin || this.validData(this.permission[code], false);
|
return this.isAdmin || this.validData(this.permission[code], false);
|
||||||
},
|
},
|
||||||
|
unifiedCreditCodeError(value) {
|
||||||
|
const code = String(value || '')
|
||||||
|
.trim()
|
||||||
|
.toUpperCase();
|
||||||
|
const charset = '0123456789ABCDEFGHJKLMNPQRTUWXY';
|
||||||
|
const weights = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
|
||||||
|
if (code.length !== 18 || ![...code].every(char => charset.includes(char))) {
|
||||||
|
return '统一社会信用代码必须为18位有效字符';
|
||||||
|
}
|
||||||
|
const sum = [...code.slice(0, 17)].reduce(
|
||||||
|
(total, char, index) => total + charset.indexOf(char) * weights[index],
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const checkCode = charset[(31 - (sum % 31)) % 31];
|
||||||
|
if (code[17] !== checkCode) {
|
||||||
|
return '统一社会信用代码校验码错误';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
resetKingdeeQueryState() {
|
||||||
|
this.kingdeeBlocked = false;
|
||||||
|
clearTimeout(this.kingdeeQueryTimer);
|
||||||
|
this.kingdeeQueryTimer = null;
|
||||||
|
},
|
||||||
|
// 新增态下重新输入统一社会信用代码后,此前金蝶回填的数据即失效,重置回填状态并允许对新代码重新查询
|
||||||
|
resetKingdeeBackfill() {
|
||||||
|
const form = this.archiveForm;
|
||||||
|
form.kingdeeStatus = 'none';
|
||||||
|
form.fullName = '';
|
||||||
|
form.legalPerson = '';
|
||||||
|
form.registeredCapital = '';
|
||||||
|
form.registeredDetailAddress = '';
|
||||||
|
form.businessScope = [];
|
||||||
|
form.businessTermType = '固定期限';
|
||||||
|
form.businessEndDate = '';
|
||||||
|
},
|
||||||
|
// 新增态下统一社会信用代码录入完成后自动查询金蝶(A902-1),防抖 500ms;
|
||||||
|
// 代码一经变化即重新查询(含改回历史代码),不做同码去重
|
||||||
|
handleKingdeeCreditCodeChange(val) {
|
||||||
|
this.kingdeeBlocked = false;
|
||||||
|
if (this.readonly || this.archiveForm.id) return;
|
||||||
|
if (this.archiveForm.kingdeeStatus === 'exist') {
|
||||||
|
this.resetKingdeeBackfill();
|
||||||
|
}
|
||||||
|
const code = String(val || '')
|
||||||
|
.trim()
|
||||||
|
.toUpperCase();
|
||||||
|
if (code.length !== 18 || this.unifiedCreditCodeError(code)) return;
|
||||||
|
clearTimeout(this.kingdeeQueryTimer);
|
||||||
|
this.kingdeeQueryTimer = setTimeout(() => this.fetchKingdeeCustomer(code), 500);
|
||||||
|
},
|
||||||
|
async fetchKingdeeCustomer(code) {
|
||||||
|
let customer = null;
|
||||||
|
try {
|
||||||
|
const res = await queryKingdeeCustomer(code);
|
||||||
|
customer = res?.data?.data || null;
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.warning('金蝶查询失败,可继续填写,审批通过后系统将自动复查');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 防止响应返回时用户已修改代码
|
||||||
|
if (String(this.archiveForm.unifiedCreditCode || '').trim().toUpperCase() !== code) return;
|
||||||
|
// 金蝶不存在(rows 为空,data 为 null 或空对象):静默返回,正常填写,不做提示
|
||||||
|
if (!customer || !customer.status) return;
|
||||||
|
if (customer.status === 'C') {
|
||||||
|
this.applyKingdeeCustomer(customer);
|
||||||
|
this.$alert(
|
||||||
|
'金蝶已创建该客户,将获取金蝶的工商信息,相关字段已自动回填并锁定。如信用代码有误,可直接修改,系统将重新查询。',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.kingdeeBlocked = true;
|
||||||
|
this.$alert('金蝶审核中,请稍后重新添加。', '提示', { confirmButtonText: '确定' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applyKingdeeCustomer(customer) {
|
||||||
|
const form = this.archiveForm;
|
||||||
|
form.kingdeeStatus = 'exist';
|
||||||
|
// 工商信息以金蝶为准,直接覆盖(后续字段锁定)
|
||||||
|
if (customer.name) form.fullName = customer.name;
|
||||||
|
if (customer.artificialperson) form.legalPerson = customer.artificialperson;
|
||||||
|
if (customer.bizpartnerAddress) form.registeredDetailAddress = customer.bizpartnerAddress;
|
||||||
|
if (customer.regcapital) {
|
||||||
|
const capital = String(customer.regcapital).replace(/,/g, '').match(/\d+(?:\.\d+)?/);
|
||||||
|
if (capital) form.registeredCapital = capital[0];
|
||||||
|
}
|
||||||
|
if (customer.businessterm) this.applyBusinessTermRecognition(customer.businessterm);
|
||||||
|
if (customer.businessscope) {
|
||||||
|
const matchedScopes = this.businessScopeOptions
|
||||||
|
.filter(
|
||||||
|
item =>
|
||||||
|
customer.businessscope.includes(item.label) ||
|
||||||
|
customer.businessscope.includes(item.value)
|
||||||
|
)
|
||||||
|
.map(item => item.value);
|
||||||
|
if (matchedScopes.length) form.businessScope = matchedScopes;
|
||||||
|
}
|
||||||
|
if (!form.shortName && customer.simplename) form.shortName = customer.simplename;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
[
|
||||||
|
'unifiedCreditCode',
|
||||||
|
'fullName',
|
||||||
|
'legalPerson',
|
||||||
|
'registeredCapital',
|
||||||
|
'businessEndDate',
|
||||||
|
'businessScope',
|
||||||
|
'registeredDetailAddress',
|
||||||
|
].forEach(prop => this.$refs.archiveForm?.validateField(prop));
|
||||||
|
});
|
||||||
|
},
|
||||||
// 检测输入框文本是否溢出,仅溢出时才允许 tooltip 显示完整地址
|
// 检测输入框文本是否溢出,仅溢出时才允许 tooltip 显示完整地址
|
||||||
checkOverflow(refName, flag) {
|
checkOverflow(refName, flag) {
|
||||||
const inst = this.$refs[refName];
|
const inst = this.$refs[refName];
|
||||||
@@ -2219,6 +2368,9 @@ export default {
|
|||||||
invoices: [],
|
invoices: [],
|
||||||
scores: [],
|
scores: [],
|
||||||
changeRecords: [],
|
changeRecords: [],
|
||||||
|
kingdeeStatus: 'none',
|
||||||
|
kingdeeFailReason: '',
|
||||||
|
kingdeeSyncTime: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getDetailList(type) {
|
getDetailList(type) {
|
||||||
@@ -3919,6 +4071,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.archiveForm = this.emptyArchive();
|
this.archiveForm = this.emptyArchive();
|
||||||
this.originalAccessType = '';
|
this.originalAccessType = '';
|
||||||
|
this.resetKingdeeQueryState();
|
||||||
this.qualificationFiles = [];
|
this.qualificationFiles = [];
|
||||||
this.qualificationUploadFiles = [];
|
this.qualificationUploadFiles = [];
|
||||||
this.ocrQualificationUploadFiles = [];
|
this.ocrQualificationUploadFiles = [];
|
||||||
@@ -3927,6 +4080,7 @@ export default {
|
|||||||
},
|
},
|
||||||
resetArchive() {
|
resetArchive() {
|
||||||
this.readonly = false;
|
this.readonly = false;
|
||||||
|
this.resetKingdeeQueryState();
|
||||||
this.changeRecordDetailVisible = false;
|
this.changeRecordDetailVisible = false;
|
||||||
this.changeRecordDetail = null;
|
this.changeRecordDetail = null;
|
||||||
this.changeRecordDetailRows = [];
|
this.changeRecordDetailRows = [];
|
||||||
@@ -4047,6 +4201,10 @@ export default {
|
|||||||
return archive;
|
return archive;
|
||||||
},
|
},
|
||||||
saveArchive() {
|
saveArchive() {
|
||||||
|
if (this.kingdeeBlocked) {
|
||||||
|
this.$message.warning('金蝶审核中,请稍后重新添加');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$refs.archiveForm.validate(valid => {
|
this.$refs.archiveForm.validate(valid => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
this.$message.warning('请先完整填写必填项');
|
this.$message.warning('请先完整填写必填项');
|
||||||
@@ -4060,6 +4218,10 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
saveAndSubmitArchive() {
|
saveAndSubmitArchive() {
|
||||||
|
if (this.kingdeeBlocked) {
|
||||||
|
this.$message.warning('金蝶审核中,请稍后重新添加');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$refs.archiveForm.validate(valid => {
|
this.$refs.archiveForm.validate(valid => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
this.$message.warning('请先完整填写必填项');
|
this.$message.warning('请先完整填写必填项');
|
||||||
@@ -4707,6 +4869,25 @@ export default {
|
|||||||
this.$message({ type: 'success', message: '审核通过!' });
|
this.$message({ type: 'success', message: '审核通过!' });
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleSyncKingdee(row) {
|
||||||
|
this.$confirm('是否确认推送金蝶?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
.then(() => syncKingdee(row.id))
|
||||||
|
.then(res => {
|
||||||
|
const archive = res?.data?.data || {};
|
||||||
|
if (archive.kingdeeStatus === 'synced') {
|
||||||
|
this.$message.success('推送成功,金蝶客户编码与客商编号一致');
|
||||||
|
} else if (archive.kingdeeStatus === 'exist') {
|
||||||
|
this.$message.info('金蝶已有该客商档案,无需推送');
|
||||||
|
} else {
|
||||||
|
this.$message.warning(`推送失败:${archive.kingdeeFailReason || '未知原因'}`);
|
||||||
|
}
|
||||||
|
this.onLoad(this.page);
|
||||||
|
});
|
||||||
|
},
|
||||||
handleReject(row) {
|
handleReject(row) {
|
||||||
this.$confirm('是否确认审核不通过?', '提示', {
|
this.$confirm('是否确认审核不通过?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
|
|||||||
Reference in New Issue
Block a user