fix(加班申请): 去掉撤销相关的状态和动作。
feat(工作报告): 开发工作报告功能
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -5,7 +5,7 @@ import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
|
||||
defineOptions({ name: 'OvertimeApplicationActionDialog' });
|
||||
|
||||
type ActionType = 'approve' | 'reject' | 'cancel';
|
||||
type ActionType = 'approve' | 'reject';
|
||||
|
||||
interface Props {
|
||||
actionType: ActionType;
|
||||
@@ -34,8 +34,7 @@ const model = reactive({
|
||||
const title = computed(() => {
|
||||
const map: Record<ActionType, string> = {
|
||||
approve: '通过加班申请',
|
||||
reject: '退回加班申请',
|
||||
cancel: '撤销加班申请'
|
||||
reject: '退回加班申请'
|
||||
};
|
||||
|
||||
return map[props.actionType];
|
||||
@@ -44,8 +43,7 @@ const title = computed(() => {
|
||||
const reasonLabel = computed(() => {
|
||||
const map: Record<ActionType, string> = {
|
||||
approve: '审核意见',
|
||||
reject: '退回原因',
|
||||
cancel: '撤销原因'
|
||||
reject: '退回原因'
|
||||
};
|
||||
|
||||
return map[props.actionType];
|
||||
@@ -58,7 +56,7 @@ const reasonPlaceholder = computed(() => {
|
||||
return `请输入${reasonLabel.value}`;
|
||||
}
|
||||
|
||||
return props.actionType === 'cancel' ? '可填写撤销原因' : '可填写审核意见';
|
||||
return '可填写审核意见';
|
||||
});
|
||||
|
||||
const rules = computed(() => ({
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { fetchGetOvertimeApplicationApprovalRecords } from '@/service/api';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import {
|
||||
formatEmptyText,
|
||||
formatOvertimeDateTime,
|
||||
getOvertimeApplicationStatusLabel
|
||||
} from './overtime-application-shared';
|
||||
|
||||
defineOptions({ name: 'OvertimeApplicationApprovalRecordDialog' });
|
||||
|
||||
interface Props {
|
||||
rowData?: Api.OvertimeApplication.OvertimeApplication | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const records = ref<Api.OvertimeApplication.OvertimeApplicationApprovalRecord[]>([]);
|
||||
|
||||
async function loadRecords() {
|
||||
if (!props.rowData?.id) {
|
||||
records.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
const { error, data } = await fetchGetOvertimeApplicationApprovalRecords(props.rowData.id);
|
||||
loading.value = false;
|
||||
|
||||
records.value = error || !data ? [] : data;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
value => {
|
||||
if (value) {
|
||||
loadRecords();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
title="加班申请审批记录"
|
||||
width="820px"
|
||||
:loading="loading"
|
||||
:show-footer="false"
|
||||
max-body-height="72vh"
|
||||
>
|
||||
<ElTable border :data="records">
|
||||
<ElTableColumn prop="approvalRound" label="轮次" width="80" />
|
||||
<ElTableColumn label="结论" width="110">
|
||||
<template #default="{ row }">{{ getOvertimeApplicationStatusLabel(row.conclusion) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="审批意见" min-width="240" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ formatEmptyText(row.opinion) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn prop="auditorName" label="审批人" width="130" show-overflow-tooltip />
|
||||
<ElTableColumn label="审批时间" width="170">
|
||||
<template #default="{ row }">{{ formatOvertimeDateTime(row.createTime) }}</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
@@ -1,22 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import { fetchGetOvertimeApplicationDetail } from '@/service/api';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import {
|
||||
formatEmptyText,
|
||||
formatOvertimeDate,
|
||||
formatOvertimeDateTime,
|
||||
getOvertimeApplicationStatusLabel,
|
||||
resolveOvertimeApplicationStatusTagType
|
||||
} from './overtime-application-shared';
|
||||
import { formatOvertimeDate, formatOvertimeDateTime } from './overtime-application-shared';
|
||||
import IconMdiCheckCircleOutline from '~icons/mdi/check-circle-outline';
|
||||
import IconMdiCloseCircleOutline from '~icons/mdi/close-circle-outline';
|
||||
|
||||
defineOptions({ name: 'OvertimeApplicationDetailDialog' });
|
||||
|
||||
interface Props {
|
||||
rowData?: Api.OvertimeApplication.OvertimeApplication | null;
|
||||
showApprovalActions?: boolean;
|
||||
actionLoading?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showApprovalActions: false,
|
||||
actionLoading: false
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
approve: [];
|
||||
reject: [];
|
||||
}>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
@@ -25,11 +31,6 @@ const visible = defineModel<boolean>('visible', {
|
||||
const loading = ref(false);
|
||||
const detailData = ref<Api.OvertimeApplication.OvertimeApplication | null>(null);
|
||||
|
||||
const statusTagType = computed(() => resolveOvertimeApplicationStatusTagType(detailData.value?.statusCode));
|
||||
const statusLabel = computed(() =>
|
||||
getOvertimeApplicationStatusLabel(detailData.value?.statusCode, detailData.value?.statusName)
|
||||
);
|
||||
|
||||
async function loadDetail() {
|
||||
if (!props.rowData?.id) {
|
||||
detailData.value = null;
|
||||
@@ -54,30 +55,96 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog v-model="visible" title="加班申请详情" preset="md" :loading="loading" :show-footer="false">
|
||||
<ElDescriptions v-if="detailData" :column="2" border>
|
||||
<ElDescriptionsItem label="状态">
|
||||
<ElTag :type="statusTagType">{{ statusLabel }}</ElTag>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="申请人">
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
title="加班申请详情"
|
||||
preset="md"
|
||||
:loading="loading"
|
||||
:show-footer="props.showApprovalActions"
|
||||
>
|
||||
<ElDescriptions v-if="detailData" class="overtime-application-detail-dialog__descriptions" :column="2" border>
|
||||
<ElDescriptionsItem label="申请人" label-class-name="overtime-application-detail-dialog__label">
|
||||
{{ detailData.applicantName }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班日期">{{ formatOvertimeDate(detailData.overtimeDate) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班时长">{{ detailData.overtimeDuration }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="审核人">
|
||||
{{ detailData.approverName }}
|
||||
<ElDescriptionsItem label="加班日期" label-class-name="overtime-application-detail-dialog__label--compact">
|
||||
{{ formatOvertimeDate(detailData.overtimeDate) }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班时长" label-class-name="overtime-application-detail-dialog__label">
|
||||
{{ detailData.overtimeDuration }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="提交时间" label-class-name="overtime-application-detail-dialog__label--compact">
|
||||
{{ formatOvertimeDateTime(detailData.submitTime) }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班原因" :span="2" label-class-name="overtime-application-detail-dialog__label">
|
||||
{{ detailData.overtimeReason }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班内容" :span="2" label-class-name="overtime-application-detail-dialog__label">
|
||||
{{ detailData.overtimeContent }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="提交时间">{{ formatOvertimeDateTime(detailData.submitTime) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="审核时间">{{ formatOvertimeDateTime(detailData.approvalTime) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="审核意见">{{ formatEmptyText(detailData.approvalComment) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班原因" :span="2">{{ detailData.overtimeReason }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="加班内容" :span="2">{{ detailData.overtimeContent }}</ElDescriptionsItem>
|
||||
</ElDescriptions>
|
||||
<ElEmpty v-else description="未获取到加班申请详情" />
|
||||
|
||||
<template #footer>
|
||||
<div class="overtime-application-detail-dialog__footer">
|
||||
<ElButton
|
||||
class="overtime-application-detail-dialog__approve-btn"
|
||||
type="success"
|
||||
:loading="props.actionLoading"
|
||||
:disabled="props.actionLoading || !detailData"
|
||||
@click="emit('approve')"
|
||||
>
|
||||
<template #icon>
|
||||
<IconMdiCheckCircleOutline />
|
||||
</template>
|
||||
通过
|
||||
</ElButton>
|
||||
<ElButton type="danger" plain :disabled="props.actionLoading || !detailData" @click="emit('reject')">
|
||||
<template #icon>
|
||||
<IconMdiCloseCircleOutline />
|
||||
</template>
|
||||
退回
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.overtime-application-detail-dialog__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.overtime-application-detail-dialog__approve-btn {
|
||||
--el-button-bg-color: #0f766e;
|
||||
--el-button-border-color: #0f766e;
|
||||
--el-button-hover-bg-color: #115e59;
|
||||
--el-button-hover-border-color: #115e59;
|
||||
--el-button-active-bg-color: #134e4a;
|
||||
--el-button-active-border-color: #134e4a;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-detail-dialog__descriptions .el-descriptions__cell) {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-detail-dialog__label),
|
||||
:deep(.overtime-application-detail-dialog__label--compact) {
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-detail-dialog__label) {
|
||||
width: 96px;
|
||||
min-width: 96px;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-detail-dialog__label--compact) {
|
||||
width: 86px;
|
||||
min-width: 86px;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-detail-dialog__readonly-input .el-input__wrapper) {
|
||||
background: linear-gradient(180deg, rgb(241 245 249 / 98%), rgb(226 232 240 / 94%)), rgb(241 245 249);
|
||||
box-shadow: 0 0 0 1px rgb(203 213 225 / 96%) inset;
|
||||
|
||||
@@ -7,16 +7,14 @@ export const overtimeApplicationStatusOptions: Array<{
|
||||
}> = [
|
||||
{ label: '待审批', value: 'pending' },
|
||||
{ label: '已通过', value: 'approved' },
|
||||
{ label: '已退回', value: 'rejected' },
|
||||
{ label: '已撤销', value: 'cancelled' }
|
||||
{ label: '已退回', value: 'rejected' }
|
||||
];
|
||||
|
||||
export const overtimeApplicationActionNameMap: Record<Api.OvertimeApplication.OvertimeApplicationActionType, string> = {
|
||||
submit: '提交',
|
||||
resubmit: '重新提交',
|
||||
approve: '通过',
|
||||
reject: '退回',
|
||||
cancel: '撤销'
|
||||
reject: '退回'
|
||||
};
|
||||
|
||||
export function getOvertimeApplicationStatusLabel(statusCode?: string | null, statusName?: string | null) {
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
<script setup lang="tsx">
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElTag } from 'element-plus';
|
||||
import { fetchGetOvertimeApplicationStatusLogs } from '@/service/api';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import {
|
||||
formatEmptyText,
|
||||
formatOvertimeDate,
|
||||
formatOvertimeDateTime,
|
||||
getOvertimeApplicationActionLabel,
|
||||
getOvertimeApplicationStatusLabel,
|
||||
resolveOvertimeApplicationStatusTagType
|
||||
} from './overtime-application-shared';
|
||||
|
||||
defineOptions({ name: 'OvertimeApplicationStatusLogDialog' });
|
||||
|
||||
interface Props {
|
||||
rowData?: Api.OvertimeApplication.OvertimeApplication | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const logs = ref<Api.OvertimeApplication.OvertimeApplicationStatusLog[]>([]);
|
||||
|
||||
async function loadLogs() {
|
||||
if (!props.rowData?.id) {
|
||||
logs.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
const { error, data } = await fetchGetOvertimeApplicationStatusLogs(props.rowData.id);
|
||||
loading.value = false;
|
||||
|
||||
logs.value = error || !data ? [] : data;
|
||||
}
|
||||
|
||||
function renderStatus(code?: string | null) {
|
||||
if (!code) {
|
||||
return '--';
|
||||
}
|
||||
|
||||
return <ElTag type={resolveOvertimeApplicationStatusTagType(code)}>{getOvertimeApplicationStatusLabel(code)}</ElTag>;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
value => {
|
||||
if (value) {
|
||||
loadLogs();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
title="状态日志"
|
||||
width="920px"
|
||||
:loading="loading"
|
||||
:show-footer="false"
|
||||
max-body-height="72vh"
|
||||
>
|
||||
<ElTable border :data="logs">
|
||||
<ElTableColumn prop="createTime" label="操作时间" width="170">
|
||||
<template #default="{ row }">{{ formatOvertimeDateTime(row.createTime) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn prop="actionType" label="动作" width="110">
|
||||
<template #default="{ row }">{{ getOvertimeApplicationActionLabel(row.actionType) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn prop="operatorName" label="操作人" width="120" show-overflow-tooltip />
|
||||
<ElTableColumn prop="fromStatus" label="原状态" width="110" :formatter="row => renderStatus(row.fromStatus)" />
|
||||
<ElTableColumn prop="toStatus" label="新状态" width="110" :formatter="row => renderStatus(row.toStatus)" />
|
||||
<ElTableColumn prop="reason" label="原因/意见" min-width="180" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ formatEmptyText(row.reason) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn prop="overtimeDateSnapshot" label="加班日期" width="120">
|
||||
<template #default="{ row }">{{ formatOvertimeDate(row.overtimeDateSnapshot) }}</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn prop="overtimeDurationSnapshot" label="时长" width="90" show-overflow-tooltip />
|
||||
</ElTable>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
Reference in New Issue
Block a user