122 lines
2.7 KiB
Vue
122 lines
2.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed, nextTick, reactive, watch } from 'vue';
|
|
import { useForm, useFormRules } from '@/hooks/common/form';
|
|
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
|
|
|
defineOptions({ name: 'OvertimeApplicationActionDialog' });
|
|
|
|
type ActionType = 'approve' | 'reject' | 'cancel';
|
|
|
|
interface Props {
|
|
actionType: ActionType;
|
|
loading?: boolean;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
loading: false
|
|
});
|
|
|
|
const emit = defineEmits<{
|
|
submit: [reason: string | null];
|
|
}>();
|
|
|
|
const visible = defineModel<boolean>('visible', {
|
|
default: false
|
|
});
|
|
|
|
const { formRef, validate } = useForm();
|
|
const { createRequiredRule } = useFormRules();
|
|
|
|
const model = reactive({
|
|
reason: ''
|
|
});
|
|
|
|
const title = computed(() => {
|
|
const map: Record<ActionType, string> = {
|
|
approve: '通过加班申请',
|
|
reject: '退回加班申请',
|
|
cancel: '撤销加班申请'
|
|
};
|
|
|
|
return map[props.actionType];
|
|
});
|
|
|
|
const reasonLabel = computed(() => {
|
|
const map: Record<ActionType, string> = {
|
|
approve: '审核意见',
|
|
reject: '退回原因',
|
|
cancel: '撤销原因'
|
|
};
|
|
|
|
return map[props.actionType];
|
|
});
|
|
|
|
const reasonRequired = computed(() => props.actionType === 'reject');
|
|
|
|
const reasonPlaceholder = computed(() => {
|
|
if (reasonRequired.value) {
|
|
return `请输入${reasonLabel.value}`;
|
|
}
|
|
|
|
return props.actionType === 'cancel' ? '可填写撤销原因' : '可填写审核意见';
|
|
});
|
|
|
|
const rules = computed(() => ({
|
|
reason: reasonRequired.value
|
|
? [
|
|
createRequiredRule(`请输入${reasonLabel.value}`),
|
|
{
|
|
validator: (_rule, value: string, callback) => {
|
|
if (!value?.trim()) {
|
|
callback(new Error(`请输入${reasonLabel.value}`));
|
|
return;
|
|
}
|
|
|
|
callback();
|
|
},
|
|
trigger: 'blur'
|
|
}
|
|
]
|
|
: []
|
|
}));
|
|
|
|
async function handleSubmit() {
|
|
await validate();
|
|
emit('submit', model.reason.trim() || null);
|
|
}
|
|
|
|
watch(
|
|
() => visible.value,
|
|
async value => {
|
|
if (value) {
|
|
model.reason = '';
|
|
await nextTick();
|
|
formRef.value?.clearValidate();
|
|
}
|
|
}
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<BusinessFormDialog
|
|
v-model="visible"
|
|
:title="title"
|
|
preset="sm"
|
|
:confirm-loading="props.loading"
|
|
@confirm="handleSubmit"
|
|
>
|
|
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top" :validate-on-rule-change="false">
|
|
<ElFormItem :label="reasonLabel" prop="reason">
|
|
<ElInput
|
|
v-model="model.reason"
|
|
type="textarea"
|
|
:rows="5"
|
|
maxlength="1000"
|
|
show-word-limit
|
|
:placeholder="reasonPlaceholder"
|
|
/>
|
|
</ElFormItem>
|
|
</ElForm>
|
|
</BusinessFormDialog>
|
|
</template>
|