Compare commits

...

2 Commits

9 changed files with 3129 additions and 92 deletions

View File

@ -579,6 +579,14 @@ export function getAllFinanceAccounts() {
})
}
// 获取流水账户级联选项
export function getAccountCascaderOptions() {
return request({
url: '/finance/account/cascader',
method: 'get'
})
}
// 账单调整相关接口
// 添加账单调整(按金额或按比例)
@ -590,6 +598,24 @@ 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) {
return request({
@ -710,4 +736,190 @@ export function deleteBillPaymentAttachment(attachmentId) {
url: `/v1/bill-payments/attachments/${attachmentId}`,
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'
})
}

View File

@ -36,6 +36,19 @@ export default {
component: () => import('@/views/finance/transaction/index.vue'),
name: 'Transaction',
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
}
]
}

View File

@ -4,8 +4,8 @@ import { API_SUCCESS_CODE } from './constants'
// 创建axios实例
const service = axios.create({
// baseURL: '/', // 修改为相对路径,使用代理
baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
baseURL: '/', // 修改为相对路径,使用代理
// baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
timeout: 10000 // 请求超时时间
})
@ -25,9 +25,9 @@ service.interceptors.request.use(
// 响应拦截器
service.interceptors.response.use(
response => {
// 如果是blob类型文件下载直接返回
// 如果是blob类型文件下载直接返回blob数据
if (response.config.responseType === 'blob') {
return response
return response.data
}
const res = response.data

File diff suppressed because it is too large Load Diff

View File

@ -33,10 +33,10 @@
</el-form-item>
<el-form-item label="结清状态" prop="clearStatus">
<el-select v-model="queryParams.clearStatus" placeholder="请选择结清状态" clearable multiple style="width: 220px">
<el-option label="未付款" value="0" />
<el-option label="已结清" value="1" />
<el-option label="部分结清" value="2" />
<el-option label="待退款" value="3" />
<el-option label="未付款" value="1" />
<el-option label="已结清" value="2" />
<el-option label="部分结清" value="3" />
<el-option label="待退款" value="4" />
<el-option label="待收款" value="5" />
<el-option label="对账确认中" value="6" />
<el-option label="已付款" value="7" />
@ -108,9 +108,21 @@
<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="pybDt" min-width="120" align="center" />
<el-table-column label="操作" width="150" align="center" fixed="right">
<el-table-column label="操作" width="200" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleViewDetail(scope.row)">查看</el-button>
<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>
</el-table-column>
</el-table>
@ -140,8 +152,11 @@
</el-dialog>
<!-- 账单详情对话框 -->
<el-dialog title="账单详情" :visible.sync="detailVisible" width="80%" append-to-body>
<el-dialog :visible.sync="detailVisible" width="80%" append-to-body title=" " :close-on-click-modal="false" :show-close="false">
<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>
</div>
</template>
@ -299,8 +314,9 @@ export default {
this.$refs.addBillForm.resetForm()
},
//
handleViewDetail(row) {
handleDetail(row) {
this.currentBill = row
console.log('打开账单详情ID:', row.id) //
this.detailVisible = true
},
//
@ -404,6 +420,24 @@ export default {
'7': '已付款'
}
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}`
})
}
}
}
@ -422,4 +456,8 @@ export default {
text-align: right;
}
}
::v-deep .el-dialog__body {
padding-top: 0;
}
</style>

View File

@ -0,0 +1,563 @@
<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>

View File

@ -0,0 +1,829 @@
<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 => {
// responseblob
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 => {
// responseblob
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 {
// responseblob
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>

View File

@ -0,0 +1,234 @@
<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>

View File

@ -10,14 +10,15 @@ module.exports = {
warnings: false,
errors: true
},
// proxy: {
// '/': {
// target: 'http://192.168.137.214:8080',
// changeOrigin: true,
// pathRewrite: {
// '^/api': '/api'
// }
// }
// }
proxy: {
'/': {
// target: 'http://192.168.137.3:8080/api/api',
target: 'http://192.168.137.214:8080/api',
changeOrigin: true,
pathRewrite: {
'^/api': '/api'
}
}
}
}
}