فهرست منبع

fix: 优化周日报

qiny 1 سال پیش
والد
کامیت
96647a734c

+ 1 - 0
client/src/views/OaSystem/personnelManagement/weeklyCenter/WeekCalendar.vue

@@ -89,6 +89,7 @@ const weekOnChange = (arr, index) => {
   if (target) {
   if (target) {
     changeData.isLog = weekLogObj.value[target.dm]
     changeData.isLog = weekLogObj.value[target.dm]
   }
   }
+  // console.log('changeData', changeData)
   onChange(changeData)
   onChange(changeData)
   // checkWeek.value = index
   // checkWeek.value = index
   checkWeek.value = {
   checkWeek.value = {

+ 202 - 0
client/src/views/OaSystem/personnelManagement/weeklyCenter/service.ts

@@ -0,0 +1,202 @@
+/**
+ * @description 所有周日报通用的方法
+ */
+import moment from 'moment'
+import request from '@/config/axios'
+import { getUserInfo } from '@/utils/tool'
+
+const userInfo = getUserInfo()
+
+// 所有请求
+const api = {
+  workDayList: '/adm/workday/list', // 获取工作日列表
+  logList: '/adm/report/list', // 获取周报日志列表
+  attendance: '/adm/attendance-sheet/list-me' // 获取考勤数据
+}
+export const http = {
+  // 获取工作日列表 YYYY-MM-DD HH:mm:ss
+  getWorkDayList: async (startDate: string, endDate: string) => {
+    // 用一种不太优雅的方式实现请求效果
+    const params = {
+      dateDay: [startDate, endDate]
+    }
+    const result: any = await request.get({ url: api.workDayList, params })
+    return result ?? []
+  },
+
+  // 获取近三个月周日报日志列表
+  getLogList: async (type: 'weekly' | 'daily', date?) => {
+    const nearThreeMonth = service.getNearThreeMonth(date)
+    const requests = [
+      request.get({
+        url: api.logList,
+        params: {
+          reportType: type,
+          reportYear: nearThreeMonth[0].reportYear,
+          reportMonth: nearThreeMonth[0].reportMonth,
+          userId: userInfo.id ?? ''
+        }
+      }),
+      request.get({
+        url: api.logList,
+        params: {
+          reportType: type,
+          reportYear: nearThreeMonth[1].reportYear,
+          reportMonth: nearThreeMonth[1].reportMonth,
+          userId: userInfo.id ?? ''
+        }
+      }),
+      request.get({
+        url: api.logList,
+        params: {
+          reportType: type,
+          reportYear: nearThreeMonth[2].reportYear,
+          reportMonth: nearThreeMonth[2].reportMonth,
+          userId: userInfo.id ?? ''
+        }
+      })
+    ]
+    const result: any = await Promise.all(requests)
+    const allLog = [...(result?.[0] ?? []), ...(result?.[1] ?? []), ...(result?.[2] ?? [])]
+    return allLog
+  },
+
+  // 获取考勤数据
+  getAttendance: async (startDate: string, endDate: string) => {
+    const params = await request.get({
+      url: api.attendance,
+      params: {
+        attendanceDate: [startDate, endDate]
+      }
+    })
+    return params ?? []
+  }
+}
+
+export const service = {
+  // 写一个方法,把人员及部门的列表数据转换为树状数据
+  transformUserListToTree: (arr: any) => {
+    const map: any = {}
+    const roots: any = []
+    // 将数组转换为以id为key的对象
+    arr.forEach((item: any) => {
+      map[item.id] = { ...item, label: item.name, children: [] }
+    })
+    // 将子节点挂载到父节点的children字段下
+    arr.forEach((item: any) => {
+      const node = {
+        id: map[item.id].id,
+        name: map[item.id].name,
+        value: map[item.id].id,
+        children: map[item.id].children ?? []
+      }
+      if (item.pid && map[item.pid]) {
+        map[item.pid].children.push(node)
+      } else if (item.pid) {
+        // console.log(`找不到对应id的父节点,删除数据: ${item.name}`)
+        // delete map[item.id]
+      } else {
+        roots.push(node)
+      }
+    })
+    return roots
+  },
+  // 返回从当前日期计算起的三个月
+  getNearThreeMonth: (date?) => {
+    return [
+      {
+        reportYear: (moment(date) ?? moment()).add(1, 'month').format('YYYY'),
+        reportMonth: (moment(date) ?? moment()).add(1, 'month').format('M')
+      },
+      {
+        reportYear: (moment(date) ?? moment()).format('YYYY'),
+        reportMonth: (moment(date) ?? moment()).format('M')
+      },
+      {
+        reportYear: (moment(date) ?? moment()).subtract(1, 'month').format('YYYY'),
+        reportMonth: (moment(date) ?? moment()).subtract(1, 'month').format('M')
+      }
+    ]
+  },
+  // 返回当前月尾那周周日 到 上上个月初那周的周一前一天的日期
+  getMonthRange: () => {
+    const endTime = moment()
+      .endOf('month')
+      .endOf('week')
+      .add(1, 'day')
+      .format('YYYY-MM-DD HH:mm:ss')
+    const startTime = moment()
+      .subtract(2, 'month')
+      .startOf('month')
+      .startOf('week')
+      .format('YYYY-MM-DD HH:mm:ss')
+    return [startTime, endTime]
+  },
+  // 将工作日数据进行整理,转成按日期划分的对象
+  setWorkDayListToObj: (data: any) => {
+    const obj: any = {}
+    data.forEach((item: any) => {
+      const date = moment(item.dateDay).format('YYYY-MM-DD')
+      obj[date] = item
+    })
+    return obj
+  },
+  // 将工作日数据进行整理,按周划分(传回来的周的划分是错的,但是时间紧迫,所以先这样)
+  setWorkDayListToWeek: (data: any) => {
+    const weekObj: any = {}
+    data.forEach((item: any) => {
+      const { dateDay, dayOfWeek, week, month, year } = item
+      const date = moment(dateDay).format('YYYY-MM-DD')
+      const desc = `这天是${year}-${month}的第${week}周的第${dayOfWeek}天`
+      // week 表示第几周, dayOfWeek 表示本周的第几天
+      const title = `${year}-${month}`
+      if (weekObj[title]) {
+        if (weekObj[title][week]) {
+          weekObj[title][week].push({ ...item, date, desc })
+        } else {
+          weekObj[title][week] = [{ ...item, date, desc }]
+        }
+      } else {
+        weekObj[title] = {
+          [week]: [{ ...item, date, desc }]
+        }
+      }
+    })
+    // console.log("weekObj", weekObj);
+    return weekObj
+  },
+  // 处理数据,将工作周划分和周日报填报情况进行合并
+  mergeWorkDayAndLogs: (workObj: any, logList: any) => {
+    const workList: any = []
+    // 把复杂的对象拆为数组
+    for (const key in workObj) {
+      for (const week in workObj[key]) {
+        const data = workObj[key][week]
+        const logs = logList.filter((item: any) => {
+          const { reportStartDate, reportEndDate } = item
+          const checkData = moment(data[data.length - 1].date)
+          return checkData.isBetween(reportStartDate, reportEndDate, null, '[]')
+        })
+        workList.push({
+          month: key,
+          week,
+          data,
+          startDate: data[0].date,
+          endDate: data[data.length - 1].date,
+          isLog: logs
+        })
+      }
+    }
+    // 再把数组重组为以月划分的对象
+    const monthObj: any = {}
+    workList.map((item: any) => {
+      const { month } = item
+      if (monthObj[month]) {
+        monthObj[month].push(item)
+      } else {
+        monthObj[month] = [item]
+      }
+    })
+    return monthObj
+  }
+}

+ 4 - 12
client/src/views/OaSystem/personnelManagement/weeklyCenter/weeklyCenter.vue

@@ -14,10 +14,10 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import WeekCalendar from './WeekCalendar.vue'
+// import WeekCalendar from './WeekCalendar.vue'
+import WeekCalendar from './weeklyLogList.vue'
 import DetailBox from '../components/DetailBoxWeek.vue'
 import DetailBox from '../components/DetailBoxWeek.vue'
 import EditorDetail from './editorDetail.vue'
 import EditorDetail from './editorDetail.vue'
-// import request from '@/config/axios'
 
 
 defineOptions({ name: 'WeeklyCenter' })
 defineOptions({ name: 'WeeklyCenter' })
 
 
@@ -31,14 +31,6 @@ const onChange = (data) => {
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-// .dailyCenterBox {
-//   width: 100%;
-//   margin-top: 35px;
-//   height: calc(100% - 35px);
-//   background-color: #fff;
-//   border-radius: 20px;
-//   padding: 30px;
-// }
 .oa-sys-list-view {
 .oa-sys-list-view {
   position: relative;
   position: relative;
 
 
@@ -54,11 +46,11 @@ const onChange = (data) => {
     justify-content: space-between;
     justify-content: space-between;
   }
   }
   .calendarBox {
   .calendarBox {
-    width: 50%;
+    width: 500px;
     position: relative;
     position: relative;
   }
   }
   .contentBox {
   .contentBox {
-    width: 50%;
+    flex: 1;
     margin-top: 20px;
     margin-top: 20px;
     height: calc(100% - 250px);
     height: calc(100% - 250px);
   }
   }

+ 237 - 0
client/src/views/OaSystem/personnelManagement/weeklyCenter/weeklyLogList.vue

@@ -0,0 +1,237 @@
+<template>
+  <div class="log-list">
+    <div class="title">
+      <div class="check-btn" @click="checkMonth('prev')">
+        <el-icon><ArrowLeftBold /></el-icon>
+      </div>
+      <div class="show-month">{{ moment(thisMonth).format('YYYY年M月') }}</div>
+      <div class="check-btn" @click="checkMonth('next')">
+        <el-icon><ArrowRightBold /></el-icon>
+      </div>
+    </div>
+    <div class="content">
+      <div
+        v-for="(item, index) in thisMonthLogs"
+        :key="item.week"
+        class="week-item"
+        :style="{ backgroundColor: item.bgColor }"
+        @click="goToWeeklyPage(item)"
+      >
+        <div class="left">
+          <div class="week-title">{{ weekTitleList[index] }}</div>
+          <div class="week-date">{{
+            `${moment(item.startDate).format('M月D日')} ~ ${moment(item.endDate).format('M月D日')}`
+          }}</div>
+        </div>
+        <div class="right">
+          <div class="icon-box" :style="{ backgroundColor: item.color }">
+            <el-icon>
+              <Check v-if="item.icon == 'Check'" />
+              <Close v-if="item.icon == 'Close'" />
+              <EditPen v-if="item.icon == 'EditPen'" />
+              <More v-if="item.icon == 'More'" />
+            </el-icon>
+          </div>
+          <span>{{ item.type }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+/**
+ * @description 首页周报列表
+ * 先获取到最近三个月的工作日列表详情,对工作日进行周数划分
+ * 再获取近三个月的周报列表,对周报填报情况进行判断
+ */
+import moment from 'moment'
+import { service, http } from './service'
+import PubsubService from '@/utils/PubsubService'
+
+interface IProp {
+  onChange: any
+}
+const { onChange } = defineProps<IProp>()
+
+// 所有的周日报和周划分
+// const allWorkDayListAndLogs = ref<any>([])
+// 本月日期
+const thisMonth = ref<any>(moment())
+// 本月的周日报和周划分
+const thisMonthLogs = ref<any>([])
+
+// 获取工作日列表
+onMounted(async () => {
+  await initPageList()
+  // console.log('thisMonthLogs', thisMonthLogs.value, moment().format('YYYY-MM-DD'))
+
+  const nowLog = thisMonthLogs.value.find((item: any) =>
+    moment().isBetween(item.startDate, item.endDate)
+  )
+  goToWeeklyPage(nowLog)
+
+  // 订阅提交(暂存)事件,执行重置事件
+  PubsubService.subscribe('sendWeeklyReportHandle-init', () => {
+    initPageList()
+  })
+})
+
+const message = useMessage()
+// 仅能查看近三个月的
+const checkMonth = (type: 'prev' | 'next') => {
+  if (type == 'next' && moment(thisMonth.value).format('YYYY-MM') == moment().format('YYYY-MM')) {
+    message.info('还未到下个月!')
+    return
+  }
+  if (type == 'prev') {
+    thisMonth.value = moment(thisMonth.value).subtract(1, 'month')
+  } else {
+    thisMonth.value = moment(thisMonth.value).add(1, 'month')
+  }
+  initPageList()
+}
+// 获取最近三个月的工作日列表详情
+const workDayList = async () => {
+  const monthRange = service.getMonthRange()
+  const workDays = await http.getWorkDayList(monthRange[0], monthRange[1])
+  const workDayObj = service.setWorkDayListToWeek(workDays)
+  return workDayObj
+}
+
+// 合并工作日和周报列表并初始化页面
+const initPageList = async () => {
+  const workObj = await workDayList()
+  const logList = await http.getLogList('weekly', thisMonth.value)
+  const allWorkDayListAndLogs = service.mergeWorkDayAndLogs(workObj, logList)
+
+  const pointer = moment(thisMonth.value).format('YYYY-M')
+  thisMonthLogs.value = allWorkDayListAndLogs[pointer].map((item: any) => {
+    // 默认未填
+    item.type = statusObj[1].type
+    item.icon = statusObj[1].icon
+    item.color = statusObj[1].color
+    item.bgColor = statusObj[1].bgColor
+    // 如果本周
+    const startOfWeek = moment().startOf('week')
+    const endOfWeek = moment().endOf('week')
+    if (moment(item.startDate).isBetween(startOfWeek, endOfWeek)) {
+      item.icon = statusObj[2].icon
+      item.color = statusObj[2].color
+      item.bgColor = statusObj[2].bgColor
+      item.type = statusObj[2].type
+    }
+    // 如果已填
+    if (item.isLog.length > 0) {
+      const isLog = item.isLog[0]
+      item.id = isLog.id
+      item.icon = statusObj[0].icon
+      item.color = statusObj[0].color
+      item.bgColor = statusObj[0].bgColor
+      item.type = statusObj[0].type
+    }
+    // 如果未到
+    if (moment(item.startDate).isAfter(moment())) {
+      item.icon = statusObj[3].icon
+      item.color = statusObj[3].color
+      item.bgColor = statusObj[3].bgColor
+      item.type = statusObj[3].type
+    }
+    return item
+  })
+}
+// 颜色列表
+const weekTitleList = ['第一周', '第二周', '第三周', '第四周', '第五周']
+const statusObj = [
+  { type: '已填', icon: 'Check', color: '#0ACE9D', bgColor: '#EAF8F4' },
+  { type: '未填', icon: 'Close', color: '#F85638', bgColor: '#F8EAEA' },
+  { type: '待填', icon: 'EditPen', color: '#1B80EB', bgColor: '#DDEDFD' },
+  { type: '未到', icon: 'More', color: '#BDC7CE', bgColor: '#F2F6FA' }
+]
+// 跳转到周报填写或详情页面
+// const { push } = useRouter()
+const goToWeeklyPage = (item: any) => {
+  // console.log('click item', item)
+  if (item.type == '未到') {
+    message.info('还未到这周!')
+    return
+  }
+  const dayOfWeek = item.data[item.data.length - 1]
+  const changeData: any = {
+    weekDate: [item.startDate, item.endDate],
+    year: dayOfWeek.year,
+    month: dayOfWeek.month,
+    week: dayOfWeek.week,
+    isLog: item.type == '已填' ? item.isLog[0] : false
+  }
+  // console.log('changeData', changeData)
+  onChange(changeData)
+}
+</script>
+<style scoped lang="scss">
+.log-list {
+  padding: 10px 10px;
+  height: calc(100% - 100px);
+  .title {
+    display: flex;
+    .check-btn {
+      font-size: 18px;
+      font-weight: bold;
+      color: #626b70;
+      cursor: pointer;
+    }
+    .show-month {
+      margin: 0 10px;
+      font-weight: bold;
+      font-size: 16px;
+      color: #2d333c;
+    }
+  }
+  .content {
+    margin-top: 20px;
+    height: 100%;
+    overflow-y: scroll;
+
+    .week-item {
+      height: 90px;
+      margin-bottom: 15px;
+      border-radius: 4px 4px 4px 4px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 10px 20px;
+      cursor: pointer;
+      .week-title {
+        font-weight: bold;
+        font-size: 17px;
+        color: #121518;
+      }
+      .week-date {
+        font-weight: 400;
+        font-size: 16px;
+        color: #2b333c;
+        margin-top: 8px;
+      }
+      .right {
+        display: flex;
+        height: 50px;
+        justify-content: space-between;
+        align-items: center;
+        padding-right: 5px;
+      }
+      .icon-box {
+        width: 20px;
+        height: 20px;
+        border-radius: 50%;
+        line-height: 20px;
+        text-align: center;
+        font-size: 12px;
+        margin: 0 10px;
+        color: #fff;
+      }
+    }
+  }
+  ::-webkit-scrollbar {
+    width: 0 !important;
+  }
+}
+</style>

+ 20 - 0
client_h5/src/pages/myLogs/Daily/index.vue

@@ -72,6 +72,10 @@ onMounted(async () => {
   if (query.date) {
   if (query.date) {
     today.value = moment(query.date).format("YYYY-MM-DD");
     today.value = moment(query.date).format("YYYY-MM-DD");
   }
   }
+
+  // 检查一下今天是否已经填了
+  await isFillLog();
+
   // 回填历史接收人
   // 回填历史接收人
   const receiveUser = await http.getReceiveUser();
   const receiveUser = await http.getReceiveUser();
   formData.receiveUserIds = receiveUser;
   formData.receiveUserIds = receiveUser;
@@ -79,6 +83,21 @@ onMounted(async () => {
   await getIsWorkDays();
   await getIsWorkDays();
 });
 });
 
 
+// 判断一下今天是否已经填了,如果是填了的就跳转到详情页
+const isFillLog = async () => {
+  const searchList = await http.getMonthLogList(
+    "daily",
+    moment(today.value).format("YYYY"),
+    moment(today.value).format("M")
+  );
+  const searchLog = searchList.find(
+    (item: any) => item.reportStartDate == today.value
+  );
+  if (searchLog) {
+    push(`/logsDetail?id=${searchLog.id}`);
+  }
+};
+
 // 日历
 // 日历
 const calendarShow = ref(false);
 const calendarShow = ref(false);
 // const onConfirm = async (value: any) => {
 // const onConfirm = async (value: any) => {
@@ -116,6 +135,7 @@ const onSubmit = async () => {
       message: submitCheck.msg,
       message: submitCheck.msg,
       position: "top",
       position: "top",
     });
     });
+    return;
   }
   }
   const result: any = await http.submitReport(params);
   const result: any = await http.submitReport(params);
   if (result.msg == "success") {
   if (result.msg == "success") {

+ 23 - 0
client_h5/src/pages/myLogs/Weekly/index.vue

@@ -84,12 +84,34 @@ onMounted(async () => {
       "YYYY/MM/DD"
       "YYYY/MM/DD"
     )} ~ ${moment(query.endDate).format("YYYY/MM/DD")}`;
     )} ~ ${moment(query.endDate).format("YYYY/MM/DD")}`;
   }
   }
+
+  // 检查一下今天是否已经填了
+  await isFillLog();
+
+  // 回填历史接收人
   const receiveUser = await http.getReceiveUser();
   const receiveUser = await http.getReceiveUser();
   formData.receiveUserIds = receiveUser;
   formData.receiveUserIds = receiveUser;
   // 获取当日详情
   // 获取当日详情
   await getIsWorkDays();
   await getIsWorkDays();
 });
 });
 
 
