1.1.67 添加工作日历日程组件。

dev
yinq 3 days ago
parent eafe86a54a
commit afbbf7aa69

@ -7,7 +7,6 @@
"license": "MIT",
"type": "module",
"scripts": {
"dev": "vite serve --mode development",
"build:prod": "vite build --mode production",
"build:dev": "vite build --mode development",
@ -37,6 +36,7 @@
"image-conversion": "2.1.1",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"lunar-javascript": "^1.7.7",
"mammoth": "^1.11.0",
"nprogress": "0.2.0",
"pinia": "3.0.2",

File diff suppressed because it is too large Load Diff

@ -0,0 +1,9 @@
export interface CalendarPendingTask {
id: string | number;
businessId: string;
businessTitle: string;
createTime?: string;
flowName?: string;
formCustom?: string;
formPath?: string;
}

@ -0,0 +1,19 @@
declare module 'lunar-javascript' {
export class Solar {
static fromYmd(year: number, month: number, day: number): Solar;
getLunar(): Lunar;
getFestivals(): string[];
}
export class Lunar {
getDay(): number;
getDayInChinese(): string;
getMonthInChinese(): string;
getFestivals(): string[];
getJieQi(): string;
}
export class HolidayUtil {
static getHoliday(day: string): { getName(): string } | null;
}
}

@ -0,0 +1,61 @@
import { HolidayUtil, Solar } from 'lunar-javascript';
export interface DayLunarInfo {
/** 单元格副标题:节日名或农历日 */
label: string;
/** 完整农历,如 四月廿七 */
fullLunar: string;
/** 节日/节气高亮 */
isHighlight: boolean;
/** 节日或节气名称 */
festival?: string;
}
const cache = new Map<string, DayLunarInfo>();
const pickSolarFestival = (festivals: string[]) => festivals.find((name) => !/^国际/.test(name));
const resolveFestival = (dateStr: string, solar: Solar, lunar: ReturnType<Solar['getLunar']>) => {
const holiday = HolidayUtil.getHoliday(dateStr);
if (holiday) return holiday.getName();
const lunarFestivals = lunar.getFestivals();
if (lunarFestivals.length) return lunarFestivals[0];
const solarFestival = pickSolarFestival(solar.getFestivals());
if (solarFestival) return solarFestival;
const jieQi = lunar.getJieQi();
if (jieQi) return jieQi;
return '';
};
export const getDayLunarInfo = (dateStr: string): DayLunarInfo => {
const cached = cache.get(dateStr);
if (cached) return cached;
const [year, month, day] = dateStr.split('-').map(Number);
const solar = Solar.fromYmd(year, month, day);
const lunar = solar.getLunar();
const festival = resolveFestival(dateStr, solar, lunar);
let label = '';
if (festival) {
label = festival;
} else if (lunar.getDay() === 1) {
label = `${lunar.getMonthInChinese()}`;
} else {
label = lunar.getDayInChinese();
}
const info: DayLunarInfo = {
label,
fullLunar: `${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`,
isHighlight: !!festival,
festival: festival || undefined
};
cache.set(dateStr, info);
return info;
};

@ -110,7 +110,7 @@
</span>
</div>
</template>
<el-tabs v-model="noticeTab" class="notice-tabs">
<el-tabs v-model="noticeTab" class="notice-tabs" :class="{ 'notice-tabs--calendar': noticeTab === 'calendar' }">
<el-tab-pane label="系统公告" name="notice">
<ul v-if="noticeList.length" class="notice-feed">
<li
@ -146,6 +146,14 @@
</ul>
<el-empty v-else description="暂无消息" :image-size="64" />
</el-tab-pane>
<el-tab-pane label="工作日历" name="calendar">
<WorkCalendar
ref="workCalendarRef"
:active="noticeTab === 'calendar'"
:pending-tasks="calendarPendingTasks"
@task-click="onCalendarTaskClick"
/>
</el-tab-pane>
</el-tabs>
</el-card>
@ -207,6 +215,8 @@ import { TimesheetInfoVO } from '@/api/oa/erp/timesheetInfo/types';
import { useUserStore } from '@/store/modules/user';
import { useNoticeStore } from '@/store/modules/notice';
import { resolveMenuPath } from '@/utils/resolveMenuPath';
import WorkCalendar from '@/components/WorkCalendar/index.vue';
import type { CalendarPendingTask } from '@/components/WorkCalendar/workCalendar.types';
import dayjs from 'dayjs';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -277,6 +287,19 @@ const visibleShortcuts = computed(() =>
);
const noticeTab = ref('notice');
const workCalendarRef = ref<InstanceType<typeof WorkCalendar>>();
const calendarPendingTasks = computed<CalendarPendingTask[]>(() =>
taskWaitList.value.map((t) => ({
id: t.id,
businessId: t.businessId,
businessTitle: t.businessTitle || '—',
createTime: t.createTime ? String(t.createTime) : undefined,
flowName: t.flowName,
formCustom: t.formCustom,
formPath: t.formPath
}))
);
const displayName = computed(() => userStore.nickname || '用户');
const displayDept = computed(() => {
@ -501,6 +524,9 @@ const loadDashboard = async () => {
const handleRefresh = () => {
loadDashboard();
if (noticeTab.value === 'calendar') {
workCalendarRef.value?.reload();
}
};
const focusMessages = () => {
@ -552,6 +578,17 @@ const onShortcutClick = (s: { menuComponent: string }) => {
openMenu(s.menuComponent);
};
const onCalendarTaskClick = (task: CalendarPendingTask) => {
const routerJumpVo = reactive<RouterJumpVo>({
businessId: task.businessId,
taskId: task.id,
type: 'approval',
formCustom: task.formCustom,
formPath: task.formPath
});
workflowCommon.routerJump(routerJumpVo, proxy);
};
onMounted(() => {
loadDashboard();
});
@ -804,6 +841,25 @@ onMounted(() => {
:deep(.el-tabs__header) {
margin-bottom: 8px;
}
:deep(.el-tabs__item) {
font-size: 13px;
padding: 0 14px;
}
:deep(.el-tab-pane) {
min-height: 0;
}
}
.notice-tabs--calendar {
:deep(.el-tabs__content) {
overflow: visible;
}
:deep(.el-card__body) {
padding-bottom: 12px;
}
}
.tab-badge {

Loading…
Cancel
Save