全部账单对接
This commit is contained in:
parent
9068135f26
commit
b573cfdb7f
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"element-china-area-data": "^6.1.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"mammoth": "^1.9.0",
|
"mammoth": "^1.9.0",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
|
@ -49,7 +49,10 @@
|
|||||||
"vue-router": "3.4.9",
|
"vue-router": "3.4.9",
|
||||||
"vuedraggable": "^2.24.3",
|
"vuedraggable": "^2.24.3",
|
||||||
"vuex": "3.6.0",
|
"vuex": "3.6.0",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5",
|
||||||
|
"element-china-area-data": "^6.1.0",
|
||||||
|
"mammoth": "^1.9.0",
|
||||||
|
"qrcode.vue": "^3.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "4.4.6",
|
"@vue/cli-plugin-babel": "4.4.6",
|
||||||
|
@ -416,7 +416,7 @@ export function uploadBillAttachment(billId, file) {
|
|||||||
formData.append('billId', billId)
|
formData.append('billId', billId)
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
return request({
|
return request({
|
||||||
url: '/bill/attachment/upload',
|
url: '/bill/upload-attachment',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
headers: {
|
||||||
@ -425,10 +425,11 @@ export function uploadBillAttachment(billId, file) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 账单附件删除
|
||||||
export function deleteBillAttachment(attachmentId) {
|
export function deleteBillAttachment(attachmentId) {
|
||||||
return request({
|
return request({
|
||||||
url: `/bill/attachment/${attachmentId}`,
|
url: `/bill/attachment/delete/${attachmentId}`,
|
||||||
method: 'delete'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,3 +448,266 @@ export function exportBillList(data) {
|
|||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 收支流水相关接口
|
||||||
|
export function getTransactionList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction/page',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTransactionDetail(id) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addTransaction(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTransaction(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportTransactionList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction/export',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTransactionAttachments(transactionId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/${transactionId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uploadTransactionAttachment(transactionId, file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('transactionId', transactionId)
|
||||||
|
formData.append('userId', localStorage.getItem('userId') || '')
|
||||||
|
formData.append('userName', localStorage.getItem('userName') || '')
|
||||||
|
formData.append('file', file)
|
||||||
|
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction/attachment',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteTransactionAttachment(attachmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/attachment/file/${attachmentId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function previewAttachment(attachmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/attachment/preview/file/${attachmentId}`,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function previewAttachmentByFileId(fileId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/attachment/preview/file/${fileId}`,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function downloadAttachment(fileId, fileName) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/attachment/download/${fileId}`,
|
||||||
|
method: 'get',
|
||||||
|
params: { fileName },
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteAttachmentByFileId(fileId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/attachment/file/${fileId}`,
|
||||||
|
method: 'delete',
|
||||||
|
params: {
|
||||||
|
userId: localStorage.getItem('userId') || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addTransactionOperation(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/transaction/operation',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTransactionOperationLogs(transactionId, query) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/transaction/${transactionId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有收支账户
|
||||||
|
export function getAllFinanceAccounts() {
|
||||||
|
return request({
|
||||||
|
url: '/finance/account/list',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账单调整相关接口
|
||||||
|
|
||||||
|
// 添加账单调整(按金额或按比例)
|
||||||
|
export function addBillAdjustment(data) {
|
||||||
|
return request({
|
||||||
|
url: '/v1/bill-adjustments',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 作废账单调整
|
||||||
|
export function voidBillAdjustment(data) {
|
||||||
|
return request({
|
||||||
|
url: '/v1/bill-adjustments/void',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页查询账单调整记录
|
||||||
|
export function getBillAdjustmentList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/v1/bill-adjustments',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取账单调整详情
|
||||||
|
export function getBillAdjustmentDetail(id) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-adjustments/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传账单调整附件
|
||||||
|
export function uploadBillAdjustmentAttachment(id, file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-adjustments/${id}/attachments`,
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除账单调整附件
|
||||||
|
export function deleteBillAdjustmentAttachment(attachmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-adjustments/attachments/${attachmentId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取账单明细
|
||||||
|
export function getBillDetailById(detailId) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-details/${detailId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取账单调整附件列表
|
||||||
|
export function getBillAdjustmentAttachmentList(adjustmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-adjustments/attachments/view/${adjustmentId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取账单操作记录
|
||||||
|
export function getBillOperationRecords(billId, params) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/operation-records/list/${billId}`,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账单支付相关接口
|
||||||
|
// 提交账单支付
|
||||||
|
export function submitBillPayment(data) {
|
||||||
|
return request({
|
||||||
|
url: '/v1/bill-payments',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页查询支付记录
|
||||||
|
export function getBillPaymentRecords(params) {
|
||||||
|
return request({
|
||||||
|
url: '/v1/bill-payments',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取支付详情
|
||||||
|
export function getBillPaymentDetail(id) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-payments/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传支付附件
|
||||||
|
export function uploadBillPaymentAttachment(id, file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-payments/${id}/attachments`,
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除支付附件
|
||||||
|
export function deleteBillPaymentAttachment(attachmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/v1/bill-payments/attachments/${attachmentId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
136
pc/src/components/RegionSelector.vue
Normal file
136
pc/src/components/RegionSelector.vue
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<el-cascader
|
||||||
|
v-model="selectedRegion"
|
||||||
|
:options="regionOptions"
|
||||||
|
:props="{ expandTrigger: 'hover', value: 'value', label: 'label' }"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
@change="handleChange"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { regionData, pcaTextArr } from 'element-china-area-data'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'RegionSelector',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [Array, String],
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请选择省/市/区'
|
||||||
|
},
|
||||||
|
// 是否使用纯文本数据
|
||||||
|
useTextData: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
regionOptions: this.useTextData ? pcaTextArr : regionData,
|
||||||
|
selectedRegion: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
// 处理传入的值,适配组件
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
// 如果是字符串,按空格分割为数组
|
||||||
|
const parts = val.split(' ').filter(item => item);
|
||||||
|
|
||||||
|
if (parts.length > 0) {
|
||||||
|
if (this.useTextData) {
|
||||||
|
// 如果使用纯文本数据,直接设置
|
||||||
|
this.selectedRegion = parts;
|
||||||
|
} else {
|
||||||
|
// 如果使用编码数据,需要转换成编码
|
||||||
|
this.convertTextToCode(parts);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.selectedRegion = [];
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(val)) {
|
||||||
|
// 已经是数组,直接使用
|
||||||
|
this.selectedRegion = val;
|
||||||
|
} else {
|
||||||
|
this.selectedRegion = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.selectedRegion = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 将文本转换为区域代码
|
||||||
|
convertTextToCode(textArray) {
|
||||||
|
// 由于没有TextToCode对象,我们需要手动查找
|
||||||
|
const findValueByLabel = (options, label, level = 0) => {
|
||||||
|
for (const option of options) {
|
||||||
|
if (option.label === label) {
|
||||||
|
return level === textArray.length - 1 ? option.value :
|
||||||
|
findValueByLabel(option.children || [], textArray[level + 1], level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = findValueByLabel(this.regionOptions, textArray[0], 0);
|
||||||
|
if (value) {
|
||||||
|
this.selectedRegion = value.split(',');
|
||||||
|
} else {
|
||||||
|
this.selectedRegion = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange(value) {
|
||||||
|
|
||||||
|
// 选择值改变时,转换为可读字符串并发送事件
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
const labels = this.getSelectedLabels(value);
|
||||||
|
const regionText = labels.join(' ');
|
||||||
|
this.$emit('input', regionText);
|
||||||
|
this.$emit('change', regionText, value, labels);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.$emit('input', '');
|
||||||
|
this.$emit('change', '', [], []);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getSelectedLabels(codes) {
|
||||||
|
// 根据选中的代码值获取对应的文本标签
|
||||||
|
const labels = [];
|
||||||
|
let options = this.regionOptions;
|
||||||
|
|
||||||
|
for (let i = 0; i < codes.length; i++) {
|
||||||
|
const code = codes[i];
|
||||||
|
const option = options.find(item => item.value === code);
|
||||||
|
|
||||||
|
if (option) {
|
||||||
|
labels.push(option.label);
|
||||||
|
options = option.children || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.el-cascader {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -30,6 +30,12 @@ export default {
|
|||||||
component: () => import('@/views/finance/billList/index.vue'),
|
component: () => import('@/views/finance/billList/index.vue'),
|
||||||
name: 'BillList',
|
name: 'BillList',
|
||||||
meta: { title: '所有账单', icon: 'el-icon-notebook-2' }
|
meta: { title: '所有账单', icon: 'el-icon-notebook-2' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'transaction',
|
||||||
|
component: () => import('@/views/finance/transaction/index.vue'),
|
||||||
|
name: 'Transaction',
|
||||||
|
meta: { title: '收支流水', icon: 'el-icon-money' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -5,8 +5,8 @@
|
|||||||
<el-form ref="chargeModeForm" :model="billForm" :rules="chargeModeRules" label-width="120px">
|
<el-form ref="chargeModeForm" :model="billForm" :rules="chargeModeRules" label-width="120px">
|
||||||
<el-form-item label="含税规则" prop="taxInclusiveRule" required>
|
<el-form-item label="含税规则" prop="taxInclusiveRule" required>
|
||||||
<el-radio-group v-model="billForm.taxInclusiveRule">
|
<el-radio-group v-model="billForm.taxInclusiveRule">
|
||||||
<el-radio label="含税">含税</el-radio>
|
<el-radio label="1" value="1">含税</el-radio>
|
||||||
<el-radio label="不含税">不含税</el-radio>
|
<el-radio label="2" value="2">不含税</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="税率(%)" prop="taxRate" required>
|
<el-form-item label="税率(%)" prop="taxRate" required>
|
||||||
@ -14,18 +14,18 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="特殊账单类型" prop="specialBillType" required>
|
<el-form-item label="特殊账单类型" prop="specialBillType" required>
|
||||||
<el-radio-group v-model="billForm.specialBillType">
|
<el-radio-group v-model="billForm.specialBillType">
|
||||||
<el-radio label="正常">正常</el-radio>
|
<el-radio label="1" value="1">正常</el-radio>
|
||||||
<el-radio label="罚金">罚金</el-radio>
|
<el-radio label="2" value="2">罚金</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="滞纳金起算天数" prop="lateFeeStartDays">
|
<el-form-item label="滞纳金起算天数" prop="ovdueStartDays">
|
||||||
<el-input-number v-model="billForm.lateFeeStartDays" :min="0" :precision="0" style="width: 200px"></el-input-number>
|
<el-input-number v-model="billForm.ovdueStartDays" :min="0" :precision="0" style="width: 200px"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="滞纳金比例(%/天)" prop="lateFeeRate">
|
<el-form-item label="滞纳金比例(%/天)" prop="ovdueIntRate">
|
||||||
<el-input-number v-model="billForm.lateFeeRate" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
<el-input-number v-model="billForm.ovdueIntRate" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="滞纳金上限(%)" prop="lateFeeLimit">
|
<el-form-item label="滞纳金上限(%)" prop="ovdueLimitRate">
|
||||||
<el-input-number v-model="billForm.lateFeeLimit" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
<el-input-number v-model="billForm.ovdueLimitRate" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
@ -64,8 +64,8 @@
|
|||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="付款方" prop="payeeId" required>
|
<el-form-item label="付款方" prop="paysdId" required>
|
||||||
<el-select v-model="billForm.payeeId" placeholder="请选择付款方" filterable remote clearable
|
<el-select v-model="billForm.paysdId" placeholder="请选择付款方" filterable remote clearable
|
||||||
:remote-method="searchPayees" @change="handlePayeeChange" style="width: 400px">
|
:remote-method="searchPayees" @change="handlePayeeChange" style="width: 400px">
|
||||||
<el-option v-for="item in payeeOptions" :key="item.id"
|
<el-option v-for="item in payeeOptions" :key="item.id"
|
||||||
:label="item.name" :value="item.id">
|
:label="item.name" :value="item.id">
|
||||||
@ -75,12 +75,12 @@
|
|||||||
<el-form-item label="币种" prop="currCode" required>
|
<el-form-item label="币种" prop="currCode" required>
|
||||||
<el-input v-model="billForm.currCode" disabled style="width: 400px"></el-input>
|
<el-input v-model="billForm.currCode" disabled style="width: 400px"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="应收金额" prop="receivableAmount" required>
|
<el-form-item label="应收金额" prop="accigRcvAmt" required>
|
||||||
<el-input-number v-model="billForm.receivableAmount" :min="0" :precision="2" style="width: 400px"></el-input-number>
|
<el-input-number v-model="billForm.accigRcvAmt" :min="0" :precision="2" style="width: 400px"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="应收日期" prop="receivableDate" required>
|
<el-form-item label="应收日期" prop="pybDt" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="billForm.receivableDate"
|
v-model="billForm.pybDt"
|
||||||
type="date"
|
type="date"
|
||||||
placeholder="选择日期"
|
placeholder="选择日期"
|
||||||
value-format="yyyy-MM-dd"
|
value-format="yyyy-MM-dd"
|
||||||
@ -139,18 +139,39 @@
|
|||||||
<el-table-column label="操作" width="200" align="center">
|
<el-table-column label="操作" width="200" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" @click="previewFile(scope.row)">预览</el-button>
|
<el-button size="mini" type="text" @click="previewFile(scope.row)">预览</el-button>
|
||||||
<el-button size="mini" type="text" @click="downloadFile(scope.row)">下载</el-button>
|
|
||||||
<el-button size="mini" type="text" class="delete-btn" @click="deleteFile(scope.$index)">删除</el-button>
|
<el-button size="mini" type="text" class="delete-btn" @click="deleteFile(scope.$index)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
|
<!-- 文件预览对话框 -->
|
||||||
|
<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">
|
||||||
|
<iframe :src="previewUrl" width="100%" height="500px" frameborder="0"></iframe>
|
||||||
|
</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">下载文件</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="previewDialogVisible = false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getFeeTypeTree } from '@/api/finance'
|
import { getFeeTypeTree, uploadBillAttachment, addBill } from '@/api/finance'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AddBill',
|
name: 'AddBill',
|
||||||
@ -167,30 +188,28 @@ export default {
|
|||||||
billForm: {
|
billForm: {
|
||||||
contractId: '',
|
contractId: '',
|
||||||
contractNumber: '',
|
contractNumber: '',
|
||||||
payeeId: '',
|
paysdId: '',
|
||||||
payeeName: '',
|
paysdName: '',
|
||||||
payeeContact: '',
|
payeeContact: '',
|
||||||
feeCategoryId: '',
|
feeCategoryId: '',
|
||||||
feeTypeId: '',
|
feeTypeId: '',
|
||||||
feeTypeName: '',
|
feTpName: '',
|
||||||
currCode: '156', // 默认人民币
|
currCode: '156', // 默认人民币
|
||||||
billingStartDate: '',
|
chggBgnDt: '',
|
||||||
billingEndDate: '',
|
chggEndDt: '',
|
||||||
receivableAmount: 0,
|
accigRcvAmt: 0,
|
||||||
price: 0,
|
taxInclusiveRule: '1',
|
||||||
priceU: '元/月',
|
|
||||||
taxInclusiveRule: '含税',
|
|
||||||
taxRate: 0,
|
taxRate: 0,
|
||||||
receivableDate: '',
|
pybDt: '',
|
||||||
specialBillType: '正常',
|
specialBillType: '1',
|
||||||
lateFeeStartDays: 0,
|
ovdueStartDays: 0,
|
||||||
lateFeeRate: 0,
|
ovdueIntRate: 0,
|
||||||
lateFeeLimit: 0,
|
ovdueLimitRate: 0,
|
||||||
companyId: '',
|
companyId: '',
|
||||||
companyName: '',
|
corNm: '',
|
||||||
accountId: '',
|
accountId: '',
|
||||||
billRemark: '',
|
billRemark: '',
|
||||||
roomInfoList: []
|
roomIds: []
|
||||||
},
|
},
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
chargeModeRules: {
|
chargeModeRules: {
|
||||||
@ -205,7 +224,7 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
billInfoRules: {
|
billInfoRules: {
|
||||||
payeeId: [
|
paysdId: [
|
||||||
{ required: true, message: '请选择付款方', trigger: 'change' }
|
{ required: true, message: '请选择付款方', trigger: 'change' }
|
||||||
],
|
],
|
||||||
companyId: [
|
companyId: [
|
||||||
@ -214,10 +233,10 @@ export default {
|
|||||||
accountId: [
|
accountId: [
|
||||||
{ required: true, message: '请选择收支账户', trigger: 'change' }
|
{ required: true, message: '请选择收支账户', trigger: 'change' }
|
||||||
],
|
],
|
||||||
receivableAmount: [
|
accigRcvAmt: [
|
||||||
{ required: true, message: '请输入应收金额', trigger: 'blur' }
|
{ required: true, message: '请输入应收金额', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
receivableDate: [
|
pybDt: [
|
||||||
{ required: true, message: '请选择应收日期', trigger: 'change' }
|
{ required: true, message: '请选择应收日期', trigger: 'change' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -244,7 +263,16 @@ export default {
|
|||||||
selectedRoomIds: [],
|
selectedRoomIds: [],
|
||||||
// 附件上传相关
|
// 附件上传相关
|
||||||
fileList: [],
|
fileList: [],
|
||||||
attachmentLoading: false
|
attachmentLoading: false,
|
||||||
|
|
||||||
|
// 预览相关
|
||||||
|
previewDialogVisible: false,
|
||||||
|
previewLoading: false,
|
||||||
|
previewUrl: '',
|
||||||
|
previewBlob: null,
|
||||||
|
currentPreviewName: '',
|
||||||
|
isPdf: false,
|
||||||
|
isImage: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -280,10 +308,10 @@ export default {
|
|||||||
children = category.financeFeeTypes.map(feeType => {
|
children = category.financeFeeTypes.map(feeType => {
|
||||||
return {
|
return {
|
||||||
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
||||||
label: feeType.feeTypeName || '未命名费用',
|
label: feeType.feTpName || '未命名费用',
|
||||||
categoryId: categoryId,
|
categoryId: categoryId,
|
||||||
// 存储原始数据以便后续使用
|
// 存储原始数据以便后续使用
|
||||||
feeTypeName: feeType.feeTypeName || '未命名费用',
|
feTpName: feeType.feTpName || '未命名费用',
|
||||||
// 确保没有更多的子节点
|
// 确保没有更多的子节点
|
||||||
children: null
|
children: null
|
||||||
}
|
}
|
||||||
@ -302,7 +330,7 @@ export default {
|
|||||||
getCompanyOptions() {
|
getCompanyOptions() {
|
||||||
// 模拟数据,实际应调用API
|
// 模拟数据,实际应调用API
|
||||||
this.companyOptions = [
|
this.companyOptions = [
|
||||||
{ id: 'C001', name: '智慧园区物业管理有限公司' }
|
{ id: 123, name: '智慧园区物业管理有限公司' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// 获取收支账户选项
|
// 获取收支账户选项
|
||||||
@ -318,8 +346,8 @@ export default {
|
|||||||
if (query) {
|
if (query) {
|
||||||
// 实际应调用API
|
// 实际应调用API
|
||||||
this.contractOptions = [
|
this.contractOptions = [
|
||||||
{ contractId: 'CT001', contractNumber: 'HT2023001', customerName: '张三' },
|
{ contractId: 11, contractNumber: 'HT2023001', customerName: '张三' },
|
||||||
{ contractId: 'CT002', contractNumber: 'HT2023002', customerName: '李四' }
|
{ contractId: 22, contractNumber: 'HT2023002', customerName: '李四' }
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
this.contractOptions = []
|
this.contractOptions = []
|
||||||
@ -338,19 +366,21 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 处理付款方变更
|
// 处理付款方变更
|
||||||
handlePayeeChange(payeeId) {
|
handlePayeeChange(paysdId) {
|
||||||
const payee = this.payeeOptions.find(item => item.id === payeeId)
|
const payee = this.payeeOptions.find(item => item.id === paysdId)
|
||||||
if (payee) {
|
if (payee) {
|
||||||
this.billForm.payeeName = payee.name
|
this.billForm.paysdName = payee.name
|
||||||
this.billForm.payeeContact = payee.contact
|
this.billForm.payeeContact = payee.contact
|
||||||
// 触发表单验证更新
|
// 触发表单验证更新
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.billInfoForm.validateField('payeeId')
|
this.$refs.billInfoForm.validateField('paysdId')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 处理费用类型变更
|
// 处理费用类型变更
|
||||||
handleFeeTypeChange(value) {
|
handleFeeTypeChange(value) {
|
||||||
|
console.log(value);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
// 查找匹配的费用类型
|
// 查找匹配的费用类型
|
||||||
let selectedFeeType = null;
|
let selectedFeeType = null;
|
||||||
@ -370,7 +400,7 @@ export default {
|
|||||||
}
|
}
|
||||||
// 检查子节点
|
// 检查子节点
|
||||||
if (category.children && category.children.length > 0) {
|
if (category.children && category.children.length > 0) {
|
||||||
const found = category.children.find(item => item.id === value);
|
const found = category.children.find(item => item.id === value[1]);
|
||||||
if (found) {
|
if (found) {
|
||||||
selectedCategory = category;
|
selectedCategory = category;
|
||||||
selectedFeeType = {
|
selectedFeeType = {
|
||||||
@ -389,25 +419,25 @@ export default {
|
|||||||
if (selectedFeeType.type === '分类') {
|
if (selectedFeeType.type === '分类') {
|
||||||
this.billForm.feeCategoryId = selectedFeeType.id;
|
this.billForm.feeCategoryId = selectedFeeType.id;
|
||||||
this.billForm.feeTypeId = '';
|
this.billForm.feeTypeId = '';
|
||||||
this.billForm.feeTypeName = selectedFeeType.name;
|
this.billForm.feTpName = selectedFeeType.name;
|
||||||
} else {
|
} else {
|
||||||
this.billForm.feeCategoryId = selectedCategory.id;
|
this.billForm.feeCategoryId = selectedCategory.id;
|
||||||
this.billForm.feeTypeId = selectedFeeType.id;
|
this.billForm.feeTypeId = selectedFeeType.id;
|
||||||
this.billForm.feeTypeName = selectedFeeType.name;
|
this.billForm.feTpName = selectedFeeType.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 清空选择
|
// 清空选择
|
||||||
this.billForm.feeCategoryId = '';
|
this.billForm.feeCategoryId = '';
|
||||||
this.billForm.feeTypeId = '';
|
this.billForm.feeTypeId = '';
|
||||||
this.billForm.feeTypeName = '';
|
this.billForm.feTpName = '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 处理公司变更
|
// 处理公司变更
|
||||||
handleCompanyChange(companyId) {
|
handleCompanyChange(companyId) {
|
||||||
const company = this.companyOptions.find(item => item.id === companyId)
|
const company = this.companyOptions.find(item => item.id === companyId)
|
||||||
if (company) {
|
if (company) {
|
||||||
this.billForm.companyName = company.name
|
this.billForm.corNm = company.name
|
||||||
// 触发表单验证更新
|
// 触发表单验证更新
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.billInfoForm.validateField('companyId')
|
this.$refs.billInfoForm.validateField('companyId')
|
||||||
@ -420,11 +450,11 @@ export default {
|
|||||||
// 处理计费周期变更
|
// 处理计费周期变更
|
||||||
handleBillingPeriodChange(val) {
|
handleBillingPeriodChange(val) {
|
||||||
if (val && val.length === 2) {
|
if (val && val.length === 2) {
|
||||||
this.billForm.billingStartDate = val[0]
|
this.billForm.chggBgnDt = val[0]
|
||||||
this.billForm.billingEndDate = val[1]
|
this.billForm.chggEndDt = val[1]
|
||||||
} else {
|
} else {
|
||||||
this.billForm.billingStartDate = ''
|
this.billForm.chggBgnDt = ''
|
||||||
this.billForm.billingEndDate = ''
|
this.billForm.chggEndDt = ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -525,9 +555,6 @@ export default {
|
|||||||
// 更新选中的房间ID列表
|
// 更新选中的房间ID列表
|
||||||
this.selectedRoomIds = roomNodes.map(node => node.id)
|
this.selectedRoomIds = roomNodes.map(node => node.id)
|
||||||
|
|
||||||
// 重置房源信息列表
|
|
||||||
this.billForm.roomInfoList = []
|
|
||||||
|
|
||||||
// 创建一个Map用于收集项目信息
|
// 创建一个Map用于收集项目信息
|
||||||
const projectMap = new Map()
|
const projectMap = new Map()
|
||||||
|
|
||||||
@ -553,20 +580,63 @@ export default {
|
|||||||
|
|
||||||
// 只有完整路径的房间才处理
|
// 只有完整路径的房间才处理
|
||||||
if (roomInfo && floorNode && buildingNode && projectNode) {
|
if (roomInfo && floorNode && buildingNode && projectNode) {
|
||||||
// 更新房源信息列表
|
// 确认项目是否已在Map中
|
||||||
this.billForm.roomInfoList.push({
|
if (!projectMap.has(projectNode.id)) {
|
||||||
roomId: roomNode.id,
|
projectMap.set(projectNode.id, {
|
||||||
roomNumber: roomInfo.roomNumber || roomNode.label.split('(')[0],
|
id: projectNode.id,
|
||||||
buildingId: buildingNode.id,
|
|
||||||
buildingName: buildingNode.label,
|
|
||||||
floorId: floorNode.id,
|
|
||||||
floorName: floorNode.label,
|
|
||||||
projectId: projectNode.id,
|
|
||||||
projectName: projectNode.label,
|
projectName: projectNode.label,
|
||||||
rentArea: roomInfo.rentalArea || 0
|
projectType: '产业园区', // 如果有projectType属性,应该使用projectNode中的值
|
||||||
|
buildings: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前项目
|
||||||
|
const project = projectMap.get(projectNode.id)
|
||||||
|
|
||||||
|
// 查找楼宇
|
||||||
|
let building = project.buildings.find(b => b.id === buildingNode.id)
|
||||||
|
if (!building) {
|
||||||
|
building = {
|
||||||
|
id: buildingNode.id,
|
||||||
|
buildingName: buildingNode.label,
|
||||||
|
buildingCode: '', // 如果有buildingCode属性,应该使用buildingNode中的值
|
||||||
|
floors: []
|
||||||
|
}
|
||||||
|
project.buildings.push(building)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找楼层
|
||||||
|
let floor = building.floors.find(f => f.id === floorNode.id)
|
||||||
|
if (!floor) {
|
||||||
|
floor = {
|
||||||
|
id: floorNode.id,
|
||||||
|
floorName: floorNode.label,
|
||||||
|
floorNumber: 0, // 如果有floorNumber属性,应该使用floorNode中的值
|
||||||
|
rooms: []
|
||||||
|
}
|
||||||
|
building.floors.push(floor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加房间
|
||||||
|
const room = {
|
||||||
|
id: roomInfo.id,
|
||||||
|
roomNumber: roomInfo.roomNumber || roomNode.label.split('(')[0],
|
||||||
|
roomType: roomInfo.roomType || '',
|
||||||
|
roomStatus: roomInfo.roomStatus || '1',
|
||||||
|
buildingArea: roomInfo.buildingArea || 0,
|
||||||
|
rentalArea: roomInfo.rentalArea || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查该房间是否已经存在
|
||||||
|
const roomExists = floor.rooms.some(r => r.id === room.id)
|
||||||
|
if (!roomExists) {
|
||||||
|
floor.rooms.push(room)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 将Map转换为数组
|
||||||
|
this.billForm.roomIds = Array.from(projectMap.values())
|
||||||
},
|
},
|
||||||
// 上传文件前检查
|
// 上传文件前检查
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
@ -586,32 +656,87 @@ export default {
|
|||||||
// 自定义上传文件
|
// 自定义上传文件
|
||||||
uploadFile(options) {
|
uploadFile(options) {
|
||||||
this.attachmentLoading = true
|
this.attachmentLoading = true
|
||||||
|
const file = options.file
|
||||||
|
|
||||||
|
// 创建临时URL供预览
|
||||||
|
const tempUrl = URL.createObjectURL(file)
|
||||||
|
const fileName = file.name
|
||||||
|
|
||||||
|
// 向上传列表中添加文件
|
||||||
|
const currentUser = this.$store.getters.name || '当前用户'
|
||||||
|
|
||||||
// 此处模拟上传,实际应调用API
|
|
||||||
setTimeout(() => {
|
|
||||||
this.fileList.push({
|
this.fileList.push({
|
||||||
name: options.file.name,
|
name: fileName,
|
||||||
url: URL.createObjectURL(options.file),
|
file: file,
|
||||||
operatorName: '当前用户',
|
url: tempUrl,
|
||||||
|
operatorName: currentUser,
|
||||||
operateTime: new Date().toLocaleString()
|
operateTime: new Date().toLocaleString()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.attachmentLoading = false
|
this.attachmentLoading = false
|
||||||
this.$message.success('上传成功')
|
this.$message.success('上传成功')
|
||||||
}, 1000)
|
|
||||||
|
console.log(this.fileList);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 预览文件
|
// 预览文件
|
||||||
previewFile(file) {
|
previewFile(file) {
|
||||||
window.open(file.url)
|
this.previewLoading = true
|
||||||
|
this.previewDialogVisible = true
|
||||||
|
this.currentPreviewName = file.name || '附件'
|
||||||
|
this.previewUrl = ''
|
||||||
|
this.isPdf = false
|
||||||
|
this.isImage = false
|
||||||
|
|
||||||
|
// 根据文件名后缀判断文件类型
|
||||||
|
const fileExt = file.name ? file.name.split('.').pop().toLowerCase() : ''
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取文件内容进行预览
|
||||||
|
const blob = file.file ? file.file : new Blob()
|
||||||
|
this.previewBlob = blob
|
||||||
|
|
||||||
|
// 设置文件类型标志
|
||||||
|
if (fileExt === 'pdf') {
|
||||||
|
this.isPdf = true
|
||||||
|
} else if (['jpg', 'jpeg', 'png', 'gif'].includes(fileExt)) {
|
||||||
|
this.isImage = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建URL用于预览
|
||||||
|
this.previewUrl = file.url || URL.createObjectURL(blob)
|
||||||
|
this.previewLoading = false
|
||||||
|
} catch (error) {
|
||||||
|
console.error('预览失败', error)
|
||||||
|
this.$message.error('获取预览数据失败')
|
||||||
|
this.previewLoading = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 下载当前预览的文件
|
||||||
|
downloadCurrentPreview() {
|
||||||
|
if (!this.previewUrl) {
|
||||||
|
this.$message.error('没有可下载的文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = this.previewUrl
|
||||||
|
link.setAttribute('download', this.currentPreviewName)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
},
|
||||||
|
|
||||||
// 下载文件
|
// 下载文件
|
||||||
downloadFile(file) {
|
downloadFile(file) {
|
||||||
// 实际应调用API下载
|
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.href = file.url
|
link.href = file.url
|
||||||
link.download = file.name
|
link.download = file.name
|
||||||
link.click()
|
link.click()
|
||||||
},
|
},
|
||||||
|
|
||||||
// 删除文件
|
// 删除文件
|
||||||
deleteFile(index) {
|
deleteFile(index) {
|
||||||
this.$confirm('确认删除该附件?', '提示', {
|
this.$confirm('确认删除该附件?', '提示', {
|
||||||
@ -631,8 +756,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.formExtension.billingPeriod && this.formExtension.billingPeriod.length === 2) {
|
if (this.formExtension.billingPeriod && this.formExtension.billingPeriod.length === 2) {
|
||||||
this.billForm.billingStartDate = this.formExtension.billingPeriod[0]
|
this.billForm.chggBgnDt = this.formExtension.billingPeriod[0]
|
||||||
this.billForm.billingEndDate = this.formExtension.billingPeriod[1]
|
this.billForm.chggEndDt = this.formExtension.billingPeriod[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.billForm
|
return this.billForm
|
||||||
@ -665,7 +790,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证是否选择了房源
|
// 验证是否选择了房源
|
||||||
if (this.billForm.roomInfoList.length === 0) {
|
if (this.billForm.roomIds.length === 0) {
|
||||||
this.$message.warning('请至少选择一个房源')
|
this.$message.warning('请至少选择一个房源')
|
||||||
this.activeTab = 'roomInfo'
|
this.activeTab = 'roomInfo'
|
||||||
resolve(false)
|
resolve(false)
|
||||||
@ -698,30 +823,28 @@ export default {
|
|||||||
this.billForm = {
|
this.billForm = {
|
||||||
contractId: '',
|
contractId: '',
|
||||||
contractNumber: '',
|
contractNumber: '',
|
||||||
payeeId: '',
|
paysdId: '',
|
||||||
payeeName: '',
|
paysdName: '',
|
||||||
payeeContact: '',
|
payeeContact: '',
|
||||||
feeCategoryId: '',
|
feeCategoryId: '',
|
||||||
feeTypeId: '',
|
feeTypeId: '',
|
||||||
feeTypeName: '',
|
feTpName: '',
|
||||||
currCode: '156', // 默认人民币
|
currCode: '156', // 默认人民币
|
||||||
billingStartDate: '',
|
chggBgnDt: '',
|
||||||
billingEndDate: '',
|
chggEndDt: '',
|
||||||
receivableAmount: 0,
|
accigRcvAmt: 0,
|
||||||
price: 0,
|
taxInclusiveRule: '1',
|
||||||
priceU: '元/月',
|
|
||||||
taxInclusiveRule: '含税',
|
|
||||||
taxRate: 0,
|
taxRate: 0,
|
||||||
receivableDate: '',
|
pybDt: '',
|
||||||
specialBillType: '正常',
|
specialBillType: '1',
|
||||||
lateFeeStartDays: 0,
|
ovdueStartDays: 0,
|
||||||
lateFeeRate: 0,
|
ovdueIntRate: 0,
|
||||||
lateFeeLimit: 0,
|
ovdueLimitRate: 0,
|
||||||
companyId: '',
|
companyId: '',
|
||||||
companyName: '',
|
corNm: '',
|
||||||
accountId: '',
|
accountId: '',
|
||||||
billRemark: '',
|
billRemark: '',
|
||||||
roomInfoList: []
|
roomIds: []
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置扩展表单数据
|
// 重置扩展表单数据
|
||||||
@ -738,7 +861,62 @@ export default {
|
|||||||
|
|
||||||
// 重置文件上传列表
|
// 重置文件上传列表
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
|
},
|
||||||
|
// 表单提交
|
||||||
|
submitForm() {
|
||||||
|
this.validateForm().then(valid => {
|
||||||
|
if (valid) {
|
||||||
|
const formData = this.getFormData()
|
||||||
|
|
||||||
|
this.loading = true
|
||||||
|
addBill(formData)
|
||||||
|
.then(response => {
|
||||||
|
if (response.code === '0000000000000000') {
|
||||||
|
this.$message.success('添加账单成功')
|
||||||
|
|
||||||
|
// 如果有附件,上传附件
|
||||||
|
if (this.fileList.length > 0) {
|
||||||
|
|
||||||
|
this.uploadAttachments(response.data)
|
||||||
|
} else {
|
||||||
|
this.$emit('success')
|
||||||
|
this.resetForm()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.message || '添加账单失败')
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('添加账单失败', error)
|
||||||
|
this.$message.error('添加账单失败,请检查表单数据')
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传附件
|
||||||
|
uploadAttachments(billId) {
|
||||||
|
const uploadPromises = this.fileList.map(fileItem => {
|
||||||
|
return uploadBillAttachment(billId, fileItem.file)
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.all(uploadPromises)
|
||||||
|
.then(() => {
|
||||||
|
this.$message.success('附件上传成功')
|
||||||
|
this.$emit('success')
|
||||||
|
this.resetForm()
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('附件上传失败', error)
|
||||||
|
this.$message.warning('账单创建成功,但部分附件上传失败')
|
||||||
|
this.$emit('success')
|
||||||
|
this.resetForm()
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -755,4 +933,45 @@ export default {
|
|||||||
color: #F56C6C;
|
color: #F56C6C;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-container {
|
||||||
|
min-height: 500px;
|
||||||
|
max-height: 700px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.preview-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-error {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 300px;
|
||||||
|
color: #909399;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-actions {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
File diff suppressed because it is too large
Load Diff
@ -2,17 +2,17 @@
|
|||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<el-form :model="queryParams" ref="queryForm" :inline="true" class="search-form">
|
<el-form :model="queryParams" ref="queryForm" :inline="true" class="search-form">
|
||||||
<el-form-item label="合同编号" prop="contractNumber">
|
<el-form-item label="合同编号" prop="contractNo">
|
||||||
<el-input v-model="queryParams.contractNumber" placeholder="请输入合同编号" clearable style="width: 220px" />
|
<el-input v-model="queryParams.contractNo" placeholder="请输入合同编号" clearable style="width: 220px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="房号" prop="roomNumber">
|
<el-form-item label="房号" prop="roomNumber">
|
||||||
<el-input v-model="queryParams.roomNumber" placeholder="请输入房号" clearable style="width: 220px" />
|
<el-input v-model="queryParams.roomNumber" placeholder="请输入房号" clearable style="width: 220px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="对方名称" prop="payeeName">
|
<el-form-item label="对方名称" prop="paysdName">
|
||||||
<el-input v-model="queryParams.payeeName" placeholder="请输入对方名称" clearable style="width: 220px" />
|
<el-input v-model="queryParams.paysdName" placeholder="请输入对方名称" clearable style="width: 220px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="账单编号" prop="billNumber">
|
<el-form-item label="账单编号" prop="totBillNo">
|
||||||
<el-input v-model="queryParams.billNumber" placeholder="请输入账单编号" clearable style="width: 220px" />
|
<el-input v-model="queryParams.totBillNo" placeholder="请输入账单编号" clearable style="width: 220px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="账单状态" prop="billStatus">
|
<el-form-item label="账单状态" prop="billStatus">
|
||||||
<el-select v-model="queryParams.billStatus" placeholder="请选择账单状态" clearable multiple style="width: 220px">
|
<el-select v-model="queryParams.billStatus" placeholder="请选择账单状态" clearable multiple style="width: 220px">
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<el-option label="关闭" value="0" />
|
<el-option label="关闭" value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="应收时间" prop="receivableDate">
|
<el-form-item label="应收时间" prop="pybDt">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="dateRange"
|
v-model="dateRange"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
@ -77,11 +77,11 @@
|
|||||||
|
|
||||||
<!-- 表格区域 -->
|
<!-- 表格区域 -->
|
||||||
<el-table v-loading="loading" :data="billList" border>
|
<el-table v-loading="loading" :data="billList" border>
|
||||||
<el-table-column label="对方名称" prop="payeeName" min-width="120" show-overflow-tooltip />
|
<el-table-column label="对方名称" prop="paysdName" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column label="项目楼宇名称" prop="projectName" min-width="120" show-overflow-tooltip />
|
<el-table-column label="项目楼宇名称" prop="projectName" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column label="房号" prop="roomNumber" min-width="100" show-overflow-tooltip />
|
<el-table-column label="房号" prop="roomNumber" min-width="100" show-overflow-tooltip />
|
||||||
<el-table-column label="账单编号" prop="billNumber" min-width="150" show-overflow-tooltip />
|
<el-table-column label="账单编号" prop="totBillNo" min-width="150" show-overflow-tooltip />
|
||||||
<el-table-column label="合同编号" prop="contractNumber" min-width="150" show-overflow-tooltip />
|
<el-table-column label="合同编号" prop="contractNo" min-width="150" show-overflow-tooltip />
|
||||||
<el-table-column label="结清状态" min-width="100" align="center">
|
<el-table-column label="结清状态" min-width="100" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="getClearStatusType(scope.row.clearStatus)">
|
<el-tag :type="getClearStatusType(scope.row.clearStatus)">
|
||||||
@ -89,25 +89,25 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="费用类型" prop="feeTypeName" min-width="120" show-overflow-tooltip />
|
<el-table-column label="费用类型" prop="feTpName" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column label="账单金额" prop="billAmount" min-width="100" align="right">
|
<el-table-column label="账单金额" prop="accblAmt" min-width="100" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.billAmount ? scope.row.billAmount.toFixed(2) : '0.00' }}
|
{{ scope.row.accblAmt ? scope.row.accblAmt.toFixed(2) : '0.00' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="应收金额" prop="receivableAmount" min-width="100" align="right">
|
<el-table-column label="应收金额" prop="accigRcvAmt" min-width="100" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.receivableAmount ? scope.row.receivableAmount.toFixed(2) : '0.00' }}
|
{{ scope.row.accigRcvAmt ? scope.row.accigRcvAmt.toFixed(2) : '0.00' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实收金额" prop="receivedAmount" min-width="100" align="right">
|
<el-table-column label="实收金额" prop="atmRecvAmt" min-width="100" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.receivedAmount ? scope.row.receivedAmount.toFixed(2) : '0.00' }}
|
{{ scope.row.atmRecvAmt ? scope.row.atmRecvAmt.toFixed(2) : '0.00' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="开始日期" prop="billingStartDate" min-width="120" align="center" />
|
<el-table-column label="开始日期" prop="chggBgnDt" min-width="120" align="center" />
|
||||||
<el-table-column label="结束日期" prop="billingEndDate" min-width="120" align="center" />
|
<el-table-column label="结束日期" prop="chggEndDt" min-width="120" align="center" />
|
||||||
<el-table-column label="应收日期" prop="receivableDate" 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="150" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<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" icon="el-icon-view" @click="handleViewDetail(scope.row)">查看</el-button>
|
||||||
@ -171,10 +171,10 @@ export default {
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
contractNumber: '',
|
contractNo: '',
|
||||||
roomNumber: '',
|
roomNumber: '',
|
||||||
payeeName: '',
|
paysdName: '',
|
||||||
billNumber: '',
|
totBillNo: '',
|
||||||
billStatus: [],
|
billStatus: [],
|
||||||
receivableDateStart: '',
|
receivableDateStart: '',
|
||||||
receivableDateEnd: '',
|
receivableDateEnd: '',
|
||||||
@ -217,7 +217,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBillList(queryParams).then(response => {
|
getBillList(queryParams).then(response => {
|
||||||
this.billList = response.data.data || []
|
this.billList = response.data.list || []
|
||||||
this.total = response.data.total
|
this.total = response.data.total
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -250,10 +250,10 @@ export default {
|
|||||||
children = category.financeFeeTypes.map(feeType => {
|
children = category.financeFeeTypes.map(feeType => {
|
||||||
return {
|
return {
|
||||||
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
||||||
label: feeType.feeTypeName || '未命名费用',
|
label: feeType.feTpName || '未命名费用',
|
||||||
categoryId: categoryId,
|
categoryId: categoryId,
|
||||||
// 存储原始数据以便后续使用
|
// 存储原始数据以便后续使用
|
||||||
feeTypeName: feeType.feeTypeName || '未命名费用',
|
feTpName: feeType.feTpName || '未命名费用',
|
||||||
// 确保没有更多的子节点
|
// 确保没有更多的子节点
|
||||||
children: null
|
children: null
|
||||||
}
|
}
|
||||||
@ -353,12 +353,28 @@ export default {
|
|||||||
this.$refs.addBillForm.validateForm().then(valid => {
|
this.$refs.addBillForm.validateForm().then(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const billData = this.$refs.addBillForm.getFormData()
|
const billData = this.$refs.addBillForm.getFormData()
|
||||||
|
billData.billType = 1
|
||||||
|
billData.billSource = 3
|
||||||
|
|
||||||
addBill(billData).then(response => {
|
addBill(billData).then(response => {
|
||||||
|
if (response.code === '0000000000000000') {
|
||||||
this.$message.success('添加账单成功')
|
this.$message.success('添加账单成功')
|
||||||
|
|
||||||
|
// 如果有附件,上传附件
|
||||||
|
const fileList = this.$refs.addBillForm.fileList
|
||||||
|
if (fileList && fileList.length > 0) {
|
||||||
|
this.$refs.addBillForm.uploadAttachments(response.data)
|
||||||
|
// 上传附件由组件内部处理后续流程,不需要在这里关闭弹窗
|
||||||
|
} else {
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
this.getList()
|
this.getList()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.message || '添加账单失败')
|
||||||
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// 错误处理
|
// 错误处理
|
||||||
|
this.$message.error('添加账单失败')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,520 @@
|
|||||||
|
<template>
|
||||||
|
<div class="transaction-detail-container" v-loading="loading">
|
||||||
|
<!-- 详情主体 -->
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<!-- 总体信息 -->
|
||||||
|
<el-tab-pane label="总体信息" name="overall">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>总体信息</span>
|
||||||
|
</div>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="对方单位名称">{{ detailData.totalInfo && detailData.totalInfo.unitName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="总金额">
|
||||||
|
<span class="amount">{{ formatAmount(detailData.totalInfo && detailData.totalInfo.totalAmount) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="已匹配金额">
|
||||||
|
<span class="amount matched">{{ formatAmount(detailData.totalInfo && detailData.totalInfo.matchedAmount) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="未匹配金额">
|
||||||
|
<span class="amount unmatched">{{ formatAmount(detailData.totalInfo && detailData.totalInfo.unmatchedAmount) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 流水信息 -->
|
||||||
|
<el-tab-pane label="流水信息" name="transaction">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>流水信息</span>
|
||||||
|
</div>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="借贷标">
|
||||||
|
<el-tag :type="(detailData.transaction && detailData.transaction.dcFlagCode === '0') ? 'danger' : 'success'">
|
||||||
|
{{ (detailData.transaction && detailData.transaction.dcFlagCode === '0') ? '借(支出)' : '贷(收入)' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="发生额">
|
||||||
|
<span class="amount">{{ formatAmount(detailData.transaction && detailData.transaction.occuAmt) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="入账日期">{{ detailData.transaction && detailData.transaction.inaccDate || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="对方单位名称">{{ detailData.transaction && detailData.transaction.unitName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="支付方式">{{ getPaymentModeName(detailData.transaction && detailData.transaction.payModeName) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="对方账号">{{ detailData.transaction && detailData.transaction.opsAccname || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="凭证号">{{ detailData.transaction && detailData.transaction.txVchrNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="收据编号">{{ detailData.transaction && detailData.transaction.receiptNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="联系人">{{ detailData.transaction && detailData.transaction.conterName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="流水账户">{{ detailData.transaction && detailData.transaction.openaccBankName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="摘要">{{ detailData.transaction && detailData.transaction.summ || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="备注">{{ detailData.transaction && detailData.transaction.remark || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 匹配账单(新增的独立标签页) -->
|
||||||
|
<el-tab-pane label="匹配账单" name="matchBills">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>匹配账单</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="detailData.relatedBills || []" border style="width: 100%">
|
||||||
|
<el-table-column prop="unitName" label="对方名称" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="feeTypeName" label="费用类型" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="费用周期" min-width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.billingStartDate || '-' }} 至 {{ scope.row.billingEndDate || '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="receivableAmount" label="应收金额" min-width="120" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ formatAmount(scope.row.receivableAmount) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="!detailData.relatedBills || detailData.relatedBills.length === 0" class="empty-data">
|
||||||
|
暂无匹配账单
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 附件信息 -->
|
||||||
|
<el-tab-pane label="附件信息" name="attachment">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>附件信息</span>
|
||||||
|
<el-button style="float: right;" type="primary" size="small" @click="handleAddAttachment">
|
||||||
|
<i class="el-icon-plus"></i> 添加附件
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="detailData.attachments || []" border style="width: 100%">
|
||||||
|
<el-table-column prop="fileName" label="文件名" min-width="250" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="createUserName" label="操作人" width="150" />
|
||||||
|
<el-table-column prop="createTime" label="操作时间" width="180" />
|
||||||
|
<el-table-column label="操作" width="200" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" @click="previewFile(scope.row)">预览</el-button>
|
||||||
|
<el-button size="mini" type="text" @click="downloadFile(scope.row)">下载</el-button>
|
||||||
|
<el-button size="mini" type="text" class="delete-btn" @click="deleteFile(scope.$index, scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="!detailData.attachments || detailData.attachments.length === 0" class="empty-data">
|
||||||
|
暂无附件
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 文件上传对话框 -->
|
||||||
|
<el-dialog title="上传附件" :visible.sync="uploadDialogVisible" width="500px" append-to-body>
|
||||||
|
<el-upload
|
||||||
|
class="upload-area"
|
||||||
|
action="#"
|
||||||
|
:http-request="uploadFile"
|
||||||
|
:file-list="uploadFileList"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
multiple
|
||||||
|
:limit="10">
|
||||||
|
<el-button type="primary">点击上传</el-button>
|
||||||
|
<div slot="tip" class="el-upload__tip">只能上传jpg/png/pdf文件,且不超过5MB</div>
|
||||||
|
</el-upload>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="uploadDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmUpload">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 操作记录 -->
|
||||||
|
<el-tab-pane label="操作记录" name="logs">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>操作记录</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="detailData.operationRecords || []" border style="width: 100%" v-loading="logsLoading">
|
||||||
|
<el-table-column prop="oprPersonNm" label="操作人" width="150" />
|
||||||
|
<el-table-column prop="oprContent" label="操作内容" min-width="250" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="createTime" label="操作时间" width="180" />
|
||||||
|
</el-table>
|
||||||
|
<div v-if="!detailData.operationRecords || detailData.operationRecords.length === 0" class="empty-data">
|
||||||
|
暂无操作记录
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<!-- 文件预览对话框 -->
|
||||||
|
<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">
|
||||||
|
<iframe :src="previewUrl" width="100%" height="500px" frameborder="0"></iframe>
|
||||||
|
</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">下载文件</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="previewDialogVisible = false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getTransactionDetail,
|
||||||
|
uploadTransactionAttachment,
|
||||||
|
deleteTransactionAttachment,
|
||||||
|
getTransactionOperationLogs,
|
||||||
|
previewAttachment,
|
||||||
|
downloadAttachment,
|
||||||
|
addTransactionOperation
|
||||||
|
} from '@/api/finance'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TransactionDetail',
|
||||||
|
props: {
|
||||||
|
transactionId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
activeTab: 'overall',
|
||||||
|
detailData: {},
|
||||||
|
|
||||||
|
// 附件相关
|
||||||
|
uploadDialogVisible: false,
|
||||||
|
uploadFileList: [],
|
||||||
|
|
||||||
|
// 预览相关
|
||||||
|
previewDialogVisible: false,
|
||||||
|
previewLoading: false,
|
||||||
|
previewUrl: '',
|
||||||
|
previewBlob: null,
|
||||||
|
currentPreviewName: '',
|
||||||
|
isPdf: false,
|
||||||
|
isImage: false,
|
||||||
|
|
||||||
|
// 操作记录相关
|
||||||
|
logsLoading: false,
|
||||||
|
logsTotal: 0,
|
||||||
|
logsQuery: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
transactionId: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getDetail()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取流水详情
|
||||||
|
getDetail() {
|
||||||
|
this.loading = true
|
||||||
|
getTransactionDetail(this.transactionId).then(response => {
|
||||||
|
this.detailData = response.data || {}
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取操作记录
|
||||||
|
getOperationLogs() {
|
||||||
|
this.logsLoading = true
|
||||||
|
this.logsQuery.transactionId = this.transactionId
|
||||||
|
getTransactionOperationLogs(this.logsQuery).then(response => {
|
||||||
|
if (this.detailData.operationRecords) {
|
||||||
|
this.detailData.operationRecords = response.data.data || []
|
||||||
|
}
|
||||||
|
this.logsTotal = response.data.total
|
||||||
|
this.logsLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.logsLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 操作记录分页大小改变
|
||||||
|
handleLogsSizeChange(val) {
|
||||||
|
this.logsQuery.pageSize = val
|
||||||
|
this.getOperationLogs()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 操作记录分页页码改变
|
||||||
|
handleLogsCurrentChange(val) {
|
||||||
|
this.logsQuery.pageNum = val
|
||||||
|
this.getOperationLogs()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 格式化金额
|
||||||
|
formatAmount(amount) {
|
||||||
|
if (amount === undefined || amount === null) {
|
||||||
|
return '0.00'
|
||||||
|
}
|
||||||
|
return parseFloat(amount).toFixed(2)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理添加附件
|
||||||
|
handleAddAttachment() {
|
||||||
|
this.uploadDialogVisible = true
|
||||||
|
this.uploadFileList = []
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传前检查
|
||||||
|
beforeUpload(file) {
|
||||||
|
const isValidType = ['image/jpeg', 'image/png', 'application/pdf'].includes(file.type)
|
||||||
|
const isLt5M = file.size / 1024 / 1024 < 5
|
||||||
|
|
||||||
|
if (!isValidType) {
|
||||||
|
this.$message.error('只能上传JPG/PNG/PDF格式的文件!')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLt5M) {
|
||||||
|
this.$message.error('文件大小不能超过5MB!')
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValidType && isLt5M
|
||||||
|
},
|
||||||
|
|
||||||
|
// 文件上传
|
||||||
|
uploadFile(options) {
|
||||||
|
// 先将文件加入上传列表,等确认后再统一上传
|
||||||
|
const file = options.file
|
||||||
|
|
||||||
|
// 创建临时URL供预览
|
||||||
|
const tempUrl = URL.createObjectURL(file)
|
||||||
|
|
||||||
|
// 向上传列表中添加文件
|
||||||
|
this.uploadFileList.push({
|
||||||
|
name: file.name,
|
||||||
|
file: file,
|
||||||
|
url: tempUrl
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确认上传
|
||||||
|
confirmUpload() {
|
||||||
|
if (this.uploadFileList.length === 0) {
|
||||||
|
this.$message.warning('请选择要上传的文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = this.$store.getters.userId || ''
|
||||||
|
const userName = this.$store.getters.name || ''
|
||||||
|
|
||||||
|
const uploadPromises = this.uploadFileList.map(fileItem => {
|
||||||
|
return uploadTransactionAttachment(this.transactionId, fileItem.file, userId, userName)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.loading = true
|
||||||
|
Promise.all(uploadPromises)
|
||||||
|
.then(() => {
|
||||||
|
this.$message.success('附件上传成功')
|
||||||
|
this.uploadDialogVisible = false
|
||||||
|
|
||||||
|
|
||||||
|
// 重新获取详情以更新附件列表
|
||||||
|
this.getDetail()
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.error('部分附件上传失败,请重试')
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 预览文件
|
||||||
|
previewFile(file) {
|
||||||
|
this.previewLoading = true
|
||||||
|
this.previewDialogVisible = true
|
||||||
|
this.currentPreviewName = file.fileName || '附件'
|
||||||
|
this.previewUrl = ''
|
||||||
|
this.isPdf = false
|
||||||
|
this.isImage = false
|
||||||
|
|
||||||
|
previewAttachment(file.fileId).then(response => {
|
||||||
|
// 判断文件类型
|
||||||
|
const contentType = response.headers['content-type']
|
||||||
|
|
||||||
|
// 创建blob对象
|
||||||
|
const blob = new Blob([response.data], { type: contentType })
|
||||||
|
this.previewBlob = blob
|
||||||
|
|
||||||
|
// 判断文件类型并设置标志
|
||||||
|
this.isPdf = contentType === 'application/pdf'
|
||||||
|
this.isImage = contentType.startsWith('image/')
|
||||||
|
|
||||||
|
// 创建URL用于预览
|
||||||
|
this.previewUrl = URL.createObjectURL(blob)
|
||||||
|
this.previewLoading = false
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('预览失败', error)
|
||||||
|
this.$message.error('获取预览数据失败')
|
||||||
|
this.previewLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下载当前预览的文件
|
||||||
|
downloadCurrentPreview() {
|
||||||
|
if (!this.previewBlob) {
|
||||||
|
this.$message.error('没有可下载的文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = URL.createObjectURL(this.previewBlob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.setAttribute('download', this.currentPreviewName)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下载文件
|
||||||
|
downloadFile(file) {
|
||||||
|
downloadAttachment(file.fileId, file.fileName).then(response => {
|
||||||
|
// 创建下载链接
|
||||||
|
const blob = new Blob([response.data])
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = window.URL.createObjectURL(blob)
|
||||||
|
link.download = file.fileName
|
||||||
|
link.style.display = 'none'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(link.href)
|
||||||
|
}).catch(() => {
|
||||||
|
this.$message.warning('无法下载该文件')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
deleteFile(index, file) {
|
||||||
|
this.$confirm('确认删除该附件?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
const userId = this.$store.getters.userId || ''
|
||||||
|
deleteTransactionAttachment(file.fileId, userId).then(() => {
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
if (this.detailData.attachments) {
|
||||||
|
this.detailData.attachments.splice(index, 1)
|
||||||
|
}
|
||||||
|
// 重新获取详情以更新附件列表
|
||||||
|
this.getDetail()
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 添加支付方式显示方法
|
||||||
|
getPaymentModeName(code) {
|
||||||
|
const paymentModeMap = {
|
||||||
|
'1': '现金',
|
||||||
|
'2': '网银转账',
|
||||||
|
'3': 'POS机',
|
||||||
|
'4': '支付宝',
|
||||||
|
'5': '微信',
|
||||||
|
'6': '转账支票',
|
||||||
|
'7': '其他方式',
|
||||||
|
'8': '线上支付'
|
||||||
|
}
|
||||||
|
return paymentModeMap[code] || code || '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.transaction-detail-container {
|
||||||
|
padding: 0 20px;
|
||||||
|
|
||||||
|
.amount {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409EFF;
|
||||||
|
|
||||||
|
&.matched {
|
||||||
|
color: #67C23A;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unmatched {
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-card {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-area {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-data {
|
||||||
|
color: #909399;
|
||||||
|
text-align: center;
|
||||||
|
padding: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-container {
|
||||||
|
min-height: 500px;
|
||||||
|
max-height: 700px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.preview-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-error {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 300px;
|
||||||
|
color: #909399;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-actions {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
352
pc/src/views/finance/transaction/index.vue
Normal file
352
pc/src/views/finance/transaction/index.vue
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-form :model="queryParams" ref="queryForm" :inline="true" class="search-form">
|
||||||
|
<el-form-item label="借贷标" prop="dcFlagCode">
|
||||||
|
<el-select v-model="queryParams.dcFlagCode" placeholder="请选择借贷标" clearable style="width: 200px">
|
||||||
|
<el-option label="借(支出)" value="0" />
|
||||||
|
<el-option label="贷(收入)" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付方式" prop="payModeName">
|
||||||
|
<el-select v-model="queryParams.payModeCode" placeholder="请选择支付方式" clearable style="width: 200px">
|
||||||
|
<el-option label="现金" value="1" />
|
||||||
|
<el-option label="网银转账" value="2" />
|
||||||
|
<el-option label="POS机" value="3" />
|
||||||
|
<el-option label="支付宝" value="4" />
|
||||||
|
<el-option label="微信" value="5" />
|
||||||
|
<el-option label="转账支票" value="6" />
|
||||||
|
<el-option label="其他方式" value="7" />
|
||||||
|
<el-option label="线上支付" value="8" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="流水账户" prop="accountId">
|
||||||
|
<el-select v-model="queryParams.accountId" placeholder="请选择流水账户" clearable filterable style="width: 200px">
|
||||||
|
<el-option v-for="item in accountOptions" :key="item.id" :label="item.accountName" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建人员" prop="createUserName">
|
||||||
|
<el-input v-model="queryParams.createUserName" placeholder="请输入创建人员" clearable style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="入账时间" prop="inaccDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="accountDateRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 240px">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间" prop="createDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="createDateRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 240px">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="发生额" prop="occuAmt">
|
||||||
|
<el-input-number v-model="queryParams.occuAmtMin" placeholder="最小值" :min="0" :precision="2" style="width: 110px" controls-position="right" />
|
||||||
|
<span style="margin: 0 5px;">-</span>
|
||||||
|
<el-input-number v-model="queryParams.occuAmtMax" placeholder="最大值" :min="0" :precision="2" style="width: 110px" controls-position="right" />
|
||||||
|
</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-button type="warning" icon="el-icon-download" style="float: right;" @click="handleExport">导出</el-button>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<el-table v-loading="loading" :data="transactionList" border>
|
||||||
|
<el-table-column label="项目楼宇名称" prop="projectName" min-width="120" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.projectName }} - {{ scope.row.buildingName }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="房号" prop="roomNo" min-width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column label="对方账号" prop="opsAccname" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column label="入账日期" prop="inaccDate" min-width="120" align="center" />
|
||||||
|
<el-table-column label="对方名称" prop="unitName" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="借贷标" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="scope.row.dcFlagCode === '0' ? 'danger' : 'success'">
|
||||||
|
{{ scope.row.dcFlagCode === '0' ? '借(支出)' : '贷(收入)' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="发生额" prop="occuAmt" min-width="100" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.occuAmt ? parseFloat(scope.row.occuAmt).toFixed(2) : '0.00' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="币种(单位)" prop="currCode" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ getCurrencyName(scope.row.currCode) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="支付方式" prop="payModeName" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ getPaymentModeName(scope.row.payModeName) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建人" prop="createUserId" min-width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column label="状态" prop="transactionStatus" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="getStatusType(scope.row.transactionStatus)">
|
||||||
|
{{ getStatusName(scope.row.transactionStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建日期" prop="createTime" min-width="120" align="center" />
|
||||||
|
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleViewDetail(scope.row)">查看</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="pagination-container">
|
||||||
|
<!-- 分页区域 -->
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page="queryParams.pageNum"
|
||||||
|
:page-sizes="[10, 20, 30, 50]"
|
||||||
|
:page-size="queryParams.pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 流水详情对话框 -->
|
||||||
|
<el-dialog title="收支流水详情" :visible.sync="detailVisible" width="80%" append-to-body>
|
||||||
|
<transaction-detail v-if="detailVisible" :transactionId="currentTransaction.id" />
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getTransactionList, exportTransactionList, getAllFinanceAccounts } from '@/api/finance'
|
||||||
|
import TransactionDetail from './components/TransactionDetail'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Transaction',
|
||||||
|
components: {
|
||||||
|
TransactionDetail
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 加载标志
|
||||||
|
loading: false,
|
||||||
|
// 收支流水列表数据
|
||||||
|
transactionList: [],
|
||||||
|
// 总记录数
|
||||||
|
total: 0,
|
||||||
|
// 入账时间范围
|
||||||
|
accountDateRange: [],
|
||||||
|
// 创建时间范围
|
||||||
|
createDateRange: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
dcFlagCode: undefined,
|
||||||
|
payModeCode: undefined,
|
||||||
|
accountId: undefined,
|
||||||
|
createUserName: undefined,
|
||||||
|
inaccDateStart: undefined,
|
||||||
|
inaccDateEnd: undefined,
|
||||||
|
createDateStart: undefined,
|
||||||
|
createDateEnd: undefined,
|
||||||
|
occuAmtMin: undefined,
|
||||||
|
occuAmtMax: undefined
|
||||||
|
},
|
||||||
|
// 收支账户选项
|
||||||
|
accountOptions: [],
|
||||||
|
// 详情对话框显示标志
|
||||||
|
detailVisible: false,
|
||||||
|
// 当前查看的流水详情
|
||||||
|
currentTransaction: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
// this.getAccountOptions()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取收支流水列表
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
// 处理查询参数
|
||||||
|
const queryParams = { ...this.queryParams }
|
||||||
|
|
||||||
|
// 处理入账时间范围
|
||||||
|
if (this.accountDateRange && this.accountDateRange.length > 0) {
|
||||||
|
queryParams.inaccDateStart = this.accountDateRange[0]
|
||||||
|
queryParams.inaccDateEnd = this.accountDateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理创建时间范围
|
||||||
|
if (this.createDateRange && this.createDateRange.length > 0) {
|
||||||
|
queryParams.createDateStart = this.createDateRange[0]
|
||||||
|
queryParams.createDateEnd = this.createDateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换支付方式编码为后端参数
|
||||||
|
if (queryParams.payModeCode) {
|
||||||
|
queryParams.payModeName = queryParams.payModeCode
|
||||||
|
delete queryParams.payModeCode
|
||||||
|
}
|
||||||
|
|
||||||
|
getTransactionList(queryParams).then(response => {
|
||||||
|
this.transactionList = response.data.data || []
|
||||||
|
this.total = response.data.total
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取收支账户选项
|
||||||
|
getAccountOptions() {
|
||||||
|
getAllFinanceAccounts().then(response => {
|
||||||
|
this.accountOptions = response.data || []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 搜索按钮操作
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 重置按钮操作
|
||||||
|
resetQuery() {
|
||||||
|
this.accountDateRange = []
|
||||||
|
this.createDateRange = []
|
||||||
|
this.$refs.queryForm.resetFields()
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 分页大小改变
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.queryParams.pageSize = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 分页页码改变
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.queryParams.pageNum = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 查看流水详情
|
||||||
|
handleViewDetail(row) {
|
||||||
|
this.currentTransaction = row
|
||||||
|
this.detailVisible = true
|
||||||
|
},
|
||||||
|
// 导出收支流水
|
||||||
|
handleExport() {
|
||||||
|
// 处理导出参数
|
||||||
|
const exportParams = { ...this.queryParams }
|
||||||
|
delete exportParams.pageNum
|
||||||
|
delete exportParams.pageSize
|
||||||
|
|
||||||
|
// 处理入账时间范围
|
||||||
|
if (this.accountDateRange && this.accountDateRange.length > 0) {
|
||||||
|
exportParams.inaccDateStart = this.accountDateRange[0]
|
||||||
|
exportParams.inaccDateEnd = this.accountDateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理创建时间范围
|
||||||
|
if (this.createDateRange && this.createDateRange.length > 0) {
|
||||||
|
exportParams.createDateStart = this.createDateRange[0]
|
||||||
|
exportParams.createDateEnd = this.createDateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$confirm('是否确认导出所有数据项?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
exportTransactionList(exportParams).then(response => {
|
||||||
|
// 创建下载链接
|
||||||
|
const blob = new Blob([response.data])
|
||||||
|
const fileName = `收支流水列表_${new Date().getTime()}.xlsx`
|
||||||
|
if (window.navigator.msSaveOrOpenBlob) {
|
||||||
|
// IE浏览器下载
|
||||||
|
navigator.msSaveBlob(blob, fileName)
|
||||||
|
} else {
|
||||||
|
// 非IE浏览器下载
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = window.URL.createObjectURL(blob)
|
||||||
|
link.download = fileName
|
||||||
|
link.style.display = 'none'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(link.href)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取币种名称
|
||||||
|
getCurrencyName(currency) {
|
||||||
|
const currencyMap = {
|
||||||
|
'156': '人民币',
|
||||||
|
'840': '美元',
|
||||||
|
'978': '欧元',
|
||||||
|
'826': '英镑',
|
||||||
|
'392': '日元'
|
||||||
|
}
|
||||||
|
return currencyMap[currency] || currency || '人民币'
|
||||||
|
},
|
||||||
|
// 获取状态类型
|
||||||
|
getStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'info',
|
||||||
|
'1': 'success'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
// 获取状态名称
|
||||||
|
getStatusName(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '处理中',
|
||||||
|
'1': '已完成'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知状态'
|
||||||
|
},
|
||||||
|
// 获取支付方式名称
|
||||||
|
getPaymentModeName(code) {
|
||||||
|
const paymentModeMap = {
|
||||||
|
'1': '现金',
|
||||||
|
'2': '网银转账',
|
||||||
|
'3': 'POS机',
|
||||||
|
'4': '支付宝',
|
||||||
|
'5': '微信',
|
||||||
|
'6': '转账支票',
|
||||||
|
'7': '其他方式',
|
||||||
|
'8': '线上支付'
|
||||||
|
}
|
||||||
|
return paymentModeMap[code] || code || '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -63,7 +63,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所属地区">
|
<el-form-item label="所属地区">
|
||||||
<el-input v-model="queryParams.region" placeholder="请输入所属地区" clearable size="small" />
|
<region-selector v-model="queryParams.region" :value="queryParams.region" placeholder="请选择所属地区" size="small" @change="handleRegionChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
@ -133,7 +133,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="所属地区" prop="region">
|
<el-form-item label="所属地区" prop="region">
|
||||||
<el-input v-model="form.region" placeholder="请输入所属地区" />
|
<region-selector v-model="form.region" placeholder="请选择所属地区" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -223,9 +223,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getProjectList, getProjectDetail, addProject, updateProject, deleteProject, getAllProjectStatistics, getTagByType } from '@/api/project'
|
import { getProjectList, getProjectDetail, addProject, updateProject, deleteProject, getAllProjectStatistics, getTagByType } from '@/api/project'
|
||||||
|
import RegionSelector from '@/components/RegionSelector'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ProjectList',
|
name: 'ProjectList',
|
||||||
|
components: {
|
||||||
|
RegionSelector
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
// 遮罩层
|
||||||
@ -338,7 +342,9 @@ export default {
|
|||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.dialogTitle = '新增项目'
|
this.dialogTitle = '新增项目'
|
||||||
// 完全重置表单数据
|
// 完全重置表单数据
|
||||||
this.form = {}
|
this.form = {
|
||||||
|
region: '' // 初始化region为空字符串以确保组件正确绑定
|
||||||
|
}
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
@ -474,6 +480,10 @@ export default {
|
|||||||
// 重置表单和校验状态
|
// 重置表单和校验状态
|
||||||
this.form = {}
|
this.form = {}
|
||||||
this.$refs['form'].clearValidate()
|
this.$refs['form'].clearValidate()
|
||||||
|
},
|
||||||
|
handleRegionChange(regionText) {
|
||||||
|
|
||||||
|
this.queryParams.region = regionText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
// proxy: {
|
// proxy: {
|
||||||
// '/': {
|
// '/': {
|
||||||
// target: 'http://192.168.137.214:8082',
|
// target: 'http://192.168.137.214:8080',
|
||||||
// changeOrigin: true,
|
// changeOrigin: true,
|
||||||
// pathRewrite: {
|
// pathRewrite: {
|
||||||
// '^/api': '/api'
|
// '^/api': '/api'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user