+// 判断一下本周是否已经填了,如果是填了的就跳转到详情页
+const isFillLog = async () => {
+  const date = thisWeek.value.split(" ~ ");
+  const searchList = await http.getMonthLogList(
+    "weekly",
+    moment(date[1]).format("YYYY"),
+    moment(date[1]).format("M")
+  );
+  const searchLog = searchList.find(
+    (item: any) => item.reportEndDate == moment(date[1]).format("YYYY-MM-DD")
+  );
+
+  if (searchLog) {
+    push(`/logsDetail?id=${searchLog.id}`);
+  }
+};
+
 // 日历
 // 日历
 const calendarShow = ref(false);
 const calendarShow = ref(false);
 // const onConfirm = async (values: any) => {
 // const onConfirm = async (values: any) => {
@@ -131,6 +153,7 @@ const onSubmit = async () => {
       message: submitCheck.msg,
       message: submitCheck.msg,
       position: "top",
       position: "top",
     });
     });
+    return;
   }
   }
   const result: any = await http.submitReport(params);
   const result: any = await http.submitReport(params);
   if (result.msg == "success") {
   if (result.msg == "success") {

+ 17 - 0
client_h5/src/pages/myLogs/http.ts

@@ -114,4 +114,21 @@ export const http = {
     ];
     ];
     return allLog;
     return allLog;
   },
   },
+  // 获取当月日志列表
+  getMonthLogList: async (
+    type: "weekly" | "daily",
+    year: string,
+    month: string
+  ) => {
+    const params = {
+      reportType: type,
+      reportYear: year,
+      reportMonth: month,
+      userId: userInfo.id ?? "",
+    };
+    const result: any = await request.get(api.logList, {
+      params,
+    });
+    return result.msg == "success" ? result.data : [];
+  },
 };
 };

+ 1 - 1
client_h5/src/pages/myLogs/service.ts

@@ -101,7 +101,7 @@ export const setWorkDayListToObj = (data: any) => {
   });
   });
   return obj;
   return obj;
 };
 };
-// 将工作日数据进行整理,按周划分(传回来的周的划分是错的,但是时间紧迫,所以先这样)
+// 将工作日数据进行整理,按周划分
 export const setWorkDayListToWeek = (data: any) => {
 export const setWorkDayListToWeek = (data: any) => {
   const weekObj: any = {};
   const weekObj: any = {};
   data.forEach((item: any) => {
   data.forEach((item: any) => {