表格修改

This commit is contained in:
lzm
2026-04-28 18:53:58 +08:00
parent 38c634f8de
commit 7fff38fb32
4 changed files with 304 additions and 172 deletions

View File

@@ -2,7 +2,7 @@ import request from '@/config/axios'
export interface ProjectOverviewExportReqVO {
year?: number
specialtyCode?: string
officeId?: number
sortType?: string
}

View File

@@ -6,17 +6,24 @@ export const useRenderMenuTitle = () => {
const renderMenuTitle = (meta: RouteMeta) => {
const { t } = useI18n()
const { title = 'Please set title', icon } = meta
const text = t(title as string)
return icon ? (
<>
<Icon icon={meta.icon}></Icon>
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
{t(title as string)}
<span
class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap"
title={text}
>
{text}
</span>
</>
) : (
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
{t(title as string)}
<span
class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap"
title={text}
>
{text}
</span>
)
}

View File

@@ -1,7 +1,7 @@
:root {
--login-bg-color: #293146;
--left-menu-max-width: 200px;
--left-menu-max-width: 224px;
--left-menu-min-width: 64px;

View File

@@ -1,75 +1,8 @@
<template>
<ContentWrap>
<div class="flex items-center justify-between gap-16px">
<div>
<div class="text-16px font-600">产值汇总报表中心</div>
<div class="mt-4px text-13px text-[var(--el-text-color-secondary)]">
页面9独立承载 7.1.5 项目总览表7.1.6 员工个人考核产值汇总
</div>
</div>
</div>
</ContentWrap>
<ContentWrap>
<el-tabs v-model="activeTab">
<el-tab-pane label="项目总览表" name="projectOverview">
<el-form :inline="true" :model="projectOverviewForm" label-width="88px">
<el-form-item label="年度">
<el-date-picker
v-model="projectOverviewYearValue"
class="!w-180px"
clearable
placeholder="请选择年度"
type="year"
value-format="YYYY"
/>
</el-form-item>
<el-form-item label="专业">
<el-select
v-model="projectOverviewForm.specialtyCode"
class="!w-220px"
clearable
placeholder="请选择专业"
>
<el-option
v-for="item in REPORT_SPECIALTY_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="排序方式">
<el-select
v-model="projectOverviewForm.sortType"
class="!w-220px"
placeholder="请选择排序方式"
>
<el-option
v-for="item in PROJECT_OVERVIEW_SORT_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
v-hasPermi="['tjt:report-summary:export']"
:loading="projectOverviewExportLoading"
plain
type="primary"
@click="handleExportProjectOverview"
>
<Icon class="mr-5px" icon="ep:download" />
导出项目总览表
</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="员工个人考核产值汇总" name="employeeSummary">
<el-form :inline="true" :model="employeeSummaryForm" label-width="100px">
<el-tab-pane label="员工产值汇总" name="employeeSummary">
<el-form :inline="true" :model="employeeSummaryForm" label-width="88px">
<el-form-item label="年度">
<el-date-picker
v-model="employeeSummaryYearValue"
@@ -80,13 +13,57 @@
value-format="YYYY"
/>
</el-form-item>
<!-- <el-form-item>
<el-button @click="getEmployeeBudgetList">
<Icon class="mr-5px" icon="ep:refresh" />
刷新预览
</el-button>
</el-form-item> -->
<el-form-item>
<el-button
v-hasPermi="['tjt:report-summary:export']"
:loading="employeeSummaryExportLoading"
plain
type="primary"
@click="openEmployeeSummaryExportDialog"
>
<Icon class="mr-5px" icon="ep:download" />
导出员工汇总
</el-button>
</el-form-item>
</el-form>
<el-table
v-loading="employeeBudgetLoading"
:data="employeeBudgetList"
class="mt-12px"
:empty-text="employeeSummaryForm.year ? '暂无年度成本预算数据' : '请先选择年度'"
>
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="员工姓名" min-width="160" prop="employeeName" />
<el-table-column align="center" label="预计年度" prop="budgetYear" width="120" />
<el-table-column align="center" label="预计发生成本" min-width="160">
<template #default="scope">
{{ formatAmount(scope.row.expectedCostAmount) }}
</template>
</el-table-column>
</el-table>
<Pagination
v-model:limit="employeeBudgetQuery.pageSize"
v-model:page="employeeBudgetQuery.pageNo"
:total="employeeBudgetTotal"
@pagination="getEmployeeBudgetList"
/>
</el-tab-pane>
<el-tab-pane label="项目产值总览" name="projectOverview">
<el-form :inline="true" :model="projectOverviewForm" label-width="88px">
<el-form-item label="专业所">
<el-select
v-model="employeeSummaryForm.officeId"
v-model="projectOverviewForm.officeId"
class="!w-220px"
clearable
placeholder="请选择专业所"
@change="handleOfficeChange"
>
<el-option
v-for="item in officeOptions"
@@ -96,47 +73,58 @@
/>
</el-select>
</el-form-item>
<el-form-item label="员工">
<el-select
v-model="employeeSummaryForm.employeeId"
class="!w-240px"
clearable
filterable
remote
reserve-keyword
placeholder="请输入员工姓名搜索"
:loading="employeeLoading"
:remote-method="searchEmployees"
<!-- <el-form-item>
<el-button @click="getProjectEmployeeList">
<Icon class="mr-5px" icon="ep:refresh" />
刷新预览
</el-button>
</el-form-item> -->
<el-form-item>
<el-button
v-hasPermi="['tjt:report-summary:export']"
:loading="projectOverviewExportLoading"
plain
type="primary"
@click="openProjectOverviewExportDialog"
>
<el-option
v-for="item in employeeOptions"
:key="item.id"
:label="item.officeName ? `${item.employeeName} / ${item.officeName}` : item.employeeName"
:value="item.id"
/>
</el-select>
<Icon class="mr-5px" icon="ep:download" />
导出项目总览
</el-button>
</el-form-item>
<el-form-item label="员工状态">
<el-select
v-model="employeeSummaryForm.employeeStatus"
class="!w-180px"
clearable
placeholder="请选择员工状态"
@change="handleEmployeeStatusChange"
</el-form>
<el-table
v-loading="projectEmployeeLoading"
:data="projectEmployeeList"
class="mt-12px"
:empty-text="projectOverviewForm.officeId ? '该专业所下暂无员工' : '请先选择专业所'"
>
<el-option
v-for="item in EMPLOYEE_STATUS_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="员工姓名" min-width="160" prop="employeeName" />
<el-table-column align="center" label="性别" prop="gender" width="100" />
<el-table-column align="center" label="所属所" min-width="180" prop="officeName" />
</el-table>
<Pagination
v-model:limit="projectEmployeeQuery.pageSize"
v-model:page="projectEmployeeQuery.pageNo"
:total="projectEmployeeTotal"
@pagination="getProjectEmployeeList"
/>
</el-select>
</el-tab-pane>
</el-tabs>
</ContentWrap>
<Dialog v-model="exportDialogVisible" :title="exportDialogTitle" width="480">
<el-form label-width="88px">
<template v-if="exportDialogType === 'employeeSummary'">
<el-form-item label="年度">
<span>{{ employeeSummaryForm.year || '-' }}</span>
</el-form-item>
<el-form-item label="排序方式">
<el-form-item label="导出排序">
<el-select
v-model="employeeSummaryForm.sortType"
class="!w-220px"
placeholder="请选择排序方式"
placeholder="请选择导出排序"
>
<el-option
v-for="item in EMPLOYEE_SUMMARY_SORT_OPTIONS"
@@ -146,66 +134,142 @@
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
v-hasPermi="['tjt:report-summary:export']"
:loading="employeeSummaryExportLoading"
plain
type="primary"
@click="handleExportEmployeeSummary"
>
<Icon class="mr-5px" icon="ep:download" />
导出员工汇总表
</el-button>
</template>
<template v-else>
<el-form-item label="专业所">
<span>{{ currentOfficeName || '-' }}</span>
</el-form-item>
<el-form-item label="年度">
<el-date-picker
v-model="projectOverviewYearValue"
class="!w-220px"
clearable
disabled
placeholder="请选择年度"
type="year"
value-format="YYYY"
/>
</el-form-item>
<el-form-item label="导出排序">
<el-select
v-model="projectOverviewForm.sortType"
class="!w-220px"
placeholder="请选择导出排序"
>
<el-option
v-for="item in PROJECT_OVERVIEW_SORT_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</template>
</el-form>
</el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="exportDialogVisible = false">取消</el-button>
<el-button :loading="currentExportLoading" type="primary" @click="submitExport">
确定导出
</el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import * as EmployeeApi from '@/api/tjt/employee'
import * as EmployeeYearCostBudgetApi from '@/api/tjt/employeeYearCostBudget'
import * as OfficeApi from '@/api/tjt/office'
import * as ReportApi from '@/api/tjt/report'
import download from '@/utils/download'
import { EMPLOYEE_STATUS_OPTIONS } from '@/views/tjt/shared/planning'
import {
EMPLOYEE_SUMMARY_SORT_OPTIONS,
PROJECT_OVERVIEW_SORT_OPTIONS,
REPORT_SPECIALTY_OPTIONS
} from '@/views/tjt/shared/report'
defineOptions({ name: 'TjtReportSummary' })
type SelectOption = {
label: string
value: string
}
type ExportDialogType = 'employeeSummary' | 'projectOverview'
const PROJECT_OVERVIEW_SORT_OPTIONS: SelectOption[] = [
{ label: '产值从高到低', value: 'output_desc' },
{ label: '产值从低到高', value: 'output_asc' },
{ label: '项目名称升序', value: 'name_asc' }
]
const EMPLOYEE_SUMMARY_SORT_OPTIONS: SelectOption[] = [
{ label: '年度合计从高到低', value: 'annual_total_desc' },
{ label: '年度合计从低到高', value: 'annual_total_asc' },
{ label: '员工姓名升序', value: 'name_asc' }
]
const message = useMessage()
const activeTab = ref('projectOverview')
const activeTab = ref('employeeSummary')
const exportDialogVisible = ref(false)
const exportDialogType = ref<ExportDialogType>('employeeSummary')
const projectOverviewExportLoading = ref(false)
const employeeSummaryExportLoading = ref(false)
const employeeLoading = ref(false)
const employeeBudgetLoading = ref(false)
const projectEmployeeLoading = ref(false)
const officeOptions = ref<OfficeApi.OfficeSimpleVO[]>([])
const employeeOptions = ref<EmployeeApi.EmployeeSimpleVO[]>([])
const employeeBudgetList = ref<EmployeeYearCostBudgetApi.EmployeeYearCostBudgetVO[]>([])
const projectEmployeeList = ref<EmployeeApi.EmployeeVO[]>([])
const employeeBudgetTotal = ref(0)
const projectEmployeeTotal = ref(0)
const currentYear = new Date().getFullYear()
const projectOverviewForm = reactive<ReportApi.ProjectOverviewExportReqVO>({
year: new Date().getFullYear(),
specialtyCode: 'water',
year: currentYear,
officeId: undefined,
sortType: 'output_desc'
})
const employeeSummaryForm = reactive<ReportApi.EmployeeOutputSummaryExportReqVO>({
year: new Date().getFullYear(),
year: currentYear,
officeId: undefined,
employeeId: undefined,
employeeStatus: '在职',
employeeStatus: undefined,
sortType: 'annual_total_desc'
})
const employeeBudgetQuery = reactive<EmployeeYearCostBudgetApi.EmployeeYearCostBudgetPageReqVO>({
pageNo: 1,
pageSize: 10,
employeeId: undefined,
employeeName: undefined,
budgetYear: currentYear,
enabledFlag: true
})
const projectEmployeeQuery = reactive<EmployeeApi.EmployeePageReqVO>({
pageNo: 1,
pageSize: 10,
employeeName: undefined,
officeId: undefined,
employeeStatus: undefined,
enabledFlag: true
})
const exportDialogTitle = computed(() =>
exportDialogType.value === 'employeeSummary' ? '导出员工产值汇总' : '导出项目产值总览'
)
const currentExportLoading = computed(() =>
exportDialogType.value === 'employeeSummary'
? employeeSummaryExportLoading.value
: projectOverviewExportLoading.value
)
const currentOfficeName = computed(() => {
return officeOptions.value.find((item) => item.id === projectOverviewForm.officeId)?.officeName || ''
})
const projectOverviewYearValue = computed({
get: () => (projectOverviewForm.year ? String(projectOverviewForm.year) : undefined),
set: (value?: string) => {
projectOverviewForm.year = value ? Number(value) : undefined
}
get: () => String(currentYear),
set: (_value?: string) => undefined
})
const employeeSummaryYearValue = computed({
@@ -215,48 +279,90 @@ const employeeSummaryYearValue = computed({
}
})
const formatAmount = (value?: number) => {
if (value === undefined || value === null) {
return ''
}
return Number(value).toFixed(2)
}
const getOfficeList = async () => {
officeOptions.value = await OfficeApi.getOfficeSimpleList()
}
const searchEmployees = async (keyword: string) => {
employeeLoading.value = true
const getEmployeeBudgetList = async () => {
if (!employeeBudgetQuery.budgetYear) {
employeeBudgetList.value = []
employeeBudgetTotal.value = 0
return
}
employeeBudgetLoading.value = true
try {
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
keyword,
officeId: employeeSummaryForm.officeId,
status: employeeSummaryForm.employeeStatus,
enabledFlag: true
})
const data = await EmployeeYearCostBudgetApi.getEmployeeYearCostBudgetPage(employeeBudgetQuery)
employeeBudgetList.value = data.list
employeeBudgetTotal.value = data.total
} finally {
employeeLoading.value = false
employeeBudgetLoading.value = false
}
}
const handleOfficeChange = () => {
employeeSummaryForm.employeeId = undefined
searchEmployees('')
const getProjectEmployeeList = async () => {
if (!projectEmployeeQuery.officeId) {
projectEmployeeList.value = []
projectEmployeeTotal.value = 0
return
}
projectEmployeeLoading.value = true
try {
const data = await EmployeeApi.getEmployeePage(projectEmployeeQuery)
projectEmployeeList.value = data.list
projectEmployeeTotal.value = data.total
} finally {
projectEmployeeLoading.value = false
}
}
const handleEmployeeStatusChange = () => {
employeeSummaryForm.employeeId = undefined
searchEmployees('')
}
const handleExportProjectOverview = async () => {
if (!projectOverviewForm.year) {
const openEmployeeSummaryExportDialog = () => {
if (!employeeSummaryForm.year) {
message.warning('请选择年度')
return
}
if (!projectOverviewForm.specialtyCode) {
message.warning('请选择专业')
exportDialogType.value = 'employeeSummary'
exportDialogVisible.value = true
}
const openProjectOverviewExportDialog = () => {
if (!projectOverviewForm.officeId) {
message.warning('请选择专业所')
return
}
exportDialogType.value = 'projectOverview'
exportDialogVisible.value = true
}
const submitExport = async () => {
if (exportDialogType.value === 'employeeSummary') {
await handleExportEmployeeSummary()
return
}
await handleExportProjectOverview()
}
const handleExportProjectOverview = async () => {
if (!projectOverviewForm.officeId) {
message.warning('请选择专业所')
return
}
if (!projectOverviewYearValue.value) {
message.warning('请选择年度')
return
}
try {
await message.exportConfirm()
projectOverviewExportLoading.value = true
projectOverviewForm.year = currentYear
const data = await ReportApi.exportProjectOverview(projectOverviewForm)
download.excel(data, '项目总览表.xlsx')
exportDialogVisible.value = false
} finally {
projectOverviewExportLoading.value = false
}
@@ -268,17 +374,36 @@ const handleExportEmployeeSummary = async () => {
return
}
try {
await message.exportConfirm()
employeeSummaryExportLoading.value = true
const data = await ReportApi.exportEmployeeOutputSummary(employeeSummaryForm)
download.excel(data, '员工个人考核产值汇总.xlsx')
download.excel(data, '员工个人考核产值汇总.xlsx')
exportDialogVisible.value = false
} finally {
employeeSummaryExportLoading.value = false
}
}
watch(
() => employeeSummaryForm.year,
(year) => {
employeeBudgetQuery.pageNo = 1
employeeBudgetQuery.budgetYear = year
getEmployeeBudgetList()
},
{ immediate: true }
)
watch(
() => projectOverviewForm.officeId,
(officeId) => {
projectEmployeeQuery.pageNo = 1
projectEmployeeQuery.officeId = officeId
getProjectEmployeeList()
},
{ immediate: true }
)
onMounted(async () => {
await getOfficeList()
await searchEmployees('')
})
</script>