fix(加班申请): 去掉撤销相关的状态和动作。

feat(工作报告): 开发工作报告功能
This commit is contained in:
dk
2026-06-11 10:56:24 +08:00
parent 2e369b23a9
commit d53a8dfae5
56 changed files with 14312 additions and 2910 deletions

View File

@@ -1,20 +1,14 @@
<script setup lang="tsx">
import { computed, markRaw, reactive, ref } from 'vue';
import { ElButton, ElMessageBox, ElTag } from 'element-plus';
import { ElButton, ElTag } from 'element-plus';
import dayjs from 'dayjs';
import {
fetchCancelOvertimeApplication,
fetchDeleteOvertimeApplication,
fetchExportOvertimeApplications,
fetchGetOvertimeApplicationPage
} from '@/service/api';
import { fetchExportOvertimeApplications, fetchGetOvertimeApplicationPage } from '@/service/api';
import { useUIPaginatedTable } from '@/hooks/common/table';
import BusinessTableActionCell, { type BusinessTableAction } from '@/components/custom/business-table-action-cell';
import OvertimeApplicationActionDialog from './modules/overtime-application-action-dialog.vue';
import OvertimeApplicationApprovalRecordDialog from './modules/overtime-application-approval-record-dialog.vue';
import OvertimeApplicationDetailDialog from './modules/overtime-application-detail-dialog.vue';
import OvertimeApplicationOperateDialog from './modules/overtime-application-operate-dialog.vue';
import OvertimeApplicationSearch from './modules/overtime-application-search.vue';
import OvertimeApplicationStatusLogDialog from './modules/overtime-application-status-log-dialog.vue';
import {
downloadBlob,
formatEmptyText,
@@ -23,16 +17,13 @@ import {
getOvertimeApplicationStatusLabel,
resolveOvertimeApplicationStatusTagType
} from './modules/overtime-application-shared';
import IconMdiCloseCircleOutline from '~icons/mdi/close-circle-outline';
import IconMdiDeleteOutline from '~icons/mdi/delete-outline';
import IconMdiEyeOutline from '~icons/mdi/eye-outline';
import IconMdiHistory from '~icons/mdi/history';
import IconMdiFileDocumentCheckOutline from '~icons/mdi/file-document-check-outline';
import IconMdiPencilOutline from '~icons/mdi/pencil-outline';
defineOptions({ name: 'OvertimeApplication' });
type OvertimeApplicationPageResponse = Awaited<ReturnType<typeof fetchGetOvertimeApplicationPage>>;
type ActionType = 'cancel';
function getInitSearchParams(): Api.OvertimeApplication.OvertimeApplicationSearchParams {
return {
@@ -69,20 +60,15 @@ function transformPageResult(response: OvertimeApplicationPageResponse, pageNo:
const searchParams = reactive(getInitSearchParams());
const operateVisible = ref(false);
const detailVisible = ref(false);
const statusLogVisible = ref(false);
const actionVisible = ref(false);
const approvalRecordVisible = ref(false);
const operateType = ref<'add' | 'edit'>('add');
const currentRow = ref<Api.OvertimeApplication.OvertimeApplication | null>(null);
const currentActionType = ref<ActionType>('cancel');
const actionSubmitting = ref(false);
const exporting = ref(false);
const ACTION_ICON_MAP = {
detail: markRaw(IconMdiEyeOutline),
statusLog: markRaw(IconMdiHistory),
edit: markRaw(IconMdiPencilOutline),
cancel: markRaw(IconMdiCloseCircleOutline),
delete: markRaw(IconMdiDeleteOutline)
approvalRecord: markRaw(IconMdiFileDocumentCheckOutline),
edit: markRaw(IconMdiPencilOutline)
};
const { columns, columnChecks, data, loading, getDataByPage, mobilePagination } = useUIPaginatedTable<
@@ -113,14 +99,14 @@ const { columns, columnChecks, data, loading, getDataByPage, mobilePagination }
prop: 'overtimeReason',
label: '加班原因',
minWidth: 180,
showOverflowTooltip: true,
className: 'overtime-application__cell-ellipsis',
formatter: row => formatEmptyText(row.overtimeReason)
},
{
prop: 'overtimeContent',
label: '加班内容',
minWidth: 200,
showOverflowTooltip: true,
className: 'overtime-application__cell-ellipsis',
formatter: row => formatEmptyText(row.overtimeContent)
},
{
@@ -134,17 +120,17 @@ const { columns, columnChecks, data, loading, getDataByPage, mobilePagination }
</ElTag>
)
},
{ prop: 'approverName', label: '审核人', minWidth: 120, showOverflowTooltip: true },
{ prop: 'approverName', label: '审核人', minWidth: 80, showOverflowTooltip: true },
{
prop: 'submitTime',
label: '提交时间',
minWidth: 170,
minWidth: 150,
formatter: row => formatOvertimeDateTime(row.submitTime)
},
{
prop: 'approvalTime',
label: '审核时间',
minWidth: 170,
minWidth: 150,
formatter: row => formatOvertimeDateTime(row.approvalTime)
},
{
@@ -171,7 +157,7 @@ function getRowActions(row: Api.OvertimeApplication.OvertimeApplication): Busine
}
];
if ((row.statusCode === 'rejected' || row.statusCode === 'cancelled') && row.allowEdit) {
if (row.statusCode === 'rejected' && row.allowEdit) {
actions.push({
key: 'edit',
label: '修改',
@@ -181,31 +167,13 @@ function getRowActions(row: Api.OvertimeApplication.OvertimeApplication): Busine
});
}
actions.push({
key: 'status-log',
label: '状态日志',
buttonType: 'info',
icon: ACTION_ICON_MAP.statusLog,
onClick: () => openStatusLog(row)
});
if (row.statusCode === 'pending') {
if (['approved', 'rejected'].includes(row.statusCode)) {
actions.push({
key: 'cancel',
label: '撤销',
buttonType: 'danger',
icon: ACTION_ICON_MAP.cancel,
onClick: () => openCancel(row)
});
}
if (row.statusCode === 'cancelled') {
actions.push({
key: 'delete',
label: '删除',
buttonType: 'danger',
icon: ACTION_ICON_MAP.delete,
onClick: () => handleDelete(row)
key: 'approval-record',
label: '审批记录',
buttonType: 'info',
icon: ACTION_ICON_MAP.approvalRecord,
onClick: () => openApprovalRecord(row)
});
}
@@ -229,15 +197,9 @@ function openDetail(row: Api.OvertimeApplication.OvertimeApplication) {
detailVisible.value = true;
}
function openStatusLog(row: Api.OvertimeApplication.OvertimeApplication) {
function openApprovalRecord(row: Api.OvertimeApplication.OvertimeApplication) {
currentRow.value = row;
statusLogVisible.value = true;
}
function openCancel(row: Api.OvertimeApplication.OvertimeApplication) {
currentRow.value = row;
currentActionType.value = 'cancel';
actionVisible.value = true;
approvalRecordVisible.value = true;
}
async function reloadTable(page = searchParams.pageNo ?? 1) {
@@ -259,49 +221,6 @@ function handleSubmitted() {
reloadTable(searchParams.pageNo ?? 1);
}
async function handleActionSubmit(reason: string | null) {
if (!currentRow.value) {
return;
}
actionSubmitting.value = true;
const { error } = await fetchCancelOvertimeApplication(currentRow.value.id, { reason });
actionSubmitting.value = false;
if (error) {
return;
}
actionVisible.value = false;
window.$message?.success('加班申请已撤销');
await reloadTable(searchParams.pageNo ?? 1);
}
async function handleDelete(row: Api.OvertimeApplication.OvertimeApplication) {
try {
await ElMessageBox.confirm(
`确定删除 ${row.applicantName} ${formatOvertimeDate(row.overtimeDate)} 的加班申请吗?`,
'删除确认',
{
type: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消'
}
);
} catch {
return;
}
const { error } = await fetchDeleteOvertimeApplication(row.id);
if (error) {
return;
}
window.$message?.success('加班申请已删除');
await reloadTable(searchParams.pageNo ?? 1);
}
async function handleExport() {
exporting.value = true;
const { error, data: blob } = await fetchExportOvertimeApplications(searchParams);
@@ -373,14 +292,7 @@ async function handleExport() {
<OvertimeApplicationDetailDialog v-model:visible="detailVisible" :row-data="currentRow" />
<OvertimeApplicationStatusLogDialog v-model:visible="statusLogVisible" :row-data="currentRow" />
<OvertimeApplicationActionDialog
v-model:visible="actionVisible"
:action-type="currentActionType"
:loading="actionSubmitting"
@submit="handleActionSubmit"
/>
<OvertimeApplicationApprovalRecordDialog v-model:visible="approvalRecordVisible" :row-data="currentRow" />
</div>
</template>
@@ -398,4 +310,12 @@ async function handleExport() {
text-overflow: ellipsis;
white-space: nowrap;
}
/* 加班原因/加班内容:单元格内容溢出时仅显示省略号,不弹出 tooltip */
:deep(.overtime-application__cell-ellipsis .cell) {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>