242 lines
7.7 KiB
Vue
242 lines
7.7 KiB
Vue
|
|
<script setup lang="ts">
|
|||
|
|
import { computed, onMounted, ref } from 'vue';
|
|||
|
|
import { onBeforeRouteLeave } from 'vue-router';
|
|||
|
|
import { fetchGetProjectReportOwnerProjectOptions } from '@/service/api';
|
|||
|
|
import { useAuth } from '@/hooks/business/auth';
|
|||
|
|
import WorkReportCreateDialog from './shared/components/create-dialog.vue';
|
|||
|
|
import WorkReportPrototypePageDialog from './shared/components/prototype-page-dialog.vue';
|
|||
|
|
import WorkReportTabs from './shared/components/tabs.vue';
|
|||
|
|
import {
|
|||
|
|
WORK_REPORT_PROJECT_OWNER_PERMISSION,
|
|||
|
|
WORK_REPORT_TYPE_LABEL,
|
|||
|
|
type WorkReportRow,
|
|||
|
|
type WorkReportType
|
|||
|
|
} from './shared/types';
|
|||
|
|
import WeeklyReportIndex from './weekly/index.vue';
|
|||
|
|
import WeeklyReportApprovalRecordDialog from './weekly/modules/approval-record-dialog.vue';
|
|||
|
|
import MonthlyReportIndex from './monthly/index.vue';
|
|||
|
|
import MonthlyReportApprovalRecordDialog from './monthly/modules/approval-record-dialog.vue';
|
|||
|
|
import ProjectReportIndex from './project/index.vue';
|
|||
|
|
import ProjectReportApprovalRecordDialog from './project/modules/approval-record-dialog.vue';
|
|||
|
|
|
|||
|
|
defineOptions({ name: 'PersonalCenterWorkReport' });
|
|||
|
|
|
|||
|
|
type PageDialogMode = 'add' | 'edit' | 'detail';
|
|||
|
|
type ReportListExpose = {
|
|||
|
|
reload: (page?: number) => Promise<void>;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const { hasAuth } = useAuth();
|
|||
|
|
|
|||
|
|
const activeTab = ref<WorkReportType>('weekly');
|
|||
|
|
const createVisible = ref(false);
|
|||
|
|
const pageDialogVisible = ref(false);
|
|||
|
|
const pageDialogMode = ref<PageDialogMode>('detail');
|
|||
|
|
const approvalRecordVisible = ref(false);
|
|||
|
|
const currentReportType = ref<WorkReportType>('weekly');
|
|||
|
|
const currentRow = ref<WorkReportRow | null>(null);
|
|||
|
|
const initialPeriod = ref<{
|
|||
|
|
periodKey: string;
|
|||
|
|
periodLabel: string;
|
|||
|
|
periodStartDate: string;
|
|||
|
|
periodEndDate: string;
|
|||
|
|
} | null>(null);
|
|||
|
|
const initialProjectId = ref('');
|
|||
|
|
const initialFlag = ref(1);
|
|||
|
|
const projectOptions = ref<Api.WorkReport.Project.ProjectReportOwnerProjectOption[]>([]);
|
|||
|
|
|
|||
|
|
const weeklyRef = ref<ReportListExpose | null>(null);
|
|||
|
|
const monthlyRef = ref<ReportListExpose | null>(null);
|
|||
|
|
const projectRef = ref<ReportListExpose | null>(null);
|
|||
|
|
|
|||
|
|
const canShowProjectTab = computed(() => hasAuth(WORK_REPORT_PROJECT_OWNER_PERMISSION));
|
|||
|
|
|
|||
|
|
/** 项目选项是否加载成功(用于项目半月报列表内部判断) */
|
|||
|
|
const projectOptionsLoaded = ref(false);
|
|||
|
|
|
|||
|
|
const visibleTabs = computed<Array<{ label: string; name: WorkReportType }>>(() => {
|
|||
|
|
const tabs: Array<{ label: string; name: WorkReportType }> = [
|
|||
|
|
{ label: WORK_REPORT_TYPE_LABEL.weekly, name: 'weekly' },
|
|||
|
|
{ label: WORK_REPORT_TYPE_LABEL.monthly, name: 'monthly' }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
if (canShowProjectTab.value) {
|
|||
|
|
tabs.push({ label: WORK_REPORT_TYPE_LABEL.project, name: 'project' });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return tabs;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const currentApprovalRecordDialogComponent = computed(() => {
|
|||
|
|
if (currentReportType.value === 'monthly') return MonthlyReportApprovalRecordDialog;
|
|||
|
|
if (currentReportType.value === 'project') return ProjectReportApprovalRecordDialog;
|
|||
|
|
return WeeklyReportApprovalRecordDialog;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
function getListRef(reportType: WorkReportType) {
|
|||
|
|
if (reportType === 'monthly') return monthlyRef.value;
|
|||
|
|
if (reportType === 'project') return projectRef.value;
|
|||
|
|
return weeklyRef.value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function loadProjectOptions() {
|
|||
|
|
if (!canShowProjectTab.value) return;
|
|||
|
|
|
|||
|
|
const { error, data } = await fetchGetProjectReportOwnerProjectOptions();
|
|||
|
|
projectOptions.value = error || !data ? [] : data;
|
|||
|
|
projectOptionsLoaded.value = !error;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openCreate(reportType: WorkReportType) {
|
|||
|
|
currentReportType.value = reportType;
|
|||
|
|
createVisible.value = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function handleCreateConfirm(
|
|||
|
|
payload:
|
|||
|
|
| { reportType: 'weekly' | 'monthly'; period: typeof initialPeriod.value extends infer T ? T : never }
|
|||
|
|
| {
|
|||
|
|
reportType: 'project';
|
|||
|
|
projectId: string;
|
|||
|
|
flag: number;
|
|||
|
|
period: typeof initialPeriod.value extends infer T ? T : never;
|
|||
|
|
}
|
|||
|
|
) {
|
|||
|
|
currentReportType.value = payload.reportType;
|
|||
|
|
pageDialogMode.value = 'add';
|
|||
|
|
currentRow.value = null;
|
|||
|
|
initialPeriod.value = payload.period as typeof initialPeriod.value;
|
|||
|
|
initialProjectId.value = 'projectId' in payload ? payload.projectId : '';
|
|||
|
|
initialFlag.value = 'flag' in payload ? payload.flag : 1;
|
|||
|
|
pageDialogVisible.value = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openEdit(reportType: WorkReportType, row: WorkReportRow) {
|
|||
|
|
currentReportType.value = reportType;
|
|||
|
|
pageDialogMode.value = 'edit';
|
|||
|
|
currentRow.value = row;
|
|||
|
|
initialPeriod.value = null;
|
|||
|
|
pageDialogVisible.value = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openDetail(reportType: WorkReportType, row: WorkReportRow) {
|
|||
|
|
currentReportType.value = reportType;
|
|||
|
|
pageDialogMode.value = 'detail';
|
|||
|
|
currentRow.value = row;
|
|||
|
|
initialPeriod.value = null;
|
|||
|
|
pageDialogVisible.value = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openApprovalRecord(reportType: WorkReportType, row: WorkReportRow) {
|
|||
|
|
currentReportType.value = reportType;
|
|||
|
|
currentRow.value = row;
|
|||
|
|
approvalRecordVisible.value = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function handleTabChange(tab: WorkReportType) {
|
|||
|
|
activeTab.value = tab;
|
|||
|
|
getListRef(tab)?.reload(1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function reloadReport(reportType = currentReportType.value) {
|
|||
|
|
await getListRef(reportType)?.reload();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function handleSubmitted() {
|
|||
|
|
pageDialogVisible.value = false;
|
|||
|
|
reloadReport(currentReportType.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function closeFloatingPanels() {
|
|||
|
|
createVisible.value = false;
|
|||
|
|
pageDialogVisible.value = false;
|
|||
|
|
approvalRecordVisible.value = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onMounted(async () => {
|
|||
|
|
await loadProjectOptions();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
onBeforeRouteLeave(() => {
|
|||
|
|
closeFloatingPanels();
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<div
|
|||
|
|
class="work-report-page-shell min-h-560px gap-16px overflow-hidden xl:grid xl:grid-cols-[240px_minmax(0,1fr)] lt-xl:flex lt-xl:flex-col lt-xl:overflow-auto"
|
|||
|
|
>
|
|||
|
|
<!-- 左侧:报告类型导航 -->
|
|||
|
|
<div class="flex-col-stretch gap-16px xl:min-h-0">
|
|||
|
|
<WorkReportTabs :active-tab="activeTab" :tabs="visibleTabs" @update:active-tab="handleTabChange" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 右侧:搜索区 + 列表区 -->
|
|||
|
|
<div class="flex-col-stretch gap-16px xl:min-h-0">
|
|||
|
|
<WeeklyReportIndex
|
|||
|
|
v-show="activeTab === 'weekly'"
|
|||
|
|
ref="weeklyRef"
|
|||
|
|
class="flex-1-hidden"
|
|||
|
|
@create="openCreate('weekly')"
|
|||
|
|
@edit="openEdit('weekly', $event)"
|
|||
|
|
@detail="openDetail('weekly', $event)"
|
|||
|
|
@approval-record="openApprovalRecord('weekly', $event)"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<MonthlyReportIndex
|
|||
|
|
v-show="activeTab === 'monthly'"
|
|||
|
|
ref="monthlyRef"
|
|||
|
|
class="flex-1-hidden"
|
|||
|
|
@create="openCreate('monthly')"
|
|||
|
|
@edit="openEdit('monthly', $event)"
|
|||
|
|
@detail="openDetail('monthly', $event)"
|
|||
|
|
@approval-record="openApprovalRecord('monthly', $event)"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<ProjectReportIndex
|
|||
|
|
v-if="canShowProjectTab"
|
|||
|
|
v-show="activeTab === 'project'"
|
|||
|
|
ref="projectRef"
|
|||
|
|
class="flex-1-hidden"
|
|||
|
|
:project-options="projectOptions"
|
|||
|
|
:project-options-loaded="projectOptionsLoaded"
|
|||
|
|
@create="openCreate('project')"
|
|||
|
|
@edit="openEdit('project', $event)"
|
|||
|
|
@detail="openDetail('project', $event)"
|
|||
|
|
@approval-record="openApprovalRecord('project', $event)"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<WorkReportCreateDialog
|
|||
|
|
v-model:visible="createVisible"
|
|||
|
|
:default-report-type="currentReportType"
|
|||
|
|
:project-visible="canShowProjectTab"
|
|||
|
|
:project-options="projectOptions"
|
|||
|
|
@confirm="handleCreateConfirm"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<WorkReportPrototypePageDialog
|
|||
|
|
v-model:visible="pageDialogVisible"
|
|||
|
|
:mode="pageDialogMode"
|
|||
|
|
scene="fill"
|
|||
|
|
:report-type="currentReportType"
|
|||
|
|
:row-data="currentRow"
|
|||
|
|
:initial-period="initialPeriod"
|
|||
|
|
:initial-project-id="initialProjectId"
|
|||
|
|
:initial-flag="initialFlag"
|
|||
|
|
@submitted="handleSubmitted"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<component
|
|||
|
|
:is="currentApprovalRecordDialogComponent"
|
|||
|
|
v-model:visible="approvalRecordVisible"
|
|||
|
|
:row-data="currentRow"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.work-report-page-shell {
|
|||
|
|
height: 100%;
|
|||
|
|
}
|
|||
|
|
</style>
|