Compare commits
No commits in common. "ecb085c6b45506423c9073960d57473d3d7dd466" and "9c342c61ab5ffe557bca563dff9577f4c15746ca" have entirely different histories.
ecb085c6b4
...
9c342c61ab
@ -579,14 +579,6 @@ export function getAllFinanceAccounts() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取流水账户级联选项
|
|
||||||
export function getAccountCascaderOptions() {
|
|
||||||
return request({
|
|
||||||
url: '/finance/account/cascader',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 账单调整相关接口
|
// 账单调整相关接口
|
||||||
|
|
||||||
// 添加账单调整(按金额或按比例)
|
// 添加账单调整(按金额或按比例)
|
||||||
@ -598,24 +590,6 @@ export function addBillAdjustment(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调整账单滞纳金专用接口
|
|
||||||
export function adjustLateFee(data) {
|
|
||||||
return request({
|
|
||||||
url: '/v1/late-fees/adjust',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 结算账单滞纳金接口
|
|
||||||
export function settleLateFee(data) {
|
|
||||||
return request({
|
|
||||||
url: '/v1/late-fees/settle',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 作废账单调整
|
// 作废账单调整
|
||||||
export function voidBillAdjustment(data) {
|
export function voidBillAdjustment(data) {
|
||||||
return request({
|
return request({
|
||||||
@ -737,189 +711,3 @@ export function deleteBillPaymentAttachment(attachmentId) {
|
|||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收据记录相关接口
|
|
||||||
export function getReceiptRecordPage(params) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/page',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取账单关联的收支流水列表
|
|
||||||
export function getBillTransactionList(billId, params) {
|
|
||||||
return request({
|
|
||||||
url: `/v1/bill/${billId}/transactions`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getReceiptRecordDetail(id) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/${id}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function voidReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/void/${id}`,
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/generate',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function previewReceipt(previewId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/preview/${previewId}`,
|
|
||||||
method: 'get',
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function downloadReceipt(previewId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/download-preview/${previewId}`,
|
|
||||||
method: 'get',
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function printReceipt(previewId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/print/${previewId}`,
|
|
||||||
method: 'get',
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function downloadReceiptByFilename(receiptFileName) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/download-by-filename',
|
|
||||||
method: 'get',
|
|
||||||
params: { receiptFileName },
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function previewReceiptByFilename(receiptFileName) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/preview-by-filename',
|
|
||||||
method: 'get',
|
|
||||||
params: { receiptFileName },
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function printReceiptByFilename(receiptFileName) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/print-by-filename',
|
|
||||||
method: 'get',
|
|
||||||
params: { receiptFileName },
|
|
||||||
responseType: 'blob'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭账单
|
|
||||||
export function closeBill(data) {
|
|
||||||
return request({
|
|
||||||
url: '/bill/close',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取可开据收据明细
|
|
||||||
export function getReceiptDetails(billId) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/details',
|
|
||||||
method: 'get',
|
|
||||||
params: { billId }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开具收据
|
|
||||||
export function issueReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/issue',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页查询收据记录
|
|
||||||
export function getReceiptRecords(billId, params) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/records',
|
|
||||||
method: 'get',
|
|
||||||
params: { billId, ...params }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取收据详情
|
|
||||||
export function getReceiptDetail(id) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/detail',
|
|
||||||
method: 'get',
|
|
||||||
params: { id }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新收据状态为已发出
|
|
||||||
export function updateReceiptIssueStatus(id) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/issue-status',
|
|
||||||
method: 'post',
|
|
||||||
data: { id }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 作废收据
|
|
||||||
export function voidReceiptById(id) {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/void',
|
|
||||||
method: 'post',
|
|
||||||
data: { id }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取支付方式选项
|
|
||||||
export function getPaymentMethodOptions() {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/payment-methods',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取收据状态选项
|
|
||||||
export function getReceiptStatusOptions() {
|
|
||||||
return request({
|
|
||||||
url: '/receipt/status-options',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取下一个收据编号
|
|
||||||
export function getNextReceiptNumberByRuleId(ruleId) {
|
|
||||||
return request({
|
|
||||||
url: `/receipt/number/next/${ruleId}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量获取收据编号
|
|
||||||
export function getBatchReceiptNumbersByRuleId(ruleId, count) {
|
|
||||||
return request({
|
|
||||||
url: `/receipt/numbers/${ruleId}/${count}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
@ -36,19 +36,6 @@ export default {
|
|||||||
component: () => import('@/views/finance/transaction/index.vue'),
|
component: () => import('@/views/finance/transaction/index.vue'),
|
||||||
name: 'Transaction',
|
name: 'Transaction',
|
||||||
meta: { title: '收支流水', icon: 'el-icon-money' }
|
meta: { title: '收支流水', icon: 'el-icon-money' }
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receiptRecord',
|
|
||||||
component: () => import('@/views/finance/receiptRecord/index.vue'),
|
|
||||||
name: 'ReceiptRecord',
|
|
||||||
meta: { title: '收据记录', icon: 'el-icon-document-copy' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receipt/issue/:billId',
|
|
||||||
component: () => import('@/views/finance/receipt/issue.vue'),
|
|
||||||
name: 'IssueReceipt',
|
|
||||||
meta: { title: '开具收据', activeMenu: '/finance/billList' },
|
|
||||||
hidden: true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ import { API_SUCCESS_CODE } from './constants'
|
|||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '/', // 修改为相对路径,使用代理
|
// baseURL: '/', // 修改为相对路径,使用代理
|
||||||
// baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
|
baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
|
||||||
|
|
||||||
timeout: 10000 // 请求超时时间
|
timeout: 10000 // 请求超时时间
|
||||||
})
|
})
|
||||||
@ -25,9 +25,9 @@ service.interceptors.request.use(
|
|||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
// 如果是blob类型(文件下载),直接返回blob数据
|
// 如果是blob类型(文件下载),直接返回
|
||||||
if (response.config.responseType === 'blob') {
|
if (response.config.responseType === 'blob') {
|
||||||
return response.data
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = response.data
|
const res = response.data
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,10 +33,10 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结清状态" prop="clearStatus">
|
<el-form-item label="结清状态" prop="clearStatus">
|
||||||
<el-select v-model="queryParams.clearStatus" placeholder="请选择结清状态" clearable multiple style="width: 220px">
|
<el-select v-model="queryParams.clearStatus" placeholder="请选择结清状态" clearable multiple style="width: 220px">
|
||||||
<el-option label="未付款" value="1" />
|
<el-option label="未付款" value="0" />
|
||||||
<el-option label="已结清" value="2" />
|
<el-option label="已结清" value="1" />
|
||||||
<el-option label="部分结清" value="3" />
|
<el-option label="部分结清" value="2" />
|
||||||
<el-option label="待退款" value="4" />
|
<el-option label="待退款" value="3" />
|
||||||
<el-option label="待收款" value="5" />
|
<el-option label="待收款" value="5" />
|
||||||
<el-option label="对账确认中" value="6" />
|
<el-option label="对账确认中" value="6" />
|
||||||
<el-option label="已付款" value="7" />
|
<el-option label="已付款" value="7" />
|
||||||
@ -108,21 +108,9 @@
|
|||||||
<el-table-column label="开始日期" prop="chggBgnDt" min-width="120" align="center" />
|
<el-table-column label="开始日期" prop="chggBgnDt" min-width="120" align="center" />
|
||||||
<el-table-column label="结束日期" prop="chggEndDt" min-width="120" align="center" />
|
<el-table-column label="结束日期" prop="chggEndDt" min-width="120" align="center" />
|
||||||
<el-table-column label="应收日期" prop="pybDt" min-width="120" align="center" />
|
<el-table-column label="应收日期" prop="pybDt" min-width="120" align="center" />
|
||||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleViewDetail(scope.row)">查看</el-button>
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
@click="handleDetail(scope.row)">
|
|
||||||
查看
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
@click="handleIssueReceipt(scope.row)"
|
|
||||||
:disabled="!canIssueReceipt(scope.row)">
|
|
||||||
开具收据
|
|
||||||
</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -152,11 +140,8 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 账单详情对话框 -->
|
<!-- 账单详情对话框 -->
|
||||||
<el-dialog :visible.sync="detailVisible" width="80%" append-to-body title=" " :close-on-click-modal="false" :show-close="false">
|
<el-dialog title="账单详情" :visible.sync="detailVisible" width="80%" append-to-body>
|
||||||
<bill-detail v-if="detailVisible" :bill-id="currentBill.id" />
|
<bill-detail v-if="detailVisible" :bill-id="currentBill.id" />
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="detailVisible = false">关 闭</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -314,9 +299,8 @@ export default {
|
|||||||
this.$refs.addBillForm.resetForm()
|
this.$refs.addBillForm.resetForm()
|
||||||
},
|
},
|
||||||
// 查看账单详情
|
// 查看账单详情
|
||||||
handleDetail(row) {
|
handleViewDetail(row) {
|
||||||
this.currentBill = row
|
this.currentBill = row
|
||||||
console.log('打开账单详情,ID:', row.id) // 添加日志帮助调试
|
|
||||||
this.detailVisible = true
|
this.detailVisible = true
|
||||||
},
|
},
|
||||||
// 导出账单操作
|
// 导出账单操作
|
||||||
@ -420,24 +404,6 @@ export default {
|
|||||||
'7': '已付款'
|
'7': '已付款'
|
||||||
}
|
}
|
||||||
return statusMap[status] || '未知状态'
|
return statusMap[status] || '未知状态'
|
||||||
},
|
|
||||||
// 判断是否可以开具收据
|
|
||||||
canIssueReceipt(row) {
|
|
||||||
// 按要求实现条件判断:
|
|
||||||
// 1. 待退款不可以开收据
|
|
||||||
// 2. 可开据金额大于0
|
|
||||||
return row.clearStatus !== '4' && // 4-待退款
|
|
||||||
(row.atmRecvAmt > 0 || (row.ovdueStatus === '1' && row.realOvdueAmount > 0))
|
|
||||||
},
|
|
||||||
|
|
||||||
// 处理开具收据
|
|
||||||
handleIssueReceipt(row) {
|
|
||||||
// 保存当前选中的账单
|
|
||||||
this.currentBill = row
|
|
||||||
// 跳转到开具收据组件或页面
|
|
||||||
this.$router.push({
|
|
||||||
path: `/finance/receipt/issue/${row.id}`
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,8 +422,4 @@ export default {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-dialog__body {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
@ -1,563 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="issue-receipt-container">
|
|
||||||
<el-card>
|
|
||||||
<div slot="header" class="clearfix">
|
|
||||||
<span>开具收据</span>
|
|
||||||
<el-button style="float: right;" size="small" @click="goBack">返回</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-loading="loading">
|
|
||||||
<!-- 账单基本信息 -->
|
|
||||||
<div class="bill-info-section">
|
|
||||||
<h3>账单基本信息</h3>
|
|
||||||
<el-descriptions :column="3" border size="medium">
|
|
||||||
<el-descriptions-item label="账单编号">{{ billInfo.totBillNo || '-' }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="交款单位">{{ billInfo.paysdName || '-' }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="费用类型">{{ billInfo.feTpName || '-' }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="费用周期">
|
|
||||||
{{ billInfo.chggBgnDt || '-' }} 至 {{ billInfo.chggEndDt || '-' }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="应收金额">{{ formatAmount(billInfo.accigRcvAmt) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="实收金额">{{ formatAmount(billInfo.atmRecvAmt) }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 收据明细列表 -->
|
|
||||||
<div class="receipt-details-section">
|
|
||||||
<h3>收据明细列表</h3>
|
|
||||||
<el-table
|
|
||||||
ref="receiptDetailsTable"
|
|
||||||
:data="receiptDetails"
|
|
||||||
border
|
|
||||||
style="width: 100%"
|
|
||||||
@selection-change="handleSelectionChange">
|
|
||||||
<el-table-column type="selection" width="55"></el-table-column>
|
|
||||||
<el-table-column prop="payerUnit" label="交款单位" min-width="150" show-overflow-tooltip></el-table-column>
|
|
||||||
<el-table-column label="收据编号" min-width="120">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-tooltip content="确定开据后会根据收据编号生成规则进行生成" placement="top">
|
|
||||||
<span>-</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="可开据金额" min-width="120" align="right">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ formatAmount(scope.row.availableAmount) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="申请开据金额" min-width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-input-number
|
|
||||||
v-model="scope.row.applyAmount"
|
|
||||||
:min="0"
|
|
||||||
:max="scope.row.availableAmount"
|
|
||||||
:precision="2"
|
|
||||||
:step="1"
|
|
||||||
@change="calculateTotalAmount"
|
|
||||||
size="small"
|
|
||||||
controls-position="right">
|
|
||||||
</el-input-number>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="feeType" label="费用类型" min-width="120" show-overflow-tooltip></el-table-column>
|
|
||||||
<el-table-column prop="payeeUnitName" label="收款单位" min-width="150" show-overflow-tooltip></el-table-column>
|
|
||||||
<el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip></el-table-column>
|
|
||||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
@click="handleEdit(scope.$index, scope.row)">
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 收据汇总 -->
|
|
||||||
<div class="receipt-summary-section">
|
|
||||||
<el-alert
|
|
||||||
title="收据汇总"
|
|
||||||
type="info"
|
|
||||||
:closable="false">
|
|
||||||
<template slot="title">
|
|
||||||
已选择 <strong>{{ selectedItems.length }}</strong> 条明细,
|
|
||||||
申请开据金额合计:<strong>{{ formatAmount(totalAmount) }}</strong>
|
|
||||||
</template>
|
|
||||||
</el-alert>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
|
||||||
<div class="action-buttons">
|
|
||||||
<el-button @click="goBack">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmIssue" :disabled="selectedItems.length === 0 || totalAmount <= 0" :loading="submitting">确认开具</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 编辑收据对话框 -->
|
|
||||||
<el-dialog title="编辑收据信息" :visible.sync="editDialogVisible" width="700px" append-to-body>
|
|
||||||
<el-form :model="editForm" :rules="editRules" ref="editForm" label-width="120px" v-loading="editLoading">
|
|
||||||
<!-- 收据信息 -->
|
|
||||||
<h4 class="dialog-section-title">收据信息</h4>
|
|
||||||
<el-form-item label="编号规则" prop="ruleId">
|
|
||||||
<el-input v-model="editForm.ruleName" disabled></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开据日期" prop="receiptDate">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="editForm.receiptDate"
|
|
||||||
type="date"
|
|
||||||
placeholder="选择日期"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
style="width: 100%">
|
|
||||||
</el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="支付方式" prop="paymentMethods">
|
|
||||||
<el-select
|
|
||||||
v-model="editForm.paymentMethods"
|
|
||||||
multiple
|
|
||||||
placeholder="请选择支付方式"
|
|
||||||
style="width: 100%">
|
|
||||||
<el-option
|
|
||||||
v-for="item in paymentMethodOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="费用类型" prop="feeType">
|
|
||||||
<el-input v-model="editForm.feeType" disabled></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="费用名称" prop="feeName">
|
|
||||||
<el-input v-model="editForm.feeName"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开据金额" prop="applyAmount">
|
|
||||||
<el-input-number
|
|
||||||
v-model="editForm.applyAmount"
|
|
||||||
:min="0"
|
|
||||||
:max="editForm.availableAmount"
|
|
||||||
:precision="2"
|
|
||||||
:step="1"
|
|
||||||
controls-position="right"
|
|
||||||
style="width: 100%">
|
|
||||||
</el-input-number>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 交款方 -->
|
|
||||||
<h4 class="dialog-section-title">交款方</h4>
|
|
||||||
<el-form-item label="交款单位" prop="payerUnit">
|
|
||||||
<el-input v-model="editForm.payerUnit" disabled></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="交款人" prop="payerName">
|
|
||||||
<el-input v-model="editForm.payerName"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="地址" prop="payerAddress">
|
|
||||||
<el-input v-model="editForm.payerAddress"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="电话" prop="payerPhone">
|
|
||||||
<el-input v-model="editForm.payerPhone"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 收款方 -->
|
|
||||||
<h4 class="dialog-section-title">收款方</h4>
|
|
||||||
<el-form-item label="收款单位" prop="payeeUnitId">
|
|
||||||
<el-select
|
|
||||||
v-model="editForm.payeeUnitId"
|
|
||||||
placeholder="请选择收款单位"
|
|
||||||
style="width: 100%"
|
|
||||||
@change="handlePayeeUnitChange">
|
|
||||||
<el-option
|
|
||||||
v-for="item in payeeUnitOptions"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收款人" prop="payeeName">
|
|
||||||
<el-input v-model="editForm.payeeName"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="地址" prop="payeeAddress">
|
|
||||||
<el-input v-model="editForm.payeeAddress"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="电话" prop="payeePhone">
|
|
||||||
<el-input v-model="editForm.payeePhone"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 备注 -->
|
|
||||||
<h4 class="dialog-section-title">备注</h4>
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
|
||||||
type="textarea"
|
|
||||||
v-model="editForm.remark"
|
|
||||||
:rows="3"
|
|
||||||
placeholder="请输入备注信息">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="saveEdit" :loading="editSubmitting">确定</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
getBillDetail,
|
|
||||||
getReceiptDetails,
|
|
||||||
issueReceipt,
|
|
||||||
getPaymentMethodOptions
|
|
||||||
} from '@/api/finance'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IssueReceipt',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
billId: null,
|
|
||||||
loading: false,
|
|
||||||
submitting: false,
|
|
||||||
billInfo: {},
|
|
||||||
receiptDetails: [],
|
|
||||||
selectedItems: [],
|
|
||||||
totalAmount: 0,
|
|
||||||
|
|
||||||
// 编辑相关
|
|
||||||
editDialogVisible: false,
|
|
||||||
editLoading: false,
|
|
||||||
editSubmitting: false,
|
|
||||||
editIndex: -1,
|
|
||||||
editForm: {
|
|
||||||
ruleId: '',
|
|
||||||
ruleName: '',
|
|
||||||
receiptDate: '',
|
|
||||||
paymentMethods: [],
|
|
||||||
feeType: '',
|
|
||||||
feeName: '',
|
|
||||||
applyAmount: 0,
|
|
||||||
availableAmount: 0,
|
|
||||||
payerUnit: '',
|
|
||||||
payerName: '',
|
|
||||||
payerAddress: '',
|
|
||||||
payerPhone: '',
|
|
||||||
payeeUnitId: '',
|
|
||||||
payeeUnitName: '',
|
|
||||||
payeeName: '',
|
|
||||||
payeeAddress: '',
|
|
||||||
payeePhone: '',
|
|
||||||
remark: ''
|
|
||||||
},
|
|
||||||
editRules: {
|
|
||||||
receiptDate: [
|
|
||||||
{ required: true, message: '请选择开据日期', trigger: 'change' }
|
|
||||||
],
|
|
||||||
paymentMethods: [
|
|
||||||
{ required: true, message: '请选择支付方式', trigger: 'change' }
|
|
||||||
],
|
|
||||||
applyAmount: [
|
|
||||||
{ required: true, message: '请输入开据金额', trigger: 'blur' }
|
|
||||||
],
|
|
||||||
payeeUnitId: [
|
|
||||||
{ required: true, message: '请选择收款单位', trigger: 'change' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// 选项数据
|
|
||||||
paymentMethodOptions: [
|
|
||||||
{ value: '1', label: '现金' },
|
|
||||||
{ value: '2', label: '网银转账' },
|
|
||||||
{ value: '3', label: 'POS机' },
|
|
||||||
{ value: '4', label: '支付宝' },
|
|
||||||
{ value: '5', label: '微信' },
|
|
||||||
{ value: '6', label: '转账支票' },
|
|
||||||
{ value: '7', label: '其他方式' },
|
|
||||||
{ value: '8', label: '线上支付' }
|
|
||||||
],
|
|
||||||
payeeUnitOptions: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.billId = this.$route.params.billId
|
|
||||||
this.fetchData()
|
|
||||||
this.fetchPaymentMethodOptions()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 获取数据
|
|
||||||
fetchData() {
|
|
||||||
this.loading = true
|
|
||||||
|
|
||||||
// 获取账单详情
|
|
||||||
getBillDetail(this.billId).then(response => {
|
|
||||||
if (response.code === '0000000000000000') {
|
|
||||||
this.billInfo = response.data || {}
|
|
||||||
|
|
||||||
// 获取可开据收据明细
|
|
||||||
this.fetchReceiptDetails()
|
|
||||||
} else {
|
|
||||||
this.$message.error(response.message || '获取账单信息失败')
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.$message.error('获取账单信息失败')
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取可开据收据明细
|
|
||||||
fetchReceiptDetails() {
|
|
||||||
getReceiptDetails(this.billId).then(response => {
|
|
||||||
if (response.code === '0000000000000000') {
|
|
||||||
this.receiptDetails = (response.data || []).map(item => {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
applyAmount: 0, // 初始为0
|
|
||||||
billId: this.billId,
|
|
||||||
availableAmount: parseFloat(item.availableAmount || 0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 处理收款单位选项
|
|
||||||
this.payeeUnitOptions = []
|
|
||||||
this.receiptDetails.forEach(item => {
|
|
||||||
if (item.payeeUnitId && item.payeeUnitName) {
|
|
||||||
// 检查是否已存在
|
|
||||||
const exists = this.payeeUnitOptions.some(option => option.id === item.payeeUnitId)
|
|
||||||
if (!exists) {
|
|
||||||
this.payeeUnitOptions.push({
|
|
||||||
id: item.payeeUnitId,
|
|
||||||
name: item.payeeUnitName
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$message.error(response.message || '获取收据明细失败')
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.$message.error('获取收据明细失败')
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取支付方式选项
|
|
||||||
fetchPaymentMethodOptions() {
|
|
||||||
getPaymentMethodOptions().then(response => {
|
|
||||||
if (response.code === '0000000000000000') {
|
|
||||||
this.paymentMethodOptions = response.data || []
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
// 使用默认选项
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 处理选择变化
|
|
||||||
handleSelectionChange(selection) {
|
|
||||||
this.selectedItems = selection
|
|
||||||
this.calculateTotalAmount()
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算总金额
|
|
||||||
calculateTotalAmount() {
|
|
||||||
this.totalAmount = this.selectedItems.reduce((sum, item) => {
|
|
||||||
return sum + parseFloat(item.applyAmount || 0)
|
|
||||||
}, 0)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 编辑收据
|
|
||||||
handleEdit(index, row) {
|
|
||||||
this.editIndex = index
|
|
||||||
|
|
||||||
// 处理日期格式,确保为YYYY-MM-DD格式
|
|
||||||
const today = new Date()
|
|
||||||
const formattedDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
|
|
||||||
|
|
||||||
// 使用对象扩展运算符复制数据,避免直接修改原对象
|
|
||||||
this.editForm = {
|
|
||||||
billId: this.billId,
|
|
||||||
billDetailId: row.billDetailId,
|
|
||||||
ruleId: row.ruleId || '',
|
|
||||||
ruleName: row.ruleName || '默认规则',
|
|
||||||
receiptDate: formattedDate,
|
|
||||||
paymentMethods: ['1'], // 默认现金
|
|
||||||
feeType: row.feeType || '',
|
|
||||||
feeName: row.feeType || '',
|
|
||||||
applyAmount: parseFloat(row.applyAmount || 0),
|
|
||||||
availableAmount: parseFloat(row.availableAmount || 0),
|
|
||||||
payerUnit: row.payerUnit || '',
|
|
||||||
payerName: '',
|
|
||||||
payerAddress: '',
|
|
||||||
payerPhone: '',
|
|
||||||
payeeUnitId: row.payeeUnitId || '',
|
|
||||||
payeeUnitName: row.payeeUnitName || '',
|
|
||||||
payeeName: '',
|
|
||||||
payeeAddress: '',
|
|
||||||
payeePhone: '',
|
|
||||||
remark: row.remark || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
this.editDialogVisible = true
|
|
||||||
|
|
||||||
// 表单验证需要在DOM更新后执行
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.editForm) {
|
|
||||||
this.$refs.editForm.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 收款单位变化
|
|
||||||
handlePayeeUnitChange(value) {
|
|
||||||
const selected = this.payeeUnitOptions.find(item => item.id === value)
|
|
||||||
if (selected) {
|
|
||||||
this.editForm.payeeUnitName = selected.name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 保存编辑
|
|
||||||
saveEdit() {
|
|
||||||
this.$refs.editForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
// 更新原始数据
|
|
||||||
if (this.editIndex >= 0 && this.editIndex < this.receiptDetails.length) {
|
|
||||||
// 构建新对象,避免直接引用
|
|
||||||
const updatedRow = { ...this.receiptDetails[this.editIndex] }
|
|
||||||
|
|
||||||
// 更新数据
|
|
||||||
updatedRow.applyAmount = this.editForm.applyAmount
|
|
||||||
updatedRow.payeeUnitId = this.editForm.payeeUnitId
|
|
||||||
updatedRow.payeeUnitName = this.editForm.payeeUnitName
|
|
||||||
updatedRow.remark = this.editForm.remark
|
|
||||||
|
|
||||||
// 更新行数据
|
|
||||||
this.$set(this.receiptDetails, this.editIndex, updatedRow)
|
|
||||||
|
|
||||||
// 如果此行已被选中,更新总金额
|
|
||||||
if (this.selectedItems.some(item => item === this.receiptDetails[this.editIndex])) {
|
|
||||||
this.calculateTotalAmount()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.editDialogVisible = false
|
|
||||||
this.$message.success('更新成功')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 确认开具收据
|
|
||||||
confirmIssue() {
|
|
||||||
if (this.selectedItems.length === 0) {
|
|
||||||
this.$message.warning('请至少选择一条收据明细')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.totalAmount <= 0) {
|
|
||||||
this.$message.warning('申请开据金额必须大于0')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$confirm('确认开具选中的收据?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.submitIssue()
|
|
||||||
}).catch(() => {})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 提交开具收据
|
|
||||||
submitIssue() {
|
|
||||||
this.submitting = true
|
|
||||||
|
|
||||||
// 构建请求数据
|
|
||||||
const receiptData = {
|
|
||||||
billId: this.billId,
|
|
||||||
receiptDate: new Date().toISOString().slice(0, 10), // 当前日期
|
|
||||||
paymentMethods: '1', // 默认现金
|
|
||||||
receiptDetails: this.selectedItems.map(item => ({
|
|
||||||
billId: this.billId,
|
|
||||||
billDetailId: item.billDetailId,
|
|
||||||
payerUnit: item.payerUnit,
|
|
||||||
availableAmount: item.availableAmount,
|
|
||||||
applyAmount: item.applyAmount,
|
|
||||||
feeType: item.feeType,
|
|
||||||
payeeUnitId: item.payeeUnitId,
|
|
||||||
payeeUnitName: item.payeeUnitName,
|
|
||||||
remark: item.remark
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
issueReceipt(receiptData).then(response => {
|
|
||||||
this.submitting = false
|
|
||||||
if (response.code === '0000000000000000') {
|
|
||||||
this.$message.success('收据开具成功')
|
|
||||||
// 返回上一页
|
|
||||||
this.$router.push('/finance/billList')
|
|
||||||
} else {
|
|
||||||
this.$message.error(response.message || '收据开具失败')
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
this.submitting = false
|
|
||||||
this.$message.error('收据开具失败: ' + (error.message || '未知错误'))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 格式化金额
|
|
||||||
formatAmount(amount) {
|
|
||||||
if (amount === undefined || amount === null) {
|
|
||||||
return '0.00 元'
|
|
||||||
}
|
|
||||||
return parseFloat(amount).toFixed(2) + ' 元'
|
|
||||||
},
|
|
||||||
|
|
||||||
// 返回上一页
|
|
||||||
goBack() {
|
|
||||||
this.$router.push('/finance/billList')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.issue-receipt-container {
|
|
||||||
padding: 20px;
|
|
||||||
|
|
||||||
.bill-info-section,
|
|
||||||
.receipt-details-section,
|
|
||||||
.receipt-summary-section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 0 0 15px;
|
|
||||||
padding-left: 10px;
|
|
||||||
border-left: 3px solid #409EFF;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-section-title {
|
|
||||||
margin: 15px 0 10px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
border-bottom: 1px solid #EBEEF5;
|
|
||||||
color: #303133;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.receipt-summary-section {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,829 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="收据详情"
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
width="80%"
|
|
||||||
:before-close="handleClose"
|
|
||||||
class="receipt-detail-dialog"
|
|
||||||
>
|
|
||||||
<el-card v-loading="loading" class="box-card">
|
|
||||||
<!-- 收据基本信息 -->
|
|
||||||
<div slot="header" class="card-header">
|
|
||||||
<span>收据基本信息</span>
|
|
||||||
</div>
|
|
||||||
<el-row :gutter="20" class="info-section">
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收据编号:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.receiptNumber }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">开据日期:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.receiptDate }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收据金额:</span>
|
|
||||||
<span class="info-value">{{ formatMoney(receiptInfo.receiptAmount) }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">支付方式:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.payModeName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">开据人:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.issuerName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">费用名称:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.feeNm }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">费用类型:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.feeTpName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收据模板:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.receiptFileName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">状态:</span>
|
|
||||||
<span class="info-value">
|
|
||||||
<el-tag :type="getStatusType(receiptInfo.receiptStatus)">{{ receiptInfo.receiptStatusName || getStatusText(receiptInfo.receiptStatus) }}</el-tag>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24" v-if="receiptInfo.receiptFileName">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收据文件:</span>
|
|
||||||
<el-dropdown>
|
|
||||||
<span class="el-dropdown-link file-link">
|
|
||||||
{{ receiptInfo.receiptFileName }}<i class="el-icon-arrow-down el-icon--right"></i>
|
|
||||||
</span>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item @click.native="downloadFile">下载</el-dropdown-item>
|
|
||||||
<el-dropdown-item @click.native="printFile">打印</el-dropdown-item>
|
|
||||||
<el-dropdown-item @click.native="handlePreviewFile">在线预览</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<!-- 交款方信息 -->
|
|
||||||
<div class="card-header section-header">
|
|
||||||
<span>交款方信息</span>
|
|
||||||
</div>
|
|
||||||
<el-row :gutter="20" class="info-section">
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">交款单位:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.paymUnitName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">交款人:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.pymerName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">电话:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.pymerPhone }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">地址:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.pymerAddr }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<!-- 收款方信息 -->
|
|
||||||
<div class="card-header section-header">
|
|
||||||
<span>收款方信息</span>
|
|
||||||
</div>
|
|
||||||
<el-row :gutter="20" class="info-section">
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收款单位:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.payeeUnitName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">收款人:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.payeeName }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">电话:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.payeePhone }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">地址:</span>
|
|
||||||
<span class="info-value">{{ receiptInfo.payeeAddr }}</span>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<!-- 款项明细 -->
|
|
||||||
<div class="card-header section-header">
|
|
||||||
<span>款项明细</span>
|
|
||||||
</div>
|
|
||||||
<el-table :data="receiptInfo.feeItems || []" border stripe class="fee-table">
|
|
||||||
<el-table-column label="费用类型" prop="feeTpName" min-width="150" />
|
|
||||||
<el-table-column label="金额" prop="amount" min-width="150">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
{{ formatMoney(row.amount) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<div class="amount-total">
|
|
||||||
<span class="amount-label">合计:</span>
|
|
||||||
<span class="amount-value">{{ formatMoney(receiptInfo.totalAmount) }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 开据账单 -->
|
|
||||||
<div class="card-header section-header">
|
|
||||||
<span>开据账单</span>
|
|
||||||
</div>
|
|
||||||
<el-table :data="receiptInfo.billInfos || []" border stripe>
|
|
||||||
<el-table-column label="账单编号" prop="billNumber" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="项目名称" prop="projectName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="楼宇名称" prop="buildingName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="房号" prop="roomNumber" min-width="80" show-overflow-tooltip />
|
|
||||||
<el-table-column label="租客" prop="payerName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="费用类型" prop="feeTpName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="应收" prop="receivableAmount" min-width="100">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
{{ formatMoney(row.receivableAmount) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="实收" prop="receivedAmount" min-width="100">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
{{ formatMoney(row.receivedAmount) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="开据金额" prop="receiptAmount" min-width="100">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
{{ formatMoney(row.receiptAmount) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="应收日期" prop="receivableDate" min-width="100" />
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<!-- 备注 -->
|
|
||||||
<div class="card-header section-header">
|
|
||||||
<span>备注</span>
|
|
||||||
</div>
|
|
||||||
<div class="remark-content">
|
|
||||||
{{ receiptInfo.remark || '无' }}
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openGenerateDialog" :disabled="!canGenerate">生成收据</el-button>
|
|
||||||
<el-button type="danger" @click="handleVoidReceipt" :disabled="!canVoid">作废</el-button>
|
|
||||||
<el-button @click="handleClose">关闭</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 生成收据弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
title="生成收据"
|
|
||||||
:visible.sync="generateReceiptDialog"
|
|
||||||
width="500px"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<el-form :model="generateForm" :rules="generateRules" ref="generateForm" label-width="100px">
|
|
||||||
<el-form-item label="收据模板" prop="templateId">
|
|
||||||
<el-select v-model="generateForm.templateId" placeholder="请选择收据模板" style="width: 100%">
|
|
||||||
<el-option
|
|
||||||
v-for="item in templateOptions"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.templateName"
|
|
||||||
:value="item.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="generateReceiptDialog = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleGenerateReceipt">确定并下载</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 作废收据弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
title="作废收据"
|
|
||||||
:visible.sync="voidReceiptDialog"
|
|
||||||
width="500px"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<el-form :model="voidForm" :rules="voidRules" ref="voidForm" label-width="100px">
|
|
||||||
<el-form-item label="作废原因" prop="reason">
|
|
||||||
<el-input
|
|
||||||
type="textarea"
|
|
||||||
:rows="3"
|
|
||||||
v-model="voidForm.reason"
|
|
||||||
placeholder="请输入作废原因"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="voidReceiptDialog = false">取消</el-button>
|
|
||||||
<el-button type="danger" @click="confirmVoidReceipt">确定作废</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 文件预览对话框 -->
|
|
||||||
<el-dialog title="收据预览" :visible.sync="previewDialogVisible" width="800px" append-to-body>
|
|
||||||
<div class="preview-container" v-loading="previewLoading">
|
|
||||||
<div v-if="previewUrl && isPdf" class="preview-iframe">
|
|
||||||
<!-- PDF文件可以直接嵌入预览 -->
|
|
||||||
<iframe :src="previewUrl" width="100%" height="500px" frameborder="0"></iframe>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="previewUrl && isOfficeDoc" class="preview-iframe">
|
|
||||||
<!-- Office文档需要下载后查看 -->
|
|
||||||
<div class="preview-doc-info">
|
|
||||||
<i class="el-icon-document"></i>
|
|
||||||
<p>Office文档需要下载后查看,请点击下方按钮下载查看</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="previewUrl && isImage" class="preview-image">
|
|
||||||
<img :src="previewUrl" style="max-width: 100%;" />
|
|
||||||
</div>
|
|
||||||
<div v-else-if="!previewLoading" class="preview-error">
|
|
||||||
<i class="el-icon-warning"></i>
|
|
||||||
<p>预览加载失败,请尝试下载后查看</p>
|
|
||||||
<div class="preview-actions">
|
|
||||||
<el-button type="primary" @click="downloadCurrentPreview" :disabled="previewLoading || (!currentPreviewId && !previewUrl)">下载文件</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="downloadCurrentPreview" :disabled="previewLoading || (!currentPreviewId && !previewUrl)">下载Word文件(.docx)</el-button>
|
|
||||||
<el-button @click="previewDialogVisible = false">关 闭</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
getReceiptRecordDetail,
|
|
||||||
generateReceipt,
|
|
||||||
downloadReceipt,
|
|
||||||
printReceipt,
|
|
||||||
previewReceipt,
|
|
||||||
voidReceipt,
|
|
||||||
downloadReceiptByFilename,
|
|
||||||
previewReceiptByFilename,
|
|
||||||
printReceiptByFilename
|
|
||||||
} from '@/api/finance'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ReceiptDetailDialog',
|
|
||||||
props: {
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
receiptId: {
|
|
||||||
type: [Number, String],
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible: false,
|
|
||||||
loading: false,
|
|
||||||
receiptInfo: {
|
|
||||||
downloadUrl: null,
|
|
||||||
printUrl: null,
|
|
||||||
previewUrl: null
|
|
||||||
},
|
|
||||||
statusMap: {
|
|
||||||
'0': { type: 'warning', text: '未发出' },
|
|
||||||
'1': { type: 'success', text: '已发出' },
|
|
||||||
'2': { type: 'info', text: '已回收' },
|
|
||||||
'3': { type: 'danger', text: '已作废' }
|
|
||||||
},
|
|
||||||
generateReceiptDialog: false,
|
|
||||||
generateForm: {
|
|
||||||
templateId: ''
|
|
||||||
},
|
|
||||||
generateRules: {
|
|
||||||
templateId: [{ required: true, message: '请选择收据模板', trigger: 'change' }]
|
|
||||||
},
|
|
||||||
templateOptions: [],
|
|
||||||
voidReceiptDialog: false,
|
|
||||||
voidForm: {
|
|
||||||
reason: ''
|
|
||||||
},
|
|
||||||
voidRules: {
|
|
||||||
reason: [{ required: true, message: '请输入作废原因', trigger: 'blur' }]
|
|
||||||
},
|
|
||||||
// 预览相关
|
|
||||||
previewDialogVisible: false,
|
|
||||||
previewLoading: false,
|
|
||||||
previewBlob: null,
|
|
||||||
currentPreviewName: '',
|
|
||||||
currentPreviewId: null,
|
|
||||||
isPdf: false,
|
|
||||||
isImage: false,
|
|
||||||
isOfficeDoc: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
canGenerate() {
|
|
||||||
// 非已作废状态都可以生成收据
|
|
||||||
return this.receiptInfo.receiptStatus && this.receiptInfo.receiptStatus !== '3'
|
|
||||||
},
|
|
||||||
canVoid() {
|
|
||||||
// 非已作废状态的收据可以作废
|
|
||||||
return this.receiptInfo.receiptStatus && this.receiptInfo.receiptStatus !== '3'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
visible(val) {
|
|
||||||
this.dialogVisible = val
|
|
||||||
if (val) {
|
|
||||||
this.getDetail()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dialogVisible(val) {
|
|
||||||
if (!val) {
|
|
||||||
this.$emit('update:visible', false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
init(row) {
|
|
||||||
this.dialogVisible = true
|
|
||||||
this.loading = true
|
|
||||||
this.receiptInfo = {
|
|
||||||
downloadUrl: null,
|
|
||||||
printUrl: null,
|
|
||||||
previewUrl: null
|
|
||||||
}
|
|
||||||
this.previewUrl = null
|
|
||||||
this.currentPreviewId = null
|
|
||||||
this.getDetail()
|
|
||||||
},
|
|
||||||
getDetail() {
|
|
||||||
this.loading = true
|
|
||||||
getReceiptRecordDetail(this.receiptId).then(response => {
|
|
||||||
this.receiptInfo = response.data
|
|
||||||
this.loading = false
|
|
||||||
// 获取可用的收据模板列表
|
|
||||||
if (response.data.templateFileNames && response.data.templateFileNames.length > 0) {
|
|
||||||
this.templateOptions = response.data.templateFileNames
|
|
||||||
} else {
|
|
||||||
this.getTemplateOptions()
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getTemplateOptions() {
|
|
||||||
// 这里应当根据楼宇ID获取相应的收据模板列表
|
|
||||||
// 为了演示,这里模拟一些模板数据
|
|
||||||
this.templateOptions = [
|
|
||||||
{ id: 1, templateName: '物业费收据模板' },
|
|
||||||
{ id: 2, templateName: '租金收据模板' },
|
|
||||||
{ id: 3, templateName: '水电费收据模板' }
|
|
||||||
]
|
|
||||||
// 如果已有收据模板ID,默认选中
|
|
||||||
if (this.receiptInfo.templateId) {
|
|
||||||
this.generateForm.templateId = this.receiptInfo.templateId
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatMoney(val) {
|
|
||||||
if (val === null || val === undefined) return '¥0.00'
|
|
||||||
return '¥' + parseFloat(val).toFixed(2)
|
|
||||||
},
|
|
||||||
getStatusType(status) {
|
|
||||||
return this.statusMap[status] ? this.statusMap[status].type : ''
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
return this.statusMap[status] ? this.statusMap[status].text : status
|
|
||||||
},
|
|
||||||
handleClose() {
|
|
||||||
this.dialogVisible = false
|
|
||||||
},
|
|
||||||
downloadFile() {
|
|
||||||
const receiptFileName = this.receiptInfo.receiptFileName
|
|
||||||
if (!receiptFileName) {
|
|
||||||
this.$message.error('收据文件名不存在')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadReceiptByFilename(receiptFileName).then(response => {
|
|
||||||
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' })
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = window.URL.createObjectURL(blob)
|
|
||||||
link.download = receiptFileName
|
|
||||||
link.click()
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('下载收据失败', error)
|
|
||||||
this.$message.error('下载收据失败')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
printFile() {
|
|
||||||
const receiptFileName = this.receiptInfo.receiptFileName
|
|
||||||
if (!receiptFileName) {
|
|
||||||
this.$message.error('收据文件名不存在')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$message.info('正在准备打印预览,请稍候...')
|
|
||||||
// 先进行预览操作,获取PDF内容
|
|
||||||
this.previewLoading = true
|
|
||||||
|
|
||||||
// 预览时使用PDF格式
|
|
||||||
previewReceiptByFilename(receiptFileName).then(response => {
|
|
||||||
try {
|
|
||||||
// 创建PDF blob对象
|
|
||||||
const blob = new Blob([response], { type: 'application/pdf' })
|
|
||||||
|
|
||||||
// 创建URL用于预览并打印
|
|
||||||
const printUrl = URL.createObjectURL(blob)
|
|
||||||
|
|
||||||
// 在新窗口中打开PDF进行打印
|
|
||||||
const printWindow = window.open('', '_blank')
|
|
||||||
|
|
||||||
if (printWindow) {
|
|
||||||
// 注入HTML内容
|
|
||||||
const htmlContent = `
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>打印预览 - ${receiptFileName}</title>
|
|
||||||
<style>
|
|
||||||
body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
|
|
||||||
#pdf-container { width: 100%; height: 100%; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<iframe id="pdf-container" src="${printUrl}" width="100%" height="100%" frameborder="0"></iframe>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 写入HTML内容
|
|
||||||
printWindow.document.open();
|
|
||||||
printWindow.document.write(htmlContent);
|
|
||||||
|
|
||||||
// 添加脚本
|
|
||||||
const scriptContent = `
|
|
||||||
// 监听打印事件
|
|
||||||
window.addEventListener('afterprint', function() {
|
|
||||||
// 打印完成后等待1秒关闭窗口
|
|
||||||
setTimeout(function() { window.close(); }, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 在iframe加载完成后自动打开打印对话框
|
|
||||||
document.getElementById('pdf-container').onload = function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
window.print();
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 如果用户10分钟内没有操作,自动关闭窗口
|
|
||||||
setTimeout(function() {
|
|
||||||
if(document.hasFocus()) window.close();
|
|
||||||
}, 600000);
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 创建并添加脚本
|
|
||||||
const scriptElement = printWindow.document.createElement('script');
|
|
||||||
scriptElement.textContent = scriptContent;
|
|
||||||
printWindow.document.head.appendChild(scriptElement);
|
|
||||||
|
|
||||||
// 完成文档写入
|
|
||||||
printWindow.document.close();
|
|
||||||
|
|
||||||
this.$message.success('打印预览已打开,打印完成后窗口将自动关闭')
|
|
||||||
} else {
|
|
||||||
this.$message.warning('打印窗口被阻止,请允许弹窗后重试')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.previewLoading = false
|
|
||||||
} catch (error) {
|
|
||||||
console.error('打印预览失败', error)
|
|
||||||
this.$message.error('打印预览失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取打印文件失败', error)
|
|
||||||
this.$message.error('获取打印文件失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handlePreviewFile() {
|
|
||||||
const receiptFileName = this.receiptInfo.receiptFileName
|
|
||||||
if (!receiptFileName) {
|
|
||||||
this.$message.error('收据文件名不存在')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.previewLoading = true
|
|
||||||
this.previewDialogVisible = true
|
|
||||||
this.currentPreviewName = receiptFileName.replace(/\.(docx|pdf)$/i, '') // 移除扩展名
|
|
||||||
this.previewUrl = null
|
|
||||||
this.currentPreviewId = null
|
|
||||||
this.isPdf = false
|
|
||||||
this.isImage = false
|
|
||||||
this.isOfficeDoc = false
|
|
||||||
|
|
||||||
// 默认使用PDF格式预览
|
|
||||||
previewReceiptByFilename(receiptFileName).then(response => {
|
|
||||||
try {
|
|
||||||
// 创建PDF blob对象
|
|
||||||
const blob = new Blob([response], { type: 'application/pdf' })
|
|
||||||
this.previewBlob = blob
|
|
||||||
this.isPdf = true
|
|
||||||
|
|
||||||
// 创建URL用于预览
|
|
||||||
this.previewUrl = URL.createObjectURL(blob)
|
|
||||||
this.previewLoading = false
|
|
||||||
} catch (error) {
|
|
||||||
console.error('预览失败', error)
|
|
||||||
this.$message.error('获取预览数据失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取预览文件失败', error)
|
|
||||||
this.$message.error('获取预览文件失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
downloadCurrentPreview() {
|
|
||||||
if (this.currentPreviewId) {
|
|
||||||
// 使用文件ID下载 - 下载为DOCX格式
|
|
||||||
this.$message.info('正在准备下载Word文件,请稍候...')
|
|
||||||
downloadReceipt(this.currentPreviewId).then(response => {
|
|
||||||
// 此时response直接是blob数据
|
|
||||||
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' })
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = window.URL.createObjectURL(blob)
|
|
||||||
link.download = this.currentPreviewName ? `${this.currentPreviewName}.docx` : `收据_${new Date().toISOString().slice(0, 10)}.docx`
|
|
||||||
link.click()
|
|
||||||
this.$message.success('Word文件下载成功')
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('下载收据失败', error)
|
|
||||||
this.$message.error('下载收据失败')
|
|
||||||
})
|
|
||||||
} else if (this.currentPreviewName) {
|
|
||||||
// 使用文件名下载(兼容旧逻辑)
|
|
||||||
this.$message.info('正在准备下载Word文件,请稍候...')
|
|
||||||
const fileName = this.currentPreviewName.endsWith('.docx') ? this.currentPreviewName : `${this.currentPreviewName}.docx`
|
|
||||||
downloadReceiptByFilename(fileName).then(response => {
|
|
||||||
// 此时response直接是blob数据
|
|
||||||
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' })
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = window.URL.createObjectURL(blob)
|
|
||||||
link.download = fileName
|
|
||||||
link.click()
|
|
||||||
this.$message.success('Word文件下载成功')
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('下载收据失败', error)
|
|
||||||
this.$message.error('下载收据失败')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$message.error('没有可下载的文件')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openGenerateDialog() {
|
|
||||||
this.generateReceiptDialog = true
|
|
||||||
},
|
|
||||||
handleGenerateReceipt() {
|
|
||||||
this.$refs.generateForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
const data = {
|
|
||||||
receiptId: this.receiptId,
|
|
||||||
templateId: this.generateForm.templateId
|
|
||||||
}
|
|
||||||
|
|
||||||
this.generateReceiptDialog = false
|
|
||||||
generateReceipt(data).then(response => {
|
|
||||||
if (response.code === '0000000000000000') {
|
|
||||||
this.$message.success('收据生成成功')
|
|
||||||
|
|
||||||
// 获取返回的文件ID - 检查返回类型
|
|
||||||
const outputFileId = typeof response.data === 'object' ?
|
|
||||||
(response.data.outputFileId || response.data.id || response.data) :
|
|
||||||
response.data
|
|
||||||
|
|
||||||
console.log('获取到的outputFileId:', outputFileId)
|
|
||||||
|
|
||||||
if (outputFileId) {
|
|
||||||
// 显示预览弹窗
|
|
||||||
this.previewDialogVisible = true
|
|
||||||
this.previewLoading = true
|
|
||||||
this.currentPreviewName = `收据_${this.receiptInfo.receiptNumber}_${new Date().toISOString().slice(0, 10)}`
|
|
||||||
this.previewUrl = null
|
|
||||||
this.isPdf = false
|
|
||||||
this.isImage = false
|
|
||||||
this.isOfficeDoc = false
|
|
||||||
this.currentPreviewId = outputFileId
|
|
||||||
|
|
||||||
// 使用文件ID进行预览 - 预览应该是PDF格式
|
|
||||||
previewReceipt(outputFileId).then(response => {
|
|
||||||
try {
|
|
||||||
// 此时response直接是blob数据
|
|
||||||
const blob = new Blob([response], { type: 'application/pdf' })
|
|
||||||
this.previewBlob = blob
|
|
||||||
this.previewUrl = URL.createObjectURL(blob)
|
|
||||||
this.isPdf = true
|
|
||||||
this.previewLoading = false
|
|
||||||
} catch (error) {
|
|
||||||
console.error('预览失败', error)
|
|
||||||
this.$message.error('获取预览数据失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取预览文件失败', error)
|
|
||||||
this.$message.error('获取预览文件失败')
|
|
||||||
this.previewLoading = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$message.warning('未获取到文件ID,无法预览')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 刷新详情数据
|
|
||||||
this.getDetail()
|
|
||||||
|
|
||||||
// 通知父组件刷新列表
|
|
||||||
this.$emit('refresh')
|
|
||||||
} else {
|
|
||||||
this.$message.error(response.message || '生成收据失败')
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('生成收据失败', error)
|
|
||||||
this.$message.error('生成收据失败')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleVoidReceipt() {
|
|
||||||
this.voidReceiptDialog = true
|
|
||||||
},
|
|
||||||
confirmVoidReceipt() {
|
|
||||||
this.$refs.voidForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
voidReceipt(this.receiptId).then(() => {
|
|
||||||
this.$message.success('收据已作废')
|
|
||||||
this.voidReceiptDialog = false
|
|
||||||
// 刷新详情数据
|
|
||||||
this.getDetail()
|
|
||||||
// 通知父组件刷新列表
|
|
||||||
this.$emit('refresh')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.box-card {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
border-top: 1px solid #EBEEF5;
|
|
||||||
padding-top: 15px;
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-section {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
.info-label {
|
|
||||||
color: #606266;
|
|
||||||
min-width: 80px;
|
|
||||||
}
|
|
||||||
.info-value {
|
|
||||||
color: #303133;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fee-table {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.amount-total {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin: 10px 0 20px;
|
|
||||||
.amount-label {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
.amount-value {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #409EFF;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.remark-content {
|
|
||||||
padding: 10px 0;
|
|
||||||
color: #606266;
|
|
||||||
min-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-link {
|
|
||||||
color: #409EFF;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-container {
|
|
||||||
min-height: 500px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-error {
|
|
||||||
text-align: center;
|
|
||||||
padding: 50px 0;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 48px;
|
|
||||||
color: #F56C6C;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #606266;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-iframe {
|
|
||||||
width: 100%;
|
|
||||||
height: 500px;
|
|
||||||
border: 1px solid #EBEEF5;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-image {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-actions {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-doc-info {
|
|
||||||
text-align: center;
|
|
||||||
padding: 50px 0;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 48px;
|
|
||||||
color: #409EFF;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #606266;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,234 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<div class="filter-container">
|
|
||||||
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
|
||||||
<el-form-item label="创建时间">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
@change="handleDateRangeChange"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="交款单位">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.paymUnitName"
|
|
||||||
placeholder="请输入交款单位"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收据编号">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.receiptNumber"
|
|
||||||
placeholder="请输入收据编号"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收款单位">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.payeeUnitName"
|
|
||||||
placeholder="请输入收款单位"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="费用名称">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.feeNm"
|
|
||||||
placeholder="请输入费用名称"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开据人">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.issuerName"
|
|
||||||
placeholder="请输入开据人"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收据状态">
|
|
||||||
<el-select v-model="queryParams.receiptStatus" placeholder="请选择" clearable>
|
|
||||||
<el-option label="未发出" value="0" />
|
|
||||||
<el-option label="已发出" value="1" />
|
|
||||||
<el-option label="已回收" value="2" />
|
|
||||||
<el-option label="已作废" value="3" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:data="receiptList"
|
|
||||||
border
|
|
||||||
stripe
|
|
||||||
highlight-current-row
|
|
||||||
@row-click="handleRowClick"
|
|
||||||
>
|
|
||||||
<el-table-column label="交款单位" prop="paymUnitName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="开据日期" prop="receiptDate" min-width="100" />
|
|
||||||
<el-table-column label="收据编号" prop="receiptNumber" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="开据金额" prop="receiptAmount" min-width="100">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
{{ row.receiptAmount ? '¥' + parseFloat(row.receiptAmount).toFixed(2) : '¥0.00' }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="交款人" prop="pymerName" min-width="100" show-overflow-tooltip />
|
|
||||||
<el-table-column label="收款单位" prop="payeeUnitName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="支付方式" prop="payModeName" min-width="100" />
|
|
||||||
<el-table-column label="楼宇名称" prop="buildingName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="收据状态" prop="receiptStatus" min-width="80">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
<el-tag :type="getStatusType(row.receiptStatus)">{{ row.receiptStatusName || getStatusText(row.receiptStatus) }}</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="费用名称" prop="feeNm" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="费用类型" prop="feeTpName" min-width="120" show-overflow-tooltip />
|
|
||||||
<el-table-column label="开据人" prop="issuerName" min-width="100" show-overflow-tooltip />
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<!-- 直接集成分页组件 -->
|
|
||||||
<div class="pagination-container" v-show="total > 0">
|
|
||||||
<el-pagination
|
|
||||||
background
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page.sync="queryParams.pageNum"
|
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
|
||||||
:page-size.sync="queryParams.pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 收据详情弹窗 -->
|
|
||||||
<receipt-detail-dialog
|
|
||||||
:visible.sync="detailDialogVisible"
|
|
||||||
:receipt-id="currentReceiptId"
|
|
||||||
@refresh="getList"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getReceiptRecordPage } from '@/api/finance'
|
|
||||||
import ReceiptDetailDialog from './components/ReceiptDetailDialog'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ReceiptRecord',
|
|
||||||
components: {
|
|
||||||
ReceiptDetailDialog
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
receiptList: [],
|
|
||||||
total: 0,
|
|
||||||
dateRange: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymUnitName: undefined,
|
|
||||||
receiptNumber: undefined,
|
|
||||||
payeeUnitName: undefined,
|
|
||||||
feeNm: undefined,
|
|
||||||
issuerName: undefined,
|
|
||||||
receiptStatus: undefined,
|
|
||||||
startDate: undefined,
|
|
||||||
endDate: undefined
|
|
||||||
},
|
|
||||||
statusMap: {
|
|
||||||
'0': { type: 'warning', text: '未发出' },
|
|
||||||
'1': { type: 'success', text: '已发出' },
|
|
||||||
'2': { type: 'info', text: '已回收' },
|
|
||||||
'3': { type: 'danger', text: '已作废' }
|
|
||||||
},
|
|
||||||
detailDialogVisible: false,
|
|
||||||
currentReceiptId: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true
|
|
||||||
getReceiptRecordPage(this.queryParams).then(response => {
|
|
||||||
this.receiptList = response.data.data
|
|
||||||
this.total = response.data.total
|
|
||||||
this.loading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleDateRangeChange(val) {
|
|
||||||
if (val) {
|
|
||||||
this.queryParams.startDate = val[0]
|
|
||||||
this.queryParams.endDate = val[1]
|
|
||||||
} else {
|
|
||||||
this.queryParams.startDate = undefined
|
|
||||||
this.queryParams.endDate = undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = []
|
|
||||||
this.queryParams = {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymUnitName: undefined,
|
|
||||||
receiptNumber: undefined,
|
|
||||||
payeeUnitName: undefined,
|
|
||||||
feeNm: undefined,
|
|
||||||
issuerName: undefined,
|
|
||||||
receiptStatus: undefined,
|
|
||||||
startDate: undefined,
|
|
||||||
endDate: undefined
|
|
||||||
}
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
getStatusType(status) {
|
|
||||||
return this.statusMap[status] ? this.statusMap[status].type : ''
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
return this.statusMap[status] ? this.statusMap[status].text : status
|
|
||||||
},
|
|
||||||
handleRowClick(row) {
|
|
||||||
this.currentReceiptId = row.id
|
|
||||||
this.detailDialogVisible = true
|
|
||||||
},
|
|
||||||
handleSizeChange(size) {
|
|
||||||
this.queryParams.pageSize = size
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
handleCurrentChange(current) {
|
|
||||||
this.queryParams.pageNum = current
|
|
||||||
this.getList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.filter-container {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
.pagination-container {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -10,15 +10,14 @@ module.exports = {
|
|||||||
warnings: false,
|
warnings: false,
|
||||||
errors: true
|
errors: true
|
||||||
},
|
},
|
||||||
proxy: {
|
// proxy: {
|
||||||
'/': {
|
// '/': {
|
||||||
// target: 'http://192.168.137.3:8080/api/api',
|
// target: 'http://192.168.137.214:8080',
|
||||||
target: 'http://192.168.137.214:8080/api',
|
// changeOrigin: true,
|
||||||
changeOrigin: true,
|
// pathRewrite: {
|
||||||
pathRewrite: {
|
// '^/api': '/api'
|
||||||
'^/api': '/api'
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user