0508修改
This commit is contained in:
@@ -14,28 +14,46 @@ export interface EmployeeOutputSummaryExportReqVO {
|
|||||||
sortType?: string
|
sortType?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportProjectBudget = (projectId: number) => {
|
export interface ProjectBudgetExportReqVO {
|
||||||
return request.download({ url: '/tjt/report/project-budget/export-excel', params: { projectId } })
|
projectId: number
|
||||||
|
year?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportProjectQuarterOutput = (planningId: number) => {
|
export interface ProjectQuarterOutputExportReqVO {
|
||||||
return request.download({
|
planningId: number
|
||||||
url: '/tjt/report/project-quarter-output/export-excel',
|
year?: number
|
||||||
params: { planningId }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportProjectLeadQuarterOutput = (planningId: number) => {
|
export interface ProjectLeadQuarterOutputExportReqVO {
|
||||||
return request.download({
|
planningId: number
|
||||||
url: '/tjt/report/project-lead-quarter-output/export-excel',
|
year?: number
|
||||||
params: { planningId }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportSpecialtyPersonOutput = (params: {
|
export interface SpecialtyPersonOutputExportReqVO {
|
||||||
planningId: number
|
planningId: number
|
||||||
specialtyCode: string
|
specialtyCode: string
|
||||||
}) => {
|
year?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportProjectBudget = (params: ProjectBudgetExportReqVO) => {
|
||||||
|
return request.download({ url: '/tjt/report/project-budget/export-excel', params })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportProjectQuarterOutput = (params: ProjectQuarterOutputExportReqVO) => {
|
||||||
|
return request.download({
|
||||||
|
url: '/tjt/report/project-quarter-output/export-excel',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportProjectLeadQuarterOutput = (params: ProjectLeadQuarterOutputExportReqVO) => {
|
||||||
|
return request.download({
|
||||||
|
url: '/tjt/report/project-lead-quarter-output/export-excel',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportSpecialtyPersonOutput = (params: SpecialtyPersonOutputExportReqVO) => {
|
||||||
return request.download({ url: '/tjt/report/specialty-person-output/export-excel', params })
|
return request.download({ url: '/tjt/report/specialty-person-output/export-excel', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ const request = (option: any) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DownloadResponseData {
|
||||||
|
data: Blob
|
||||||
|
fileName?: string
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
get: async <T = any>(option: any) => {
|
get: async <T = any>(option: any) => {
|
||||||
const res = await request({ method: 'GET', ...option })
|
const res = await request({ method: 'GET', ...option })
|
||||||
@@ -35,9 +41,9 @@ export default {
|
|||||||
const res = await request({ method: 'PUT', ...option })
|
const res = await request({ method: 'PUT', ...option })
|
||||||
return res.data as unknown as T
|
return res.data as unknown as T
|
||||||
},
|
},
|
||||||
download: async <T = any>(option: any) => {
|
download: async <T = DownloadResponseData>(option: any) => {
|
||||||
const res = await request({ method: 'GET', responseType: 'blob', ...option })
|
const res = await request({ method: 'GET', responseType: 'blob', ...option })
|
||||||
return res as unknown as Promise<T>
|
return res as T
|
||||||
},
|
},
|
||||||
upload: async <T = any>(option: any) => {
|
upload: async <T = any>(option: any) => {
|
||||||
option.headersType = 'multipart/form-data'
|
option.headersType = 'multipart/form-data'
|
||||||
|
|||||||
@@ -20,6 +20,29 @@ import { ApiEncrypt } from '@/utils/encrypt'
|
|||||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||||
const { result_code, base_url, request_timeout } = config
|
const { result_code, base_url, request_timeout } = config
|
||||||
|
|
||||||
|
const resolveDownloadFileName = (contentDisposition?: string) => {
|
||||||
|
if (!contentDisposition) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const decodeFileName = (value: string) => {
|
||||||
|
const normalizedValue = value.trim().replace(/^"(.*)"$/, '$1').replace(/\+/g, '%20')
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(normalizedValue)
|
||||||
|
} catch (error) {
|
||||||
|
return normalizedValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const filenameStarMatch = contentDisposition.match(/filename\*\s*=\s*([^;]+)/i)
|
||||||
|
if (filenameStarMatch?.[1]) {
|
||||||
|
return decodeFileName(filenameStarMatch[1].replace(/^UTF-8''/i, ''))
|
||||||
|
}
|
||||||
|
const filenameMatch = contentDisposition.match(/filename\s*=\s*([^;]+)/i)
|
||||||
|
if (filenameMatch?.[1]) {
|
||||||
|
return decodeFileName(filenameMatch[1])
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
|
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
|
||||||
const ignoreMsgs = [
|
const ignoreMsgs = [
|
||||||
'无效的刷新令牌', // 刷新令牌被删除时,不用提示
|
'无效的刷新令牌', // 刷新令牌被删除时,不用提示
|
||||||
@@ -141,7 +164,10 @@ service.interceptors.response.use(
|
|||||||
) {
|
) {
|
||||||
// 注意:如果导出的响应为 json,说明可能失败了,不直接返回进行下载
|
// 注意:如果导出的响应为 json,说明可能失败了,不直接返回进行下载
|
||||||
if (response.data.type !== 'application/json') {
|
if (response.data.type !== 'application/json') {
|
||||||
return response.data
|
return {
|
||||||
|
data: response.data,
|
||||||
|
fileName: resolveDownloadFileName(response.headers['content-disposition'])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
data = await new Response(response.data).json()
|
data = await new Response(response.data).json()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,38 @@
|
|||||||
const download0 = (data: Blob, fileName: string, mineType: string) => {
|
export interface DownloadSource {
|
||||||
|
data: BlobPart
|
||||||
|
fileName?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveDownloadPayload = (source: BlobPart | DownloadSource, fallbackFileName?: string) => {
|
||||||
|
if (
|
||||||
|
source &&
|
||||||
|
typeof source === 'object' &&
|
||||||
|
!(source instanceof Blob) &&
|
||||||
|
!(source instanceof ArrayBuffer) &&
|
||||||
|
'data' in source
|
||||||
|
) {
|
||||||
|
const resolvedSource = source as DownloadSource
|
||||||
|
return {
|
||||||
|
data: resolvedSource.data,
|
||||||
|
fileName: resolvedSource.fileName || fallbackFileName || 'download'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
data: source as BlobPart,
|
||||||
|
fileName: fallbackFileName || 'download'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const download0 = (source: BlobPart | DownloadSource, fileName: string | undefined, mineType: string) => {
|
||||||
|
const payload = resolveDownloadPayload(source, fileName)
|
||||||
// 创建 blob
|
// 创建 blob
|
||||||
const blob = new Blob([data], { type: mineType })
|
const blob = new Blob([payload.data], { type: mineType })
|
||||||
// 创建 href 超链接,点击进行下载
|
// 创建 href 超链接,点击进行下载
|
||||||
window.URL = window.URL || window.webkitURL
|
window.URL = window.URL || window.webkitURL
|
||||||
const href = URL.createObjectURL(blob)
|
const href = URL.createObjectURL(blob)
|
||||||
const downA = document.createElement('a')
|
const downA = document.createElement('a')
|
||||||
downA.href = href
|
downA.href = href
|
||||||
downA.download = fileName
|
downA.download = payload.fileName
|
||||||
downA.click()
|
downA.click()
|
||||||
// 销毁超连接
|
// 销毁超连接
|
||||||
window.URL.revokeObjectURL(href)
|
window.URL.revokeObjectURL(href)
|
||||||
@@ -14,27 +40,27 @@ const download0 = (data: Blob, fileName: string, mineType: string) => {
|
|||||||
|
|
||||||
const download = {
|
const download = {
|
||||||
// 下载 Excel 方法
|
// 下载 Excel 方法
|
||||||
excel: (data: Blob, fileName: string) => {
|
excel: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'application/vnd.ms-excel')
|
download0(data, fileName, 'application/vnd.ms-excel')
|
||||||
},
|
},
|
||||||
// 下载 Word 方法
|
// 下载 Word 方法
|
||||||
word: (data: Blob, fileName: string) => {
|
word: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'application/msword')
|
download0(data, fileName, 'application/msword')
|
||||||
},
|
},
|
||||||
// 下载 Zip 方法
|
// 下载 Zip 方法
|
||||||
zip: (data: Blob, fileName: string) => {
|
zip: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'application/zip')
|
download0(data, fileName, 'application/zip')
|
||||||
},
|
},
|
||||||
// 下载 Html 方法
|
// 下载 Html 方法
|
||||||
html: (data: Blob, fileName: string) => {
|
html: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'text/html')
|
download0(data, fileName, 'text/html')
|
||||||
},
|
},
|
||||||
// 下载 Markdown 方法
|
// 下载 Markdown 方法
|
||||||
markdown: (data: Blob, fileName: string) => {
|
markdown: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'text/markdown')
|
download0(data, fileName, 'text/markdown')
|
||||||
},
|
},
|
||||||
// 下载 Json 方法
|
// 下载 Json 方法
|
||||||
json: (data: Blob, fileName: string) => {
|
json: (data: BlobPart | DownloadSource, fileName?: string) => {
|
||||||
download0(data, fileName, 'application/json')
|
download0(data, fileName, 'application/json')
|
||||||
},
|
},
|
||||||
// 下载图片(允许跨域)
|
// 下载图片(允许跨域)
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
import type { FormRules } from 'element-plus'
|
import type { FormRules } from 'element-plus'
|
||||||
import * as EmployeeApi from '@/api/tjt/employee'
|
import * as EmployeeApi from '@/api/tjt/employee'
|
||||||
import * as EmployeeYearCostBudgetApi from '@/api/tjt/employeeYearCostBudget'
|
import * as EmployeeYearCostBudgetApi from '@/api/tjt/employeeYearCostBudget'
|
||||||
import { EMPLOYEE_STATUS, formatAmountText } from '@/views/tjt/shared/planning'
|
import { formatAmountText } from '@/views/tjt/shared/planning'
|
||||||
|
|
||||||
defineOptions({ name: 'TjtEmployeeYearCostBudget' })
|
defineOptions({ name: 'TjtEmployeeYearCostBudget' })
|
||||||
|
|
||||||
@@ -251,7 +251,6 @@ const searchEmployees = async (keyword: string) => {
|
|||||||
try {
|
try {
|
||||||
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
||||||
keyword,
|
keyword,
|
||||||
status: EMPLOYEE_STATUS.active,
|
|
||||||
enabledFlag: true
|
enabledFlag: true
|
||||||
})
|
})
|
||||||
ensureEmployeeOption()
|
ensureEmployeeOption()
|
||||||
|
|||||||
@@ -401,7 +401,6 @@ const searchEmployees = async (keyword: string) => {
|
|||||||
try {
|
try {
|
||||||
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
||||||
keyword,
|
keyword,
|
||||||
status: '在职',
|
|
||||||
enabledFlag: true
|
enabledFlag: true
|
||||||
})
|
})
|
||||||
ensureEmployeeOptions(formData.value.rolePersons)
|
ensureEmployeeOptions(formData.value.rolePersons)
|
||||||
|
|||||||
@@ -208,6 +208,28 @@
|
|||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<Dialog v-model="exportDialogVisible" title="导出项目考核产值预算表" width="420">
|
||||||
|
<el-form label-width="88px">
|
||||||
|
<el-form-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="exportYearValue"
|
||||||
|
class="!w-220px"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择年度"
|
||||||
|
type="year"
|
||||||
|
value-format="YYYY"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="exportDialogVisible = false">取消</el-button>
|
||||||
|
<el-button :loading="exportLoading" type="primary" @click="submitProjectBudgetExport">
|
||||||
|
确定导出
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -226,10 +248,13 @@ import {
|
|||||||
defineOptions({ name: 'TjtReportBudget' })
|
defineOptions({ name: 'TjtReportBudget' })
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const currentYear = new Date().getFullYear()
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const planningLoading = ref(false)
|
const planningLoading = ref(false)
|
||||||
const exportLoading = ref(false)
|
const exportLoading = ref(false)
|
||||||
|
const exportDialogVisible = ref(false)
|
||||||
|
const exportYear = ref<number>()
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
||||||
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
||||||
@@ -252,6 +277,13 @@ const queryProjectStartYearValue = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const exportYearValue = computed({
|
||||||
|
get: () => (exportYear.value ? String(exportYear.value) : undefined),
|
||||||
|
set: (value?: string) => {
|
||||||
|
exportYear.value = value ? Number(value) : undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const totalPlanningAmount = computed(() =>
|
const totalPlanningAmount = computed(() =>
|
||||||
planningList.value.reduce((sum, item) => sum + Number(item.planningAmount || 0), 0)
|
planningList.value.reduce((sum, item) => sum + Number(item.planningAmount || 0), 0)
|
||||||
)
|
)
|
||||||
@@ -313,11 +345,28 @@ const handleExportProjectBudget = async () => {
|
|||||||
message.warning('请先选择项目')
|
message.warning('请先选择项目')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
exportYear.value = currentProject.value.projectStartYear || currentYear
|
||||||
|
exportDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitProjectBudgetExport = async () => {
|
||||||
|
if (!currentProject.value?.id) {
|
||||||
|
message.warning('请先选择项目')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!exportYear.value) {
|
||||||
|
message.warning('请选择年度')
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await message.exportConfirm()
|
await message.exportConfirm()
|
||||||
exportLoading.value = true
|
exportLoading.value = true
|
||||||
const data = await ReportApi.exportProjectBudget(currentProject.value.id)
|
const data = await ReportApi.exportProjectBudget({
|
||||||
download.excel(data, `${currentProject.value.projectName}_项目考核产值预算表.xlsx`)
|
projectId: currentProject.value.id,
|
||||||
|
year: exportYear.value
|
||||||
|
})
|
||||||
|
download.excel(data, `${currentProject.value.projectName}_${exportYear.value}_项目考核产值预算表.xlsx`)
|
||||||
|
exportDialogVisible.value = false
|
||||||
} finally {
|
} finally {
|
||||||
exportLoading.value = false
|
exportLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,6 +210,28 @@
|
|||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<Dialog v-model="exportDialogVisible" :title="exportDialogTitle" width="420">
|
||||||
|
<el-form label-width="88px">
|
||||||
|
<el-form-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="exportYearValue"
|
||||||
|
class="!w-220px"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择年度"
|
||||||
|
type="year"
|
||||||
|
value-format="YYYY"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="exportDialogVisible = false">取消</el-button>
|
||||||
|
<el-button :loading="currentExportLoading" type="primary" @click="submitExport">
|
||||||
|
确定导出
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -244,6 +266,8 @@ interface QuarterYearRow {
|
|||||||
quarters: PlanningQuarterApi.ProjectPlanningQuarterVO[]
|
quarters: PlanningQuarterApi.ProjectPlanningQuarterVO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExportDialogType = 'projectQuarter' | 'projectLeadQuarter'
|
||||||
|
|
||||||
const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
|
const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
|
||||||
{ label: '项目经理/项目负责人', value: 'project_lead' },
|
{ label: '项目经理/项目负责人', value: 'project_lead' },
|
||||||
{ label: '建筑专业', value: 'arch' },
|
{ label: '建筑专业', value: 'arch' },
|
||||||
@@ -256,12 +280,16 @@ const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const currentYear = new Date().getFullYear()
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const planningLoading = ref(false)
|
const planningLoading = ref(false)
|
||||||
const quarterLoading = ref(false)
|
const quarterLoading = ref(false)
|
||||||
const exportQuarterLoading = ref(false)
|
const exportQuarterLoading = ref(false)
|
||||||
const exportLeadLoading = ref(false)
|
const exportLeadLoading = ref(false)
|
||||||
|
const exportDialogVisible = ref(false)
|
||||||
|
const exportDialogType = ref<ExportDialogType>('projectQuarter')
|
||||||
|
const exportYear = ref<number>()
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
||||||
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
||||||
@@ -288,6 +316,23 @@ const queryProjectStartYearValue = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const exportDialogTitle = computed(() =>
|
||||||
|
exportDialogType.value === 'projectQuarter' ? '导出专业间年度季度计取表' : '导出项目负责人计取表'
|
||||||
|
)
|
||||||
|
|
||||||
|
const currentExportLoading = computed(() =>
|
||||||
|
exportDialogType.value === 'projectQuarter'
|
||||||
|
? exportQuarterLoading.value
|
||||||
|
: exportLeadLoading.value
|
||||||
|
)
|
||||||
|
|
||||||
|
const exportYearValue = computed({
|
||||||
|
get: () => (exportYear.value ? String(exportYear.value) : undefined),
|
||||||
|
set: (value?: string) => {
|
||||||
|
exportYear.value = value ? Number(value) : undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const toNumeric = (value?: number | string | null) => {
|
const toNumeric = (value?: number | string | null) => {
|
||||||
const numericValue = Number(value ?? 0)
|
const numericValue = Number(value ?? 0)
|
||||||
return Number.isNaN(numericValue) ? 0 : numericValue
|
return Number.isNaN(numericValue) ? 0 : numericValue
|
||||||
@@ -552,14 +597,9 @@ const handleExportProjectQuarter = async () => {
|
|||||||
message.warning('请先选择合约规划')
|
message.warning('请先选择合约规划')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
exportDialogType.value = 'projectQuarter'
|
||||||
await message.exportConfirm()
|
exportYear.value = currentPlanning.value.planningStartYear || currentYear
|
||||||
exportQuarterLoading.value = true
|
exportDialogVisible.value = true
|
||||||
const data = await ReportApi.exportProjectQuarterOutput(currentPlanning.value.id)
|
|
||||||
download.excel(data, '专业间年度季度计取表.xlsx')
|
|
||||||
} finally {
|
|
||||||
exportQuarterLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleExportProjectLeadQuarter = async () => {
|
const handleExportProjectLeadQuarter = async () => {
|
||||||
@@ -567,11 +607,66 @@ const handleExportProjectLeadQuarter = async () => {
|
|||||||
message.warning('请先选择合约规划')
|
message.warning('请先选择合约规划')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
exportDialogType.value = 'projectLeadQuarter'
|
||||||
|
exportYear.value = currentPlanning.value.planningStartYear || currentYear
|
||||||
|
exportDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitExport = async () => {
|
||||||
|
if (exportDialogType.value === 'projectQuarter') {
|
||||||
|
await submitProjectQuarterExport()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await submitProjectLeadQuarterExport()
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitProjectQuarterExport = async () => {
|
||||||
|
if (!currentPlanning.value?.id) {
|
||||||
|
message.warning('请先选择合约规划')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!exportYear.value) {
|
||||||
|
message.warning('请选择年度')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await message.exportConfirm()
|
||||||
|
exportQuarterLoading.value = true
|
||||||
|
const data = await ReportApi.exportProjectQuarterOutput({
|
||||||
|
planningId: currentPlanning.value.id,
|
||||||
|
year: exportYear.value
|
||||||
|
})
|
||||||
|
download.excel(
|
||||||
|
data,
|
||||||
|
`${currentProject.value?.projectName || '项目'}_${exportYear.value}_专业间年度季度计取表.xlsx`
|
||||||
|
)
|
||||||
|
exportDialogVisible.value = false
|
||||||
|
} finally {
|
||||||
|
exportQuarterLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitProjectLeadQuarterExport = async () => {
|
||||||
|
if (!currentPlanning.value?.id) {
|
||||||
|
message.warning('请先选择合约规划')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!exportYear.value) {
|
||||||
|
message.warning('请选择年度')
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await message.exportConfirm()
|
await message.exportConfirm()
|
||||||
exportLeadLoading.value = true
|
exportLeadLoading.value = true
|
||||||
const data = await ReportApi.exportProjectLeadQuarterOutput(currentPlanning.value.id)
|
const data = await ReportApi.exportProjectLeadQuarterOutput({
|
||||||
download.excel(data, '项目负责人年度季度计取表.xlsx')
|
planningId: currentPlanning.value.id,
|
||||||
|
year: exportYear.value
|
||||||
|
})
|
||||||
|
download.excel(
|
||||||
|
data,
|
||||||
|
`${currentProject.value?.projectName || '项目'}_${exportYear.value}_项目负责人年度季度计取表.xlsx`
|
||||||
|
)
|
||||||
|
exportDialogVisible.value = false
|
||||||
} finally {
|
} finally {
|
||||||
exportLeadLoading.value = false
|
exportLeadLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,28 @@
|
|||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<Dialog v-model="exportDialogVisible" title="导出专业内人员计取表" width="420">
|
||||||
|
<el-form label-width="88px">
|
||||||
|
<el-form-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="exportYearValue"
|
||||||
|
class="!w-220px"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择年度"
|
||||||
|
type="year"
|
||||||
|
value-format="YYYY"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="exportDialogVisible = false">取消</el-button>
|
||||||
|
<el-button :loading="exportSpecialtyLoading" type="primary" @click="submitSpecialtyExport">
|
||||||
|
确定导出
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -199,10 +221,13 @@ interface SpecialtyGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const currentYear = new Date().getFullYear()
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const planningLoading = ref(false)
|
const planningLoading = ref(false)
|
||||||
const exportSpecialtyLoading = ref(false)
|
const exportSpecialtyLoading = ref(false)
|
||||||
|
const exportDialogVisible = ref(false)
|
||||||
|
const exportYear = ref<number>()
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
||||||
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
||||||
@@ -228,6 +253,13 @@ const queryProjectStartYearValue = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const exportYearValue = computed({
|
||||||
|
get: () => (exportYear.value ? String(exportYear.value) : undefined),
|
||||||
|
set: (value?: string) => {
|
||||||
|
exportYear.value = value ? Number(value) : undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const roundRatio = (value?: number | string | null) => {
|
const roundRatio = (value?: number | string | null) => {
|
||||||
const numericValue = Number(value || 0)
|
const numericValue = Number(value || 0)
|
||||||
return Number.isNaN(numericValue) ? 0 : Number(numericValue.toFixed(4))
|
return Number.isNaN(numericValue) ? 0 : Number(numericValue.toFixed(4))
|
||||||
@@ -393,14 +425,36 @@ const handleExportSpecialtyPerson = async () => {
|
|||||||
message.warning('请选择具体专业后再导出')
|
message.warning('请选择具体专业后再导出')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
exportYear.value = currentPlanning.value.planningStartYear || currentYear
|
||||||
|
exportDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitSpecialtyExport = async () => {
|
||||||
|
if (!currentPlanning.value?.id) {
|
||||||
|
message.warning('请先选择合约规划')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!canExportCurrentGroup.value || !currentGroup.value?.specialtyCode) {
|
||||||
|
message.warning('请选择具体专业后再导出')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!exportYear.value) {
|
||||||
|
message.warning('请选择年度')
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await message.exportConfirm()
|
await message.exportConfirm()
|
||||||
exportSpecialtyLoading.value = true
|
exportSpecialtyLoading.value = true
|
||||||
const data = await ReportApi.exportSpecialtyPersonOutput({
|
const data = await ReportApi.exportSpecialtyPersonOutput({
|
||||||
planningId: currentPlanning.value.id,
|
planningId: currentPlanning.value.id,
|
||||||
specialtyCode: currentGroup.value.specialtyCode
|
specialtyCode: currentGroup.value.specialtyCode,
|
||||||
|
year: exportYear.value
|
||||||
})
|
})
|
||||||
download.excel(data, `${currentGroup.value.specialtyName || '专业'}内人员年度季度计取表.xlsx`)
|
download.excel(
|
||||||
|
data,
|
||||||
|
`${currentProject.value?.projectName || '项目'}_${exportYear.value}_${currentGroup.value.specialtyName || '专业'}内人员年度季度计取表.xlsx`
|
||||||
|
)
|
||||||
|
exportDialogVisible.value = false
|
||||||
} finally {
|
} finally {
|
||||||
exportSpecialtyLoading.value = false
|
exportSpecialtyLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,6 @@
|
|||||||
v-model="projectOverviewYearValue"
|
v-model="projectOverviewYearValue"
|
||||||
class="!w-220px"
|
class="!w-220px"
|
||||||
clearable
|
clearable
|
||||||
disabled
|
|
||||||
placeholder="请选择年度"
|
placeholder="请选择年度"
|
||||||
type="year"
|
type="year"
|
||||||
value-format="YYYY"
|
value-format="YYYY"
|
||||||
@@ -268,8 +267,10 @@ const currentOfficeName = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const projectOverviewYearValue = computed({
|
const projectOverviewYearValue = computed({
|
||||||
get: () => String(currentYear),
|
get: () => (projectOverviewForm.year ? String(projectOverviewForm.year) : undefined),
|
||||||
set: (_value?: string) => undefined
|
set: (value?: string) => {
|
||||||
|
projectOverviewForm.year = value ? Number(value) : undefined
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const employeeSummaryYearValue = computed({
|
const employeeSummaryYearValue = computed({
|
||||||
@@ -336,6 +337,9 @@ const openProjectOverviewExportDialog = () => {
|
|||||||
message.warning('请选择专业所')
|
message.warning('请选择专业所')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (!projectOverviewForm.year) {
|
||||||
|
projectOverviewForm.year = currentYear
|
||||||
|
}
|
||||||
exportDialogType.value = 'projectOverview'
|
exportDialogType.value = 'projectOverview'
|
||||||
exportDialogVisible.value = true
|
exportDialogVisible.value = true
|
||||||
}
|
}
|
||||||
@@ -353,15 +357,17 @@ const handleExportProjectOverview = async () => {
|
|||||||
message.warning('请选择专业所')
|
message.warning('请选择专业所')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!projectOverviewYearValue.value) {
|
if (!projectOverviewForm.year) {
|
||||||
message.warning('请选择年度')
|
message.warning('请选择年度')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
projectOverviewExportLoading.value = true
|
projectOverviewExportLoading.value = true
|
||||||
projectOverviewForm.year = currentYear
|
|
||||||
const data = await ReportApi.exportProjectOverview(projectOverviewForm)
|
const data = await ReportApi.exportProjectOverview(projectOverviewForm)
|
||||||
download.excel(data, '项目总览表.xlsx')
|
download.excel(
|
||||||
|
data,
|
||||||
|
`${currentOfficeName.value || '专业所'}_${projectOverviewForm.year}_项目总览表.xlsx`
|
||||||
|
)
|
||||||
exportDialogVisible.value = false
|
exportDialogVisible.value = false
|
||||||
} finally {
|
} finally {
|
||||||
projectOverviewExportLoading.value = false
|
projectOverviewExportLoading.value = false
|
||||||
@@ -376,7 +382,7 @@ const handleExportEmployeeSummary = async () => {
|
|||||||
try {
|
try {
|
||||||
employeeSummaryExportLoading.value = true
|
employeeSummaryExportLoading.value = true
|
||||||
const data = await ReportApi.exportEmployeeOutputSummary(employeeSummaryForm)
|
const data = await ReportApi.exportEmployeeOutputSummary(employeeSummaryForm)
|
||||||
download.excel(data, '员工个人考核产值汇总表.xlsx')
|
download.excel(data, `${employeeSummaryForm.year}_员工个人考核产值汇总表.xlsx`)
|
||||||
exportDialogVisible.value = false
|
exportDialogVisible.value = false
|
||||||
} finally {
|
} finally {
|
||||||
employeeSummaryExportLoading.value = false
|
employeeSummaryExportLoading.value = false
|
||||||
|
|||||||
@@ -455,7 +455,6 @@ const searchEmployees = async (keyword: string) => {
|
|||||||
try {
|
try {
|
||||||
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
employeeOptions.value = await EmployeeApi.getEmployeeSimpleList({
|
||||||
keyword,
|
keyword,
|
||||||
status: '在职',
|
|
||||||
enabledFlag: true
|
enabledFlag: true
|
||||||
})
|
})
|
||||||
editRoleList.value.forEach((row) => ensureEmployeeOptions(row.persons))
|
editRoleList.value.forEach((row) => ensureEmployeeOptions(row.persons))
|
||||||
|
|||||||
Reference in New Issue
Block a user