refactor(mes): 优化假期设置交互,精简接口对齐后端

1. 右键改左键点击弹出设置弹窗,阻止非当前月切换
2. 弹窗打开时调 get-by-day 接口回显已有 type 和 remark
3. 新增备注(remark)输入框,时间戳传参用 formatDate 转换
4. HolidayType 枚举抽取到 mes/utils/constants.ts 统一管理
5. 精简 API:移除 page/export/update/delete,create 改为 save
pull/871/MERGE
YunaiV 2026-02-16 20:59:01 +08:00
parent f40b415b9c
commit 369d3bbff2
5 changed files with 70 additions and 95 deletions

View File

@ -3,10 +3,8 @@ import request from '@/config/axios'
// MES 假期设置 VO
export interface CalHolidayVO {
id: number // 编号
theDay: string // 日期
type: string // 日期类型
startTime: string // 开始时间
endTime: string // 结束时间
day: number // 日期(时间戳)
type: number // 日期类型
remark: string // 备注
attribute1: string // 预留字段1
attribute2: string // 预留字段2
@ -17,12 +15,7 @@ export interface CalHolidayVO {
// MES 假期设置 API
export const CalHolidayApi = {
// 查询假期设置分页
getHolidayPage: async (params: any) => {
return await request.get({ url: `/mes/cal/holiday/page`, params })
},
// 查询所有假期设置列表(日历组件用,不分页)
// 查询所有假期设置列表
getHolidayList: async () => {
return await request.get({ url: `/mes/cal/holiday/list` })
},

View File

@ -255,5 +255,7 @@ export enum DICT_TYPE {
// ========== MES - 制造执行系统模块 ==========
MES_CLIENT_TYPE = 'mes_client_type', // MES 客户类型
MES_VENDOR_LEVEL = 'mes_vendor_level', // MES 供应商级别
MES_CAL_HOLIDAY_TYPE = 'mes_cal_holiday_type' // MES 假期类型
MES_CAL_HOLIDAY_TYPE = 'mes_cal_holiday_type', // MES 假期类型
MES_TM_TOOL_STATUS = 'mes_tm_tool_status', // MES 工具状态
MES_TM_MAINTEN_TYPE = 'mes_tm_mainten_type' // MES 保养维护类型
}

View File

@ -8,13 +8,13 @@
label-width="80px"
v-loading="formLoading"
>
<el-form-item label="日期" prop="theDay">
<el-input v-model="formData.theDayDisplay" readonly />
<el-form-item label="日期" prop="day">
<el-input :model-value="dayDisplay" readonly />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-radio-group v-model="formData.type">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.MES_CAL_HOLIDAY_TYPE)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_CAL_HOLIDAY_TYPE)"
:key="dict.value"
:value="dict.value"
>
@ -22,6 +22,9 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
@ -30,8 +33,10 @@
</Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { CalHolidayApi } from '@/api/mes/cal/holiday'
import { formatDate } from '@/utils/formatTime'
import { HolidayType } from '@/views/mes/utils/constants'
defineOptions({ name: 'HolidayForm' })
@ -39,10 +44,11 @@ const message = useMessage()
const dialogVisible = ref(false)
const formLoading = ref(false)
const dayDisplay = ref('') // yyyy-MM-dd
const formData = ref({
theDay: '' as string, // yyyy-MM-dd 00:00:00
theDayDisplay: '' as string, //
type: 'HOLIDAY' as string
day: undefined as number | undefined, //
type: HolidayType.WORKDAY as number, //
remark: '' as string
})
const formRules = reactive({
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
@ -50,13 +56,22 @@ const formRules = reactive({
const formRef = ref()
/** 打开弹窗 */
const open = (day: string) => {
const open = async (day: string) => {
dialogVisible.value = true
resetForm()
formData.value.theDayDisplay = day
// theDay datetime yyyy-MM-dd 00:00:00
// TODO @
formData.value.theDay = day + ' 00:00:00'
dayDisplay.value = day
formData.value.day = new Date(day + ' 00:00:00').getTime()
formLoading.value = true
//
try {
const data = await CalHolidayApi.getHolidayByDay(formatDate(formData.value.day as any))
if (data) {
formData.value.type = data.type ?? HolidayType.WORKDAY
formData.value.remark = data.remark ?? ''
}
} finally {
formLoading.value = false
}
}
defineExpose({ open })
@ -66,7 +81,7 @@ const submitForm = async () => {
await formRef.value.validate()
formLoading.value = true
try {
await CalHolidayApi.createHoliday(formData.value as any)
await CalHolidayApi.saveHoliday(formData.value as any)
message.success('设置成功')
dialogVisible.value = false
emit('success')
@ -78,10 +93,11 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
theDay: '',
theDayDisplay: '',
type: 'HOLIDAY'
day: undefined,
type: HolidayType.WORKDAY,
remark: ''
}
dayDisplay.value = ''
formRef.value?.resetFields()
}
</script>

View File

@ -1,7 +1,6 @@
<!-- MES 假期设置 - 日历视图 -->
<template>
<ContentWrap>
<!-- TODO @AI从周一到周日这样的视图 -->
<el-calendar v-model="currentDate">
<template #date-cell="{ data }">
<div class="calendar-cell" @contextmenu.prevent="onRightClick(data)">
@ -9,24 +8,15 @@
<span class="solar-day" :class="{ weekend: isWeekend(data.day) }">
{{ data.day.split('-')[2] }}
</span>
<el-tag
v-if="holidaySet.has(data.day)"
size="small"
effect="dark"
type="success"
>
<el-tag v-if="holidaySet.has(data.day)" size="small" effect="dark" type="success">
</el-tag>
<el-tag
v-else-if="workdaySet.has(data.day)"
size="small"
effect="dark"
type="primary"
>
</el-tag>
<el-tag v-else size="small" effect="dark"> </el-tag>
</div>
<div class="lunar-day" :class="{ festival: hasFestival(data.day) }">
<div
class="text-12px text-#909399 mt-4px"
:class="{ 'text-#67c23a': hasFestival(data.day) }"
>
{{ getLunarDisplay(data.day) }}
</div>
</div>
@ -39,46 +29,46 @@
</template>
<script setup lang="ts">
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
import { formatDate } from '@/utils/formatTime'
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import PluginLunar from 'dayjs-plugin-lunar'
import { SolarDay } from 'tyme4ts'
import HolidayForm from './HolidayForm.vue'
import { checkPermi } from '@/utils/permission'
import { HolidayType } from '@/views/mes/utils/constants'
dayjs.locale('zh-cn')
dayjs.extend(PluginLunar)
defineOptions({ name: 'MesCalHoliday' })
const message = useMessage()
const currentDate = ref(new Date())
const holidaySet = ref(new Set<string>()) // HOLIDAY
const workdaySet = ref(new Set<string>()) // WORKDAY
const holidaySet = ref(new Set<string>()) //
const formRef = ref()
/** 获取假期列表 */
const getList = async () => {
holidaySet.value.clear()
workdaySet.value.clear()
const list = await CalHolidayApi.getHolidayList()
if (list) {
list.forEach((item: CalHolidayVO) => {
// theDay datetime 10 yyyy-MM-dd
const day = item.theDay ? item.theDay.substring(0, 10) : ''
if (!day) {
return
}
if (item.type === 'HOLIDAY') {
// day long yyyy-MM-dd
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
if (day && item.type === HolidayType.HOLIDAY) {
holidaySet.value.add(day)
} else if (item.type === 'WORKDAY') {
workdaySet.value.add(day)
}
})
}
}
/** 右键点击日期 */
const onRightClick = (data: { day: string }) => {
//
/** 点击日期 */
const onClickDay = (data: { type: string; day: string }) => {
//
if (data.type !== 'current-month') {
return
}
if (!checkPermi(['mes:cal-holiday:create'])) {
message.warning('没有假期设置权限')
return
@ -96,14 +86,14 @@ const isWeekend = (day: string): boolean => {
/** 获取农历显示信息 */
const getLunarInfo = (day: string) => {
const parts = day.split('-')
const y = parseInt(parts[0]), m = parseInt(parts[1]), d = parseInt(parts[2])
const year = parseInt(parts[0])
const month = parseInt(parts[1])
const date = parseInt(parts[2])
try {
const solarDay = SolarDay.fromYmd(y, m, d)
const solarDay = SolarDay.fromYmd(year, month, date)
const lunarDay = solarDay.getLunarDay()
//
const solarFestival = solarDay.getFestival()
//
const lunarFestival = lunarDay.getFestival()
const solarFestival = solarDay.getFestival() //
const lunarFestival = lunarDay.getFestival() //
// dayIndex === 0
const termDay = solarDay.getTermDay()
const termName = termDay.getDayIndex() === 0 ? termDay.getSolarTerm().getName() : null
@ -138,36 +128,4 @@ const hasFestival = (day: string): boolean => {
onMounted(() => {
getList()
})
// TODO @AI使 unocss style
</script>
<style scoped>
.calendar-cell {
height: 100%;
padding: 4px;
}
.calendar-cell-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.solar-day {
font-size: 16px;
font-weight: 500;
}
.solar-day.weekend {
color: #f56c6c;
}
.lunar-day {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
.lunar-day.festival {
color: #67c23a;
}
</style>

View File

@ -10,6 +10,12 @@ export const MesItemOrProductEnum = {
}
} as const
/** MES 假期类型枚举 */
export const HolidayType = {
WORKDAY: 1, // 工作日
HOLIDAY: 2 // 节假日
} as const
/** 获取物料/产品标识的标签 */
export const getItemOrProductLabel = (value: string): string => {
for (const item of Object.values(MesItemOrProductEnum)) {