144 lines
3.6 KiB
Vue
144 lines
3.6 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
|
import { fetchGetOvertimeApplicationStatusDict } from '@/service/api';
|
|
import TableSearchFields, { type SearchField } from '@/components/custom/table-search-fields.vue';
|
|
|
|
defineOptions({ name: 'OvertimeApplicationSearch' });
|
|
|
|
interface Option {
|
|
label: string;
|
|
value: string | number;
|
|
}
|
|
|
|
interface Props {
|
|
teamMode?: boolean;
|
|
subordinateOptions?: Option[];
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
teamMode: false,
|
|
subordinateOptions: () => []
|
|
});
|
|
|
|
const emit = defineEmits<{
|
|
reset: [];
|
|
search: [];
|
|
}>();
|
|
|
|
const model = defineModel<Api.OvertimeApplication.OvertimeApplicationSearchParams>('model', {
|
|
required: true
|
|
});
|
|
|
|
const searchModel = reactive<Record<string, any>>({
|
|
applicantIds: undefined,
|
|
overtimeDate: undefined,
|
|
statusCode: undefined,
|
|
approverName: ''
|
|
});
|
|
|
|
const statusOptions = ref<Array<{ label: string; value: string }>>([]);
|
|
|
|
let syncingFromSource = false;
|
|
|
|
watch(
|
|
() => [model.value.applicantIds, model.value.overtimeDate, model.value.statusCode, model.value.approverName] as const,
|
|
([applicantIds, overtimeDate, statusCode, approverName]) => {
|
|
syncingFromSource = true;
|
|
searchModel.applicantIds = applicantIds;
|
|
searchModel.overtimeDate = overtimeDate;
|
|
searchModel.statusCode = statusCode;
|
|
searchModel.approverName = approverName ?? '';
|
|
syncingFromSource = false;
|
|
},
|
|
{ immediate: true, flush: 'sync' }
|
|
);
|
|
|
|
watch(
|
|
() => [searchModel.applicantIds, searchModel.overtimeDate, searchModel.statusCode, searchModel.approverName] as const,
|
|
([applicantIds, overtimeDate, statusCode, approverName]) => {
|
|
if (syncingFromSource) {
|
|
return;
|
|
}
|
|
|
|
model.value.applicantIds = applicantIds;
|
|
model.value.applicantName = undefined;
|
|
model.value.overtimeDate = overtimeDate;
|
|
model.value.statusCode = statusCode;
|
|
model.value.approverName = approverName?.trim() || undefined;
|
|
},
|
|
{ flush: 'sync' }
|
|
);
|
|
|
|
async function loadStatusOptions() {
|
|
const { error, data } = await fetchGetOvertimeApplicationStatusDict();
|
|
|
|
if (error || !data) {
|
|
statusOptions.value = [];
|
|
return;
|
|
}
|
|
|
|
statusOptions.value = data.map(item => ({
|
|
label: item.statusName,
|
|
value: item.statusCode
|
|
}));
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await loadStatusOptions();
|
|
});
|
|
|
|
const fields = computed<SearchField[]>(() => {
|
|
const baseFields: SearchField[] = [
|
|
...(props.teamMode
|
|
? [
|
|
{
|
|
key: 'applicantIds',
|
|
label: '申请人',
|
|
type: 'select' as const,
|
|
options: props.subordinateOptions,
|
|
placeholder: '请选择申请人',
|
|
transformValue: (value: string | number | null | undefined) => (value ? [value] : undefined),
|
|
resolveValue: (value: unknown) => (Array.isArray(value) ? value[0] : value)
|
|
}
|
|
]
|
|
: []),
|
|
{
|
|
key: 'overtimeDate',
|
|
label: '加班日期',
|
|
type: 'dateRange',
|
|
placeholder: '请选择加班日期'
|
|
},
|
|
{
|
|
key: 'statusCode',
|
|
label: '状态',
|
|
type: 'select',
|
|
options: statusOptions.value,
|
|
placeholder: '请选择状态'
|
|
}
|
|
];
|
|
|
|
if (props.teamMode) {
|
|
baseFields.push({
|
|
key: 'approverName',
|
|
label: '审批人',
|
|
type: 'input',
|
|
placeholder: '请输入审批人'
|
|
});
|
|
}
|
|
|
|
return baseFields;
|
|
});
|
|
|
|
function handleReset() {
|
|
emit('reset');
|
|
}
|
|
|
|
function handleSearch() {
|
|
emit('search');
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<TableSearchFields v-model="searchModel" :fields="fields" :columns="4" @reset="handleReset" @search="handleSearch" />
|
|
</template>
|