From 3bb04f80ebf3d8625a7c0dd0f91b32615cbb498b Mon Sep 17 00:00:00 2001 From: fyy <2717885210@qq.com> Date: Wed, 6 Aug 2025 16:47:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workforceManagement/calendarView.vue | 273 +++++++-- .../category/category-modal.vue | 137 +++++ .../property/personalCenter/category/data.ts | 69 +++ .../personalCenter/category/index.vue | 153 +++++ .../personalCenter/components/apply-modal.vue | 149 +++++ .../components/approval-card.vue | 93 +++ .../components/approval-content.vue | 26 + .../components/approval-details.vue | 41 ++ .../components/approval-modal.vue | 227 +++++++ .../components/approval-panel.vue | 556 ++++++++++++++++++ .../components/approval-rejection-modal.vue | 146 +++++ .../components/approval-timeline-item.vue | 81 +++ .../components/approval-timeline.vue | 21 + .../components/copy-component.vue | 98 +++ .../components/flow-designer.vue | 52 ++ .../components/flow-info-modal.vue | 38 ++ .../components/flow-interfere-modal.vue | 171 ++++++ .../components/flow-preview.vue | 28 + .../personalCenter/components/helper.tsx | 60 ++ .../personalCenter/components/index.ts | 30 + .../components/user-select-modal.vue | 378 ++++++++++++ .../personalCenter/leave/api/index.ts | 62 ++ .../personalCenter/leave/api/model.d.ts | 107 ++++ .../property/personalCenter/leave/data.tsx | 175 ++++++ .../property/personalCenter/leave/index.vue | 200 +++++++ .../leave/leave-description.vue | 45 ++ .../personalCenter/leave/leave-form.vue | 192 ++++++ .../personalCenter/leave/leaveEdit.vue | 11 + .../personalCenter/leaveApplication/data.ts | 111 +++- .../personalCenter/leaveApplication/index.vue | 42 +- .../processDefinition/category-tree.vue | 114 ++++ .../processDefinition/constant.ts | 36 ++ .../personalCenter/processDefinition/data.tsx | 103 ++++ .../processDefinition/design.vue | 11 + .../processDefinition/index.vue | 378 ++++++++++++ .../process-definition-deploy-modal.vue | 73 +++ .../process-definition-modal.vue | 137 +++++ .../personalCenter/processInstance/data.tsx | 91 +++ .../personalCenter/processInstance/index.vue | 240 ++++++++ .../instance-invalid-modal.vue | 67 +++ .../instance-variable-modal.vue | 28 + .../personalCenter/task/allTaskWaiting.vue | 360 ++++++++++++ .../property/personalCenter/task/constant.ts | 7 + .../personalCenter/task/myDocument.vue | 257 ++++++++ .../personalCenter/task/taskCopyList.vue | 299 ++++++++++ .../personalCenter/task/taskFinish.vue | 299 ++++++++++ .../personalCenter/task/taskWaiting.vue | 302 ++++++++++ 47 files changed, 6522 insertions(+), 52 deletions(-) create mode 100644 apps/web-antd/src/views/property/personalCenter/category/category-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/category/data.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/category/index.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/apply-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-card.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-content.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-details.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-panel.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-rejection-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-timeline-item.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/approval-timeline.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/copy-component.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/flow-designer.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/flow-info-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/flow-interfere-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/flow-preview.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/components/helper.tsx create mode 100644 apps/web-antd/src/views/property/personalCenter/components/index.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/components/user-select-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/api/index.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/api/model.d.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/data.tsx create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/index.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/leave-description.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/leave-form.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/leave/leaveEdit.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/category-tree.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/constant.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/data.tsx create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/design.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/index.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/process-definition-deploy-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processDefinition/process-definition-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processInstance/data.tsx create mode 100644 apps/web-antd/src/views/property/personalCenter/processInstance/index.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processInstance/instance-invalid-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/processInstance/instance-variable-modal.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/task/allTaskWaiting.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/task/constant.ts create mode 100644 apps/web-antd/src/views/property/personalCenter/task/myDocument.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/task/taskCopyList.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/task/taskFinish.vue create mode 100644 apps/web-antd/src/views/property/personalCenter/task/taskWaiting.vue diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue index 774f9aa0..b60874bf 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue @@ -7,6 +7,7 @@ import dayjs from 'dayjs'; import arrangementModal from './arrangement-modal.vue'; import { useVbenModal } from '@vben/common-ui'; import { arrangementCalender } from '#/api/property/attendanceManagement/arrangement'; // 导入接口 +import { Modal } from 'ant-design-vue'; const emit = defineEmits<{ (e: 'changeView', value: boolean): void; @@ -19,6 +20,8 @@ const calendarData = reactive([]); const loading = ref(false); // 查询日历数据 const fetchCalendarData = async (month?: string) => { + console.log(123); + try { loading.value = true; const params = { @@ -32,47 +35,150 @@ const fetchCalendarData = async (month?: string) => { month || selectedDate.value?.format('YYYY-MM') || dayjs().format('YYYY-MM'); //当前月份的开始日期 + + // 清空之前的数据 + calendarData.length = 0; + // 生成日历渲染数据结构 for (const row of res.rows) { if (row.endDate) { + const startDate = dayjs(row.startDate); + const endDate = dayjs(row.endDate); + const currentMonthStart = dayjs(currentMonth).startOf('month'); + const currentMonthEnd = dayjs(currentMonth).endOf('month'); + //当开始时间小于当前月份的开始日期 - if (row.startDate <= currentMonth) { - console.log(row, '小'); - + if (startDate.isBefore(currentMonthStart) || startDate.isSame(currentMonthStart, 'day')) { + console.log(row, '小 - 开始时间小于等于当前月份开始时间'); + console.log('开始时间:', row.startDate); + console.log('结束时间:', row.endDate); + console.log('当前月份开始:', currentMonthStart.format('YYYY-MM-DD')); + console.log('当前月份结束:', currentMonthEnd.format('YYYY-MM-DD')); + //如果结束时间小于当前月份的结束时间,则生成当前月份开始时间到row.endDate结束时间的n条数据 //如果结束时间大于等于当前月份的结束时间,则生成当前月份开始时间到当前月份结束时间(即当前月份天数)的n条数据 + + // 确定结束日期:取row.endDate和当前月份结束日期的较小值 + const actualEndDate = endDate.isBefore(currentMonthEnd) ? endDate : currentMonthEnd; + console.log('实际结束日期:', actualEndDate.format('YYYY-MM-DD')); + + // 生成从当前月份开始到实际结束日期的数据 + let currentDate = currentMonthStart; + let generatedCount = 0; + while (currentDate.isSame(actualEndDate, 'day') || currentDate.isBefore(actualEndDate, 'day')) { + calendarData.push({ + date: currentDate.format('YYYY-MM-DD'), + item: { + id: row.id, + groupName: row.attendanceGroup.groupName, + groupId: row.attendanceGroup.id, + startDate: row.startDate, + endDate: row.endDate, + }, + }); + generatedCount++; + currentDate = currentDate.add(1, 'day'); + } + console.log(`生成了 ${generatedCount} 条数据`); } else { //当开始时间大于当前月份的开始日期 //如果结束时间小于当前月份的结束时间,则生成开始时间到结束时间的n条数据 - console.log(row, '大'); + console.log(row, '大 - 开始时间大于当前月份开始时间'); + console.log('开始时间:', row.startDate); + console.log('结束时间:', row.endDate); + console.log('当前月份开始:', currentMonthStart.format('YYYY-MM-DD')); + console.log('当前月份结束:', currentMonthEnd.format('YYYY-MM-DD')); + + // 确定结束日期:取row.endDate和当前月份结束日期的较小值 + const actualEndDate = endDate.isBefore(currentMonthEnd) ? endDate : currentMonthEnd; + console.log('实际结束日期:', actualEndDate.format('YYYY-MM-DD')); + + // 生成从开始日期到实际结束日期的数据 + let currentDate = startDate; + let generatedCount = 0; + while (currentDate.isSame(actualEndDate, 'day') || currentDate.isBefore(actualEndDate, 'day')) { + calendarData.push({ + date: currentDate.format('YYYY-MM-DD'), + item: { + id: row.id, + groupName: row.attendanceGroup.groupName, + groupId: row.attendanceGroup.id, + startDate: row.startDate, + endDate: row.endDate, + }, + }); + generatedCount++; + currentDate = currentDate.add(1, 'day'); + } + console.log(`生成了 ${generatedCount} 条数据`); } } else { + // 没有结束日期的情况,只在开始日期添加一条数据 calendarData.push({ - data: row.startDate, + date: row.startDate, item: { id: row.id, groupName: row.attendanceGroup.groupName, groupId: row.attendanceGroup.id, + startDate: row.startDate, + endDate: row.endDate, }, }); } } - // if (response) { - // calendarData.value = response.data || []; - // console.log('日历数据:', calendarData.value); - // } + console.log('日历数据:', calendarData); + //变量calendarData,日期相同的数据放到一个对象中,数据结构为scheduleData + + // 将calendarData按日期分组,形成scheduleData结构 + const groupedData = new Map(); + + // 遍历calendarData,按日期分组 + calendarData.forEach(item => { + const date = item.date; + if (!groupedData.has(date)) { + groupedData.set(date, []); + } + groupedData.get(date)!.push(item.item); + }); + + // 转换为scheduleData格式 + scheduleData.length = 0; // 清空原有数据 + groupedData.forEach((items, date) => { + scheduleData.push({ + date: date, + list: items.map(item => ({ + type: 'success' as BadgeProps['status'], + content: item.groupName || '排班安排', + item: item + })) + }); + }); + + console.log('处理后的scheduleData:', scheduleData); + + // 测试:验证生成的日历数据 + console.log('=== 日历数据验证 ==='); + console.log('当前月份:', currentMonth); + console.log('原始数据条数:', res.rows.length); + console.log('生成的日历数据条数:', calendarData.length); + console.log('分组后的数据条数:', scheduleData.length); + + // 验证是否有重复日期 + const dateCounts = new Map(); + calendarData.forEach(item => { + const count = dateCounts.get(item.date) || 0; + dateCounts.set(item.date, count + 1); + }); + + console.log('日期分布:', Object.fromEntries(dateCounts)); + console.log('=== 验证完成 ==='); + } catch (error) { + console.error('获取日历数据失败:', error); + message.error('获取日历数据失败'); } finally { loading.value = false; } }; - -// 切换视图模式 -function handleViewModeChange(e: RadioChangeEvent): void { - // 将父组件的isCalenderView变为true - emit('changeView', e.target.value); -} - -// 日历模拟数据 const scheduleData: { date: string; list: { type: BadgeProps['status']; content: string }[]; @@ -81,18 +187,25 @@ const scheduleData: { { date: '2025-07-06', list: [{ type: 'success', content: '8月8日事件' }] }, // ... ]; +// 切换视图模式 +function handleViewModeChange(e: RadioChangeEvent): void { + // 将父组件的isCalenderView变为true + emit('changeView', e.target.value); +} const getListData2 = ( current: Dayjs, -): { type: BadgeProps['status']; content: string }[] => { +): { type: BadgeProps['status']; content: string; item?: any }[] => { const dateStr = current.format('YYYY-MM-DD'); - // 优先使用接口数据 - if (calendarData.length > 0) { - const found = calendarData.find((item) => item.date === dateStr); + + // 使用scheduleData结构 + if (scheduleData.length > 0) { + const found = scheduleData.find((item) => item.date === dateStr); if (found) { - return found.list || []; + return found.list; } } + // 如果没有找到数据,返回空数组 return []; }; @@ -130,13 +243,8 @@ const getListData = ( return listData || []; }; -const getMonthData = (value: Dayjs) => { - if (value.month() === 8) { - return 1394; - } -}; function customHeader() { - // 返回你想要的VNode或null + // 返回想要的VNode或null return null; // 什么都不显示 } const [ArrangementModal, modalApi] = useVbenModal({ @@ -147,6 +255,57 @@ function handleAdd() { modalApi.open(); } +// 编辑排班 +function handleEdit(item: any) { +console.log(815328); + + // modalApi.setData({ + // id: item.id, + // groupId: item.groupId, + // startDate: item.startDate, + // endDate: item.endDate, + // }); + // modalApi.open(); +} + +// 删除排班 +function handleDelete(item: any) { + Modal.confirm({ + title: '确认删除', + content: '确定要删除这个排班安排吗?', + onOk: async () => { + try { + // 这里需要调用删除接口 + // await deleteArrangement(item.id); + message.success('删除成功'); + fetchCalendarData(); + } catch (error) { + console.error('删除失败:', error); + message.error('删除失败'); + } + }, + }); +} + +// 查看详情 +function handleViewDetails(item: any) { + // 这里可以打开详情弹窗或跳转到详情页面 + console.log('查看详情:', item); +} + +// 获取指定日期的所有排班项目 +function getScheduleItemsByDate(date: string) { + const found = scheduleData.find((item) => item.date === date); + return found ? found.list : []; +} + +// 查看某日期的所有排班详情 +function handleViewDateDetails(date: string) { + const items = getScheduleItemsByDate(date); + console.log(`${date} 的所有排班安排:`, items); + // 这里可以打开详情弹窗显示该日期的所有排班 +} + // 页面初始化时加载数据 onMounted(() => { fetchCalendarData(); @@ -169,6 +328,7 @@ onMounted(() => { picker="month" v-model:value="selectedDate" @change="fetchCalendarData()" + @select="fetchCalendarData()" /> @@ -187,29 +347,32 @@ onMounted(() => { - @@ -228,6 +391,32 @@ onMounted(() => { text-overflow: ellipsis; font-size: 12px; } +.events li { + margin-bottom: 4px; + padding: 4px; + /* background-color: #f6ffed; */ + /* border: 1px solid #b7eb8f; */ + border-radius: 4px; + font-size: 12px; +} +.events li span { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; +} +.events li .action-buttons { + display: flex; + gap: 4px; + margin-top: 2px; +} +.events li a { + font-size: 11px; + text-decoration: none; +} +.events li a:hover { + text-decoration: underline; +} .notes-month { text-align: center; font-size: 28px; diff --git a/apps/web-antd/src/views/property/personalCenter/category/category-modal.vue b/apps/web-antd/src/views/property/personalCenter/category/category-modal.vue new file mode 100644 index 00000000..c2816b44 --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/category/category-modal.vue @@ -0,0 +1,137 @@ + + + diff --git a/apps/web-antd/src/views/property/personalCenter/category/data.ts b/apps/web-antd/src/views/property/personalCenter/category/data.ts new file mode 100644 index 00000000..9dfe1940 --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/category/data.ts @@ -0,0 +1,69 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + +export const querySchema: FormSchemaGetter = () => [ + { + fieldName: 'categoryName', + label: '分类名称', + component: 'Input', + }, + { + fieldName: 'categoryCode', + label: '分类编码', + component: 'Input', + }, +]; + +export const columns: VxeGridProps['columns'] = [ + { + field: 'categoryName', + title: '分类名称', + treeNode: true, + }, + { + field: 'orderNum', + title: '排序', + }, + { + field: 'createTime', + title: '创建时间', + }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + resizable: false, + width: 'auto', + }, +]; + +export const modalSchema: FormSchemaGetter = () => [ + { + label: 'categoryId', + fieldName: 'categoryId', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + fieldName: 'parentId', + label: '父级分类', + rules: 'required', + defaultValue: 100, + component: 'TreeSelect', + }, + { + fieldName: 'categoryName', + label: '分类名称', + component: 'Input', + rules: 'required', + }, + { + fieldName: 'orderNum', + label: '排序', + component: 'InputNumber', + }, +]; diff --git a/apps/web-antd/src/views/property/personalCenter/category/index.vue b/apps/web-antd/src/views/property/personalCenter/category/index.vue new file mode 100644 index 00000000..5131775d --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/category/index.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/web-antd/src/views/property/personalCenter/components/apply-modal.vue b/apps/web-antd/src/views/property/personalCenter/components/apply-modal.vue new file mode 100644 index 00000000..d0116f03 --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/components/apply-modal.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/apps/web-antd/src/views/property/personalCenter/components/approval-card.vue b/apps/web-antd/src/views/property/personalCenter/components/approval-card.vue new file mode 100644 index 00000000..d8f1a060 --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/components/approval-card.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/apps/web-antd/src/views/property/personalCenter/components/approval-content.vue b/apps/web-antd/src/views/property/personalCenter/components/approval-content.vue new file mode 100644 index 00000000..8db040d0 --- /dev/null +++ b/apps/web-antd/src/views/property/personalCenter/components/approval-content.vue @@ -0,0 +1,26 @@ + + + +