页面优化

This commit is contained in:
ahui
2025-08-13 10:29:52 +08:00
parent 2ea34bfbd5
commit 2a9f5be895
2 changed files with 383 additions and 384 deletions

View File

@@ -85,17 +85,17 @@
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useUi } from '@fast-crud/fast-crud'; import { useUi } from '@fast-crud/fast-crud';
import { ref, defineProps, PropType, watch, computed, onMounted } from 'vue'; import { ref, defineProps, PropType, watch, computed, onMounted } from 'vue';
import Holidays from 'date-holidays'; import Holidays from 'date-holidays';
import Lunar from 'lunar-javascript'; import Lunar from 'lunar-javascript';
const LUNAR = Lunar.Lunar; // 农历 const LUNAR = Lunar.Lunar; // 农历
const SOLAR = Lunar.Solar; // 阳历 const SOLAR = Lunar.Solar; // 阳历
const props = defineProps({ const props = defineProps({
modelValue: {}, modelValue: {},
// 日期多选 // 日期多选
multiple: { type: Boolean, default: false }, multiple: { type: Boolean, default: false },
@@ -114,15 +114,15 @@
selectable: { type: Boolean, default: true }, selectable: { type: Boolean, default: true },
// 验证日期是否有效 // 验证日期是否有效
validDate: { type: Object as PropType<ValidDateFunc>, default: () => ((d: Date) => true) } validDate: { type: Object as PropType<ValidDateFunc>, default: () => ((d: Date) => true) }
}); });
type ValidDateFunc = (d: Date) => boolean; type ValidDateFunc = (d: Date) => boolean;
type PositionType = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center' | 'center-left' | 'center-right' | 'center-top'; type PositionType = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center' | 'center-left' | 'center-right' | 'center-top';
const today = new Date(); const today = new Date();
const showHoliday = ref<boolean>(true); // 显示节日 const showHoliday = ref<boolean>(true); // 显示节日
const showDetailedHoliday = ref<boolean>(false); // 显示详细的国际节日 const showDetailedHoliday = ref<boolean>(false); // 显示详细的国际节日
const showJieQi = ref<boolean>(true); // 显示节气 const showJieQi = ref<boolean>(true); // 显示节气
const showLunarHoliday = ref<boolean>(true); // 显示农历节日 const showLunarHoliday = ref<boolean>(true); // 显示农历节日
const watermarkPositionMap: { [key: string]: any } = { const watermarkPositionMap: { [key: string]: any } = {
'top-left': { top: '40px', left: 0, transformOrigin: '0 0' }, 'top-left': { top: '40px', left: 0, transformOrigin: '0 0' },
'top-right': { top: '40px', right: 0, transformOrigin: '100% 0' }, 'top-right': { top: '40px', right: 0, transformOrigin: '100% 0' },
'bottom-left': { bottom: 0, left: 0, transformOrigin: '0 100%' }, 'bottom-left': { bottom: 0, left: 0, transformOrigin: '0 100%' },
@@ -132,9 +132,9 @@
'center-right': { top: '50%', right: 0, transformOrigin: '100% 50%' }, 'center-right': { top: '50%', right: 0, transformOrigin: '100% 50%' },
'center-top': { top: 0, left: '50%', transformOrigin: '50% 0', transform: 'translate(-50%, 40px) scale(10)' }, 'center-top': { top: 0, left: '50%', transformOrigin: '50% 0', transform: 'translate(-50%, 40px) scale(10)' },
'center-bottom': { bottom: 0, left: '50%', transformOrigin: '50% 100%', transform: 'translate(-50%, 0) scale(10)' }, 'center-bottom': { bottom: 0, left: '50%', transformOrigin: '50% 100%', transform: 'translate(-50%, 0) scale(10)' },
}; };
// 获取当月第一周的第一天(包括上个月) // 获取当月第一周的第一天(包括上个月)
const calendarFirstDay = (current: Date = new Date()) => { const calendarFirstDay = (current: Date = new Date()) => {
let today = new Date(current); // 指定天 let today = new Date(current); // 指定天
let firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1); // 月初天 let firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1); // 月初天
let weekOfFirstDay = firstDayOfMonth.getDay(); // 周几0日 let weekOfFirstDay = firstDayOfMonth.getDay(); // 周几0日
@@ -143,9 +143,9 @@
// 月初减去周几,不+1是因为从日历周日开始 // 月初减去周几,不+1是因为从日历周日开始
firstDayOfWeek.setDate(firstDayOfMonth.getDate() - weekOfFirstDay); firstDayOfWeek.setDate(firstDayOfMonth.getDate() - weekOfFirstDay);
return new Date(firstDayOfWeek); return new Date(firstDayOfWeek);
}; };
// 获取当月最后一周的最后一天(包括下个月) // 获取当月最后一周的最后一天(包括下个月)
const calendarLastDay = (current: Date = new Date()) => { const calendarLastDay = (current: Date = new Date()) => {
let today = new Date(current); // 指定天 let today = new Date(current); // 指定天
let lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1); // 月末天 let lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1); // 月末天
lastDayOfMonth.setDate(lastDayOfMonth.getDate() - 1); lastDayOfMonth.setDate(lastDayOfMonth.getDate() - 1);
@@ -155,8 +155,8 @@
// 月末加剩下周几,要-1是因为日历到周六结束 // 月末加剩下周几,要-1是因为日历到周六结束
lastDayOfWeek.setDate(lastDayOfMonth.getDate() + (7 - weekOfFirstDay - 1)); lastDayOfWeek.setDate(lastDayOfMonth.getDate() + (7 - weekOfFirstDay - 1));
return new Date(lastDayOfWeek); return new Date(lastDayOfWeek);
}; };
const generateDateList = (startDate: Date, endDate: Date): Date[] => { // 生成日期列表 const generateDateList = (startDate: Date, endDate: Date): Date[] => { // 生成日期列表
let dates = []; let dates = [];
let s = new Date(startDate); let s = new Date(startDate);
let e = new Date(endDate); let e = new Date(endDate);
@@ -165,17 +165,17 @@
s.setDate(s.getDate() + 1); s.setDate(s.getDate() + 1);
} }
return dates; return dates;
}; };
// 日历当前页范围 // 日历当前页范围
interface CalendarCell { interface CalendarCell {
date: Date; date: Date;
selected: boolean; selected: boolean;
disabled: boolean; disabled: boolean;
currentMonth: boolean; currentMonth: boolean;
holiday: string; holiday: string;
}; };
const currentCalendarDate = ref<Date>(new Date()); const currentCalendarDate = ref<Date>(new Date());
const calendarList = computed(() => { const calendarList = computed(() => {
let dates = (!!props.range && props.range[0] && props.range[1]) ? let dates = (!!props.range && props.range[0] && props.range[1]) ?
generateDateList(props.range[0], props.range[1]) : generateDateList(props.range[0], props.range[1]) :
generateDateList(calendarFirstDay(currentCalendarDate.value), calendarLastDay(currentCalendarDate.value)); generateDateList(calendarFirstDay(currentCalendarDate.value), calendarLastDay(currentCalendarDate.value));
@@ -202,23 +202,23 @@
let res: CalendarCell[][] = []; let res: CalendarCell[][] = [];
for (let i = 0; i < 6; i++) res.push(proce_dates.slice(i * 7, (i + 1) * 7)); for (let i = 0; i < 6; i++) res.push(proce_dates.slice(i * 7, (i + 1) * 7));
return res; return res;
}); });
// 控件 // 控件
const turnToPreM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() - 1, 1); const turnToPreM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() - 1, 1);
const turnToNextM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() + 1, 1); const turnToNextM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() + 1, 1);
const turnToPreY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() - 1, currentCalendarDate.value.getMonth(), 1); const turnToPreY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() - 1, currentCalendarDate.value.getMonth(), 1);
const turnToNextY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() + 1, currentCalendarDate.value.getMonth(), 1); const turnToNextY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() + 1, currentCalendarDate.value.getMonth(), 1);
const turnToToday = () => currentCalendarDate.value = new Date(); const turnToToday = () => currentCalendarDate.value = new Date();
// 如果禁止跨页则跨页时清空选择 // 如果禁止跨页则跨页时清空选择
watch( watch(
() => currentCalendarDate.value, () => currentCalendarDate.value,
(v, ov) => props.crossPage ? {} : (v, ov) => props.crossPage ? {} :
(v.toLocaleDateString('en-CA') === ov.toLocaleDateString('en-CA') ? {} : clear()) (v.toLocaleDateString('en-CA') === ov.toLocaleDateString('en-CA') ? {} : clear())
); );
// 单元格事件 // 单元格事件
const onCalenderCellHover = ({ target }: MouseEvent) => (target as HTMLElement).classList.add('onhover'); const onCalenderCellHover = ({ target }: MouseEvent) => (target as HTMLElement).classList.add('onhover');
const onCalenderCellUnhover = ({ target }: MouseEvent) => (target as HTMLElement).classList.remove('onhover'); const onCalenderCellUnhover = ({ target }: MouseEvent) => (target as HTMLElement).classList.remove('onhover');
const onCalenderCellClick = (e: MouseEvent) => { const onCalenderCellClick = (e: MouseEvent) => {
if (!props.selectable) return; if (!props.selectable) return;
let strValue = (e.target as HTMLElement).dataset.date as string; let strValue = (e.target as HTMLElement).dataset.date as string;
if (strValue === undefined) return; if (strValue === undefined) return;
@@ -232,9 +232,9 @@
} }
// 这里阻止了点击取消选中需要通过tag的x来取消 // 这里阻止了点击取消选中需要通过tag的x来取消
else (data.value?.toLocaleDateString('en-CA') === strValue ? {} : onDataChange(value)); else (data.value?.toLocaleDateString('en-CA') === strValue ? {} : onDataChange(value));
}; };
// 选择回显 // 选择回显
const handleTagClose = (d: Date) => { const handleTagClose = (d: Date) => {
let strValue = d.toLocaleDateString('en-CA'); let strValue = d.toLocaleDateString('en-CA');
if (props.multiple) { if (props.multiple) {
let d = (data.value as Date[]).map((v) => v.toLocaleDateString('en-CA')); let d = (data.value as Date[]).map((v) => v.toLocaleDateString('en-CA'));
@@ -242,10 +242,10 @@
onDataChange(d); onDataChange(d);
} }
else onDataChange(null); else onDataChange(null);
}; };
// 节假日 // 节假日
const holidays = new Holidays('CN'); const holidays = new Holidays('CN');
const yearHolidays = computed(() => { const yearHolidays = computed(() => {
let h = holidays.getHolidays(currentCalendarDate.value.getFullYear()); let h = holidays.getHolidays(currentCalendarDate.value.getFullYear());
let proce_h: { [key: string]: string } = {}; let proce_h: { [key: string]: string } = {};
let _h: string[] = []; let _h: string[] = [];
@@ -257,32 +257,32 @@
_h.push(hn); _h.push(hn);
} }
return proce_h return proce_h
}); });
// fs-crud部分 // fs-crud部分
const data = ref<any>(); const data = ref<any>();
const emit = defineEmits(['update:modelValue', 'onSave', 'onClose', 'onClosed']); const emit = defineEmits(['update:modelValue', 'onSave', 'onClose', 'onClosed']);
watch( watch(
() => props.modelValue, () => props.modelValue,
(val) => { (val) => {
if (val === undefined) data.value = props.multiple ? [] : null; if (val === undefined) data.value = props.multiple ? [] : null;
else data.value = props.multiple ? (val as Date[]).map((v: Date) => new Date(v)) : val; else data.value = props.multiple ? (val as Date[]).map((v: Date) => new Date(v)) : val;
}, },
{ immediate: true } { immediate: true }
); );
const { ui } = useUi(); const { ui } = useUi();
const formValidator = ui.formItem.injectFormItemContext(); const formValidator = ui.formItem.injectFormItemContext();
const onDataChange = (value: any) => { const onDataChange = (value: any) => {
emit('update:modelValue', value); emit('update:modelValue', value);
formValidator.onChange(); formValidator.onChange();
formValidator.onBlur(); formValidator.onBlur();
}; };
const reset = () => { // 重置日历 const reset = () => { // 重置日历
currentCalendarDate.value = new Date(); currentCalendarDate.value = new Date();
onDataChange(props.multiple ? [] : null); onDataChange(props.multiple ? [] : null);
}; };
const clear = () => onDataChange(props.multiple ? [] : null); // 清空数据 const clear = () => onDataChange(props.multiple ? [] : null); // 清空数据
defineExpose({ defineExpose({
data, data,
onDataChange, onDataChange,
reset, reset,
@@ -291,27 +291,27 @@
showDetailedHoliday, showDetailedHoliday,
showJieQi, showJieQi,
showLunarHoliday showLunarHoliday
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.selected-show { .selected-show {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.controls { .controls {
width: 100%; width: 100%;
height: 40px; height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.calender { .calender {
position: relative; position: relative;
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;
@@ -398,6 +398,5 @@
} }
} }
} }
} }
</style> </style>

View File

@@ -91,7 +91,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
rowHandle: { rowHandle: {
//固定右侧 //固定右侧
fixed: 'right', fixed: 'right',
width: 200, width: 220,
buttons: { buttons: {
view: { view: {
show: false, show: false,