fix(产品需求、项目需求、工作报告、我的绩效、加班申请): 1、修复搜索区域的下拉框,无法搜索的问题。2、修复工作报告内容溢出的问题。3、修复我的待办 - 待审批,里面的二级tabs没有加权限的问题。4、优化周报里工作日志展示时的分隔符。5、优化项目需求池、我的绩效请求重复发送、影响效率的问题。
feat(我的绩效): 1、增加我的绩效在工作台可以直接处理的功能。2、增加我的绩效全部导出时,合并多个excel的sheet为一个excel的功能。
This commit is contained in:
@@ -7,13 +7,18 @@ import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
|
||||
defineOptions({ name: 'PerformanceActionDialog' });
|
||||
|
||||
type ActionType = 'confirm' | 'reject';
|
||||
|
||||
interface Props {
|
||||
rowData?: Api.Performance.Sheet.Sheet | null;
|
||||
actionType: 'confirm' | 'reject';
|
||||
actionType?: ActionType;
|
||||
selectableActionType?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
rowData: null
|
||||
rowData: null,
|
||||
actionType: 'confirm',
|
||||
selectableActionType: false
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
@@ -26,13 +31,25 @@ const { formRef, validate } = useForm();
|
||||
const { createRequiredRule } = useFormRules();
|
||||
|
||||
const submitting = ref(false);
|
||||
const form = reactive({
|
||||
const form = reactive<{
|
||||
actionType: ActionType;
|
||||
reason: string;
|
||||
}>({
|
||||
actionType: 'confirm',
|
||||
reason: ''
|
||||
});
|
||||
|
||||
const isReject = computed(() => props.actionType === 'reject');
|
||||
const title = computed(() => (isReject.value ? '退回绩效表' : '确认绩效表'));
|
||||
const confirmText = computed(() => (isReject.value ? '确认退回' : '确认'));
|
||||
const isReject = computed(() => form.actionType === 'reject');
|
||||
const title = computed(() => {
|
||||
if (props.selectableActionType) return '绩效审批';
|
||||
return isReject.value ? '退回绩效表' : '确认绩效表';
|
||||
});
|
||||
const confirmText = computed(() => {
|
||||
if (props.selectableActionType) return '确认提交';
|
||||
return isReject.value ? '确认退回' : '确认';
|
||||
});
|
||||
const opinionLabel = computed(() => (isReject.value ? '退回原因' : '审批意见'));
|
||||
const opinionPlaceholder = computed(() => (isReject.value ? `请输入${opinionLabel.value}` : '可填写审批意见'));
|
||||
const rules = computed<FormRules>(() => ({
|
||||
reason: isReject.value ? [createRequiredRule('请输入退回原因')] : []
|
||||
}));
|
||||
@@ -63,6 +80,7 @@ async function handleSubmit() {
|
||||
|
||||
watch(visible, isVisible => {
|
||||
if (!isVisible) return;
|
||||
form.actionType = props.actionType;
|
||||
form.reason = '';
|
||||
});
|
||||
</script>
|
||||
@@ -84,16 +102,119 @@ watch(visible, isVisible => {
|
||||
<ElDescriptionsItem label="实际得分">{{ props.rowData?.actualScoreTotal ?? '--' }}</ElDescriptionsItem>
|
||||
</ElDescriptions>
|
||||
|
||||
<ElFormItem class="mt-16px" :label="isReject ? '退回原因' : '确认意见'" prop="reason">
|
||||
<div v-if="props.selectableActionType" class="performance-action-dialog__approval-form">
|
||||
<div class="audit-field">
|
||||
<label>审批结论</label>
|
||||
<div class="audit-conclusion">
|
||||
<button
|
||||
type="button"
|
||||
class="conclusion-btn"
|
||||
:class="{
|
||||
active: form.actionType === 'confirm',
|
||||
pass: form.actionType === 'confirm'
|
||||
}"
|
||||
@click="form.actionType = 'confirm'"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5" />
|
||||
<path
|
||||
d="M5 8.5L7 10.5L11 6"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
确认
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="conclusion-btn"
|
||||
:class="{
|
||||
active: form.actionType === 'reject',
|
||||
reject: form.actionType === 'reject'
|
||||
}"
|
||||
@click="form.actionType = 'reject'"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M6 6L10 10M10 6L6 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
退回
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ElFormItem class="mt-16px" :label="opinionLabel" prop="reason">
|
||||
<ElInput
|
||||
v-model="form.reason"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
:placeholder="isReject ? '请输入退回原因' : '可填写确认意见'"
|
||||
:placeholder="opinionPlaceholder"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.performance-action-dialog__approval-form {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.audit-field {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.audit-field label {
|
||||
color: #475467;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.audit-conclusion {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.conclusion-btn {
|
||||
height: 44px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
border: 1px solid #d8e0e8;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
color: #475467;
|
||||
font: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
}
|
||||
|
||||
.conclusion-btn:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.conclusion-btn.active.pass {
|
||||
border-color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.conclusion-btn.active.reject {
|
||||
border-color: #dc2626;
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,11 +26,13 @@ interface Props {
|
||||
rowData?: Api.Performance.Sheet.Sheet | null;
|
||||
mode: 'view' | 'edit' | 'create';
|
||||
subordinateOptions?: SubordinateOption[];
|
||||
showApprovalFooter?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
rowData: null,
|
||||
subordinateOptions: () => []
|
||||
subordinateOptions: () => [],
|
||||
showApprovalFooter: false
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
@@ -38,6 +40,7 @@ const visible = defineModel<boolean>('visible', { default: false });
|
||||
const emit = defineEmits<{
|
||||
saved: [];
|
||||
savedAndSent: [];
|
||||
startApproval: [];
|
||||
}>();
|
||||
|
||||
const { formRef, validate } = useForm();
|
||||
@@ -83,6 +86,7 @@ const drawerTitle = computed(() => {
|
||||
return `${action}绩效 Excel${name ? ` - ${name}` : ''}`;
|
||||
});
|
||||
const canSave = computed(() => props.mode !== 'view');
|
||||
const showApprovalFooter = computed(() => props.mode === 'view' && props.showApprovalFooter);
|
||||
const drawerSize = computed(() => (viewportWidth.value >= 2560 ? '60%' : '88%'));
|
||||
|
||||
function syncViewportWidth() {
|
||||
@@ -93,6 +97,10 @@ function handleClose() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
function handleStartApproval() {
|
||||
emit('startApproval');
|
||||
}
|
||||
|
||||
function disposeUniver() {
|
||||
try {
|
||||
univerInstance?.dispose?.();
|
||||
@@ -687,10 +695,16 @@ onMounted(() => {
|
||||
<div ref="containerRef" class="performance-excel-editor__container" />
|
||||
</div>
|
||||
|
||||
<template v-if="canSave" #footer>
|
||||
<template v-if="canSave || showApprovalFooter" #footer>
|
||||
<div class="performance-excel-editor__footer">
|
||||
<ElButton :loading="saving" :disabled="sending" @click="handleSaveDraft">保存草稿</ElButton>
|
||||
<ElButton type="primary" :loading="sending" :disabled="saving" @click="handleSaveAndSend">发送绩效</ElButton>
|
||||
<template v-if="canSave">
|
||||
<ElButton :loading="saving" :disabled="sending" @click="handleSaveDraft">保存草稿</ElButton>
|
||||
<ElButton type="primary" :loading="sending" :disabled="saving" @click="handleSaveAndSend">发送绩效</ElButton>
|
||||
</template>
|
||||
<template v-else-if="showApprovalFooter">
|
||||
<ElButton @click="handleClose">退出审批</ElButton>
|
||||
<ElButton type="primary" @click="handleStartApproval">开始审批</ElButton>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</ElDrawer>
|
||||
|
||||
@@ -45,7 +45,14 @@ const baseFields = computed<SearchField[]>(() => [
|
||||
|
||||
const teamFields = computed<SearchField[]>(() => [
|
||||
baseFields.value[0],
|
||||
{ key: 'employeeId', label: '下属', type: 'select', placeholder: '请选择下属', options: props.subordinateOptions },
|
||||
{
|
||||
key: 'employeeId',
|
||||
label: '下属',
|
||||
type: 'select',
|
||||
placeholder: '请选择下属',
|
||||
options: props.subordinateOptions,
|
||||
filterable: true
|
||||
},
|
||||
{ key: 'employeeDeptId', label: '部门', type: 'select', placeholder: '请选择部门', options: props.deptOptions },
|
||||
{ key: 'managerName', label: '直属上级', type: 'input', placeholder: '请输入直属上级' },
|
||||
baseFields.value[1]
|
||||
|
||||
@@ -255,7 +255,7 @@ watch(visible, isVisible => {
|
||||
</ElTooltip>
|
||||
</div>
|
||||
<ElTooltip placement="top" effect="light">
|
||||
<template #content>支持 .xlsx、.xls,选择后会在这里显示文件名</template>
|
||||
<template #content>仅支持 .xlsx格式,选择后会在这里显示文件名</template>
|
||||
<button type="button" class="performance-template-dialog__hint-button" aria-label="Excel 文件说明">
|
||||
<icon-mdi-information-outline />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user