✨ feat(mes): 优化排班日历查询逻辑,支持批量班组查询
重构排班日历查询功能,简化代码实现,支持一次性查询多个班组的排班记录。 新增班组编号集合字段,提升查询效率和可读性。pull/871/MERGE
parent
f8553abcdd
commit
1b3a41da14
|
|
@ -33,26 +33,16 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CalCalendarApi, CalCalendarDayVO } from '@/api/mes/cal/calendar'
|
||||
import { CalTeamApi, CalTeamVO } from '@/api/mes/cal/team'
|
||||
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { HolidayType } from '@/views/mes/utils/constants'
|
||||
import CalendarDateCell from './CalendarDateCell.vue'
|
||||
import CalendarLegend from './CalendarLegend.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import PluginLunar from 'dayjs-plugin-lunar'
|
||||
import { useCalendar } from './useCalendar'
|
||||
|
||||
dayjs.locale('zh-cn')
|
||||
dayjs.extend(PluginLunar)
|
||||
const { loading, currentDate, calendarDayMap, holidaySet, loadHolidays, fetchCalendar, watchMonth } =
|
||||
useCalendar()
|
||||
|
||||
const loading = ref(false)
|
||||
const currentDate = ref(new Date()) // 日历当前显示月份
|
||||
const selectedTeamId = ref<number>() // 当前选中的班组编号
|
||||
const teamList = ref<CalTeamVO[]>([]) // 所有班组列表
|
||||
const calendarDayMap = ref<Map<string, CalCalendarDayVO>>(new Map()) // key: yyyy-MM-dd
|
||||
const holidaySet = ref(new Set<string>()) // 节假日日期集合,key: yyyy-MM-dd
|
||||
|
||||
/** 获取班组列表,并默认选中第一个 */
|
||||
const getTeamList = async () => {
|
||||
|
|
@ -62,71 +52,28 @@ const getTeamList = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
/** 获取节假日列表,构建节假日日期集合 */
|
||||
const getHolidayList = async () => {
|
||||
holidaySet.value.clear()
|
||||
const list = await CalHolidayApi.getHolidayList()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalHolidayVO) => {
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day && item.type === HolidayType.HOLIDAY) {
|
||||
holidaySet.value.add(day)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询当前月份的排班日历,按选中班组过滤 */
|
||||
const fetchCalendar = async () => {
|
||||
const doFetch = () => {
|
||||
if (!selectedTeamId.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
// 计算当前月份的起止时间
|
||||
const date = currentDate.value
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
const startDay = new Date(year, month, 1)
|
||||
const endDay = new Date(year, month + 1, 0, 23, 59, 59)
|
||||
const list = await CalCalendarApi.getCalendarList({
|
||||
queryType: 'TEAM',
|
||||
teamId: selectedTeamId.value,
|
||||
startDay: formatDate(startDay, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endDay: formatDate(endDay, 'YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
// 转为 Map 方便按日期快速查找
|
||||
calendarDayMap.value.clear()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalCalendarDayVO) => {
|
||||
// 后端返回的 day 为时间戳(long),格式化为 yyyy-MM-dd 作为 Map key
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day) {
|
||||
calendarDayMap.value.set(day, { ...item, day })
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
fetchCalendar({ queryType: 'TEAM', teamId: selectedTeamId.value })
|
||||
}
|
||||
|
||||
/** 点击左侧班组后切换并刷新日历 */
|
||||
const onSelectTeam = (id: number) => {
|
||||
selectedTeamId.value = id
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
|
||||
/** 监听月份切换,重新加载当月排班 */
|
||||
watch(currentDate, () => {
|
||||
watchMonth(() => {
|
||||
if (selectedTeamId.value) {
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
})
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getTeamList()
|
||||
getHolidayList()
|
||||
loadHolidays()
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -33,91 +33,38 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CalCalendarApi, CalCalendarDayVO } from '@/api/mes/cal/calendar'
|
||||
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { HolidayType } from '@/views/mes/utils/constants'
|
||||
import CalendarDateCell from './CalendarDateCell.vue'
|
||||
import CalendarLegend from './CalendarLegend.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import PluginLunar from 'dayjs-plugin-lunar'
|
||||
import { useCalendar } from './useCalendar'
|
||||
|
||||
dayjs.locale('zh-cn')
|
||||
dayjs.extend(PluginLunar)
|
||||
const { loading, currentDate, calendarDayMap, holidaySet, loadHolidays, fetchCalendar, watchMonth } =
|
||||
useCalendar()
|
||||
|
||||
const loading = ref(false)
|
||||
const currentDate = ref(new Date()) // 日历当前显示月份
|
||||
const selectedType = ref<number>() // 当前选中的班组类型(枚举 MES_CAL_CALENDAR_TYPE)
|
||||
const calendarDayMap = ref<Map<string, CalCalendarDayVO>>(new Map()) // key: yyyy-MM-dd
|
||||
const holidaySet = ref(new Set<string>()) // 节假日日期集合,key: yyyy-MM-dd
|
||||
|
||||
/** 获取节假日列表,构建节假日日期集合 */
|
||||
const getHolidayList = async () => {
|
||||
holidaySet.value.clear()
|
||||
const list = await CalHolidayApi.getHolidayList()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalHolidayVO) => {
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day && item.type === HolidayType.HOLIDAY) {
|
||||
holidaySet.value.add(day)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询当前月份的排班日历,按选中分类过滤 */
|
||||
const fetchCalendar = async () => {
|
||||
const doFetch = () => {
|
||||
if (!selectedType.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
// 计算当前月份的起止时间
|
||||
const date = currentDate.value
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
const startDay = new Date(year, month, 1)
|
||||
const endDay = new Date(year, month + 1, 0, 23, 59, 59)
|
||||
const list = await CalCalendarApi.getCalendarList({
|
||||
queryType: 'TYPE',
|
||||
calendarType: selectedType.value,
|
||||
startDay: formatDate(startDay, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endDay: formatDate(endDay, 'YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
// 转为 Map 方便按日期快速查找
|
||||
calendarDayMap.value.clear()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalCalendarDayVO) => {
|
||||
// 后端返回的 day 为时间戳(long),格式化为 yyyy-MM-dd 作为 Map key
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day) {
|
||||
calendarDayMap.value.set(day, { ...item, day })
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
fetchCalendar({ queryType: 'TYPE', calendarType: selectedType.value })
|
||||
}
|
||||
|
||||
/** 点击左侧分类后切换并刷新日历 */
|
||||
const onSelectType = (value: number) => {
|
||||
selectedType.value = value
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
|
||||
/** 监听月份切换,重新加载当月排班 */
|
||||
watch(currentDate, () => {
|
||||
watchMonth(() => {
|
||||
if (selectedType.value) {
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
})
|
||||
|
||||
/** 初始化:加载节假日,并默认选中第一个分类 */
|
||||
onMounted(() => {
|
||||
getHolidayList()
|
||||
loadHolidays()
|
||||
const opts = getIntDictOptions(DICT_TYPE.MES_CAL_CALENDAR_TYPE)
|
||||
if (opts.length > 0) {
|
||||
onSelectType(opts[0].value as number)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@
|
|||
<el-select
|
||||
v-model="userId"
|
||||
filterable
|
||||
placeholder="请选择人员"
|
||||
remote
|
||||
:remote-method="remoteSearchUser"
|
||||
:loading="userSearchLoading"
|
||||
placeholder="请输入人员姓名搜索"
|
||||
class="!w-200px"
|
||||
@change="onUserQuery"
|
||||
>
|
||||
|
|
@ -41,91 +44,54 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CalCalendarApi, CalCalendarDayVO } from '@/api/mes/cal/calendar'
|
||||
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
|
||||
import { getSimpleUserList, UserVO } from '@/api/system/user'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { HolidayType } from '@/views/mes/utils/constants'
|
||||
import CalendarDateCell from './CalendarDateCell.vue'
|
||||
import CalendarLegend from './CalendarLegend.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import PluginLunar from 'dayjs-plugin-lunar'
|
||||
import { useCalendar } from './useCalendar'
|
||||
|
||||
dayjs.locale('zh-cn')
|
||||
dayjs.extend(PluginLunar)
|
||||
const { loading, currentDate, calendarDayMap, holidaySet, loadHolidays, fetchCalendar, watchMonth } =
|
||||
useCalendar()
|
||||
|
||||
const loading = ref(false)
|
||||
const currentDate = ref(new Date()) // 日历当前显示月份
|
||||
const userId = ref<number>() // 当前选中的用户编号
|
||||
const userList = ref<UserVO[]>([]) // 所有用户列表
|
||||
const calendarDayMap = ref<Map<string, CalCalendarDayVO>>(new Map()) // key: yyyy-MM-dd
|
||||
const holidaySet = ref(new Set<string>()) // 节假日日期集合,key: yyyy-MM-dd
|
||||
const userList = ref<UserVO[]>([]) // 搜索到的用户列表
|
||||
const userSearchLoading = ref(false) // 远程搜索加载状态
|
||||
let allUserList: UserVO[] = [] // 缓存全量用户列表
|
||||
|
||||
/** 获取节假日列表,构建节假日日期集合 */
|
||||
const getHolidayList = async () => {
|
||||
holidaySet.value.clear()
|
||||
const list = await CalHolidayApi.getHolidayList()
|
||||
if (!list) {
|
||||
return
|
||||
/** 远程搜索用户 */
|
||||
const remoteSearchUser = (query: string) => {
|
||||
if (query) {
|
||||
userSearchLoading.value = true
|
||||
// 从缓存的全量列表中前端过滤
|
||||
userList.value = allUserList.filter((user) =>
|
||||
user.nickname?.toLowerCase().includes(query.toLowerCase())
|
||||
)
|
||||
userSearchLoading.value = false
|
||||
} else {
|
||||
userList.value = []
|
||||
}
|
||||
list.forEach((item: CalHolidayVO) => {
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day && item.type === HolidayType.HOLIDAY) {
|
||||
holidaySet.value.add(day)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询当前月份的排班日历,按选中人员过滤 */
|
||||
const fetchCalendar = async () => {
|
||||
const doFetch = () => {
|
||||
if (!userId.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
// 计算当前月份的起止时间
|
||||
const date = currentDate.value
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
const startDay = new Date(year, month, 1)
|
||||
const endDay = new Date(year, month + 1, 0, 23, 59, 59)
|
||||
const list = await CalCalendarApi.getCalendarList({
|
||||
queryType: 'USER',
|
||||
userId: userId.value,
|
||||
startDay: formatDate(startDay, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endDay: formatDate(endDay, 'YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
// 转为 Map 方便按日期快速查找
|
||||
calendarDayMap.value.clear()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalCalendarDayVO) => {
|
||||
// 后端返回的 day 为时间戳(long),格式化为 yyyy-MM-dd 作为 Map key
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day) {
|
||||
calendarDayMap.value.set(day, { ...item, day })
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
fetchCalendar({ queryType: 'USER', userId: userId.value })
|
||||
}
|
||||
|
||||
/** 查询按钮 / 下拉选人后刷新日历 */
|
||||
const onUserQuery = () => {
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
|
||||
/** 监听月份切换,重新加载当月排班 */
|
||||
watch(currentDate, () => {
|
||||
watchMonth(() => {
|
||||
if (userId.value) {
|
||||
fetchCalendar()
|
||||
doFetch()
|
||||
}
|
||||
})
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
userList.value = await getSimpleUserList()
|
||||
await getHolidayList()
|
||||
allUserList = await getSimpleUserList()
|
||||
await loadHolidays()
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
import { ref, watch } from 'vue'
|
||||
import { CalCalendarApi, CalCalendarDayVO } from '@/api/mes/cal/calendar'
|
||||
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { HolidayType } from '@/views/mes/utils/constants'
|
||||
|
||||
/**
|
||||
* 排班日历通用 composable
|
||||
*
|
||||
* 封装日历组件中通用的响应式状态、假期加载、排班查询、月份切换逻辑
|
||||
*/
|
||||
export function useCalendar() {
|
||||
const loading = ref(false)
|
||||
const currentDate = ref(new Date())
|
||||
const calendarDayMap = ref<Map<string, CalCalendarDayVO>>(new Map())
|
||||
const holidaySet = ref(new Set<string>())
|
||||
|
||||
/** 获取节假日列表,按当前月份范围加载 */
|
||||
const loadHolidays = async () => {
|
||||
holidaySet.value.clear()
|
||||
const { startDay, endDay } = getMonthRange()
|
||||
const list = await CalHolidayApi.getHolidayList({
|
||||
startDay: formatDate(startDay, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endDay: formatDate(endDay, 'YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalHolidayVO) => {
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day && item.type === HolidayType.HOLIDAY) {
|
||||
holidaySet.value.add(day)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询排班日历,params 由调用方提供 queryType 相关参数 */
|
||||
const fetchCalendar = async (params: Record<string, any>) => {
|
||||
loading.value = true
|
||||
try {
|
||||
const { startDay, endDay } = getMonthRange()
|
||||
const list = await CalCalendarApi.getCalendarList({
|
||||
...params,
|
||||
startDay: formatDate(startDay, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endDay: formatDate(endDay, 'YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
calendarDayMap.value.clear()
|
||||
if (!list) {
|
||||
return
|
||||
}
|
||||
list.forEach((item: CalCalendarDayVO) => {
|
||||
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
|
||||
if (day) {
|
||||
calendarDayMap.value.set(day, { ...item, day })
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 计算当前月份的起止时间 */
|
||||
const getMonthRange = () => {
|
||||
const date = currentDate.value
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
return {
|
||||
startDay: new Date(year, month, 1),
|
||||
endDay: new Date(year, month + 1, 0, 23, 59, 59)
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听月份切换,调用回调刷新数据 */
|
||||
const watchMonth = (callback: () => void) => {
|
||||
watch(currentDate, () => {
|
||||
loadHolidays().then()
|
||||
callback()
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
currentDate,
|
||||
calendarDayMap,
|
||||
holidaySet,
|
||||
loadHolidays,
|
||||
fetchCalendar,
|
||||
watchMonth
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,9 @@
|
|||
class="w-1/1"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型编码" prop="code">
|
||||
<el-input v-model="formData.code" placeholder="请输入类型编码" />
|
||||
<el-form-item label="设备类型编码" prop="code" v-if="formType === 'update'">
|
||||
<!-- TODO @AI:点击后生成,不要这里自动生成; -->
|
||||
<el-input v-model="formData.code" placeholder="系统自动生成" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入类型名称" />
|
||||
|
|
@ -75,7 +76,6 @@ const formData = ref({
|
|||
})
|
||||
const formRules = reactive({
|
||||
parentId: [{ required: true, message: '上级类型不能为空', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '类型编码不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '类型名称不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
||||
|
|
|
|||
Loading…
Reference in New Issue