add 项目利润结算
parent
ad6d91f78c
commit
6b0dd8728b
|
|
@ -3,27 +3,36 @@ import request from '@/config/axios'
|
|||
// 项目利润结算 VO
|
||||
export interface ProjectSettlementVO {
|
||||
id: number; // 结算记录ID
|
||||
projectId: number; // 关联项目ID
|
||||
projectId: number; // 项目ID
|
||||
projectName: string; // 项目名称
|
||||
piles: string; // 枪数
|
||||
settlementPeriod: string; // 结算周期(如:2023-Q1)
|
||||
period: number; // 总期数
|
||||
settlementDate: Date; // 结算日期
|
||||
actualRevenue: number; // 实际营收
|
||||
governmentSubsidy: number; // 政府补贴收入
|
||||
otherIncome: number; // 其他项目收入
|
||||
totalIncome: number; // 总收入
|
||||
incomeRemark: string; // 收入备注
|
||||
electricityCost: number; // 电费成本
|
||||
venueRent: number; // 场地租金
|
||||
venueDeposit: number; // 项目押金
|
||||
projectPromotion: number; // 项目推介费
|
||||
equipmentUpgrade: number; // 设备更新购置费
|
||||
managementCost: number; // 管理费用
|
||||
taxCost: number; // 税收
|
||||
startDate: string | Date | number[]; // 结算开始时间
|
||||
endDate: string | Date; // 结算结束时间
|
||||
settlementDate: string | Date | number[]; // 结算日期
|
||||
previousLossCarryover: number; // 上期亏损转结
|
||||
grossProfit: number; // 毛利润
|
||||
netProfit: number; // 净利润
|
||||
expenseRemark: string; // 支出备注
|
||||
settlementStatus: number; // 结算状态
|
||||
proofAttachment: string; // 结算凭证附件
|
||||
remark: string; // 结算备注
|
||||
actualRevenue?: number; // 实际营收
|
||||
governmentSubsidy?: number; // 政府补贴收入
|
||||
otherIncome?: number; // 其他项目收入
|
||||
totalIncome?: number; // 总收入
|
||||
incomeRemark?: string; // 收入备注
|
||||
electricityCost?: number; // 电费成本
|
||||
venueRent?: number; // 场地租金
|
||||
venueDeposit?: number; // 项目押金
|
||||
projectPromotion?: number; // 项目推介费
|
||||
equipmentUpgrade?: number; // 设备更新购置费
|
||||
managementCost?: number; // 管理费用
|
||||
taxCost?: number; // 税收
|
||||
otherExpenses?: number; // 其他支出
|
||||
totalExpenses?: number; // 总支出
|
||||
shareAmount?: number; // 分成金额
|
||||
expenseRemark?: string; // 支出备注
|
||||
proofAttachment?: string; // 结算凭证附件
|
||||
remark?: string; // 结算备注
|
||||
}
|
||||
|
||||
// 查询项目利润结算分页
|
||||
|
|
@ -55,3 +64,8 @@ export const deleteProjectSettlement = async (id: number) => {
|
|||
export const exportProjectSettlement = async (params: any) => {
|
||||
return await request.download({ url: `/crm/project-settlement/export-excel`, params })
|
||||
}
|
||||
|
||||
// 导出项目利润结算明细 Excel
|
||||
export const exportProjectSettlementDetail = async (params: any) => {
|
||||
return await request.download({ url: `/crm/receivable/export-settlement-excel`, params })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,399 @@
|
|||
<template>
|
||||
<div class="el-quarter-picker">
|
||||
<el-popover
|
||||
v-model:visible="visible"
|
||||
:disabled="!canPopover"
|
||||
:tabindex="null"
|
||||
placement="bottom-start"
|
||||
transition="el-zoom-in-top"
|
||||
width="300"
|
||||
trigger="click">
|
||||
|
||||
<div class="el-date-picker el-quarter-popover-content">
|
||||
<div class="el-picker-panel__body">
|
||||
<div class="el-date-picker__header el-date-picker__header--bordered" style="margin:0px; line-height:30px">
|
||||
<button
|
||||
type="button"
|
||||
@click="clickLast"
|
||||
aria-label="前一年"
|
||||
class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"></button>
|
||||
<span role="button" class="el-date-picker__header-label" @click="clickYear">{{ title }}</span>
|
||||
<button
|
||||
type="button"
|
||||
@click="clickNext"
|
||||
aria-label="后一年"
|
||||
class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"></button>
|
||||
</div>
|
||||
<div class="el-picker-panel__content" style="margin:0px; width:100%">
|
||||
<table class="el-month-table" style="">
|
||||
<tbody>
|
||||
<tr v-for="line in lineCount" :key="line">
|
||||
<td v-for="index in (line * 4 <= viewList.length ? 4 : viewList.length - (line - 1) * 4)" :key="index" :class="{ today: viewList[(line - 1) * 4 + index - 1].current, current: viewList[(line - 1) * 4 + index - 1].active }">
|
||||
<div><a class="cell" @click="clickItem(viewList[(line - 1) * 4 + index - 1])">{{ viewList[(line - 1) * 4 + index - 1].label }}</a></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #reference>
|
||||
<el-input
|
||||
@change="changeText"
|
||||
@mouseenter="mouseEnter"
|
||||
@mouseleave="mouseLeave"
|
||||
:placeholder="placeholder"
|
||||
v-model="text"
|
||||
:size="size"
|
||||
:readonly="!canEdit"
|
||||
:disabled="disabled">
|
||||
<template #prefix>
|
||||
<i class="el-input__icon el-icon-date"></i>
|
||||
</template>
|
||||
<template #suffix>
|
||||
<i class="el-input__icon el-icon-circle-close" v-show="showClear" style="cursor:pointer" @click.stop="clear"></i>
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ElQuarterPicker',
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
default: 'yyyy年第Q季度'
|
||||
},
|
||||
valueFormat: {
|
||||
type: String,
|
||||
default: 'yyyy-qq'
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
showClear: false, // 控制清空按钮展示
|
||||
canEdit: true, // 是否可编辑
|
||||
canPopover: true, // 选择器弹出是否可用
|
||||
text: '', // 文本框值
|
||||
viewType: 1, // 视图类型,1季度,2年度
|
||||
viewYear: 0, // 当前年份
|
||||
viewList: [], // 数据列表
|
||||
lineCount: 0, // 数据行数
|
||||
title: '', // 选择器标题
|
||||
data: [0, 0] // 当前选择年度-季度
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue(val) {
|
||||
this.changeValue(val)
|
||||
},
|
||||
readonly(val) {
|
||||
this.canEdit = !val && this.editable
|
||||
this.canPopover = !this.disabled && !val
|
||||
},
|
||||
editable(val) {
|
||||
this.canEdit = !this.readonly && val
|
||||
},
|
||||
disabled(val) {
|
||||
this.canPopover = !val && !this.readonly
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.changeValue(this.modelValue)
|
||||
|
||||
// 设置文本框是否可编辑
|
||||
this.canEdit = !this.readonly && this.editable
|
||||
this.canPopover = !this.disabled && !this.readonly
|
||||
|
||||
// 监听按键(上下左右键可以切换季度)
|
||||
document.onkeydown = (event) => {
|
||||
if (this.visible) {
|
||||
const data = [this.data[0], this.data[1]]
|
||||
if (data[0] < 1 || data[1] < 1) {
|
||||
// 以当前季度为标准
|
||||
const curDate = new Date()
|
||||
data[0] = curDate.getFullYear()
|
||||
data[1] = parseInt(curDate.getMonth() / 3) + 1
|
||||
}
|
||||
if (event.code === 'ArrowLeft') {
|
||||
// 上一个季度
|
||||
if (data[1] === 1) {
|
||||
data[0] = data[0] - 1
|
||||
data[1] = 4
|
||||
} else {
|
||||
data[1] = data[1] - 1
|
||||
}
|
||||
} else if (event.code === 'ArrowRight') {
|
||||
// 下一个季度
|
||||
if (data[1] === 4) {
|
||||
data[0] = data[0] + 1
|
||||
data[1] = 1
|
||||
} else {
|
||||
data[1] = data[1] + 1
|
||||
}
|
||||
} else if (event.code === 'ArrowUp') {
|
||||
// 上一年季度
|
||||
data[0] = data[0] - 1
|
||||
} else if (event.code === 'ArrowDown') {
|
||||
// 下一年季度
|
||||
data[0] = data[0] + 1
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
// 超过年限的不处理
|
||||
if (data[0] < 1000 || data[0] > 9999) {
|
||||
return
|
||||
}
|
||||
this.data = data
|
||||
this.viewType = 1
|
||||
this.viewYear = data[0]
|
||||
this.$emit('update:modelValue', this.formatTo(data, this.valueFormat))
|
||||
}
|
||||
}
|
||||
},
|
||||
unmounted() {
|
||||
document.onkeydown = null
|
||||
},
|
||||
methods: {
|
||||
// 季度文本变更
|
||||
changeText() {
|
||||
if (this.checkFormat(this.format, this.text)) {
|
||||
// 设置值
|
||||
this.formatFrom(this.text, this.format)
|
||||
this.$emit('update:modelValue', this.formatTo(this.data, this.valueFormat))
|
||||
} else {
|
||||
// 输入了无效的格式,还原回原来的值
|
||||
if (this.data[0] < 1 || this.data[1] < 1) {
|
||||
this.text = ''
|
||||
} else {
|
||||
this.text = this.formatTo(this.data, this.format)
|
||||
}
|
||||
}
|
||||
this.visible = false
|
||||
},
|
||||
// 鼠标进入
|
||||
mouseEnter() {
|
||||
if (!this.disabled && !this.readonly && this.clearable && this.text !== '') {
|
||||
this.showClear = true
|
||||
}
|
||||
},
|
||||
// 鼠标离开
|
||||
mouseLeave() {
|
||||
if (!this.disabled && this.clearable) {
|
||||
this.showClear = false
|
||||
}
|
||||
},
|
||||
// 清除季度
|
||||
clear() {
|
||||
this.showClear = false
|
||||
this.visible = false
|
||||
this.$emit('update:modelValue', '')
|
||||
},
|
||||
// 季度值变更
|
||||
changeValue(val) {
|
||||
this.viewType = 1
|
||||
if (val) {
|
||||
// 反向格式化
|
||||
this.formatFrom(val, this.valueFormat)
|
||||
this.text = this.formatTo(this.data, this.format)
|
||||
this.viewYear = this.data[0]
|
||||
} else {
|
||||
this.text = ''
|
||||
this.data = [0, 0]
|
||||
this.viewYear = new Date().getFullYear()
|
||||
}
|
||||
this.initView()
|
||||
},
|
||||
// 初始化视图数据
|
||||
initView() {
|
||||
const list = []
|
||||
const curDate = new Date()
|
||||
const curYear = curDate.getFullYear()
|
||||
const curQuarter = parseInt(curDate.getMonth() / 3) + 1
|
||||
if (this.viewType === 1) {
|
||||
let index = 0
|
||||
for (const i of '一二三四') {
|
||||
index++
|
||||
const item = { label: '第' + i + '季度', year: this.viewYear, quarter: index, current: false, active: false }
|
||||
if (this.viewYear === curYear && index === curQuarter) {
|
||||
item.current = true
|
||||
} else if (this.viewYear === this.data[0] && index === this.data[1]) {
|
||||
item.active = true
|
||||
}
|
||||
list.push(item)
|
||||
}
|
||||
this.title = this.viewYear + ' 年'
|
||||
} else {
|
||||
const start = parseInt(this.viewYear / 10) * 10
|
||||
this.viewYear = start
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const year = start + i
|
||||
const item = { label: year + '', year: year, current: false, active: false }
|
||||
if (year === curYear) {
|
||||
item.current = true
|
||||
} else if (year === this.data[0]) {
|
||||
item.active = true
|
||||
}
|
||||
list.push(item)
|
||||
}
|
||||
this.title = start + ' 年 - ' + (start + 9) + ' 年'
|
||||
}
|
||||
this.viewList = list
|
||||
this.lineCount = parseInt(list.length / 4)
|
||||
if (list.length % 4 > 0) {
|
||||
this.lineCount++
|
||||
}
|
||||
},
|
||||
// 校验季度格式是否正确
|
||||
checkFormat(pattern, val) {
|
||||
// 格式转成正则表达式
|
||||
let text = ''
|
||||
for (const char of pattern) {
|
||||
const dict = '\\^$.+?*[]{}!'
|
||||
if (dict.indexOf(char) === -1) {
|
||||
text += char
|
||||
} else {
|
||||
text += '\\' + char
|
||||
}
|
||||
}
|
||||
text = text.replace('yyyy', '[1-9]\\d{3}')
|
||||
text = text.replace('qq', '0[1-4]')
|
||||
text = text.replace('q', '[1-4]')
|
||||
text = text.replace('Q', '[一二三四]')
|
||||
text = '^' + text + '$'
|
||||
const patt = new RegExp(text)
|
||||
return patt.test(val)
|
||||
},
|
||||
// 格式化季度到指定格式
|
||||
formatTo(data, pattern) {
|
||||
let text = pattern.replace('yyyy', '' + data[0])
|
||||
text = text.replace('qq', '0' + data[1])
|
||||
text = text.replace('q', '' + data[1])
|
||||
text = text.replace('Q', '一二三四'.substr(data[1] - 1, 1))
|
||||
return text
|
||||
},
|
||||
// 以指定格式解析季度
|
||||
formatFrom(str, pattern) {
|
||||
const year = this.findText(str, pattern, 'yyyy')
|
||||
const quarter = this.findText(str, pattern, ['qq', 'q', 'Q'])
|
||||
this.data = [year, quarter]
|
||||
},
|
||||
// 查找文本数值
|
||||
findText(str, pattern, find) {
|
||||
if (find instanceof Array) {
|
||||
for (const f of find) {
|
||||
const val = this.findText(str, pattern, f)
|
||||
if (val !== -1) {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
const index = pattern.indexOf(find)
|
||||
if (index === -1) {
|
||||
return index
|
||||
}
|
||||
const val = str.substr(index, find.length)
|
||||
if (find === 'Q') {
|
||||
return '一二三四'.indexOf(val) + 1
|
||||
} else {
|
||||
return parseInt(val)
|
||||
}
|
||||
},
|
||||
// 年份点击
|
||||
clickYear() {
|
||||
if (this.viewType !== 1) {
|
||||
return
|
||||
}
|
||||
// 切换年度选择器
|
||||
this.viewType = 2
|
||||
this.initView()
|
||||
},
|
||||
// 季度选择
|
||||
clickItem(item) {
|
||||
if (this.viewType === 1) {
|
||||
// 选择季度
|
||||
this.$emit('update:modelValue', this.formatTo([item.year, item.quarter], this.valueFormat))
|
||||
this.visible = false
|
||||
} else {
|
||||
// 选择年度
|
||||
this.viewType = 1
|
||||
this.viewYear = item.year
|
||||
this.initView()
|
||||
}
|
||||
},
|
||||
// 上一年
|
||||
clickLast() {
|
||||
if (this.viewYear > 1000) {
|
||||
if (this.viewType === 1) {
|
||||
this.viewYear--
|
||||
this.initView()
|
||||
} else {
|
||||
this.viewYear = this.viewYear - 10
|
||||
this.initView()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 下一年
|
||||
clickNext() {
|
||||
if (this.viewYear < 9999) {
|
||||
if (this.viewType === 1) {
|
||||
this.viewYear++
|
||||
this.initView()
|
||||
} else {
|
||||
this.viewYear = this.viewYear + 10
|
||||
this.initView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-quarter-picker {
|
||||
width: 220px;
|
||||
display: inline-block;
|
||||
}
|
||||
.el-quarter-popover-content {
|
||||
max-width: 100%;
|
||||
word-break: break-all;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
|
@ -599,6 +599,17 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
activeMenu: '/crm/station-site'
|
||||
},
|
||||
component: () => import('@/views/crm/stationsite/detail/index.vue')
|
||||
},
|
||||
{
|
||||
path: 'project/settlement/:id',
|
||||
name: 'CrmProjectSettlementDetail',
|
||||
meta: {
|
||||
title: '利润结算详情',
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
activeMenu: '/crm/project/settlement'
|
||||
},
|
||||
component: () => import('@/views/crm/project/settlement/detail/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
v-loading="formLoading"
|
||||
>
|
||||
<el-row>
|
||||
{{ formData }}
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="deptId">
|
||||
<el-select
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="40%">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
|
|
@ -7,47 +7,79 @@
|
|||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="关联项目ID" prop="projectId">
|
||||
<el-select
|
||||
v-model="formData.projectId"
|
||||
filterable
|
||||
placeholder="请选择关联项目"
|
||||
class="!w-100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算周期(如:2023-Q1)" prop="settlementPeriod">
|
||||
<el-input v-model="formData.settlementPeriod" placeholder="请输入结算周期(如:2023-Q1)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="总期数" prop="period">
|
||||
<el-input v-model.number="formData.period" placeholder="请输入总期数" type="number" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="formData.settlementDate"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择结算日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="收入备注" prop="incomeRemark">
|
||||
<el-input v-model="formData.incomeRemark" placeholder="请输入收入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="支出备注" prop="expenseRemark">
|
||||
<el-input v-model="formData.expenseRemark" placeholder="请输入支出备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结算凭证附件" prop="proofAttachment">
|
||||
<UploadFile v-model="formData.proofAttachment" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结算备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入结算备注" />
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-select
|
||||
v-model="formData.projectId"
|
||||
filterable
|
||||
placeholder="请选择关联项目"
|
||||
class="!w-100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结算周期" prop="settlementPeriod">
|
||||
<el-quarter-picker v-model="formData.settlementPeriod" placeholder="选择季度" value-format="yyyy-q" clearable style="width: 100%"
|
||||
popper-class="full-width-datepicker" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="formData.settlementDate"
|
||||
type="date"
|
||||
placeholder="选择结算日期"
|
||||
style="width: 100%"
|
||||
popper-class="full-width-datepicker"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算开始时间" prop="startDate">
|
||||
<el-date-picker
|
||||
v-model="formData.startDate"
|
||||
type="date"
|
||||
placeholder="选择结算开始时间"
|
||||
style="width: 100%"
|
||||
popper-class="full-width-datepicker"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算结束时间" prop="endDate">
|
||||
<el-date-picker
|
||||
v-model="formData.endDate"
|
||||
type="date"
|
||||
placeholder="选择结算结束时间"
|
||||
style="width: 100%"
|
||||
popper-class="full-width-datepicker"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="收入备注" prop="incomeRemark">
|
||||
<el-input v-model="formData.incomeRemark" placeholder="请输入收入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="支出备注" prop="expenseRemark">
|
||||
<el-input v-model="formData.expenseRemark" placeholder="请输入支出备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
|
|
@ -58,6 +90,7 @@
|
|||
<script setup lang="ts">
|
||||
import * as ProjectSettlementApi from '@/api/crm/project/settlement'
|
||||
import * as ProjectApi from '@/api/crm/project'
|
||||
import ElQuarterPicker from '@/components/ElQuarterPicker/index.vue'
|
||||
|
||||
/** 项目利润结算 表单 */
|
||||
defineOptions({ name: 'ProjectSettlementForm' })
|
||||
|
|
@ -74,6 +107,8 @@ const formData = ref({
|
|||
projectId: undefined,
|
||||
settlementPeriod: undefined,
|
||||
period: undefined,
|
||||
startDate: undefined,
|
||||
endDate: undefined,
|
||||
settlementDate: undefined,
|
||||
incomeRemark: undefined,
|
||||
expenseRemark: undefined,
|
||||
|
|
@ -81,8 +116,8 @@ const formData = ref({
|
|||
remark: undefined,
|
||||
})
|
||||
const formRules = reactive({
|
||||
projectId: [{ required: true, message: '关联项目ID不能为空', trigger: 'blur' }],
|
||||
settlementPeriod: [{ required: true, message: '结算周期(如:2023-Q1)不能为空', trigger: 'blur' }],
|
||||
projectId: [{ required: true, message: '项目不能为空', trigger: 'blur' }],
|
||||
settlementPeriod: [{ required: true, message: '结算周期不能为空', trigger: 'blur' }],
|
||||
settlementDate: [{ required: true, message: '结算日期不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
|
@ -139,6 +174,8 @@ const resetForm = () => {
|
|||
projectId: undefined,
|
||||
settlementPeriod: undefined,
|
||||
period: undefined,
|
||||
startDate: undefined,
|
||||
endDate: undefined,
|
||||
settlementDate: undefined,
|
||||
incomeRemark: undefined,
|
||||
expenseRemark: undefined,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-form-item labssel="项目" prop="projectId">
|
||||
<el-select
|
||||
v-model="queryParams.projectId"
|
||||
clearable
|
||||
|
|
@ -23,19 +23,18 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算周期(如:2023-Q1)" prop="settlementPeriod">
|
||||
<el-input
|
||||
v-model="queryParams.settlementPeriod"
|
||||
placeholder="请输入结算周期(如:2023-Q1)"
|
||||
<el-form-item label="结算周期" prop="settlementPeriod">
|
||||
<el-quarter-picker
|
||||
v-model="queryParams.settlementPeriod"
|
||||
placeholder="选择季度"
|
||||
value-format="yyyy-q"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="queryParams.settlementDate"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
|
|
@ -53,17 +52,6 @@
|
|||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-220px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
|
|
@ -91,18 +79,39 @@
|
|||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="项目名称" align="center" prop="projectName" />
|
||||
<el-table-column label="枪数" align="center" prop="settlementPeriod" />
|
||||
<el-table-column label="结算周期(如:2023-Q1)" align="center" prop="settlementPeriod" />
|
||||
<el-table-column label="结算开始时间" align="center" prop="settlementDate" />
|
||||
<el-table-column label="结算结束时间" align="center" prop="settlementDate" />
|
||||
<el-table-column label="结算日期" align="center" prop="settlementDate" />
|
||||
|
||||
<el-table-column label="项目名称" align="center" prop="projectName">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" @click="goDetail(scope.row)">{{ scope.row.projectName }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="枪数" align="center" prop="piles" />
|
||||
<el-table-column label="结算周期" align="center" prop="settlementPeriod" >
|
||||
<template #default="scope">
|
||||
{{ formatQuarterPeriod(scope.row.settlementPeriod) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算开始时间" align="center" prop="startDate">
|
||||
<template #default="scope">
|
||||
{{ scope.row.startDate ? formatDate(scope.row.startDate, 'YYYY-MM-DD') : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算结束时间" align="center" prop="endDate">
|
||||
<template #default="scope">
|
||||
{{ scope.row.endDate ? formatDate(scope.row.endDate, 'YYYY-MM-DD') : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算日期" align="center" prop="settlementDate">
|
||||
<template #default="scope">
|
||||
{{ scope.row.settlementDate ? formatDate(scope.row.settlementDate, 'YYYY-MM-DD') : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总期数" align="center" prop="period" />
|
||||
<el-table-column label="毛利润" align="center" prop="settlementDate" />
|
||||
<el-table-column label="单枪毛利润" align="center" prop="settlementDate" />
|
||||
<el-table-column label="净利润" align="center" prop="settlementDate" />
|
||||
<el-table-column label="毛利润" align="center" prop="grossProfit" />
|
||||
<el-table-column label="上期亏损转结" align="center" prop="previousLossCarryover" />
|
||||
<el-table-column label="净利润" align="center" prop="netProfit" />
|
||||
<el-table-column label="结算状态" align="center" prop="settlementStatus" />
|
||||
<el-table-column label="操作" align="center" min-width="120px">
|
||||
<el-table-column label="操作" align="center" min-width="180px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
|
|
@ -137,11 +146,23 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as ProjectSettlementApi from '@/api/crm/project/settlement'
|
||||
import * as ProjectApi from '@/api/crm/project'
|
||||
import ProjectSettlementForm from './ProjectSettlementForm.vue'
|
||||
import ElQuarterPicker from '@/components/ElQuarterPicker/index.vue'
|
||||
|
||||
// 结算周期格式化:'2024-1' => '2024年第一季度'
|
||||
function formatQuarterPeriod(val?: string) {
|
||||
if (!val) return ''
|
||||
const match = val.match(/^(\d{4})-(\d)$/)
|
||||
if (!match) return val
|
||||
const year = match[1]
|
||||
const quarter = match[2]
|
||||
const quarterMap = { '1': '第一季度', '2': '第二季度', '3': '第三季度', '4': '第四季度' }
|
||||
return `${year}年${quarterMap[quarter] || quarter}`
|
||||
}
|
||||
|
||||
/** 项目利润结算 列表 */
|
||||
defineOptions({ name: 'CrmProjectSettlement' })
|
||||
|
|
@ -223,6 +244,17 @@ const handleExport = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 跳转到项目结算明细页面 */
|
||||
const router = useRouter()
|
||||
function goDetail(row: ProjectSettlementApi.ProjectSettlementVO) {
|
||||
router.push({
|
||||
name: 'CrmProjectSettlementDetail',
|
||||
params: { id: row.id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
|
|
|
|||
Loading…
Reference in New Issue