add 往来明细

pull/853/head
wersd 2025-09-04 21:32:14 +08:00
parent e43b61da12
commit f08f0df6b6
11 changed files with 561 additions and 26 deletions

View File

@ -27,50 +27,50 @@ export interface SortingField {
}
// 查询项目月度统计分页
export const getProjectMonthlyStatPage = async (data: ProjectMonthlyStatPageReqVO) => {
return await request.post({ url: `/crm/project-monthly-stat/page`, data })
return await request.post({ url: `/crm/project/monthly-stat/page`, data })
}
// 查询项目月度统计详情
export const getProjectMonthlyStat = async (id: number) => {
return await request.get({ url: `/crm/project-monthly-stat/get?id=` + id })
return await request.get({ url: `/crm/project/monthly-stat/get?id=` + id })
}
// 新增项目月度统计
export const createProjectMonthlyStat = async (data: ProjectMonthlyStatVO) => {
return await request.post({ url: `/crm/project-monthly-stat/create`, data })
return await request.post({ url: `/crm/project/monthly-stat/create`, data })
}
// 修改项目月度统计
export const updateProjectMonthlyStat = async (data: ProjectMonthlyStatVO) => {
return await request.put({ url: `/crm/project-monthly-stat/update`, data })
return await request.put({ url: `/crm/project/monthly-stat/update`, data })
}
// 删除项目月度统计
export const deleteProjectMonthlyStat = async (id: number) => {
return await request.delete({ url: `/crm/project-monthly-stat/delete?id=` + id })
return await request.delete({ url: `/crm/project/monthly-stat/delete?id=` + id })
}
// 导出项目月度统计 Excel
export const exportProjectMonthlyStat = async (params: any) => {
return await request.download({ url: `/crm/project-monthly-stat/export-excel`, params })
return await request.download({ url: `/crm/project/monthly-stat/export-excel`, params })
}
// 同步项目月度统计
export const syncProjectMonthlyStat = async (data: ProjectMonthlyStatVO) => {
return await request.put({ url: `/crm/project-monthly-stat/sync`, data })
return await request.put({ url: `/crm/project/monthly-stat/sync`, data })
}
// 查询项目月度统计图数据
export const getProjectMonthlyStatChartData = async (params: any) => {
return await request.get({ url: `/crm/project-monthly-stat/get-chart-data`, params})
return await request.get({ url: `/crm/project/monthly-stat/get-chart-data`, params})
}
// 查询项目对比图数据
export const getProjectCompareChartData = async (data: any) => {
return await request.post({ url: `/crm/project-monthly-stat/get-project-data`, data})
return await request.post({ url: `/crm/project/monthly-stat/get-project-data`, data})
}
// 获取项目列表
export const getProjectSimpleList = async () => {
return await request.get({ url: `/crm/project-monthly-stat/project-simple-list` })
return await request.get({ url: `/crm/project/monthly-stat/project-simple-list` })
}

View File

