admin-vue3/src/views/crm/project/settlement/index.vue

357 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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="settlementPeriod">
<el-quarter-picker
v-model="queryParams.settlementPeriod"
placeholder="选择季度"
value-format="yyyy-q"
clearable
/>
</el-form-item>
<el-form-item label="结算日期" prop="settlementDate">
<el-date-picker
v-model="queryParams.settlementDate"
value-format="YYYY-MM-DD"
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 label="结算状态" prop="settlementStatus">
<el-select
v-model="queryParams.settlementStatus"
placeholder="请选择结算状态"
clearable
class="!w-240px"
>
<el-option label="请选择字典生成" value="" />
</el-select>
</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-settlement:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:project-settlement: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">
<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.name }}</el-link>
</template>
</el-table-column>
<el-table-column label="枪数" align="center" prop="piles" width="200px"/>
<el-table-column label="结算周期" align="center" prop="settlementPeriod" width="200px">
<template #default="scope">
{{ formatQuarterPeriod(scope.row.settlementPeriod) }}
</template>
</el-table-column>
<el-table-column label="总期数" align="center" prop="period" width="200px"/>
<el-table-column label="结算开始时间" align="center" prop="startDate" width="200px">
<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" width="200px">
<template #default="scope">
{{ scope.row.endDate ? formatDate(scope.row.endDate, 'YYYY-MM-DD') : '' }}
</template>
</el-table-column>
<el-table-column label="毛利润" align="center" prop="grossProfit" width="200px"/>
<el-table-column label="上期亏损转结" align="center" prop="previousLossCarryover" width="200px" />
<el-table-column label="净利润" align="center" prop="netProfit" width="200px"/>
<!-- <el-table-column label="结算状态" align="center" prop="settlementStatus" /> -->
<el-table-column label="结算日期" align="center" prop="settlementDate" width="200px">
<template #default="scope">
{{ scope.row.settlementDate ? formatDate(scope.row.settlementDate, 'YYYY-MM-DD') : '' }}
</template>
</el-table-column>
<el-table-column align="center" label="结算状态" prop="settlementStatus" width="160">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_PROJECT_SETTLEMENT_STATUS" :value="scope.row.settlementStatus" />
</template>
</el-table-column>
<el-table-column label="对账回执" align="center" prop="proofAttachment" width="200px">
<template #default="scope">
<el-button
v-if="scope.row.proofAttachment"
link
type="primary"
@click="openFile(scope.row.proofAttachment)"
class="text-blue-500 hover:text-blue-700"
>
<Icon icon="ep:document" class="mr-1" />
下载回执
</el-button>
<span v-else class="text-gray-400">暂无回执</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180px" fixed="right">
<template #default="scope">
<el-button
v-if="scope.row.settlementStatus === 0"
link
type="success"
@click="settelment(scope.row.id)"
v-hasPermi="['crm:project-settlement:update']"
>
结算
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:project-settlement:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:project-settlement:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<ProjectSettlementForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
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'
import { DICT_TYPE } from '@/utils/dict'
import { ElMessageBox } from 'element-plus'
// '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' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref<ProjectSettlementApi.ProjectSettlementVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
projectId: undefined,
settlementPeriod: undefined,
settlementDate: [],
settlementStatus: undefined,
createTime: [],
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const projectOptions = ref<ProjectApi.ProjectVO[]>([])
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProjectSettlementApi.getProjectSettlementPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
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 ProjectSettlementApi.deleteProjectSettlement(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await ProjectSettlementApi.exportProjectSettlement(queryParams)
download.excel(data, '项目利润结算.xls')
} catch {
} finally {
exportLoading.value = false
}
}
// 结算按钮方法
const settelment = async (id: number) => {
try {
// 结算的二次确认
await message.confirm("是否发起结算?")
// 发起结算
await ProjectSettlementApi.settelmentProjectSettlementDetail(id)
message.success(t('结算成功'))
// 刷新列表
await getList()
} catch {}
}
/** 跳转到项目结算明细页面 */
const router = useRouter()
function goDetail(row: ProjectSettlementApi.ProjectSettlementVO) {
router.push({
name: 'CrmProjectSettlementDetail',
params: { id: row.id }
})
}
/** 打开文件 */
const openFile = (fileUrl: string) => {
if (!fileUrl) {
message.warning('文件链接不存在')
return
}
// 获取文件名
const fileName = fileUrl.split('/').pop() || '未知文件'
// 获取文件扩展名
const fileExtension = fileName.split('.').pop()?.toLowerCase()
// 根据文件类型处理
if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExtension || '')) {
// 图片文件:在新窗口中打开
window.open(fileUrl, '_blank')
} else if (['pdf'].includes(fileExtension || '')) {
// PDF文件在新窗口中打开
window.open(fileUrl, '_blank')
} else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(fileExtension || '')) {
// Office文件直接下载
downloadFile(fileUrl, fileName)
} else {
// 其他文件:提示用户选择操作
ElMessageBox.confirm('是否下载该文件?', '文件操作', {
confirmButtonText: '下载',
cancelButtonText: '在线查看',
type: 'info'
}).then(() => {
downloadFile(fileUrl, fileName)
}).catch(() => {
window.open(fileUrl, '_blank')
})
}
}
/** 下载文件 */
const downloadFile = (url: string, fileName: string) => {
const link = document.createElement('a')
link.href = url
link.download = fileName
link.target = '_blank'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
/** 初始化 **/
onMounted(async () => {
await getList()
// 获取项目列表
projectOptions.value = await ProjectApi.getProjectSimpleList();
})
</script>