Merge branch 'master' of http://git.lionquexpress.com/wuweihua/BMS
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
<basic-table ref="tableRef" :columns="columns" :search-columns="searchColumns" :search-label-width="82" :query="queryList" :default-params="defaultSearchParams" row-key="arBillId" :selection="false">
|
||||
<template #toolbar>
|
||||
<el-col :span="1.5"><el-button type="primary" plain icon="Plus" v-hasPermi="['ar:bill:generate']" @click="generateOpen = true">生成账单</el-button></el-col>
|
||||
<el-col v-if="customerScoped" :span="1.5"><el-button type="info" plain icon="Close" @click="clearCustomerFilter">清除客户条件</el-button></el-col>
|
||||
</template>
|
||||
<template #search-customerId="{ model }">
|
||||
<customer-select v-model="model.customerId" placeholder="请选择客户" :page-size="1000" />
|
||||
@@ -16,6 +17,7 @@
|
||||
<el-button v-if="row.status === AR_BILL_STATUS.DRAFT" link type="success" v-hasPermi="['ar:bill:confirm']" @click="confirmBill(row)">确认</el-button>
|
||||
<el-button v-if="row.status === AR_BILL_STATUS.DRAFT || row.status === AR_BILL_STATUS.CONFIRMED" link type="warning" v-hasPermi="['ar:bill:void']" @click="voidBill(row)">作废</el-button>
|
||||
<el-button v-if="row.status !== AR_BILL_STATUS.DRAFT && row.status !== AR_BILL_STATUS.VOID" link type="primary" v-hasPermi="['ar:bill:export']" @click="exportBill(row)">导出</el-button>
|
||||
<el-button v-if="canGoWriteoff(row)" link type="primary" v-hasPermi="['customer:bill:writeoff']" @click="goWriteoff(row)">去核销</el-button>
|
||||
</template>
|
||||
</basic-table>
|
||||
|
||||
@@ -33,6 +35,7 @@ import { AR_BILL_STATUS, AR_BILL_STATUS_OPTIONS, AR_BILL_STATUS_TYPES } from '@/
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const tableRef = ref()
|
||||
// 从客户余额页“查看账单”跳入时,按当前客户预筛选(重置后仍保留该条件)
|
||||
const defaultSearchParams = computed(() => ({
|
||||
@@ -43,12 +46,13 @@ const detailLoading = ref(false)
|
||||
const detail = ref(null)
|
||||
const generateOpen = ref(false)
|
||||
const statusOptions = AR_BILL_STATUS_OPTIONS
|
||||
const customerScoped = computed(() => Boolean(route.query.customerId))
|
||||
const columns = [
|
||||
{ label: '账单号', prop: 'billNo', minWidth: 180, showOverflowTooltip: true }, { label: '账单名称', prop: 'billName', minWidth: 180, showOverflowTooltip: true }, { label: '客户名称', prop: 'customerName', minWidth: 130, showOverflowTooltip: true }, { label: '客户编码', prop: 'customerCode', minWidth: 120, showOverflowTooltip: true },
|
||||
{ label: '账单截止日', prop: 'billPeriodEnd', minWidth: 120, formatter: row => `截至 ${date(row.billPeriodEnd)}` }, { label: '订单数', prop: 'orderCount', width: 80 },
|
||||
{ label: '应收总额', prop: 'totalAmount', width: 120, align: 'right', slot: 'totalAmount' }, { label: '已核销', prop: 'writtenOffAmount', width: 110, align: 'right', slot: 'writtenOffAmount' },
|
||||
{ label: '未核销', prop: 'unwrittenAmount', width: 110, align: 'right', slot: 'unwrittenAmount' }, { label: '状态', prop: 'status', width: 110, slot: 'status' },
|
||||
{ label: '账单日期', prop: 'billDate', width: 120, formatter: row => date(row.billDate) }, { label: '操作', prop: 'action', width: 260, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||
{ label: '账单日期', prop: 'billDate', width: 120, formatter: row => date(row.billDate) }, { label: '操作', prop: 'action', width: 330, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||
]
|
||||
const searchColumns = [
|
||||
{ label: '账单号', prop: 'billNo', component: 'input', placeholder: '账单号', width: '180px' }, { label: '账单名称', prop: 'billName', component: 'input', placeholder: '账单名称', width: '180px' }, { label: '客户名称', prop: 'customerId', component: 'input', placeholder: '请选择客户', width: '220px' }, { label: '客户编码', prop: 'customerCode', component: 'input', placeholder: '客户编码', width: '140px' },
|
||||
@@ -62,6 +66,40 @@ function confirmBill(row) { proxy.$modal.confirm(`确认账单「${row.billNo}
|
||||
function voidBill(row) { proxy.$prompt(`请输入账单「${row.billNo}」的作废原因`, '作废账单', { inputPattern: /\S+/, inputErrorMessage: '作废原因不能为空' }).then(({ value }) => voidArBill(row.arBillId, { remark: value })).then(() => { proxy.$modal.msgSuccess('账单已作废'); tableRef.value.refresh(); viewBill(row) }).catch(() => {}) }
|
||||
function exportBill(row) { if (!row?.arBillId) return; exportArBill(row.arBillId).then(res => { proxy.$modal.msgSuccess('导出成功'); tableRef.value.refresh(); if (detailOpen.value) viewBill(row); if (res.data?.exportId) downloadExport(res.data) }) }
|
||||
function downloadExport(row) { downloadArBillExport(row.exportId).then(blob => saveAs(blob, row.fileName || `账单_${row.exportId}.xlsx`)) }
|
||||
function clearCustomerFilter() {
|
||||
const query = { ...route.query }
|
||||
delete query.customerId
|
||||
router.replace({ path: route.path, query })
|
||||
}
|
||||
|
||||
// 从客户余额页重复进入不同客户时,路由组件会被复用,需同步更新表格内部查询条件
|
||||
watch(() => route.query.customerId, (newId, oldId) => {
|
||||
if (String(newId || '') === String(oldId || '')) return
|
||||
tableRef.value?.setQueryParams({
|
||||
customerId: newId ? Number(newId) : undefined,
|
||||
pageNum: 1
|
||||
})
|
||||
tableRef.value?.handleQuery()
|
||||
})
|
||||
|
||||
function canGoWriteoff(row) {
|
||||
if (!row?.customerId) return false
|
||||
const canWriteoffStatus = row.status === AR_BILL_STATUS.CONFIRMED
|
||||
|| row.status === AR_BILL_STATUS.PARTIAL_WRITTEN_OFF
|
||||
return canWriteoffStatus && Number(row.unwrittenAmount) > 0
|
||||
}
|
||||
function goWriteoff(row) {
|
||||
if (!canGoWriteoff(row)) return
|
||||
router.push({
|
||||
path: '/customersupplier/customer-money/index',
|
||||
query: {
|
||||
customerId: row.customerId,
|
||||
customerName: row.customerName || '',
|
||||
customerCode: row.customerCode || '',
|
||||
tab: 'billWriteoff'
|
||||
}
|
||||
})
|
||||
}
|
||||
function date(value) { return value ? String(value).slice(0, 10) : '-' }
|
||||
function money(value) { const num = Number(value); return Number.isNaN(num) ? '-' : num.toFixed(2) }
|
||||
function statusText(value) { return statusOptions.find(item => item.value === value)?.label || value || '-' }
|
||||
|
||||
+50
-6
@@ -43,7 +43,7 @@
|
||||
<el-col :xs="12" :sm="8" :md="4">
|
||||
<el-card shadow="hover" class="balance-card">
|
||||
<div class="balance-label">
|
||||
总额度
|
||||
信用额度
|
||||
<el-button link type="primary" size="small" @click="openAdjustDialog('CREDIT')"
|
||||
v-hasPermi="['customer:credit:adjust']">调整</el-button>
|
||||
</div>
|
||||
@@ -127,15 +127,27 @@
|
||||
<span>{{ scope.row.currency }} {{ formatMoney(scope.row.amount) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="汇率" align="center" width="110">
|
||||
<el-table-column label="汇率" align="center" width="100">
|
||||
<template #default="scope">{{ formatRate(scope.row.exchangeRate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="汇率来源" align="center" width="110">
|
||||
<template #default="scope">
|
||||
<el-tooltip v-if="scope.row.rateSourceDesc" :content="scope.row.rateSourceDesc" placement="top">
|
||||
<el-tag :type="receiptRateSourceTag(scope.row.rateSource)" size="small">
|
||||
{{ receiptRateSourceLabel(scope.row.rateSource) }}
|
||||
</el-tag>
|
||||
</el-tooltip>
|
||||
<el-tag v-else :type="receiptRateSourceTag(scope.row.rateSource)" size="small">
|
||||
{{ receiptRateSourceLabel(scope.row.rateSource) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="本位币金额(CNY)" align="center" width="140">
|
||||
<template #default="scope">
|
||||
<span class="money-in">{{ formatMoney(scope.row.baseAmount) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="待核销(CNY)" align="center" prop="unallocatedAmount" width="110" />
|
||||
<!-- <el-table-column label="待核销(CNY)" align="center" prop="unallocatedAmount" width="110" />-->
|
||||
<el-table-column label="收款方式" align="center" prop="payMethod" width="110">
|
||||
<template #default="scope">{{ formatOption(payMethodOptions, scope.row.payMethod) }}</template>
|
||||
</el-table-column>
|
||||
@@ -596,7 +608,14 @@
|
||||
style="width: 100%;"
|
||||
@input="handleRateInput"
|
||||
/>
|
||||
<div class="rate-tip">1 {{ receiptDialog.form.currency || 'CNY' }} = {{ formatRate(receiptDialog.form.exchangeRate) }} CNY<span v-if="receiptDialog.form.currency !== 'CNY'">,默认取汇率表,可手工修改</span></div>
|
||||
<div class="rate-tip">
|
||||
1 {{ receiptDialog.form.currency || 'CNY' }} = {{ formatRate(receiptDialog.form.exchangeRate) }} CNY
|
||||
<el-tag v-if="receiptDialog.form.currency === 'CNY'" size="small" type="info" effect="plain" style="margin-left: 6px;">系统默认</el-tag>
|
||||
<el-tag v-else-if="rateEdited" size="small" type="warning" effect="dark" style="margin-left: 6px;">手工修改</el-tag>
|
||||
<el-tag v-else-if="receiptDialog.form.exchangeRate" size="small" type="success" effect="plain" style="margin-left: 6px;">汇率表{{ rateSourceInfo.source ? '·' + rateSourceInfo.source : '' }}</el-tag>
|
||||
<span v-else style="color: var(--el-color-warning);"> 汇率表未配置,请手工录入</span>
|
||||
<span v-if="receiptDialog.form.currency !== 'CNY'">,默认取汇率表,可手工修改</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -678,6 +697,14 @@
|
||||
<span class="money-in">{{ viewDialog.data.currency }} {{ formatMoney(viewDialog.data.amount) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="对CNY汇率">{{ formatRate(viewDialog.data.exchangeRate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="汇率来源">
|
||||
<el-tag :type="receiptRateSourceTag(viewDialog.data.rateSource)" size="small">
|
||||
{{ receiptRateSourceLabel(viewDialog.data.rateSource) }}
|
||||
</el-tag>
|
||||
<span v-if="viewDialog.data.rateSourceDesc" style="margin-left: 8px; color: var(--el-text-color-secondary);">
|
||||
{{ viewDialog.data.rateSourceDesc }}
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="本位币金额">
|
||||
<span class="money-in">CNY {{ formatMoney(viewDialog.data.baseAmount) }}</span>
|
||||
</el-descriptions-item>
|
||||
@@ -1006,6 +1033,14 @@ function creditChangeTag(v) {
|
||||
function isCreditUsageFlow(changeType) {
|
||||
return changeType === 'OCCUPY' || changeType === 'RELEASE'
|
||||
}
|
||||
/** 收款汇率来源文案:RATE_TABLE汇率表 / MANUAL手工修改 / SYSTEM系统默认(本币) */
|
||||
function receiptRateSourceLabel(v) {
|
||||
return { RATE_TABLE: '汇率表', MANUAL: '手工修改', SYSTEM: '系统默认' }[v] || '系统默认'
|
||||
}
|
||||
/** 收款汇率来源标签颜色 */
|
||||
function receiptRateSourceTag(v) {
|
||||
return { RATE_TABLE: 'success', MANUAL: 'warning', SYSTEM: 'info' }[v] || 'info'
|
||||
}
|
||||
function formatMoney(val) {
|
||||
const num = Number(val)
|
||||
return isNaN(num) ? '0.00' : num.toFixed(2)
|
||||
@@ -1277,6 +1312,7 @@ const receiptRules = {
|
||||
|
||||
function resetReceiptForm() {
|
||||
rateEdited.value = false
|
||||
rateSourceInfo.value = { source: '', ratePath: '' }
|
||||
receiptDialog.form = {
|
||||
customerId: route.query.customerId || null,
|
||||
receivedAt: proxy.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
|
||||
@@ -1299,12 +1335,15 @@ function handleAddReceipt() {
|
||||
|
||||
/** 汇率是否被手工修改过(修改后切换币种/日期不再自动覆盖) */
|
||||
const rateEdited = ref(false)
|
||||
/** 汇率表返回的来源信息(source: 中国银行等;ratePath: DIRECT/REVERSE/CROSS),仅用于表单实时展示 */
|
||||
const rateSourceInfo = ref({ source: '', ratePath: '' })
|
||||
|
||||
/** 按收款日期从汇率表取该币种对CNY即期汇率 */
|
||||
function fetchDefaultRate() {
|
||||
const cur = receiptDialog.form.currency
|
||||
if (!cur || cur === 'CNY') {
|
||||
receiptDialog.form.exchangeRate = 1
|
||||
rateSourceInfo.value = { source: '', ratePath: 'SAME' }
|
||||
return
|
||||
}
|
||||
const bizDate = receiptDialog.form.receivedAt
|
||||
@@ -1312,11 +1351,15 @@ function fetchDefaultRate() {
|
||||
: proxy.parseTime(new Date(), '{y}-{m}-{d}')
|
||||
convertToBase({ amount: 1, currency: cur, rateType: '0', bizDate })
|
||||
.then(res => {
|
||||
if (!rateEdited.value) receiptDialog.form.exchangeRate = Number(res.data.rate)
|
||||
if (!rateEdited.value) {
|
||||
receiptDialog.form.exchangeRate = Number(res.data.rate)
|
||||
rateSourceInfo.value = { source: res.data.source || '', ratePath: res.data.ratePath || 'DIRECT' }
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!rateEdited.value) {
|
||||
receiptDialog.form.exchangeRate = undefined
|
||||
rateSourceInfo.value = { source: '', ratePath: '' }
|
||||
proxy.$modal.msgWarning(`汇率表中未维护 ${cur} 对 CNY 的汇率,请手工录入汇率`)
|
||||
}
|
||||
})
|
||||
@@ -1325,6 +1368,7 @@ function fetchDefaultRate() {
|
||||
/** 切换币种:重置手工标记并重新取默认汇率 */
|
||||
function handleCurrencyChange() {
|
||||
rateEdited.value = false
|
||||
rateSourceInfo.value = { source: '', ratePath: '' }
|
||||
fetchDefaultRate()
|
||||
}
|
||||
|
||||
@@ -1803,7 +1847,7 @@ function initPage() {
|
||||
// 重置页面状态,避免上一个客户的数据残留
|
||||
customer.value = {}
|
||||
accountList.value = []
|
||||
activeTab.value = 'receipt'
|
||||
activeTab.value = route.query.tab === 'billWriteoff' ? 'billWriteoff' : 'receipt'
|
||||
receiptDialog.visible = false
|
||||
viewDialog.visible = false
|
||||
viewDialog.data = null
|
||||
|
||||
@@ -214,10 +214,11 @@ const open = ref(false)
|
||||
const calcResult = ref(null)
|
||||
|
||||
const rateTypeOptions = [
|
||||
{ value: '0', label: '即期汇率' },
|
||||
{ value: '1', label: '月初汇率' },
|
||||
{ value: '2', label: '月末汇率' },
|
||||
{ value: '3', label: '固定汇率' }
|
||||
{ value: '0', label: '即期汇率' }
|
||||
// ,
|
||||
// { value: '1', label: '月初汇率' },
|
||||
// { value: '2', label: '月末汇率' },
|
||||
// { value: '3', label: '固定汇率' }
|
||||
]
|
||||
|
||||
/** 常用币种兜底 + 从国家资料(币种)去重加载 */
|
||||
|
||||
Reference in New Issue
Block a user