业务财务相关页面对接
This commit is contained in:
parent
3ac7dbff00
commit
9068135f26
@ -1,4 +1,4 @@
|
|||||||
NODE_ENV = 'development'
|
NODE_ENV = 'development'
|
||||||
|
|
||||||
# 开发环境API地址
|
# 开发环境API地址
|
||||||
VUE_APP_BASE_API = http://192.168.137.3:8080/api
|
VUE_APP_BASE_API = http://192.168.137.3:8080/api/api
|
@ -68,7 +68,7 @@ export function getLabelFields() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
code: '000000',
|
code: '0000000000000000',
|
||||||
msg: 'success',
|
msg: 'success',
|
||||||
data: fieldData
|
data: fieldData
|
||||||
});
|
});
|
||||||
|
@ -337,4 +337,113 @@ export function getFeeTypeTree(params) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览账单
|
||||||
|
export function previewBill(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/charging-standard/bill/preview',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成账单
|
||||||
|
export function generateBill(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/charging-standard/bill/generate',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询账单-收费标准关联表数据
|
||||||
|
* @param {Object} data - 查询参数
|
||||||
|
* @returns {Promise} - 返回Promise对象
|
||||||
|
*/
|
||||||
|
export function getBillChargingStandardRelPage(data) {
|
||||||
|
return request({
|
||||||
|
url: '/finance/bill-charging-standard-rel/page',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取特定标准ID的绑定房间账单列表
|
||||||
|
* @param {string} standardId 收费标准ID
|
||||||
|
*/
|
||||||
|
export function getBillsByStandardId(standardId) {
|
||||||
|
return request({
|
||||||
|
url: `/finance/bill-charging-standard-rel/${standardId}/bills`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账单管理接口
|
||||||
|
export function addBill(data) {
|
||||||
|
return request({
|
||||||
|
url: '/bill/add',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBillList(data) {
|
||||||
|
return request({
|
||||||
|
url: '/bill/list',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBillDetail(billId) {
|
||||||
|
return request({
|
||||||
|
url: `/bill/detail/${billId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uploadBillAttachment(billId, file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('billId', billId)
|
||||||
|
formData.append('file', file)
|
||||||
|
return request({
|
||||||
|
url: '/bill/attachment/upload',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteBillAttachment(attachmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/bill/attachment/${attachmentId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBillAttachmentList(billId) {
|
||||||
|
return request({
|
||||||
|
url: `/bill/attachment/list/${billId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportBillList(data) {
|
||||||
|
return request({
|
||||||
|
url: '/bill/export',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
}
|
}
|
@ -24,6 +24,12 @@ export default {
|
|||||||
component: () => import('@/views/finance/chargeStandard/index.vue'),
|
component: () => import('@/views/finance/chargeStandard/index.vue'),
|
||||||
name: 'ChargeStandard',
|
name: 'ChargeStandard',
|
||||||
meta: { title: '收费标准', icon: 'el-icon-price-tag' }
|
meta: { title: '收费标准', icon: 'el-icon-price-tag' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'billList',
|
||||||
|
component: () => import('@/views/finance/billList/index.vue'),
|
||||||
|
name: 'BillList',
|
||||||
|
meta: { title: '所有账单', icon: 'el-icon-notebook-2' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ import { API_SUCCESS_CODE } from './constants'
|
|||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '/', // 修改为相对路径,使用代理
|
// baseURL: '/', // 修改为相对路径,使用代理
|
||||||
// baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
|
baseURL: process.env.VUE_APP_BASE_API, // 使用环境变量中的接口地址
|
||||||
|
|
||||||
timeout: 10000 // 请求超时时间
|
timeout: 10000 // 请求超时时间
|
||||||
})
|
})
|
||||||
|
@ -169,6 +169,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listClassification, getClassification, addClassification, updateClassification, delClassification, enableClassification, disableClassification, getClassificationTree, checkClassificationInUse, getChildClassifications, delClassificationBatch } from '@/api/asset/classification'
|
import { listClassification, getClassification, addClassification, updateClassification, delClassification, enableClassification, disableClassification, getClassificationTree, checkClassificationInUse, getChildClassifications, delClassificationBatch } from '@/api/asset/classification'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetClassification',
|
name: 'AssetClassification',
|
||||||
@ -262,7 +263,7 @@ export default {
|
|||||||
status: undefined // 获取所有状态的分类,包括启用和禁用
|
status: undefined // 获取所有状态的分类,包括启用和禁用
|
||||||
}
|
}
|
||||||
getClassificationTree(params).then(res => {
|
getClassificationTree(params).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 处理返回的树形数据,确保字段名称正确
|
// 处理返回的树形数据,确保字段名称正确
|
||||||
this.classTree = this.processTreeData(res.data)
|
this.classTree = this.processTreeData(res.data)
|
||||||
|
|
||||||
@ -363,7 +364,7 @@ export default {
|
|||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listClassification(this.queryParams).then(res => {
|
listClassification(this.queryParams).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 转换API返回数据结构为驼峰命名
|
// 转换API返回数据结构为驼峰命名
|
||||||
this.classList = this.convertSnakeToCamel(res.data.list)
|
this.classList = this.convertSnakeToCamel(res.data.list)
|
||||||
this.total = res.data.total
|
this.total = res.data.total
|
||||||
@ -420,7 +421,7 @@ export default {
|
|||||||
pageNum: this.queryParams.pageNum,
|
pageNum: this.queryParams.pageNum,
|
||||||
pageSize: this.queryParams.pageSize
|
pageSize: this.queryParams.pageSize
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.classList = this.convertSnakeToCamel(res.data.list)
|
this.classList = this.convertSnakeToCamel(res.data.list)
|
||||||
this.total = res.data.total
|
this.total = res.data.total
|
||||||
} else {
|
} else {
|
||||||
@ -472,7 +473,7 @@ export default {
|
|||||||
handleEdit(row) {
|
handleEdit(row) {
|
||||||
const id = row.id
|
const id = row.id
|
||||||
getClassification(id).then(res => {
|
getClassification(id).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 将API响应数据映射到表单字段,使用驼峰命名
|
// 将API响应数据映射到表单字段,使用驼峰命名
|
||||||
this.form = {
|
this.form = {
|
||||||
id: res.data.id,
|
id: res.data.id,
|
||||||
@ -524,7 +525,7 @@ export default {
|
|||||||
|
|
||||||
const method = this.form.id ? updateClassification : addClassification
|
const method = this.form.id ? updateClassification : addClassification
|
||||||
method(submitData).then(res => {
|
method(submitData).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('操作成功')
|
this.$message.success('操作成功')
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
|
|
||||||
@ -556,14 +557,14 @@ export default {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
// 先检查分类是否被使用
|
// 先检查分类是否被使用
|
||||||
checkClassificationInUse(row.id).then(res => {
|
checkClassificationInUse(row.id).then(res => {
|
||||||
if (res.code === '000000' && res.data) {
|
if (res.code === API_SUCCESS_CODE && res.data) {
|
||||||
this.$message.error('该分类已被使用,无法删除')
|
this.$message.error('该分类已被使用,无法删除')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 未被使用,执行删除操作
|
// 未被使用,执行删除操作
|
||||||
const lastModUserId = this.$store.getters.userId || ''
|
const lastModUserId = this.$store.getters.userId || ''
|
||||||
delClassification(row.id, lastModUserId).then(res => {
|
delClassification(row.id, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
// 重新获取树形结构,确保更新多级分类
|
// 重新获取树形结构,确保更新多级分类
|
||||||
this.getTree()
|
this.getTree()
|
||||||
@ -590,7 +591,7 @@ export default {
|
|||||||
const lastModUserId = this.$store.getters.userId || ''
|
const lastModUserId = this.$store.getters.userId || ''
|
||||||
const method = row.status === '1' ? disableClassification : enableClassification
|
const method = row.status === '1' ? disableClassification : enableClassification
|
||||||
method(row.id, lastModUserId).then(res => {
|
method(row.id, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success(`${action}成功`)
|
this.$message.success(`${action}成功`)
|
||||||
// 状态变更后,可能会影响树的显示,所以也需要刷新树
|
// 状态变更后,可能会影响树的显示,所以也需要刷新树
|
||||||
this.getTree()
|
this.getTree()
|
||||||
@ -663,7 +664,7 @@ export default {
|
|||||||
// 执行批量删除操作
|
// 执行批量删除操作
|
||||||
this.loading = true
|
this.loading = true
|
||||||
delClassificationBatch(selectedIds, lastModUserId).then(res => {
|
delClassificationBatch(selectedIds, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('批量删除成功')
|
this.$message.success('批量删除成功')
|
||||||
// 重新获取树形结构,确保更新多级分类
|
// 重新获取树形结构,确保更新多级分类
|
||||||
this.getTree()
|
this.getTree()
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
import { getAsset } from '@/api/asset/inventory'
|
import { getAsset } from '@/api/asset/inventory'
|
||||||
import { getClassificationTree } from '@/api/asset/classification'
|
import { getClassificationTree } from '@/api/asset/classification'
|
||||||
import { getLocationTree } from '@/api/asset/location'
|
import { getLocationTree } from '@/api/asset/location'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetDetail',
|
name: 'AssetDetail',
|
||||||
@ -89,7 +90,7 @@ export default {
|
|||||||
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
getAsset(this.assetId).then(response => {
|
getAsset(this.assetId).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.assetDetail = response.data || {}
|
this.assetDetail = response.data || {}
|
||||||
console.log('资产详情数据:', this.assetDetail)
|
console.log('资产详情数据:', this.assetDetail)
|
||||||
} else {
|
} else {
|
||||||
@ -134,7 +135,7 @@ export default {
|
|||||||
/** 获取资产分类树形选项 */
|
/** 获取资产分类树形选项 */
|
||||||
getClassificationOptions() {
|
getClassificationOptions() {
|
||||||
getClassificationTree({ status: '1' }).then(response => {
|
getClassificationTree({ status: '1' }).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.classificationOptions = this.processClassificationTree(response.data || [])
|
this.classificationOptions = this.processClassificationTree(response.data || [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -164,7 +165,7 @@ export default {
|
|||||||
/** 获取位置树选项 */
|
/** 获取位置树选项 */
|
||||||
getLocationOptions() {
|
getLocationOptions() {
|
||||||
getLocationTree().then(response => {
|
getLocationTree().then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.locationOptions = this.processLocationTree(response.data || [])
|
this.locationOptions = this.processLocationTree(response.data || [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -227,7 +227,6 @@ import { getAsset, addAsset, updateAsset, listCompanies, listUsers, uploadAssetI
|
|||||||
import { getClassificationTree } from '@/api/asset/classification'
|
import { getClassificationTree } from '@/api/asset/classification'
|
||||||
import { getLocationTree } from '@/api/asset/location'
|
import { getLocationTree } from '@/api/asset/location'
|
||||||
import { API_SUCCESS_CODE } from '@/utils/constants'
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetForm',
|
name: 'AssetForm',
|
||||||
props: {
|
props: {
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLabelConfig } from '@/api/asset/inventory'
|
import { getLabelConfig } from '@/api/asset/inventory'
|
||||||
import QrcodeVue from 'qrcode.vue'
|
import QrcodeVue from 'qrcode.vue'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetLabelPrint',
|
name: 'AssetLabelPrint',
|
||||||
@ -93,7 +94,7 @@ export default {
|
|||||||
getLabelConfig() {
|
getLabelConfig() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
getLabelConfig().then(response => {
|
getLabelConfig().then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.labelConfig = response.data
|
this.labelConfig = response.data
|
||||||
|
|
||||||
// 如果API返回了需要显示的字段,则使用API返回的字段
|
// 如果API返回了需要显示的字段,则使用API返回的字段
|
||||||
|
@ -267,6 +267,7 @@ import { getLocationTree } from '@/api/asset/location'
|
|||||||
import AssetDetail from './components/AssetDetail'
|
import AssetDetail from './components/AssetDetail'
|
||||||
import AssetForm from './components/AssetForm'
|
import AssetForm from './components/AssetForm'
|
||||||
import AssetLabelPrint from './components/AssetLabelPrint'
|
import AssetLabelPrint from './components/AssetLabelPrint'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetInventory',
|
name: 'AssetInventory',
|
||||||
@ -449,7 +450,7 @@ export default {
|
|||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listAssets(this.queryParams).then(response => {
|
listAssets(this.queryParams).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.assetList = response.data.list || []
|
this.assetList = response.data.list || []
|
||||||
this.total = response.data.total
|
this.total = response.data.total
|
||||||
}
|
}
|
||||||
@ -471,7 +472,7 @@ export default {
|
|||||||
/** 获取资产分类树形选项 */
|
/** 获取资产分类树形选项 */
|
||||||
getClassificationOptions() {
|
getClassificationOptions() {
|
||||||
getClassificationTree({ status: '1' }).then(response => {
|
getClassificationTree({ status: '1' }).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.classificationOptions = this.processClassificationTree(response.data || [])
|
this.classificationOptions = this.processClassificationTree(response.data || [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -480,7 +481,7 @@ export default {
|
|||||||
/** 获取资产位置树形选项 */
|
/** 获取资产位置树形选项 */
|
||||||
getLocationOptions() {
|
getLocationOptions() {
|
||||||
getLocationTree().then(response => {
|
getLocationTree().then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.locationOptions = this.processLocationTree(response.data || [])
|
this.locationOptions = this.processLocationTree(response.data || [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -529,7 +530,7 @@ export default {
|
|||||||
/** 获取公司选项 */
|
/** 获取公司选项 */
|
||||||
getCompanyOptions() {
|
getCompanyOptions() {
|
||||||
listCompanies().then(response => {
|
listCompanies().then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.companyOptions = response.data || []
|
this.companyOptions = response.data || []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -541,7 +542,7 @@ export default {
|
|||||||
this.adminLoading = true
|
this.adminLoading = true
|
||||||
listUsers({ name: query }).then(response => {
|
listUsers({ name: query }).then(response => {
|
||||||
this.adminLoading = false
|
this.adminLoading = false
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.adminOptions = response.data || []
|
this.adminOptions = response.data || []
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -672,7 +673,7 @@ export default {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
return deleteAsset(row.assetCode)
|
return deleteAsset(row.assetCode)
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
this.getList()
|
this.getList()
|
||||||
}
|
}
|
||||||
@ -694,7 +695,7 @@ export default {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
return deleteAssets(assetCodes)
|
return deleteAssets(assetCodes)
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('批量删除成功')
|
this.$message.success('批量删除成功')
|
||||||
this.getList()
|
this.getList()
|
||||||
}
|
}
|
||||||
@ -745,7 +746,7 @@ export default {
|
|||||||
this.upload.isUploading = false
|
this.upload.isUploading = false
|
||||||
this.$refs.upload.clearFiles()
|
this.$refs.upload.clearFiles()
|
||||||
this.upload.open = false
|
this.upload.open = false
|
||||||
if (response.code === '000000') {
|
if (response.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('导入成功' + (response.data && response.data.successCount ? response.data.successCount : 0) + '条数据')
|
this.$message.success('导入成功' + (response.data && response.data.successCount ? response.data.successCount : 0) + '条数据')
|
||||||
this.getList()
|
this.getList()
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ import {
|
|||||||
listLabelTemplates, addLabelTemplate, updateLabelTemplate,
|
listLabelTemplates, addLabelTemplate, updateLabelTemplate,
|
||||||
getLabelFields, getFieldSampleValues
|
getLabelFields, getFieldSampleValues
|
||||||
} from '@/api/asset/label'
|
} from '@/api/asset/label'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetLabel',
|
name: 'AssetLabel',
|
||||||
@ -153,7 +154,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const res = await listLabelTemplates();
|
const res = await listLabelTemplates();
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
const labelData = res.data;
|
const labelData = res.data;
|
||||||
this.labelId = labelData.id;
|
this.labelId = labelData.id;
|
||||||
@ -209,7 +210,7 @@ export default {
|
|||||||
async getFieldOptions() {
|
async getFieldOptions() {
|
||||||
try {
|
try {
|
||||||
const res = await getLabelFields();
|
const res = await getLabelFields();
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.availableFields = res.data || [];
|
this.availableFields = res.data || [];
|
||||||
console.log("获取到的字段选项: ", this.availableFields);
|
console.log("获取到的字段选项: ", this.availableFields);
|
||||||
} else {
|
} else {
|
||||||
@ -342,7 +343,7 @@ export default {
|
|||||||
|
|
||||||
savePromise.then(res => {
|
savePromise.then(res => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('标签设置保存成功');
|
this.$message.success('标签设置保存成功');
|
||||||
// 重新获取标签设置
|
// 重新获取标签设置
|
||||||
this.getLabelSettings();
|
this.getLabelSettings();
|
||||||
|
@ -174,6 +174,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listLocation, getLocation, addLocation, updateLocation, delLocation, enableLocation, disableLocation, getLocationTree, checkLocationInUse, getChildLocations, delLocationBatch, checkLocationCode } from '@/api/asset/location'
|
import { listLocation, getLocation, addLocation, updateLocation, delLocation, enableLocation, disableLocation, getLocationTree, checkLocationInUse, getChildLocations, delLocationBatch, checkLocationCode } from '@/api/asset/location'
|
||||||
|
import { API_SUCCESS_CODE } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetLocation',
|
name: 'AssetLocation',
|
||||||
@ -245,7 +246,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
checkLocationCode(this.form.id, value).then(res => {
|
checkLocationCode(this.form.id, value).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
callback()
|
callback()
|
||||||
} else {
|
} else {
|
||||||
@ -265,7 +266,7 @@ export default {
|
|||||||
status: undefined // 获取所有状态的位置
|
status: undefined // 获取所有状态的位置
|
||||||
}
|
}
|
||||||
getLocationTree(params).then(res => {
|
getLocationTree(params).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 处理返回的树形数据,确保字段名称正确
|
// 处理返回的树形数据,确保字段名称正确
|
||||||
this.locationTree = this.processTreeData(res.data)
|
this.locationTree = this.processTreeData(res.data)
|
||||||
|
|
||||||
@ -387,7 +388,7 @@ export default {
|
|||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listLocation(this.queryParams).then(res => {
|
listLocation(this.queryParams).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 转换API返回数据结构为驼峰命名
|
// 转换API返回数据结构为驼峰命名
|
||||||
this.locationList = this.convertSnakeToCamel(res.data.list)
|
this.locationList = this.convertSnakeToCamel(res.data.list)
|
||||||
this.total = res.data.total
|
this.total = res.data.total
|
||||||
@ -410,7 +411,7 @@ export default {
|
|||||||
pageNum: this.queryParams.pageNum,
|
pageNum: this.queryParams.pageNum,
|
||||||
pageSize: this.queryParams.pageSize
|
pageSize: this.queryParams.pageSize
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.locationList = this.convertSnakeToCamel(res.data.list)
|
this.locationList = this.convertSnakeToCamel(res.data.list)
|
||||||
this.total = res.data.total
|
this.total = res.data.total
|
||||||
} else {
|
} else {
|
||||||
@ -464,7 +465,7 @@ export default {
|
|||||||
handleEdit(row) {
|
handleEdit(row) {
|
||||||
const id = row.id
|
const id = row.id
|
||||||
getLocation(id).then(res => {
|
getLocation(id).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
// 将API响应数据映射到表单字段,使用驼峰命名
|
// 将API响应数据映射到表单字段,使用驼峰命名
|
||||||
this.form = {
|
this.form = {
|
||||||
id: res.data.id,
|
id: res.data.id,
|
||||||
@ -518,7 +519,7 @@ export default {
|
|||||||
|
|
||||||
const method = this.form.id ? updateLocation : addLocation
|
const method = this.form.id ? updateLocation : addLocation
|
||||||
method(submitData).then(res => {
|
method(submitData).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('操作成功')
|
this.$message.success('操作成功')
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
|
|
||||||
@ -550,14 +551,14 @@ export default {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
// 先检查位置是否被使用
|
// 先检查位置是否被使用
|
||||||
checkLocationInUse(row.id).then(res => {
|
checkLocationInUse(row.id).then(res => {
|
||||||
if (res.code === '000000' && res.data) {
|
if (res.code === API_SUCCESS_CODE && res.data) {
|
||||||
this.$message.error('该位置已被使用,无法删除')
|
this.$message.error('该位置已被使用,无法删除')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 未被使用,执行删除操作
|
// 未被使用,执行删除操作
|
||||||
const lastModUserId = this.$store.getters.userId || ''
|
const lastModUserId = this.$store.getters.userId || ''
|
||||||
delLocation(row.id, lastModUserId).then(res => {
|
delLocation(row.id, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
// 重新获取树形结构,确保更新多级结构
|
// 重新获取树形结构,确保更新多级结构
|
||||||
this.getTree()
|
this.getTree()
|
||||||
@ -584,7 +585,7 @@ export default {
|
|||||||
const lastModUserId = this.$store.getters.userId || ''
|
const lastModUserId = this.$store.getters.userId || ''
|
||||||
const method = row.status === '1' ? disableLocation : enableLocation
|
const method = row.status === '1' ? disableLocation : enableLocation
|
||||||
method(row.id, lastModUserId).then(res => {
|
method(row.id, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success(`${action}成功`)
|
this.$message.success(`${action}成功`)
|
||||||
// 状态变更后,可能会影响树的显示,所以也需要刷新树
|
// 状态变更后,可能会影响树的显示,所以也需要刷新树
|
||||||
this.getTree()
|
this.getTree()
|
||||||
@ -657,7 +658,7 @@ export default {
|
|||||||
// 执行批量删除操作
|
// 执行批量删除操作
|
||||||
this.loading = true
|
this.loading = true
|
||||||
delLocationBatch(selectedIds, lastModUserId).then(res => {
|
delLocationBatch(selectedIds, lastModUserId).then(res => {
|
||||||
if (res.code === '000000') {
|
if (res.code === API_SUCCESS_CODE) {
|
||||||
this.$message.success('批量删除成功')
|
this.$message.success('批量删除成功')
|
||||||
// 重新获取树形结构,确保更新多级结构
|
// 重新获取树形结构,确保更新多级结构
|
||||||
this.getTree()
|
this.getTree()
|
||||||
|
758
pc/src/views/finance/billList/components/AddBill.vue
Normal file
758
pc/src/views/finance/billList/components/AddBill.vue
Normal file
@ -0,0 +1,758 @@
|
|||||||
|
<template>
|
||||||
|
<div class="add-bill-container">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<el-tab-pane label="收费模式" name="chargeMode">
|
||||||
|
<el-form ref="chargeModeForm" :model="billForm" :rules="chargeModeRules" label-width="120px">
|
||||||
|
<el-form-item label="含税规则" prop="taxInclusiveRule" required>
|
||||||
|
<el-radio-group v-model="billForm.taxInclusiveRule">
|
||||||
|
<el-radio label="含税">含税</el-radio>
|
||||||
|
<el-radio label="不含税">不含税</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="税率(%)" prop="taxRate" required>
|
||||||
|
<el-input-number v-model="billForm.taxRate" :min="0" :max="100" :precision="2" style="width: 200px"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="特殊账单类型" prop="specialBillType" required>
|
||||||
|
<el-radio-group v-model="billForm.specialBillType">
|
||||||
|
<el-radio label="正常">正常</el-radio>
|
||||||
|
<el-radio label="罚金">罚金</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="滞纳金起算天数" prop="lateFeeStartDays">
|
||||||
|
<el-input-number v-model="billForm.lateFeeStartDays" :min="0" :precision="0" style="width: 200px"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="滞纳金比例(%/天)" prop="lateFeeRate">
|
||||||
|
<el-input-number v-model="billForm.lateFeeRate" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="滞纳金上限(%)" prop="lateFeeLimit">
|
||||||
|
<el-input-number v-model="billForm.lateFeeLimit" :min="0" :max="100" :precision="10" style="width: 200px"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="账单信息" name="billInfo">
|
||||||
|
<el-form ref="formExtension" :model="formExtension" :rules="formExtensionRules" label-width="120px" style="margin-bottom: 20px;">
|
||||||
|
<el-form-item label="费用类型" prop="feeTypeSelected" required>
|
||||||
|
<el-cascader v-model="formExtension.feeTypeSelected" :options="feeTypeOptions" :props="{
|
||||||
|
label: 'label',
|
||||||
|
value: 'id',
|
||||||
|
children: 'children',
|
||||||
|
expandTrigger: 'hover'
|
||||||
|
}"
|
||||||
|
clearable filterable placeholder="请选择费用类型" @change="handleFeeTypeChange" style="width: 400px">
|
||||||
|
</el-cascader>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="计费周期" prop="billingPeriod" required>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formExtension.billingPeriod"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
@change="handleBillingPeriodChange"
|
||||||
|
style="width: 400px">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form ref="billInfoForm" :model="billForm" :rules="billInfoRules" label-width="120px">
|
||||||
|
<el-form-item label="关联合同" prop="contractId">
|
||||||
|
<el-select v-model="billForm.contractId" placeholder="请选择关联合同" filterable remote clearable
|
||||||
|
:remote-method="searchContracts" style="width: 400px">
|
||||||
|
<el-option v-for="item in contractOptions" :key="item.contractId"
|
||||||
|
:label="item.contractNumber + ' - ' + item.customerName" :value="item.contractId">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="付款方" prop="payeeId" required>
|
||||||
|
<el-select v-model="billForm.payeeId" placeholder="请选择付款方" filterable remote clearable
|
||||||
|
:remote-method="searchPayees" @change="handlePayeeChange" style="width: 400px">
|
||||||
|
<el-option v-for="item in payeeOptions" :key="item.id"
|
||||||
|
:label="item.name" :value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="币种" prop="currCode" required>
|
||||||
|
<el-input v-model="billForm.currCode" disabled style="width: 400px"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应收金额" prop="receivableAmount" required>
|
||||||
|
<el-input-number v-model="billForm.receivableAmount" :min="0" :precision="2" style="width: 400px"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应收日期" prop="receivableDate" required>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="billForm.receivableDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 400px">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="所属公司" prop="companyId" required>
|
||||||
|
<el-select v-model="billForm.companyId" placeholder="请选择所属公司" filterable @change="handleCompanyChange" style="width: 400px">
|
||||||
|
<el-option v-for="item in companyOptions" :key="item.id"
|
||||||
|
:label="item.name" :value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="收支账户" prop="accountId" required>
|
||||||
|
<el-select v-model="billForm.accountId" placeholder="请选择收支账户" filterable style="width: 400px">
|
||||||
|
<el-option v-for="item in accountOptions" :key="item.id"
|
||||||
|
:label="item.name" :value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账单备注" prop="billRemark">
|
||||||
|
<el-input type="textarea" v-model="billForm.billRemark" placeholder="请输入账单备注" rows="3" style="width: 400px"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="房源信息" name="roomInfo">
|
||||||
|
<el-tree
|
||||||
|
ref="roomTree"
|
||||||
|
:data="roomTreeData"
|
||||||
|
show-checkbox
|
||||||
|
node-key="id"
|
||||||
|
:props="{ label: 'label', children: 'children' }"
|
||||||
|
:default-checked-keys="selectedRoomIds"
|
||||||
|
@check="handleRoomTreeCheck">
|
||||||
|
</el-tree>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="账单附件" name="attachment">
|
||||||
|
<el-upload
|
||||||
|
class="upload-area"
|
||||||
|
action="#"
|
||||||
|
:http-request="uploadFile"
|
||||||
|
:file-list="fileList"
|
||||||
|
: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>
|
||||||
|
|
||||||
|
<el-table v-loading="attachmentLoading" :data="fileList" border style="width: 100%; margin-top: 20px">
|
||||||
|
<el-table-column prop="name" label="文件名" min-width="200" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="operatorName" label="操作人" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="operateTime" label="操作时间" width="180"></el-table-column>
|
||||||
|
<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)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getFeeTypeTree } from '@/api/finance'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AddBill',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeTab: 'chargeMode',
|
||||||
|
// 账单表单数据
|
||||||
|
billForm: {
|
||||||
|
contractId: '',
|
||||||
|
contractNumber: '',
|
||||||
|
payeeId: '',
|
||||||
|
payeeName: '',
|
||||||
|
payeeContact: '',
|
||||||
|
feeCategoryId: '',
|
||||||
|
feeTypeId: '',
|
||||||
|
feeTypeName: '',
|
||||||
|
currCode: '156', // 默认人民币
|
||||||
|
billingStartDate: '',
|
||||||
|
billingEndDate: '',
|
||||||
|
receivableAmount: 0,
|
||||||
|
price: 0,
|
||||||
|
priceU: '元/月',
|
||||||
|
taxInclusiveRule: '含税',
|
||||||
|
taxRate: 0,
|
||||||
|
receivableDate: '',
|
||||||
|
specialBillType: '正常',
|
||||||
|
lateFeeStartDays: 0,
|
||||||
|
lateFeeRate: 0,
|
||||||
|
lateFeeLimit: 0,
|
||||||
|
companyId: '',
|
||||||
|
companyName: '',
|
||||||
|
accountId: '',
|
||||||
|
billRemark: '',
|
||||||
|
roomInfoList: []
|
||||||
|
},
|
||||||
|
// 表单验证规则
|
||||||
|
chargeModeRules: {
|
||||||
|
taxInclusiveRule: [
|
||||||
|
{ required: true, message: '请选择含税规则', trigger: 'change' }
|
||||||
|
],
|
||||||
|
taxRate: [
|
||||||
|
{ required: true, message: '请输入税率', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
specialBillType: [
|
||||||
|
{ required: true, message: '请选择特殊账单类型', trigger: 'change' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
billInfoRules: {
|
||||||
|
payeeId: [
|
||||||
|
{ required: true, message: '请选择付款方', trigger: 'change' }
|
||||||
|
],
|
||||||
|
companyId: [
|
||||||
|
{ required: true, message: '请选择所属公司', trigger: 'change' }
|
||||||
|
],
|
||||||
|
accountId: [
|
||||||
|
{ required: true, message: '请选择收支账户', trigger: 'change' }
|
||||||
|
],
|
||||||
|
receivableAmount: [
|
||||||
|
{ required: true, message: '请输入应收金额', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
receivableDate: [
|
||||||
|
{ required: true, message: '请选择应收日期', trigger: 'change' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 额外表单数据和验证规则
|
||||||
|
formExtension: {
|
||||||
|
feeTypeSelected: null,
|
||||||
|
billingPeriod: []
|
||||||
|
},
|
||||||
|
formExtensionRules: {
|
||||||
|
feeTypeSelected: [
|
||||||
|
{ required: true, message: '请选择费用类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
billingPeriod: [
|
||||||
|
{ type: 'array', required: true, message: '请选择计费周期', trigger: 'change' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 选择项相关
|
||||||
|
contractOptions: [],
|
||||||
|
payeeOptions: [],
|
||||||
|
feeTypeOptions: [],
|
||||||
|
companyOptions: [],
|
||||||
|
accountOptions: [],
|
||||||
|
roomTreeData: [],
|
||||||
|
selectedRoomIds: [],
|
||||||
|
// 附件上传相关
|
||||||
|
fileList: [],
|
||||||
|
attachmentLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getFeeTypeOptions()
|
||||||
|
this.getCompanyOptions()
|
||||||
|
this.getRoomTreeData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取费用类型选项
|
||||||
|
getFeeTypeOptions() {
|
||||||
|
getFeeTypeTree({ level: 2 }).then(response => {
|
||||||
|
if (response.code === '0000000000000000') {
|
||||||
|
// 数据预处理
|
||||||
|
this.feeTypeOptions = this.processTreeData(response.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理费用类型树形数据
|
||||||
|
processTreeData(data) {
|
||||||
|
if (!data || !Array.isArray(data) || data.length === 0) {
|
||||||
|
console.warn('无费用类型数据')
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.map(category => {
|
||||||
|
// 确保id字段存在
|
||||||
|
const categoryId = category.id || Math.random().toString(36).substr(2, 9)
|
||||||
|
|
||||||
|
// 处理子节点
|
||||||
|
let children = []
|
||||||
|
if (category.financeFeeTypes && Array.isArray(category.financeFeeTypes)) {
|
||||||
|
children = category.financeFeeTypes.map(feeType => {
|
||||||
|
return {
|
||||||
|
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
||||||
|
label: feeType.feeTypeName || '未命名费用',
|
||||||
|
categoryId: categoryId,
|
||||||
|
// 存储原始数据以便后续使用
|
||||||
|
feeTypeName: feeType.feeTypeName || '未命名费用',
|
||||||
|
// 确保没有更多的子节点
|
||||||
|
children: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: categoryId,
|
||||||
|
label: category.categoryName || '未命名分类',
|
||||||
|
categoryName: category.categoryName || '未命名分类',
|
||||||
|
children: children.length > 0 ? children : null
|
||||||
|
}
|
||||||
|
}).filter(item => item.children && item.children.length > 0)
|
||||||
|
},
|
||||||
|
// 获取公司选项
|
||||||
|
getCompanyOptions() {
|
||||||
|
// 模拟数据,实际应调用API
|
||||||
|
this.companyOptions = [
|
||||||
|
{ id: 'C001', name: '智慧园区物业管理有限公司' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 获取收支账户选项
|
||||||
|
getAccountOptions(companyId) {
|
||||||
|
// 模拟数据,实际应调用API
|
||||||
|
this.accountOptions = [
|
||||||
|
{ id: 1, name: '运营账户-工商银行' },
|
||||||
|
{ id: 2, name: '日常账户-建设银行' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 搜索合同
|
||||||
|
searchContracts(query) {
|
||||||
|
if (query) {
|
||||||
|
// 实际应调用API
|
||||||
|
this.contractOptions = [
|
||||||
|
{ contractId: 'CT001', contractNumber: 'HT2023001', customerName: '张三' },
|
||||||
|
{ contractId: 'CT002', contractNumber: 'HT2023002', customerName: '李四' }
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
this.contractOptions = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 搜索付款方
|
||||||
|
searchPayees(query) {
|
||||||
|
if (query) {
|
||||||
|
// 实际应调用API
|
||||||
|
this.payeeOptions = [
|
||||||
|
{ id: '10001', name: '张三', contact: '13812345678' },
|
||||||
|
{ id: '10002', name: '李四', contact: '13987654321' }
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
this.payeeOptions = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理付款方变更
|
||||||
|
handlePayeeChange(payeeId) {
|
||||||
|
const payee = this.payeeOptions.find(item => item.id === payeeId)
|
||||||
|
if (payee) {
|
||||||
|
this.billForm.payeeName = payee.name
|
||||||
|
this.billForm.payeeContact = payee.contact
|
||||||
|
// 触发表单验证更新
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.billInfoForm.validateField('payeeId')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理费用类型变更
|
||||||
|
handleFeeTypeChange(value) {
|
||||||
|
if (value) {
|
||||||
|
// 查找匹配的费用类型
|
||||||
|
let selectedFeeType = null;
|
||||||
|
let selectedCategory = null;
|
||||||
|
|
||||||
|
// 在所有分类中查找
|
||||||
|
for (const category of this.feeTypeOptions) {
|
||||||
|
// 先检查是否选中的是分类
|
||||||
|
if (category.id === value) {
|
||||||
|
selectedCategory = category;
|
||||||
|
selectedFeeType = {
|
||||||
|
id: category.id,
|
||||||
|
name: category.label,
|
||||||
|
type: '分类'
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 检查子节点
|
||||||
|
if (category.children && category.children.length > 0) {
|
||||||
|
const found = category.children.find(item => item.id === value);
|
||||||
|
if (found) {
|
||||||
|
selectedCategory = category;
|
||||||
|
selectedFeeType = {
|
||||||
|
id: found.id,
|
||||||
|
name: found.label,
|
||||||
|
categoryName: category.label,
|
||||||
|
type: '费用类型'
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedFeeType) {
|
||||||
|
// 设置费用分类ID和费用类型ID
|
||||||
|
if (selectedFeeType.type === '分类') {
|
||||||
|
this.billForm.feeCategoryId = selectedFeeType.id;
|
||||||
|
this.billForm.feeTypeId = '';
|
||||||
|
this.billForm.feeTypeName = selectedFeeType.name;
|
||||||
|
} else {
|
||||||
|
this.billForm.feeCategoryId = selectedCategory.id;
|
||||||
|
this.billForm.feeTypeId = selectedFeeType.id;
|
||||||
|
this.billForm.feeTypeName = selectedFeeType.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 清空选择
|
||||||
|
this.billForm.feeCategoryId = '';
|
||||||
|
this.billForm.feeTypeId = '';
|
||||||
|
this.billForm.feeTypeName = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理公司变更
|
||||||
|
handleCompanyChange(companyId) {
|
||||||
|
const company = this.companyOptions.find(item => item.id === companyId)
|
||||||
|
if (company) {
|
||||||
|
this.billForm.companyName = company.name
|
||||||
|
// 触发表单验证更新
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.billInfoForm.validateField('companyId')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 重新获取收支账户
|
||||||
|
this.billForm.accountId = ''
|
||||||
|
this.getAccountOptions(companyId)
|
||||||
|
},
|
||||||
|
// 处理计费周期变更
|
||||||
|
handleBillingPeriodChange(val) {
|
||||||
|
if (val && val.length === 2) {
|
||||||
|
this.billForm.billingStartDate = val[0]
|
||||||
|
this.billForm.billingEndDate = val[1]
|
||||||
|
} else {
|
||||||
|
this.billForm.billingStartDate = ''
|
||||||
|
this.billForm.billingEndDate = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取房源树形数据
|
||||||
|
getRoomTreeData() {
|
||||||
|
// 模拟房源数据,与收费标准页面相同格式
|
||||||
|
const roomData = [
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"projectName": "智慧产业园",
|
||||||
|
"projectType": "产业园区",
|
||||||
|
"buildings": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8",
|
||||||
|
"projectName": "测试-1",
|
||||||
|
"projectType": "产业园区",
|
||||||
|
"buildings": [
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"buildingName": "4121",
|
||||||
|
"buildingCode": "1234",
|
||||||
|
"floors": [
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"floorName": "123",
|
||||||
|
"floorNumber": 11,
|
||||||
|
"rooms": [
|
||||||
|
{
|
||||||
|
"id": 31,
|
||||||
|
"roomNumber": "504",
|
||||||
|
"roomType": null,
|
||||||
|
"roomStatus": "1",
|
||||||
|
"buildingArea": 122.00,
|
||||||
|
"rentalArea": 20.99
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 30,
|
||||||
|
"roomNumber": "504",
|
||||||
|
"roomType": null,
|
||||||
|
"roomStatus": "1",
|
||||||
|
"buildingArea": 122.00,
|
||||||
|
"rentalArea": 20.99
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32,
|
||||||
|
"roomNumber": "505",
|
||||||
|
"roomType": null,
|
||||||
|
"roomStatus": "1",
|
||||||
|
"buildingArea": 122.00,
|
||||||
|
"rentalArea": 20.99
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 转换为树形结构
|
||||||
|
this.roomTreeData = roomData.map(project => {
|
||||||
|
return {
|
||||||
|
id: project.id,
|
||||||
|
label: project.projectName,
|
||||||
|
children: project.buildings.map(building => {
|
||||||
|
return {
|
||||||
|
id: building.id,
|
||||||
|
label: building.buildingName,
|
||||||
|
children: building.floors.map(floor => {
|
||||||
|
return {
|
||||||
|
id: floor.id,
|
||||||
|
label: floor.floorName,
|
||||||
|
children: floor.rooms.map(room => {
|
||||||
|
return {
|
||||||
|
id: room.id,
|
||||||
|
label: `${room.roomNumber}(${room.rentalArea}㎡)`,
|
||||||
|
isRoom: true,
|
||||||
|
// 保存原始数据供选择
|
||||||
|
roomData: room
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理房源树选择
|
||||||
|
handleRoomTreeCheck(node, data) {
|
||||||
|
// 只选择叶子节点(房间)
|
||||||
|
const checkedNodes = this.$refs.roomTree.getCheckedNodes(true)
|
||||||
|
// 过滤出所有房间节点
|
||||||
|
const roomNodes = checkedNodes.filter(node => node.isRoom)
|
||||||
|
|
||||||
|
// 更新选中的房间ID列表
|
||||||
|
this.selectedRoomIds = roomNodes.map(node => node.id)
|
||||||
|
|
||||||
|
// 重置房源信息列表
|
||||||
|
this.billForm.roomInfoList = []
|
||||||
|
|
||||||
|
// 创建一个Map用于收集项目信息
|
||||||
|
const projectMap = new Map()
|
||||||
|
|
||||||
|
// 处理每个房间节点
|
||||||
|
roomNodes.forEach(roomNode => {
|
||||||
|
// 查找节点路径
|
||||||
|
let currentNode = this.$refs.roomTree.getNode(roomNode.id)
|
||||||
|
let roomInfo = roomNode.roomData
|
||||||
|
let floorNode, buildingNode, projectNode
|
||||||
|
|
||||||
|
// 向上遍历找到楼层、楼宇和项目节点
|
||||||
|
while (currentNode && currentNode.parent) {
|
||||||
|
const parent = currentNode.parent
|
||||||
|
if (parent.level === 3) { // 楼层级别
|
||||||
|
floorNode = parent.data
|
||||||
|
} else if (parent.level === 2) { // 楼宇级别
|
||||||
|
buildingNode = parent.data
|
||||||
|
} else if (parent.level === 1) { // 项目级别
|
||||||
|
projectNode = parent.data
|
||||||
|
}
|
||||||
|
currentNode = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有完整路径的房间才处理
|
||||||
|
if (roomInfo && floorNode && buildingNode && projectNode) {
|
||||||
|
// 更新房源信息列表
|
||||||
|
this.billForm.roomInfoList.push({
|
||||||
|
roomId: roomNode.id,
|
||||||
|
roomNumber: roomInfo.roomNumber || roomNode.label.split('(')[0],
|
||||||
|
buildingId: buildingNode.id,
|
||||||
|
buildingName: buildingNode.label,
|
||||||
|
floorId: floorNode.id,
|
||||||
|
floorName: floorNode.label,
|
||||||
|
projectId: projectNode.id,
|
||||||
|
projectName: projectNode.label,
|
||||||
|
rentArea: roomInfo.rentalArea || 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 上传文件前检查
|
||||||
|
beforeUpload(file) {
|
||||||
|
const isValidType = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'application/pdf'
|
||||||
|
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) {
|
||||||
|
this.attachmentLoading = true
|
||||||
|
|
||||||
|
// 此处模拟上传,实际应调用API
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fileList.push({
|
||||||
|
name: options.file.name,
|
||||||
|
url: URL.createObjectURL(options.file),
|
||||||
|
operatorName: '当前用户',
|
||||||
|
operateTime: new Date().toLocaleString()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.attachmentLoading = false
|
||||||
|
this.$message.success('上传成功')
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
// 预览文件
|
||||||
|
previewFile(file) {
|
||||||
|
window.open(file.url)
|
||||||
|
},
|
||||||
|
// 下载文件
|
||||||
|
downloadFile(file) {
|
||||||
|
// 实际应调用API下载
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.url
|
||||||
|
link.download = file.name
|
||||||
|
link.click()
|
||||||
|
},
|
||||||
|
// 删除文件
|
||||||
|
deleteFile(index) {
|
||||||
|
this.$confirm('确认删除该附件?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.fileList.splice(index, 1)
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
// 获取表单数据
|
||||||
|
getFormData() {
|
||||||
|
// 确保billForm中包含来自formExtension的数据
|
||||||
|
if (this.formExtension.feeTypeSelected) {
|
||||||
|
// 费用类型已经在handleFeeTypeChange中设置
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.formExtension.billingPeriod && this.formExtension.billingPeriod.length === 2) {
|
||||||
|
this.billForm.billingStartDate = this.formExtension.billingPeriod[0]
|
||||||
|
this.billForm.billingEndDate = this.formExtension.billingPeriod[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.billForm
|
||||||
|
},
|
||||||
|
// 表单验证
|
||||||
|
validateForm() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
// 验证收费模式表单
|
||||||
|
this.$refs.chargeModeForm.validate(valid1 => {
|
||||||
|
if (!valid1) {
|
||||||
|
this.activeTab = 'chargeMode'
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证费用类型和计费周期表单
|
||||||
|
this.$refs.formExtension.validate(valid2 => {
|
||||||
|
if (!valid2) {
|
||||||
|
this.activeTab = 'billInfo'
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证账单信息表单
|
||||||
|
this.$refs.billInfoForm.validate(valid3 => {
|
||||||
|
if (!valid3) {
|
||||||
|
this.activeTab = 'billInfo'
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证是否选择了房源
|
||||||
|
if (this.billForm.roomInfoList.length === 0) {
|
||||||
|
this.$message.warning('请至少选择一个房源')
|
||||||
|
this.activeTab = 'roomInfo'
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 重置表单
|
||||||
|
resetForm() {
|
||||||
|
// 重置表单验证状态
|
||||||
|
if (this.$refs.chargeModeForm) {
|
||||||
|
this.$refs.chargeModeForm.resetFields()
|
||||||
|
}
|
||||||
|
if (this.$refs.billInfoForm) {
|
||||||
|
this.$refs.billInfoForm.resetFields()
|
||||||
|
}
|
||||||
|
if (this.$refs.formExtension) {
|
||||||
|
this.$refs.formExtension.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换到第一个标签
|
||||||
|
this.activeTab = 'chargeMode'
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
this.billForm = {
|
||||||
|
contractId: '',
|
||||||
|
contractNumber: '',
|
||||||
|
payeeId: '',
|
||||||
|
payeeName: '',
|
||||||
|
payeeContact: '',
|
||||||
|
feeCategoryId: '',
|
||||||
|
feeTypeId: '',
|
||||||
|
feeTypeName: '',
|
||||||
|
currCode: '156', // 默认人民币
|
||||||
|
billingStartDate: '',
|
||||||
|
billingEndDate: '',
|
||||||
|
receivableAmount: 0,
|
||||||
|
price: 0,
|
||||||
|
priceU: '元/月',
|
||||||
|
taxInclusiveRule: '含税',
|
||||||
|
taxRate: 0,
|
||||||
|
receivableDate: '',
|
||||||
|
specialBillType: '正常',
|
||||||
|
lateFeeStartDays: 0,
|
||||||
|
lateFeeRate: 0,
|
||||||
|
lateFeeLimit: 0,
|
||||||
|
companyId: '',
|
||||||
|
companyName: '',
|
||||||
|
accountId: '',
|
||||||
|
billRemark: '',
|
||||||
|
roomInfoList: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置扩展表单数据
|
||||||
|
this.formExtension = {
|
||||||
|
feeTypeSelected: null,
|
||||||
|
billingPeriod: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置房源选择
|
||||||
|
this.selectedRoomIds = []
|
||||||
|
if (this.$refs.roomTree) {
|
||||||
|
this.$refs.roomTree.setCheckedKeys([])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置文件上传列表
|
||||||
|
this.fileList = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.add-bill-container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.upload-area {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
256
pc/src/views/finance/billList/components/BillDetail.vue
Normal file
256
pc/src/views/finance/billList/components/BillDetail.vue
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bill-detail-container">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<el-tab-pane label="账单基本信息" name="basicInfo">
|
||||||
|
<el-descriptions :column="3" border size="medium">
|
||||||
|
<el-descriptions-item label="账单编号">{{ billDetail.billNumber }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="账单来源">{{ getBillSourceName(billDetail.billSource) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="账单状态">
|
||||||
|
<el-tag :type="billDetail.billStatus === '1' ? 'success' : 'info'">
|
||||||
|
{{ billDetail.billStatus === '1' ? '开启' : '关闭' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="对方名称">{{ billDetail.payeeName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="支付联系方式">{{ billDetail.payeeContact }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="关联合同">{{ billDetail.contractNumber || '无' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="费用类型">{{ billDetail.feeTypeName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="计费周期">
|
||||||
|
{{ billDetail.billingStartDate }} 至 {{ billDetail.billingEndDate }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应收日期">{{ billDetail.receivableDate }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="结清状态">
|
||||||
|
<el-tag :type="getClearStatusType(billDetail.clearStatus)">
|
||||||
|
{{ getClearStatusName(billDetail.clearStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="逾期状态">
|
||||||
|
<el-tag :type="billDetail.overdueStatus === '1' ? 'danger' : 'success'">
|
||||||
|
{{ billDetail.overdueStatus === '1' ? '逾期' : '正常' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="滞纳金状态">
|
||||||
|
<el-tag :type="getLateFeeStatusType(billDetail.lateFeeStatus)">
|
||||||
|
{{ getLateFeeStatusName(billDetail.lateFeeStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="账单金额">{{ formatAmount(billDetail.billAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应收金额">{{ formatAmount(billDetail.receivableAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="实收金额">{{ formatAmount(billDetail.receivedAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="需收金额">{{ formatAmount(billDetail.needAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="调整金额">{{ formatAmount(billDetail.adjustAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应收滞纳金">{{ formatAmount(billDetail.receivableLateFee) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="税率">{{ billDetail.taxRate }}%</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="税额">{{ formatAmount(billDetail.taxAmount) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="含税规则">{{ billDetail.taxInclusiveRule }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="特殊账单类型">{{ billDetail.specialBillType }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="开据状态">
|
||||||
|
<el-tag :type="billDetail.receiptStatus === '1' ? 'success' : 'info'">
|
||||||
|
{{ billDetail.receiptStatus === '1' ? '已开据' : '未开据' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="所属公司">{{ billDetail.companyName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="租赁数(计租面积)">{{ billDetail.rentArea }} ㎡</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="项目名称">{{ billDetail.projectName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="账单备注" :span="3">{{ billDetail.billRemark || '无' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="房源信息" name="roomInfo">
|
||||||
|
<el-table :data="roomList" border style="width: 100%">
|
||||||
|
<el-table-column prop="roomNumber" label="房号" min-width="100"></el-table-column>
|
||||||
|
<el-table-column prop="floorName" label="楼层" min-width="100"></el-table-column>
|
||||||
|
<el-table-column prop="buildingName" label="楼宇" min-width="120"></el-table-column>
|
||||||
|
<el-table-column prop="projectName" label="项目" min-width="150"></el-table-column>
|
||||||
|
<el-table-column prop="rentArea" label="计租面积(㎡)" min-width="120" align="right"></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="roomList.length === 0" class="empty-data">
|
||||||
|
<el-empty description="暂无房源信息"></el-empty>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="附件信息" name="attachment">
|
||||||
|
<el-table :data="attachmentList" border style="width: 100%">
|
||||||
|
<el-table-column prop="fileName" label="文件名" min-width="200" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="operatorName" label="操作人" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="operateTime" label="操作时间" width="180"></el-table-column>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="attachmentList.length === 0" class="empty-data">
|
||||||
|
<el-empty description="暂无附件信息"></el-empty>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="操作记录" name="operationLog">
|
||||||
|
<el-table :data="operationList" border style="width: 100%">
|
||||||
|
<el-table-column prop="operationType" label="操作类型" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="operatorName" label="操作人" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="operateTime" label="操作时间" width="180"></el-table-column>
|
||||||
|
<el-table-column prop="remark" label="备注" min-width="300" show-overflow-tooltip></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="operationList.length === 0" class="empty-data">
|
||||||
|
<el-empty description="暂无操作记录"></el-empty>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getBillDetail, getBillAttachmentList } from '@/api/finance'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BillDetail',
|
||||||
|
props: {
|
||||||
|
billId: {
|
||||||
|
type: [Number, String],
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeTab: 'basicInfo',
|
||||||
|
loading: false,
|
||||||
|
billDetail: {},
|
||||||
|
roomList: [],
|
||||||
|
attachmentList: [],
|
||||||
|
operationList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getBillData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取账单数据
|
||||||
|
getBillData() {
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
// 获取账单详情
|
||||||
|
getBillDetail(this.billId).then(response => {
|
||||||
|
this.billDetail = response.data || {}
|
||||||
|
|
||||||
|
// 模拟房源信息数据,实际应从接口获取或者账单详情中提取
|
||||||
|
this.roomList = [
|
||||||
|
{
|
||||||
|
roomId: 'R001',
|
||||||
|
roomNumber: this.billDetail.roomNumber || '',
|
||||||
|
floorName: '1层',
|
||||||
|
buildingName: '智慧园区A栋',
|
||||||
|
projectName: this.billDetail.projectName || '',
|
||||||
|
rentArea: this.billDetail.rentArea || 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取附件列表
|
||||||
|
getBillAttachmentList(this.billId).then(response => {
|
||||||
|
this.attachmentList = response.data || []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 模拟操作记录数据,实际应从接口获取
|
||||||
|
this.operationList = [
|
||||||
|
{
|
||||||
|
operationType: '创建账单',
|
||||||
|
operatorName: '系统管理员',
|
||||||
|
operateTime: '2023-06-20 10:30:00',
|
||||||
|
remark: '创建新账单'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 格式化金额
|
||||||
|
formatAmount(amount) {
|
||||||
|
if (amount === undefined || amount === null) {
|
||||||
|
return '0.00'
|
||||||
|
}
|
||||||
|
return parseFloat(amount).toFixed(2) + ' 元'
|
||||||
|
},
|
||||||
|
// 获取账单来源名称
|
||||||
|
getBillSourceName(source) {
|
||||||
|
const sourceMap = {
|
||||||
|
'1': '合同账单',
|
||||||
|
'2': '收费标准账单',
|
||||||
|
'3': '自建全部账单',
|
||||||
|
'4': '自建关联合同账单',
|
||||||
|
'5': '自建未关联合同账单'
|
||||||
|
}
|
||||||
|
return sourceMap[source] || '未知来源'
|
||||||
|
},
|
||||||
|
// 获取结清状态类型
|
||||||
|
getClearStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'info',
|
||||||
|
'1': 'success',
|
||||||
|
'2': 'warning',
|
||||||
|
'3': 'danger',
|
||||||
|
'5': 'primary',
|
||||||
|
'6': 'info',
|
||||||
|
'7': 'success'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
// 获取结清状态名称
|
||||||
|
getClearStatusName(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '未付款',
|
||||||
|
'1': '已结清',
|
||||||
|
'2': '部分结清',
|
||||||
|
'3': '待退款',
|
||||||
|
'5': '待收款',
|
||||||
|
'6': '对账确认中',
|
||||||
|
'7': '已付款'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知状态'
|
||||||
|
},
|
||||||
|
// 获取滞纳金状态类型
|
||||||
|
getLateFeeStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'info',
|
||||||
|
'1': 'warning',
|
||||||
|
'2': 'success'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
// 获取滞纳金状态名称
|
||||||
|
getLateFeeStatusName(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '无滞纳金',
|
||||||
|
'1': '有滞纳金',
|
||||||
|
'2': '滞纳金免除'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知状态'
|
||||||
|
},
|
||||||
|
// 预览文件
|
||||||
|
previewFile(file) {
|
||||||
|
window.open(file.storePath)
|
||||||
|
},
|
||||||
|
// 下载文件
|
||||||
|
downloadFile(file) {
|
||||||
|
// 实际应调用API下载
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.storePath
|
||||||
|
link.download = file.fileName
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bill-detail-container {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
.empty-data {
|
||||||
|
margin: 20px 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
409
pc/src/views/finance/billList/index.vue
Normal file
409
pc/src/views/finance/billList/index.vue
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-form :model="queryParams" ref="queryForm" :inline="true" class="search-form">
|
||||||
|
<el-form-item label="合同编号" prop="contractNumber">
|
||||||
|
<el-input v-model="queryParams.contractNumber" placeholder="请输入合同编号" clearable style="width: 220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="房号" prop="roomNumber">
|
||||||
|
<el-input v-model="queryParams.roomNumber" placeholder="请输入房号" clearable style="width: 220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="对方名称" prop="payeeName">
|
||||||
|
<el-input v-model="queryParams.payeeName" placeholder="请输入对方名称" clearable style="width: 220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账单编号" prop="billNumber">
|
||||||
|
<el-input v-model="queryParams.billNumber" placeholder="请输入账单编号" clearable style="width: 220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账单状态" prop="billStatus">
|
||||||
|
<el-select v-model="queryParams.billStatus" placeholder="请选择账单状态" clearable multiple style="width: 220px">
|
||||||
|
<el-option label="开启" value="1" />
|
||||||
|
<el-option label="关闭" value="0" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应收时间" prop="receivableDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
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="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="5" />
|
||||||
|
<el-option label="对账确认中" value="6" />
|
||||||
|
<el-option label="已付款" value="7" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账单来源" prop="billSource">
|
||||||
|
<el-select v-model="queryParams.billSource" placeholder="请选择账单来源" clearable style="width: 220px">
|
||||||
|
<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-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="费用类型" prop="feeType">
|
||||||
|
<el-cascader
|
||||||
|
v-model="feeTypeSelected"
|
||||||
|
:options="feeTypeOptions"
|
||||||
|
:props="{
|
||||||
|
label: 'label',
|
||||||
|
value: 'id',
|
||||||
|
children: 'children',
|
||||||
|
emitPath: false,
|
||||||
|
expandTrigger: 'hover'
|
||||||
|
}"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择费用类型"
|
||||||
|
style="width: 220px">
|
||||||
|
</el-cascader>
|
||||||
|
</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="success" icon="el-icon-plus" style="float: right;" @click="handleAdd">添加收款账单</el-button>
|
||||||
|
<el-button type="warning" icon="el-icon-download" style="float: right; margin-right: 10px;" @click="handleExport">导出</el-button>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<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="projectName" min-width="120" 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="contractNumber" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column label="结清状态" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="getClearStatusType(scope.row.clearStatus)">
|
||||||
|
{{ getClearStatusName(scope.row.clearStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="费用类型" prop="feeTypeName" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="账单金额" prop="billAmount" min-width="100" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.billAmount ? scope.row.billAmount.toFixed(2) : '0.00' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="应收金额" prop="receivableAmount" min-width="100" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.receivableAmount ? scope.row.receivableAmount.toFixed(2) : '0.00' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="实收金额" prop="receivedAmount" min-width="100" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.receivedAmount ? scope.row.receivedAmount.toFixed(2) : '0.00' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="开始日期" prop="billingStartDate" min-width="120" align="center" />
|
||||||
|
<el-table-column label="结束日期" prop="billingEndDate" min-width="120" align="center" />
|
||||||
|
<el-table-column label="应收日期" prop="receivableDate" min-width="120" align="center" />
|
||||||
|
<el-table-column label="操作" width="150" 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="dialogVisible" width="80%" append-to-body @closed="handleDialogClosed">
|
||||||
|
<add-bill ref="addBillForm" />
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitAddBill">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 账单详情对话框 -->
|
||||||
|
<el-dialog title="账单详情" :visible.sync="detailVisible" width="80%" append-to-body>
|
||||||
|
<bill-detail v-if="detailVisible" :bill-id="currentBill.id" />
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getFeeTypeTree, getBillList, exportBillList, addBill, getBillDetail } from '@/api/finance'
|
||||||
|
import AddBill from './components/AddBill'
|
||||||
|
import BillDetail from './components/BillDetail'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BillList',
|
||||||
|
components: {
|
||||||
|
AddBill,
|
||||||
|
BillDetail
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 加载标志
|
||||||
|
loading: false,
|
||||||
|
// 账单列表数据
|
||||||
|
billList: [],
|
||||||
|
// 总记录数
|
||||||
|
total: 0,
|
||||||
|
// 时间范围
|
||||||
|
dateRange: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
contractNumber: '',
|
||||||
|
roomNumber: '',
|
||||||
|
payeeName: '',
|
||||||
|
billNumber: '',
|
||||||
|
billStatus: [],
|
||||||
|
receivableDateStart: '',
|
||||||
|
receivableDateEnd: '',
|
||||||
|
clearStatus: [],
|
||||||
|
billSource: '',
|
||||||
|
feeTypeId: undefined,
|
||||||
|
feeCategoryId: undefined
|
||||||
|
},
|
||||||
|
// 费用类型选择
|
||||||
|
feeTypeSelected: undefined,
|
||||||
|
// 费用类型选项
|
||||||
|
feeTypeOptions: [],
|
||||||
|
// 对话框显示标志
|
||||||
|
dialogVisible: false,
|
||||||
|
detailVisible: false,
|
||||||
|
// 当前查看的账单详情
|
||||||
|
currentBill: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
this.getFeeTypeOptions()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取账单列表
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
// 处理查询参数
|
||||||
|
const queryParams = { ...this.queryParams }
|
||||||
|
|
||||||
|
// 处理日期范围
|
||||||
|
if (this.dateRange && this.dateRange.length > 0) {
|
||||||
|
queryParams.receivableDateStart = this.dateRange[0]
|
||||||
|
queryParams.receivableDateEnd = this.dateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理费用类型
|
||||||
|
if (this.feeTypeSelected) {
|
||||||
|
queryParams.feeTypeId = this.feeTypeSelected
|
||||||
|
}
|
||||||
|
|
||||||
|
getBillList(queryParams).then(response => {
|
||||||
|
this.billList = response.data.data || []
|
||||||
|
this.total = response.data.total
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取费用类型选项
|
||||||
|
getFeeTypeOptions() {
|
||||||
|
getFeeTypeTree({ level: 2 }).then(response => {
|
||||||
|
if (response.code === '0000000000000000') {
|
||||||
|
// 数据预处理
|
||||||
|
this.feeTypeOptions = this.processTreeData(response.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理费用类型树形数据
|
||||||
|
processTreeData(data) {
|
||||||
|
if (!data || !Array.isArray(data) || data.length === 0) {
|
||||||
|
console.warn('无费用类型数据')
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.map(category => {
|
||||||
|
// 确保id字段存在
|
||||||
|
const categoryId = category.id || Math.random().toString(36).substr(2, 9)
|
||||||
|
|
||||||
|
// 处理子节点
|
||||||
|
let children = []
|
||||||
|
if (category.financeFeeTypes && Array.isArray(category.financeFeeTypes)) {
|
||||||
|
children = category.financeFeeTypes.map(feeType => {
|
||||||
|
return {
|
||||||
|
id: feeType.id || Math.random().toString(36).substr(2, 9),
|
||||||
|
label: feeType.feeTypeName || '未命名费用',
|
||||||
|
categoryId: categoryId,
|
||||||
|
// 存储原始数据以便后续使用
|
||||||
|
feeTypeName: feeType.feeTypeName || '未命名费用',
|
||||||
|
// 确保没有更多的子节点
|
||||||
|
children: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: categoryId,
|
||||||
|
label: category.categoryName || '未命名分类',
|
||||||
|
categoryName: category.categoryName || '未命名分类',
|
||||||
|
children: children.length > 0 ? children : null
|
||||||
|
}
|
||||||
|
}).filter(item => item.children && item.children.length > 0)
|
||||||
|
},
|
||||||
|
// 搜索按钮操作
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 重置按钮操作
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = []
|
||||||
|
this.feeTypeSelected = undefined
|
||||||
|
this.$refs.queryForm.resetFields()
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 分页大小改变
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.queryParams.pageSize = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 分页页码改变
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.queryParams.pageNum = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 添加账单操作
|
||||||
|
handleAdd() {
|
||||||
|
this.dialogVisible = true
|
||||||
|
},
|
||||||
|
// 关闭对话框时重置表单
|
||||||
|
handleDialogClosed() {
|
||||||
|
this.$refs.addBillForm.resetForm()
|
||||||
|
},
|
||||||
|
// 查看账单详情
|
||||||
|
handleViewDetail(row) {
|
||||||
|
this.currentBill = row
|
||||||
|
this.detailVisible = true
|
||||||
|
},
|
||||||
|
// 导出账单操作
|
||||||
|
handleExport() {
|
||||||
|
// 处理导出参数
|
||||||
|
const exportParams = { ...this.queryParams }
|
||||||
|
delete exportParams.pageNum
|
||||||
|
delete exportParams.pageSize
|
||||||
|
|
||||||
|
// 处理日期范围
|
||||||
|
if (this.dateRange && this.dateRange.length > 0) {
|
||||||
|
exportParams.receivableDateStart = this.dateRange[0]
|
||||||
|
exportParams.receivableDateEnd = this.dateRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理费用类型
|
||||||
|
if (this.feeTypeSelected) {
|
||||||
|
exportParams.feeTypeId = this.feeTypeSelected
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$confirm('是否确认导出所有数据项?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
exportBillList(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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 提交添加账单
|
||||||
|
submitAddBill() {
|
||||||
|
// 先进行表单验证
|
||||||
|
this.$refs.addBillForm.validateForm().then(valid => {
|
||||||
|
if (valid) {
|
||||||
|
const billData = this.$refs.addBillForm.getFormData()
|
||||||
|
addBill(billData).then(response => {
|
||||||
|
this.$message.success('添加账单成功')
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
}).catch(() => {
|
||||||
|
// 错误处理
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取清算状态显示类型
|
||||||
|
getClearStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'info',
|
||||||
|
'1': 'success',
|
||||||
|
'2': 'warning',
|
||||||
|
'3': 'danger',
|
||||||
|
'5': 'primary',
|
||||||
|
'6': 'info',
|
||||||
|
'7': 'success'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
// 获取清算状态名称
|
||||||
|
getClearStatusName(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '未付款',
|
||||||
|
'1': '已结清',
|
||||||
|
'2': '部分结清',
|
||||||
|
'3': '待退款',
|
||||||
|
'5': '待收款',
|
||||||
|
'6': '对账确认中',
|
||||||
|
'7': '已付款'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知状态'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,7 @@
|
|||||||
<div class="fee-type-search">
|
<div class="fee-type-search">
|
||||||
<el-form :inline="true" :model="queryParams" class="search-form">
|
<el-form :inline="true" :model="queryParams" class="search-form">
|
||||||
<el-form-item label="费用名称">
|
<el-form-item label="费用名称">
|
||||||
<el-input v-model="queryParams.feeTypeName" placeholder="请输入费用名称" clearable
|
<el-input v-model="queryParams.feTpName" placeholder="请输入费用名称" clearable
|
||||||
@keyup.enter.native="handleQuery"></el-input>
|
@keyup.enter.native="handleQuery"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<!-- 费用类型表格 -->
|
<!-- 费用类型表格 -->
|
||||||
<el-table v-loading="loading" :data="typeList" border>
|
<el-table v-loading="loading" :data="typeList" border>
|
||||||
<el-table-column type="index" width="50" align="center" label="序号"></el-table-column>
|
<el-table-column type="index" width="50" align="center" label="序号"></el-table-column>
|
||||||
<el-table-column prop="feeTypeName" label="费用名称" min-width="140"></el-table-column>
|
<el-table-column prop="feTpName" label="费用名称" min-width="140"></el-table-column>
|
||||||
<el-table-column label="费用分类" min-width="120" align="center">
|
<el-table-column label="费用分类" min-width="120" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ getCategoryNameById(scope.row.categoryId) }}
|
{{ getCategoryNameById(scope.row.categoryId) }}
|
||||||
@ -129,8 +129,8 @@
|
|||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="费用类型名称" prop="feeTypeName">
|
<el-form-item label="费用类型名称" prop="feTpName">
|
||||||
<el-input v-model="typeForm.feeTypeName" placeholder="请输入费用类型名称" :disabled="typeEdit"
|
<el-input v-model="typeForm.feTpName" placeholder="请输入费用类型名称" :disabled="typeEdit"
|
||||||
style="width: 100%"></el-input>
|
style="width: 100%"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
@ -186,7 +186,7 @@ export default {
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
feeTypeName: undefined,
|
feTpName: undefined,
|
||||||
categoryId: null
|
categoryId: null
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -216,13 +216,13 @@ export default {
|
|||||||
typeEdit: false,
|
typeEdit: false,
|
||||||
typeForm: {
|
typeForm: {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
feeTypeName: '',
|
feTpName: '',
|
||||||
categoryId: null,
|
categoryId: null,
|
||||||
status: '1',
|
status: '1',
|
||||||
defauVerFlag: '0'
|
defauVerFlag: '0'
|
||||||
},
|
},
|
||||||
typeRules: {
|
typeRules: {
|
||||||
feeTypeName: [
|
feTpName: [
|
||||||
{ required: true, message: '费用类型名称不能为空', trigger: 'blur' },
|
{ required: true, message: '费用类型名称不能为空', trigger: 'blur' },
|
||||||
{ min: 2, max: 50, message: '费用类型名称长度必须在2-50个字符之间', trigger: 'blur' }
|
{ min: 2, max: 50, message: '费用类型名称长度必须在2-50个字符之间', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
@ -296,7 +296,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 重置查询操作
|
// 重置查询操作
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.queryParams.feeTypeName = undefined
|
this.queryParams.feTpName = undefined
|
||||||
this.handleQuery()
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
// 每页条数改变
|
// 每页条数改变
|
||||||
@ -411,7 +411,7 @@ export default {
|
|||||||
// 重置表单数据
|
// 重置表单数据
|
||||||
this.typeForm = {
|
this.typeForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
feeTypeName: '',
|
feTpName: '',
|
||||||
categoryId: this.selectedCategoryId ? parseInt(this.selectedCategoryId) : null,
|
categoryId: this.selectedCategoryId ? parseInt(this.selectedCategoryId) : null,
|
||||||
status: '1',
|
status: '1',
|
||||||
defauVerFlag: '0'
|
defauVerFlag: '0'
|
||||||
@ -455,7 +455,7 @@ export default {
|
|||||||
// 创建提交的数据对象,只包含需要的字段
|
// 创建提交的数据对象,只包含需要的字段
|
||||||
const submitData = {
|
const submitData = {
|
||||||
id: this.typeForm.id,
|
id: this.typeForm.id,
|
||||||
feeTypeName: this.typeForm.feeTypeName,
|
feTpName: this.typeForm.feTpName,
|
||||||
categoryId: this.typeForm.categoryId,
|
categoryId: this.typeForm.categoryId,
|
||||||
status: this.typeForm.status
|
status: this.typeForm.status
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- 搜索栏 -->
|
<!-- 搜索栏 -->
|
||||||
<div class="filter-container">
|
<div class="filter-container">
|
||||||
<el-input v-model="queryParams.payeeNameUnitName" placeholder="请输入收款方单位名称" clearable style="width: 250px;" class="filter-item" />
|
<el-input v-model="queryParams.payeeUnitName" placeholder="请输入收款方单位名称" clearable style="width: 250px;" class="filter-item" />
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
<el-button type="primary" icon="el-icon-plus" style="float: right;" @click="handleAdd">新增收款方信息</el-button>
|
<el-button type="primary" icon="el-icon-plus" style="float: right;" @click="handleAdd">新增收款方信息</el-button>
|
||||||
@ -17,10 +17,10 @@
|
|||||||
{{ formatCompanyName(scope.row.companyId) }}
|
{{ formatCompanyName(scope.row.companyId) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="payeeNameUnitName" label="收款方单位名称" />
|
<el-table-column prop="payeeUnitName" label="收款方单位名称" />
|
||||||
<el-table-column prop="payeeName" label="收款人" />
|
<el-table-column prop="payeeName" label="收款人" />
|
||||||
<el-table-column prop="addr" label="地址" />
|
<el-table-column prop="payeeAddr" label="地址" />
|
||||||
<el-table-column prop="contTel" label="电话" />
|
<el-table-column prop="payeePhone" label="电话" />
|
||||||
<el-table-column prop="buildingIds" label="应用楼宇">
|
<el-table-column prop="buildingIds" label="应用楼宇">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ formatBuildingNames(scope.row.buildingIds) }}
|
{{ formatBuildingNames(scope.row.buildingIds) }}
|
||||||
@ -53,17 +53,17 @@
|
|||||||
:value="item.id" />
|
:value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收款方单位名称" prop="payeeNameUnitName">
|
<el-form-item label="收款方单位名称" prop="payeeUnitName">
|
||||||
<el-input v-model="form.payeeNameUnitName" placeholder="请输入收款方单位名称" />
|
<el-input v-model="form.payeeUnitName" placeholder="请输入收款方单位名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收款人" prop="payeeName">
|
<el-form-item label="收款人" prop="payeeName">
|
||||||
<el-input v-model="form.payeeName" placeholder="请输入收款人" />
|
<el-input v-model="form.payeeName" placeholder="请输入收款人" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="地址" prop="addr">
|
<el-form-item label="地址" prop="payeeAddr">
|
||||||
<el-input v-model="form.addr" placeholder="请输入地址" />
|
<el-input v-model="form.payeeAddr" placeholder="请输入地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="电话" prop="contTel">
|
<el-form-item label="电话" prop="payeePhone">
|
||||||
<el-input v-model="form.contTel" placeholder="请输入电话" />
|
<el-input v-model="form.payeePhone" placeholder="请输入电话" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="应用楼宇" prop="buildingIds">
|
<el-form-item label="应用楼宇" prop="buildingIds">
|
||||||
<el-popover
|
<el-popover
|
||||||
@ -127,7 +127,7 @@ export default {
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
current: 1,
|
current: 1,
|
||||||
size: 10,
|
size: 10,
|
||||||
payeeNameUnitName: ''
|
payeeUnitName: ''
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@ -140,10 +140,10 @@ export default {
|
|||||||
// 收款方信息
|
// 收款方信息
|
||||||
payeeInfo: {
|
payeeInfo: {
|
||||||
companyId: '',
|
companyId: '',
|
||||||
payeeNameUnitName: '',
|
payeeUnitName: '',
|
||||||
payeeName: '',
|
payeeName: '',
|
||||||
addr: '',
|
payeeAddr: '',
|
||||||
contTel: '',
|
payeePhone: '',
|
||||||
buildingIds: []
|
buildingIds: []
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -174,10 +174,10 @@ export default {
|
|||||||
// 表单数据
|
// 表单数据
|
||||||
form: {
|
form: {
|
||||||
companyId: '',
|
companyId: '',
|
||||||
payeeNameUnitName: '',
|
payeeUnitName: '',
|
||||||
payeeName: '',
|
payeeName: '',
|
||||||
addr: '',
|
payeeAddr: '',
|
||||||
contTel: '',
|
payeePhone: '',
|
||||||
buildingIds: [],
|
buildingIds: [],
|
||||||
buildingNames: ''
|
buildingNames: ''
|
||||||
},
|
},
|
||||||
@ -187,13 +187,13 @@ export default {
|
|||||||
companyId: [
|
companyId: [
|
||||||
{ required: true, message: '请选择关联公司', trigger: 'change' }
|
{ required: true, message: '请选择关联公司', trigger: 'change' }
|
||||||
],
|
],
|
||||||
payeeNameUnitName: [
|
payeeUnitName: [
|
||||||
{ required: true, message: '请输入收款方单位名称', trigger: 'blur' }
|
{ required: true, message: '请输入收款方单位名称', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
payeeName: [
|
payeeName: [
|
||||||
{ required: true, message: '请输入收款人', trigger: 'blur' }
|
{ required: true, message: '请输入收款人', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
contTel: [
|
payeePhone: [
|
||||||
{ pattern: /^(\d{3,4}-\d{7,8}(-\d{1,4})?|1[3-9]\d{9})$/, message: '电话格式不正确', trigger: 'blur' }
|
{ pattern: /^(\d{3,4}-\d{7,8}(-\d{1,4})?|1[3-9]\d{9})$/, message: '电话格式不正确', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
buildingIds: [
|
buildingIds: [
|
||||||
@ -222,10 +222,10 @@ export default {
|
|||||||
this.payeeList = [{
|
this.payeeList = [{
|
||||||
id: 1,
|
id: 1,
|
||||||
companyId: 'COM001',
|
companyId: 'COM001',
|
||||||
payeeNameUnitName: '智慧园区管理有限公司',
|
payeeUnitName: '智慧园区管理有限公司',
|
||||||
payeeName: '张三',
|
payeeName: '张三',
|
||||||
addr: '北京市海淀区中关村大街1号',
|
payeeAddr: '北京市海淀区中关村大街1号',
|
||||||
contTel: '13800138000',
|
payeePhone: '13800138000',
|
||||||
buildingIds: 'BLD001,BLD002'
|
buildingIds: 'BLD001,BLD002'
|
||||||
}]
|
}]
|
||||||
this.total = 1
|
this.total = 1
|
||||||
@ -239,10 +239,10 @@ export default {
|
|||||||
this.payeeList = [{
|
this.payeeList = [{
|
||||||
id: 1,
|
id: 1,
|
||||||
companyId: 'COM001',
|
companyId: 'COM001',
|
||||||
payeeNameUnitName: '智慧园区管理有限公司',
|
payeeUnitName: '智慧园区管理有限公司',
|
||||||
payeeName: '张三',
|
payeeName: '张三',
|
||||||
addr: '北京市海淀区中关村大街1号',
|
payeeAddr: '北京市海淀区中关村大街1号',
|
||||||
contTel: '13800138000',
|
payeePhone: '13800138000',
|
||||||
buildingIds: 'BLD001,BLD002'
|
buildingIds: 'BLD001,BLD002'
|
||||||
}]
|
}]
|
||||||
this.total = 1
|
this.total = 1
|
||||||
@ -348,7 +348,7 @@ export default {
|
|||||||
this.queryParams = {
|
this.queryParams = {
|
||||||
current: 1,
|
current: 1,
|
||||||
size: 10,
|
size: 10,
|
||||||
payeeNameUnitName: ''
|
payeeUnitName: ''
|
||||||
}
|
}
|
||||||
this.getPayeeList()
|
this.getPayeeList()
|
||||||
},
|
},
|
||||||
@ -371,10 +371,10 @@ export default {
|
|||||||
this.currentId = null
|
this.currentId = null
|
||||||
this.form = {
|
this.form = {
|
||||||
companyId: '',
|
companyId: '',
|
||||||
payeeNameUnitName: '',
|
payeeUnitName: '',
|
||||||
payeeName: '',
|
payeeName: '',
|
||||||
addr: '',
|
payeeAddr: '',
|
||||||
contTel: '',
|
payeePhone: '',
|
||||||
buildingIds: [],
|
buildingIds: [],
|
||||||
buildingNames: ''
|
buildingNames: ''
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,14 @@ module.exports = {
|
|||||||
warnings: false,
|
warnings: false,
|
||||||
errors: true
|
errors: true
|
||||||
},
|
},
|
||||||
proxy: {
|
// proxy: {
|
||||||
'/': {
|
// '/': {
|
||||||
target: 'http://192.168.137.214:8082/api',
|
// target: 'http://192.168.137.214:8082',
|
||||||
changeOrigin: true,
|
// changeOrigin: true,
|
||||||
pathRewrite: {
|
// pathRewrite: {
|
||||||
'^/api': '/api'
|
// '^/api': '/api'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user