feat(新增加班申请功能): 新增申请功能,可在工作台进行审核。
fix(dict_data): 在字典数据新增、编辑时可以操作颜色类型字段(color_type)。
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
||||
import { RDMS_OVERTIME_DURATION_DICT_CODE } from '@/constants/dict';
|
||||
import {
|
||||
fetchCreateOvertimeApplication,
|
||||
fetchGetLoginUserDirectManager,
|
||||
fetchGetOvertimeApplicationDetail,
|
||||
fetchUpdateRejectedOvertimeApplication
|
||||
} from '@/service/api';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import BusinessFormSection from '@/components/custom/business-form-section.vue';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
|
||||
defineOptions({ name: 'OvertimeApplicationOperateDialog' });
|
||||
|
||||
type OperateType = 'add' | 'edit';
|
||||
|
||||
interface Props {
|
||||
operateType: OperateType;
|
||||
rowData?: Api.OvertimeApplication.OvertimeApplication | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
submitted: [];
|
||||
}>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const { formRef, validate } = useForm();
|
||||
const { createRequiredRule } = useFormRules();
|
||||
|
||||
const detailLoading = ref(false);
|
||||
const submitting = ref(false);
|
||||
const approverName = ref('');
|
||||
|
||||
const currentUserName = computed(() => authStore.userInfo.nickname || authStore.userInfo.userName || '--');
|
||||
const isEdit = computed(() => props.operateType === 'edit');
|
||||
const title = computed(() => (isEdit.value ? '修改并重新提交' : '新增加班申请'));
|
||||
|
||||
const model = reactive<Api.OvertimeApplication.SaveOvertimeApplicationParams>(createDefaultModel());
|
||||
|
||||
const rules = computed(
|
||||
() =>
|
||||
({
|
||||
overtimeDate: [createRequiredRule('请选择加班日期')],
|
||||
overtimeDuration: [createRequiredRule('请选择加班时长')],
|
||||
overtimeReason: [
|
||||
createRequiredRule('请输入加班原因'),
|
||||
{
|
||||
validator: (_rule, value: string, callback) => {
|
||||
if (!value?.trim()) {
|
||||
callback(new Error('请输入加班原因'));
|
||||
return;
|
||||
}
|
||||
|
||||
callback();
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
overtimeContent: [
|
||||
createRequiredRule('请输入加班内容'),
|
||||
{
|
||||
validator: (_rule, value: string, callback) => {
|
||||
if (!value?.trim()) {
|
||||
callback(new Error('请输入加班内容'));
|
||||
return;
|
||||
}
|
||||
|
||||
callback();
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
approverId: [createRequiredRule('请选择审核人')]
|
||||
}) satisfies Record<keyof Api.OvertimeApplication.SaveOvertimeApplicationParams, App.Global.FormRule[]>
|
||||
);
|
||||
|
||||
function createDefaultModel(): Api.OvertimeApplication.SaveOvertimeApplicationParams {
|
||||
return {
|
||||
overtimeDate: '',
|
||||
overtimeDuration: '',
|
||||
overtimeReason: '',
|
||||
overtimeContent: '',
|
||||
approverId: ''
|
||||
};
|
||||
}
|
||||
|
||||
async function loadDirectManagerAsDefaultApprover() {
|
||||
const { error, data } = await fetchGetLoginUserDirectManager();
|
||||
|
||||
if (!error && data?.id) {
|
||||
model.approverId = data.id;
|
||||
approverName.value = data.nickname;
|
||||
}
|
||||
}
|
||||
|
||||
async function initModel() {
|
||||
detailLoading.value = true;
|
||||
Object.assign(model, createDefaultModel());
|
||||
approverName.value = '';
|
||||
|
||||
if (isEdit.value && props.rowData) {
|
||||
const { error, data } = await fetchGetOvertimeApplicationDetail(props.rowData.id);
|
||||
const detail = error || !data ? props.rowData : data;
|
||||
|
||||
model.overtimeDate = detail.overtimeDate;
|
||||
model.overtimeDuration = detail.overtimeDuration;
|
||||
model.overtimeReason = detail.overtimeReason;
|
||||
model.overtimeContent = detail.overtimeContent;
|
||||
model.approverId = detail.approverId;
|
||||
approverName.value = detail.approverName;
|
||||
} else {
|
||||
await loadDirectManagerAsDefaultApprover();
|
||||
}
|
||||
|
||||
detailLoading.value = false;
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await validate();
|
||||
|
||||
const payload: Api.OvertimeApplication.SaveOvertimeApplicationParams = {
|
||||
overtimeDate: model.overtimeDate,
|
||||
overtimeDuration: model.overtimeDuration,
|
||||
overtimeReason: model.overtimeReason.trim(),
|
||||
overtimeContent: model.overtimeContent.trim(),
|
||||
approverId: model.approverId
|
||||
};
|
||||
|
||||
submitting.value = true;
|
||||
|
||||
const result =
|
||||
isEdit.value && props.rowData
|
||||
? await fetchUpdateRejectedOvertimeApplication(props.rowData.id, payload)
|
||||
: await fetchCreateOvertimeApplication(payload);
|
||||
|
||||
submitting.value = false;
|
||||
|
||||
if (result.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success(isEdit.value ? '加班申请已重新提交' : '加班申请已提交');
|
||||
visible.value = false;
|
||||
emit('submitted');
|
||||
}
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
value => {
|
||||
if (value) {
|
||||
initModel();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top" :validate-on-rule-change="false">
|
||||
<BusinessFormSection title="申请信息">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="申请人">
|
||||
<ElInput
|
||||
class="overtime-application-operate-dialog__readonly-input"
|
||||
:model-value="currentUserName"
|
||||
readonly
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="审核人" prop="approverId">
|
||||
<ElInput
|
||||
class="overtime-application-operate-dialog__readonly-input"
|
||||
:model-value="approverName"
|
||||
readonly
|
||||
placeholder="暂无直属上级"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="加班日期" prop="overtimeDate" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.overtimeDate"
|
||||
class="w-full"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="请选择加班日期"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="加班时长" prop="overtimeDuration">
|
||||
<DictSelect
|
||||
v-model="model.overtimeDuration"
|
||||
:dict-code="RDMS_OVERTIME_DURATION_DICT_CODE"
|
||||
placeholder="请选择加班时长"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</BusinessFormSection>
|
||||
|
||||
<BusinessFormSection title="加班说明">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="加班原因" prop="overtimeReason">
|
||||
<ElInput
|
||||
v-model="model.overtimeReason"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入加班原因"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="加班内容" prop="overtimeContent">
|
||||
<ElInput
|
||||
v-model="model.overtimeContent"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
placeholder="请输入加班内容"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</BusinessFormSection>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.overtime-application-operate-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;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-operate-dialog__readonly-input .el-input__wrapper:hover),
|
||||
:deep(.overtime-application-operate-dialog__readonly-input.is-focus .el-input__wrapper) {
|
||||
box-shadow: 0 0 0 1px rgb(203 213 225 / 96%) inset;
|
||||
}
|
||||
|
||||
:deep(.overtime-application-operate-dialog__readonly-input .el-input__inner) {
|
||||
color: rgb(51 65 85 / 96%);
|
||||
cursor: default;
|
||||
-webkit-text-fill-color: rgb(51 65 85 / 96%);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user