@ -4,7 +4,7 @@ import request from '@/config/axios'
export interface ProjectSettlementVO {
id: number; // 结算记录ID
projectId: number; // 项目ID
projectName: string; // 项目名称
name: string; // 项目名称
piles: string; // 枪数
settlementPeriod: string; // 结算周期(如:2023-Q1)
period: number; // 总期数
@ -37,32 +37,32 @@ export interface ProjectSettlementVO {
// 查询项目利润结算分页
export const getProjectSettlementPage = async (params: any) => {
return await request.get({ url: `/crm/project-settlement/page`, params })
return await request.get({ url: `/crm/project/settlement/page`, params })
}
// 查询项目利润结算详情
export const getProjectSettlement = async (id: number) => {
return await request.get({ url: `/crm/project-settlement/get?id=` + id })
return await request.get({ url: `/crm/project/settlement/get?id=` + id })
}
// 新增项目利润结算
export const createProjectSettlement = async (data: ProjectSettlementVO) => {
return await request.post({ url: `/crm/project-settlement/create`, data })
return await request.post({ url: `/crm/project/settlement/create`, data })
}
// 修改项目利润结算
export const updateProjectSettlement = async (data: ProjectSettlementVO) => {
return await request.put({ url: `/crm/project-settlement/update`, data })
return await request.put({ url: `/crm/project/settlement/update`, data })
}
// 删除项目利润结算
export const deleteProjectSettlement = async (id: number) => {
return await request.delete({ url: `/crm/project-settlement/delete?id=` + id })
return await request.delete({ url: `/crm/project/settlement/delete?id=` + id })
}
// 导出项目利润结算 Excel
export const exportProjectSettlement = async (params: any) => {
return await request.download({ url: `/crm/project-settlement/export-excel`, params })
return await request.download({ url: `/crm/project/settlement/export-excel`, params })
}
// 导出项目利润结算明细 Excel

View File

@ -0,0 +1,49 @@
import request from '@/config/axios'
// CRM项目往来明细 VO
export interface ProjectTransactionDetailVO {
id: number // 主键ID
projectId: number // 关联项目ID
projectName: string // 项目名称
date: Date // 缴存日期
userId: number // 投资人
userName: string // 投资人名称
investmentAmount: number // 投资金额
saveAmount: number // 缴存金额
}
// 查询CRM项目往来明细分页
export const getProjectTransactionDetailPage = async (params: any) => {
return await request.get({ url: `/crm/project/transaction-detail/page`, params })
}
// 查询CRM项目往来明细详情
export const getProjectTransactionDetail = async (id: number) => {
return await request.get({ url: `/crm/project/transaction-detail/get?id=` + id })
}
// 新增CRM项目往来明细
export const createProjectTransactionDetail = async (data: ProjectTransactionDetailVO) => {
return await request.post({ url: `/crm/project/transaction-detail/create`, data })
}
// 修改CRM项目往来明细
export const updateProjectTransactionDetail = async (data: ProjectTransactionDetailVO) => {
return await request.put({ url: `/crm/project/transaction-detail/update`, data })
}
// 删除CRM项目往来明细
export const deleteProjectTransactionDetail = async (id: number) => {
return await request.delete({ url: `/crm/project/transaction-detail/delete?id=` + id })
}
// 导出CRM项目往来明细 Excel
export const exportProjectTransactionDetail = async (params: any) => {
return await request.download({ url: `/crm/project/transaction-detail/export-excel`, params })
}
// 查询CRM项目往来明细分页合计
export const getProjectTransactionDetailTotal = async (params: any) => {
return await request.get({ url: `/crm/project/transaction-detail/page-total`, params })
}

View File

@ -57,7 +57,7 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column align="center" label="项目名称" prop="deptName" min-width="250"/>
<el-table-column align="center" label="项目名称" prop="name" min-width="250"/>
<el-table-column align="center" label="场地租赁合同" prop="cooperationAgreement" width="200">
<template #default="scope">
<template v-if="scope.row.cooperationAgreement && scope.row.cooperationAgreementConfig == undefined">

View File

@ -75,7 +75,7 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column align="center" label="项目名称" prop="deptName" min-width="300"/>
<el-table-column align="center" label="项目名称" prop="name" min-width="300"/>
<el-table-column label="项目总投资额(万元)" align="center" prop="totalInvestment" width="180"/>
<el-table-column label="枪数" align="center" prop="estimatedPiles" />

View File

@ -126,8 +126,8 @@
:show-overflow-tooltip="true"
@sort-change="handleSortChange"
>
<el-table-column label="项目名称" align="center" prop="projectName" fixed="left" min-width="200px"/>
{{ SCOPE.row }}
<el-table-column label="项目名称" align="center" prop="name" fixed="left" min-width="200px"/>
<el-table-column label="枪数" align="center" prop="estimatedPiles" width="100px"/>
<el-table-column label="统计月份" align="center" prop="statMonth" sortable="custom" width="160px"/>
<el-table-column label="总充电量(度)" align="center" prop="chargingQuantity" sortable="custom" width="160px"/>

View File

@ -9,7 +9,7 @@
>
<el-row>
<el-col :span="12">
<el-form-item label="项目" prop="projectId" min-width="260px">
<el-form-item label="项目" prop="projectId">
<el-select
v-model="formData.projectId"
filterable

View File

@ -2,7 +2,7 @@
<div v-loading="loading">
<div class="flex items-start justify-between">
<div>
<span class="text-md font-bold">{{ settlement.projectName || '' }}</span>
<span class="text-md font-bold">{{ settlement.name || '' }}</span>
</div>
<div>
<slot></slot>
@ -12,7 +12,7 @@
<ContentWrap class="mt-10px">
<el-descriptions :column="3" direction="horizontal" class="mb-10px">
<el-descriptions-item label="项目名称:">
{{ settlement.projectName || '' }}
{{ settlement.name || '' }}
</el-descriptions-item>
<el-descriptions-item label="枪数:">
{{ settlement.piles || '' }}

View File

@ -81,9 +81,9 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="项目名称" align="center" prop="projectName" fixed="left" min-width="200px">
<el-table-column label="项目名称" align="center" prop="name" fixed="left" min-width="200px">
<template #default="scope">
<el-link type="primary" @click="goDetail(scope.row)">{{ scope.row.projectName }}</el-link>
<el-link type="primary" @click="goDetail(scope.row)">{{ scope.row.name }}</el-link>
</template>
</el-table-column>
<el-table-column label="枪数" align="center" prop="piles" width="200px"/>

View File

@ -0,0 +1,204 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-row :gutter="20">
<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="date">
<el-date-picker
v-model="formData.date"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择缴存日期"
style="width: 100%"
popper-class="full-width-datepicker"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="投资人" prop="userId">
<el-select
v-model="formData.userId"
filterable
clearable
placeholder="请选择用户"
>
<el-option
v-for="user in userOptions"
:key="user.id"
:label="user.nickname"
:value="user.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="投资金额" prop="investmentAmount">
<el-input v-model="formData.investmentAmount" placeholder="请输入投资金额" type="number" @input="onAmountInput('investmentAmount')" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="缴存金额" prop="saveAmount">
<el-input v-model="formData.saveAmount" placeholder="请输入缴存金额" type="number" @input="onAmountInput('saveAmount')" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
const validateProjectRequired = (_: any, __: any, callback: any) => {
const userId = formData.value.userId;
const projectId = formData.value.projectId;
if (userId !== 1 && userId !== '1') {
if (projectId === undefined || projectId === '' || projectId === null) {
callback(new Error('请选择项目'));
return;
}
}
callback();
};
import * as ProjectTransactionDetailApi from '@/api/crm/project/transaction'
import * as ProjectApi from '@/api/crm/project'
import * as UserApi from '@/api/system/user'
/** CRM项目往来明细 表单 */
defineOptions({ name: 'ProjectTransactionDetailForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
projectId: undefined,
date: undefined,
userId: undefined,
investmentAmount: undefined,
saveAmount: undefined,
})
const validateAmountExclusive = (_: any, __: any, callback: any) => {
const investment = formData.value.investmentAmount;
const save = formData.value.saveAmount;
if ((investment === undefined || investment === '' || investment === null) && (save === undefined || save === '' || save === null)) {
callback(new Error('投资金额和缴存金额必须填写一个'));
} else if ((investment !== undefined && investment !== '' && investment !== null) && (save !== undefined && save !== '' && save !== null)) {
callback(new Error('投资金额和缴存金额只能填写一个'));
} else {
callback();
}
};
const formRules = reactive({
date: [{ required: true, message: '缴存日期不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '投资人不能为空', trigger: 'blur' }],
projectId: [{ validator: validateProjectRequired, trigger: 'blur' }],
investmentAmount: [{ validator: validateAmountExclusive, trigger: 'blur' }],
saveAmount: [{ validator: validateAmountExclusive, trigger: 'blur' }],
})
const formRef = ref() // Ref
const projectOptions = ref<ProjectApi.ProjectVO[]>([])
const userOptions = ref<any[]>([])
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProjectTransactionDetailApi.getProjectTransactionDetail(id)
} finally {
formLoading.value = false
}
}
//
projectOptions.value = await ProjectApi.getProjectSimpleList();
//
userOptions.value = await UserApi.getSimpleUserList()
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProjectTransactionDetailApi.ProjectTransactionDetailVO
if (formType.value === 'create') {
await ProjectTransactionDetailApi.createProjectTransactionDetail(data)
message.success(t('common.createSuccess'))
} else {
await ProjectTransactionDetailApi.updateProjectTransactionDetail(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 金额输入控制两位小数 */
const onAmountInput = (field: 'investmentAmount' | 'saveAmount') => {
let val = formData.value[field]
if (val !== undefined && val !== null) {
//
const strVal = String(val).replace(/^(\d+)(\.\d{0,2})?.*$/, '$1$2')
formData.value[field] = strVal as any
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
projectId: undefined,
date: undefined,
userId: undefined,
investmentAmount: undefined,
saveAmount: undefined,
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,282 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="项目" prop="projectId">
<el-select
v-model="queryParams.projectId"
clearable
filterable
@keyup.enter="handleQuery"
class="!w-240px"
>
<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="缴存日期" prop="date">
<el-date-picker
v-model="queryParams.date"
value-format="YYYY-MM-DD"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="投资人/代管人" prop="userId" label-width="120px">
<el-select
v-model="queryParams.userId"
filterable
clearable
placeholder="请选择投资人/代管人"
class="!w-220px"
>
<el-option
v-for="user in userOptions"
:key="user.id"
:label="user.nickname"
:value="user.id"
/>
</el-select>
</el-form-item>
<el-form-item label="投资金额" prop="investmentAmount">
<el-input
v-model="queryParams.investmentAmount"
placeholder="请输入投资金额"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
type="number"
/>
</el-form-item>
<el-form-item label="缴存金额" prop="saveAmount">
<el-input
v-model="queryParams.saveAmount"
placeholder="请输入缴存金额"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
type="number"
/>
</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>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:project-transaction-detail:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:project-transaction-detail:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" show-summary :summary-method="getSummaries">
<el-table-column label="缴存日期" align="center" prop="date" fixed="left" width="300px">
<template #default="scope">
{{ scope.row.date ? formatDate(scope.row.date, 'YYYY-MM-DD') : '' }}
</template>
</el-table-column>
<el-table-column label="投资人/代管人" align="center" prop="userName" width="300px"/>
<el-table-column label="项目名称" align="center" prop="projectName" min-width="260px"/>
<el-table-column label="投资款/分红" align="center" prop="investmentAmount" width="300px"/>
<el-table-column label="缴存/支取" align="center" prop="saveAmount" width="300px"/>
<el-table-column label="相差数" align="center" prop="diff" width="300px"/>
<el-table-column label="操作" align="center" fixed="right" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:project-transaction-detail:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:project-transaction-detail:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getData"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProjectTransactionDetailForm ref="formRef" @success="getData" />
</template>
<script setup lang="ts">
import download from '@/utils/download'
import { formatDate } from '@/utils/formatTime'
import * as ProjectTransactionDetailApi from '@/api/crm/project/transaction'
import * as ProjectApi from '@/api/crm/project'
import * as UserApi from '@/api/system/user'
import ProjectTransactionDetailForm from './ProjectTransactionDetailForm.vue'
import { get } from 'http'
/** CRM项目往来明细 列表 */
defineOptions({ name: 'CrmProjectTransactionDetail' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProjectTransactionDetailApi.ProjectTransactionDetailVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
projectId: undefined,
date: [],
userId: undefined,
investmentAmount: undefined,
saveAmount: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const projectOptions = ref<ProjectApi.ProjectVO[]>([])
const userOptions = ref<any[]>([])
//
const totalInvestmentAmount = ref(0)
const totalSaveAmount = ref(0)
const totalDiff = ref(0)
const getData = async () => {
getList()
getTotal()
};
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProjectTransactionDetailApi.getProjectTransactionDetailPage(queryParams)
list.value = data.list.map(item => ({
...item,
diff: (Number(item.saveAmount) || 0) - (Number(item.investmentAmount) || 0)
}))
total.value = data.total
} finally {
loading.value = false
}
}
/** 查询列表 */
const getTotal = async () => {
loading.value = true
try {
const data = await ProjectTransactionDetailApi.getProjectTransactionDetailTotal(queryParams)
totalInvestmentAmount.value = data.totalInvestmentAmount || 0
totalSaveAmount.value = data.totalSaveAmount || 0
totalDiff.value = (data.totalSaveAmount || 0) - (data.totalInvestmentAmount || 0)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getData()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProjectTransactionDetailApi.deleteProjectTransactionDetail(id)
message.success(t('common.delSuccess'))
//
await getData()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProjectTransactionDetailApi.exportProjectTransactionDetail(queryParams)
download.excel(data, '往来明细.xls')
} catch {
} finally {
exportLoading.value = false
}
}
//
const getSummaries = (param: any) => {
const sums: any[] = [];
//
sums[0] = '合计'; //
sums[1] = '-';
sums[2] = '-';
sums[3] = totalInvestmentAmount.value;
sums[4] = totalSaveAmount.value;
sums[5] = totalDiff.value;
sums[6] = '';
return sums;
}
/** 初始化 **/
onMounted(async () => {
await getData()
//
projectOptions.value = await ProjectApi.getProjectSimpleList();
//
userOptions.value = await UserApi.getSimpleUserList()
})
</script>