Parcourir la source

feat: 周日报功能基本完成

qiny il y a 1 an
Parent
commit
5ace4e1103

+ 5 - 3
client/src/components/UserSelect/index.vue

@@ -9,16 +9,18 @@ interface ISelect {
   construction?: 'simple' | 'tree' // 简单 | 树形 默认简单
   multiple?: boolean // 是否多选 默认false
   onChange?: (any) => any
+  defaultValue?: any[]
 }
 const {
   type = 'user',
   construction = 'simple',
   multiple = false,
-  onChange
+  onChange,
+  defaultValue = []
 } = defineProps<ISelect>()
 
 const selectUser = ref(null) // 选中用户(单选)
-const selectUserList = ref([]) // 选中的用户列表
+const selectUserList = ref(defaultValue) // 选中的用户列表
 const treeUserList = ref<any[]>()
 const simpleUserList = ref<any[]>()
 const getUserList = async () => {
@@ -112,7 +114,7 @@ const checkOnChange = (data) => {
       show-checkbox
       :check-strictly="false"
       filterable
-      multiple
+      :multiple="multiple"
       @check-change="checkOnChange"
     />
   </div>

+ 128 - 59
client/src/views/OaSystem/personnelManagement/dailyCenter/AmountOfWork.vue

@@ -9,17 +9,17 @@
           {{ '工作项目' + (defaultTotalTime ? `(总耗时${defaultTotalTime}小时)` : '') }}
         </div>
         <div class="right">
-          <!-- <el-input placeholder="搜索项目" /> -->
+          <el-input
+            ref="searchInputRef"
+            placeholder="搜索项目"
+            v-model="searchValue"
+            @input="searchOnchange"
+            clearable
+          />
         </div>
       </div>
       <ul class="list-ul">
         <li v-for="(item, index) in dataList" :key="index" @click="handleClick(item)">
-          <div class="project-name">
-            <!-- <span>{{
-              popperInfoList[index].count ? `(${popperInfoList[index].count}小时)` : ''
-            }}</span>
-            {{ item['name'] }} -->
-          </div>
           <div class="project-write">
             <el-popover
               ref="popperRef"
@@ -27,13 +27,11 @@
               placement="top-end"
               :width="400"
               trigger="click"
-              :visible="popperInfoList[index].visible"
+              :visible="item.visible"
             >
               <template #reference>
-                <div class="time-select" @click="popperInfoList[index].visible = true">
-                  <span>{{
-                    popperInfoList[index].count ? `(${popperInfoList[index].count}小时)` : ''
-                  }}</span>
+                <div class="time-select" @click="item.visible = true">
+                  <span>{{ item.count ? `(${item.count}小时)` : '' }}</span>
                   {{ item['name'] }}
                 </div>
               </template>
@@ -43,7 +41,7 @@
                   <div class="panel-input-number">
                     输入时间:
                     <el-input-number
-                      v-model="popperInfoList[index].count"
+                      v-model="item.count"
                       class="input-number"
                       :min="0"
                       :max="80"
@@ -54,15 +52,15 @@
                   <div class="panel-numeric-key">
                     <ul>
                       <li
-                        v-for="(item, i) in 40"
+                        v-for="(num, i) in 40"
                         :style="{
-                          background: i + 1 === popperInfoList[index].count ? '#1b80eb' : '#f7f8fa',
-                          color: i + 1 === popperInfoList[index].count ? '#fff' : '#2d333c'
+                          background: i + 1 === item.count ? '#1b80eb' : '#f7f8fa',
+                          color: i + 1 === item.count ? '#fff' : '#2d333c'
                         }"
                         :key="i"
-                        @click="changeCount(item, index)"
+                        @click="changeCount(num, index)"
                       >
-                        <span>{{ item }}</span>
+                        <span>{{ num }}</span>
                       </li>
                     </ul>
                   </div>
@@ -82,6 +80,7 @@
 </template>
 
 <script setup lang="ts">
+/** 周日报相同文件 */
 import request from '@/config/axios'
 import { getUserInfo } from '@/utils/tool'
 // 获取用户信息
@@ -91,19 +90,55 @@ defineOptions({ name: 'WorkHoursSelect' })
 
 interface IProp {
   onChange: (any) => any
+  initialData?: any[] // 初始数据
+  nowDate: string
 }
-const { onChange } = defineProps<IProp>()
-
+const props = defineProps<IProp>()
+const { onChange } = props
+const { initialData, nowDate } = toRefs(props)
 // 默认工作项目总时长
 const defaultTotalTime = ref(0)
 // 工时填写弹框的ref
 const popperRef = ref<any>(null)
-const popperInfoList = ref<any>([])
 // 初始化数据
 const dataList = ref<any[]>([])
-// for (let i = 0; i < 10; i++) {}
+
+const setInitData = () => {
+  if (initialData.value && initialData.value.length > 0) {
+    const initialObj = {}
+    initialData.value.forEach((item) => {
+      initialObj[item.projectId] = item.workTime
+    })
+    const timer = setTimeout(() => {
+      dataList.value = dataList.value.map((item) => {
+        let count = 0
+        if (initialObj[item.id]) {
+          count = initialObj[item.id]
+        }
+        return {
+          ...item,
+          count
+        }
+      })
+      dataList.value.sort((x, y) => y['count'] - x['count'])
+      clearTimeout(timer)
+    }, 0)
+  } else {
+    getAllProject()
+  }
+  getTotalTime()
+}
+
+watch(
+  () => nowDate.value,
+  () => {
+    setInitData()
+  }
+)
+
 onMounted(() => {
   getAllProject()
+  setInitData()
 })
 // 获取任务列表
 const getAllProject = async () => {
@@ -118,17 +153,13 @@ const getAllProject = async () => {
     '/business'
   )
   dataList.value = records.map((item) => {
-    popperInfoList.value.push({
+    return {
       visible: false,
       count: 0,
-      id: item.id
-    })
-    return {
       name: item.xmmc,
       id: item.id
     }
   })
-  // console.log('result', records)
 }
 
 // 临时存储数量
@@ -137,47 +168,92 @@ const tempCount = ref(0)
 // 工时数量
 const changeCount = (val, index) => {
   // 获取临时数量
-  tempCount.value = popperInfoList.value[index].count
-  popperInfoList.value[index].count = val
+  tempCount.value = dataList.value[index].count
+  dataList.value[index].count = val
 }
 
-// 提交工时
-const panelSubmit = (index: number) => {
-  popperInfoList.value[index].visible = false
-  defaultTotalTime.value = popperInfoList.value.reduce((total, item) => {
+// 计算总工时
+const getTotalTime = () => {
+  defaultTotalTime.value = dataList.value.reduce((total, item) => {
     return total + item.count
   }, 0)
+}
+
+// 提交工时
+const panelSubmit = (index: number) => {
+  dataList.value[index].visible = false
+  getTotalTime()
   tempCount.value = 0
   // 提交后进行一下数据排序
-  popperInfoList.value.sort((x, y) => y['count'] - x['count'])
-  dataList.value.sort((a, b) => {
-    const idA = a.id
-    const idB = b.id
-    // 在 popperInfoList 中找到对应的对象,并获取其索引
-    const indexA = popperInfoList.value.findIndex((item) => item.id === idA)
-    const indexB = popperInfoList.value.findIndex((item) => item.id === idB)
-    // 根据 popperInfoList 的顺序对 dataList 进行排序
-    return indexA - indexB
-  })
+  dataList.value.sort((x, y) => y['count'] - x['count'])
+
   // 提交工时后将已填数据传出去
-  const countList = popperInfoList.value
+  const countList = dataList.value
     .filter((item) => item.count > 0)
     .map((item) => ({
       workTime: item.count,
       projectId: item.id
     }))
   onChange(countList)
+
+  // 提交工时后清空搜索框
+  if (tempSearchList.value.length > 0) {
+    searchInputRef.value?.clear()
+  }
 }
 
 // 取消选择
 const panelCancel = (index: number) => {
-  popperInfoList.value[index] = {
+  dataList.value[index] = {
+    ...dataList.value[index],
     visible: false,
     count: tempCount.value
   }
-  defaultTotalTime.value = popperInfoList.value.reduce((total, item) => {
-    return total + item.count
-  }, 0)
+  getTotalTime()
+}
+
+// 搜索内容的临时存储
+const searchInputRef = ref<any>(null)
+const tempSearchList = ref<any[]>([])
+const searchValue = ref('')
+// 搜索内容改变时触发
+const searchOnchange = (val: string) => {
+  // 搜索框第一次搜索时触发
+  if (tempSearchList.value.length < dataList.value.length) {
+    tempSearchList.value = dataList.value
+  }
+  // 搜索内容为空时,清空搜索列表,并显示全部数据
+  if (val.length == 0) {
+    clearSearch()
+    return
+  }
+  // 使用 filter() 方法进行模糊查询
+  const filteredArray = tempSearchList.value.filter((item) => {
+    // 创建正则表达式,忽略大小写,并且匹配关键词
+    const regex = new RegExp(val, 'i')
+    // 使用正则表达式测试数组中的每个元素
+    return regex.test(item.name)
+  })
+  dataList.value = filteredArray
+}
+// 清除内容时触发
+const clearSearch = () => {
+  const countObj = {}
+  dataList.value.forEach((item) => {
+    countObj[item.id] = item.count
+  })
+  tempSearchList.value.forEach((item) => {
+    if (countObj[item.id]) {
+      // 如果有值,则赋值
+      item.count = countObj[item.id]
+    }
+  })
+  // 顺便进行一下数据排序
+  tempSearchList.value.sort((x, y) => y['count'] - x['count'])
+  // 还原全部数据
+  dataList.value = tempSearchList.value
+  tempSearchList.value = []
+  getTotalTime()
 }
 
 interface IProject {
@@ -220,7 +296,7 @@ const handleClick = (val: IProject): void => {
     height: 100%;
     border: 1px solid #dee0e3;
     .title {
-      padding: 8px 24px;
+      padding: 8px 20px;
       background-color: #f7f8fa;
       color: #121518;
       display: flex;
@@ -229,7 +305,7 @@ const handleClick = (val: IProject): void => {
     }
     .list-ul {
       width: 100%;
-      height: calc(100% - 45px);
+      height: calc(100% - 50px);
       overflow-y: scroll;
       text-align: center;
       background-color: #fff;
@@ -237,20 +313,13 @@ const handleClick = (val: IProject): void => {
       li {
         text-align: left;
         color: #2d333c;
-        padding: 10px 15px;
+        padding: 6px 10px;
         cursor: pointer;
-        display: flex;
         justify-content: space-between;
         &:hover {
           background-color: #d3e5ff;
         }
-        .project-name {
-          // flex: 0;
-          // span {
-          //   color: #1b80eb;
-          // }
-          width: 0;
-        }
+
         .project-write {
           width: 100%;
           padding-left: 10px;

+ 0 - 334
client/src/views/OaSystem/personnelManagement/dailyCenter/OaCalendar copy.vue

@@ -1,334 +0,0 @@
-<template>
-  <div class="OaCalendar">
-    <div class="selectBox">
-      <el-icon class="icon1" @click="lastClick"><ArrowLeftBold /></el-icon>
-      <p>{{ moment(nowTime).format('YYYY年MM月') }}</p>
-      <el-icon class="icon1" @click="nextClick"><ArrowRightBold /></el-icon>
-    </div>
-    <div class="contentBox">
-      <div class="ulBox">
-        <ul>
-          <li
-            v-for="(item, index) in dailyReportAttendances"
-            :key="index"
-            :style="{ width: `calc(100% / ${dailyReportAttendances.length})` }"
-          >
-            <div
-              :class="[
-                item.isworkday === 0 ? 'topBoxPa' : 'topBox',
-                moment().format('YYYY-MM-DD') == item['date'] ? 'isToday' : ''
-              ]"
-            >
-              <p>{{ item.day }}</p>
-            </div>
-            <div class="bomBox" @click="$emit('click', item)" :class="`imgHover_${item['state']}`">
-              <template v-if="item['isworkday'] === 1">
-                <img v-if="_iconMap[item['state']]" :src="_iconMap[item['state']]" />
-                <span v-else class="leave" :title="item['state']">假</span>
-              </template>
-            </div>
-          </li>
-        </ul>
-      </div>
-      <div class="infoBox">
-        <span>已填写(天)</span>
-        <p>{{ dailyReportCount }}</p>
-      </div>
-    </div>
-  </div>
-</template>
-<script setup lang="ts">
-import request from '@/config/axios'
-import moment from 'moment'
-import { getAssetURL } from '@/utils/auth'
-
-interface ItemState {
-  id: string // 日报ID
-  date: string //日期
-  year: string //年份
-  month: string //月份
-  day: string //日期
-  isworkday: number //是否工作日
-  state: string //leaveMap
-}
-const leaveMap = {
-  11: '事假',
-  12: '病假',
-  13: '婚假',
-  14: '产假',
-  15: '陪产假',
-  19: '丧假',
-  16: '工伤',
-  17: '年假',
-  18: '调休'
-}
-const $emit = defineEmits<{
-  (e: 'click', v: object): void
-}>()
-const dailyReportAttendances = ref<ItemState[]>([])
-const nowTime: any = ref(moment().format('YYYY-MM'))
-const dailyReportCount = ref<number>(0)
-
-// const dictMap: any = getDictOptions(DICT_TYPE.ADM_ATTENDANCE_STATUS)
-const _iconMap: Object = {
-  '99': getAssetURL('kq/1'), //99 正常
-  '-1': getAssetURL('kq/2') //-1 未填
-}
-const getWorkDayList = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
-  const urlApi = `/adm/workday/list`
-  const params = {
-    dateDay: [
-      nowTimeObj.startOf('months').format('YYYY-MM-DD HH:mm:ss'),
-      nowTimeObj.endOf('months').format('YYYY-MM-DD HH:mm:ss')
-    ]
-  }
-  return await request.get({ url: urlApi, params })
-}
-const getDailyReportList = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
-  const urlApi = `/adm/report/query-month`
-  const params = {
-    reportYear: nowTimeObj.format('YYYY'),
-    reportMonth: nowTimeObj.format('MM')
-  }
-  return await request.get({ url: urlApi, params })
-}
-const getAttendanceSheetListMine = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
-  const urlApi = `/adm/attendance-sheet/list-me`
-  const params = {
-    attendanceTime: [
-      nowTimeObj.startOf('months').format('YYYY-MM-DD HH:mm:ss'),
-      nowTimeObj.endOf('months').format('YYYY-MM-DD HH:mm:ss')
-    ]
-  }
-  return await request.get({ url: urlApi, params })
-}
-
-const initDailyReportData = async (): Promise<any> => {
-  //日报统计
-  const dailyReports: [] = await getDailyReportList()
-  const dailyReportMap: Map<string, Map<string, string>> = new Map()
-  dailyReports.forEach((item) => {
-    dailyReportMap[moment(item['fillingDate']).format('YYYY-MM-DD')] = {
-      id: item['id'],
-      statu: '99'
-    }
-  })
-  dailyReportCount.value = dailyReports.length
-  //考勤统计
-  const attendances: [] = await getAttendanceSheetListMine()
-  const attendanceState: Map<string, string> = new Map()
-  attendances.forEach((item) => {
-    if (leaveMap[item['attendanceStatus']]) {
-      attendanceState[moment(item['attendanceTime']).format('YYYY-MM-DD')] =
-        item['attendanceStatus']
-    }
-  })
-  //节假日统计
-  const workdays: [] = await getWorkDayList()
-  const dailyReportList: ItemState[] = []
-  workdays.forEach((item) => {
-    const date = moment(item['dateDay']).format('YYYY-MM-DD')
-    const _dailyReportMap = dailyReportList[date]
-    const _attendanceState = attendanceState[date]
-    if (_dailyReportMap) {
-      dailyReportList.push({
-        id: _dailyReportMap['id'],
-        date: moment(item['dateDay']).format('YYYY-MM-DD'),
-        year: moment(item['dateDay']).format('YYYY'),
-        month: moment(item['dateDay']).format('MM'),
-        day: moment(item['dateDay']).format('DD'),
-        isworkday: item['isworkday'],
-        state: _dailyReportMap['statu']
-      })
-    } else if (_attendanceState) {
-      dailyReportList.push({
-        id: '',
-        date: moment(item['dateDay']).format('YYYY-MM-DD'),
-        year: moment(item['dateDay']).format('YYYY'),
-        month: moment(item['dateDay']).format('MM'),
-        day: moment(item['dateDay']).format('DD'),
-        isworkday: item['isworkday'],
-        state: _attendanceState
-      })
-    } else {
-      dailyReportList.push({
-        id: '',
-        date: moment(item['dateDay']).format('YYYY-MM-DD'),
-        year: moment(item['dateDay']).format('YYYY'),
-        month: moment(item['dateDay']).format('MM'),
-        day: moment(item['dateDay']).format('DD'),
-        isworkday: item['isworkday'],
-        state: item['isworkday'] === 0 ? '' : '-1'
-      })
-    }
-  })
-  dailyReportAttendances.value = dailyReportList
-  console.log(dailyReportAttendances.value)
-}
-const lastClick: () => void = (): void => {
-  let time: any = moment(nowTime.value).subtract(1, 'months').format('YYYY-MM')
-  nowTime.value = moment(time).format('YYYY-MM')
-  initDailyReportData()
-}
-const nextClick: () => void = (): void => {
-  let time: any = moment(nowTime.value).add(1, 'months').format('YYYY-MM')
-  nowTime.value = moment(time).format('YYYY-MM')
-  initDailyReportData()
-}
-initDailyReportData()
-</script>
-<style lang="scss" scoped>
-.OaCalendar {
-  width: 100%;
-  .selectBox {
-    display: flex;
-    align-items: center;
-    margin-bottom: 10px;
-    .icon1 {
-      cursor: pointer;
-    }
-    p {
-      font-weight: 600;
-      color: #2d333c;
-      margin: 0 10px;
-      user-select: none;
-      cursor: pointer;
-    }
-  }
-  .contentBox {
-    width: 100%;
-    height: 80px;
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    border: 1px solid #dee0e3;
-
-    .ulBox {
-      width: calc(100% - 120px);
-      height: 100%;
-      ul {
-        width: 100%;
-        height: 100%;
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-      }
-      li {
-        height: 100%;
-        > div {
-          &:first-child {
-            width: 100%;
-            height: 50%;
-            border: 1px solid #dee0e3;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            border-right: 0;
-            border-top: 0;
-            background-color: #f7f8fa;
-            &.isToday {
-              background-color: #2e77e6;
-              > p {
-                color: #fff;
-              }
-            }
-          }
-        }
-        .topBox {
-          p {
-            color: #121518;
-            user-select: none;
-          }
-        }
-        .topBoxPa {
-          p {
-            color: #b9c3c9;
-          }
-        }
-        .topBox:hover {
-          p {
-            color: #1b80eb;
-          }
-        }
-
-        .bomBox {
-          width: 100%;
-          height: 50%;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          &.imgHover_-1,
-          &.imgHover_99 {
-            cursor: pointer;
-          }
-          &.imgHover_-1:hover {
-            position: relative;
-            &::after {
-              position: absolute;
-              display: block;
-              content: '补';
-              width: 100%;
-              height: 100%;
-              background-color: #fff;
-              top: 0px;
-              left: 0px;
-              line-height: 40px;
-              text-align: center;
-              color: #999;
-            }
-          }
-          &.imgHover {
-            &:hover {
-              border: 1px solid #f00;
-            }
-          }
-          img {
-            user-select: none;
-          }
-          > span {
-            cursor: pointer;
-            &.leave {
-              color: #f00;
-              cursor: default;
-            }
-          }
-        }
-      }
-      li:first-child {
-        .topBox {
-          border-left: 0;
-        }
-      }
-      li:last-child {
-        .topBox {
-          border-right: 0;
-        }
-      }
-    }
-    .infoBox {
-      width: 120px;
-      height: 100%;
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-      flex-wrap: wrap;
-      background-color: #edf0f4;
-      border-left: 1px solid #dee0e3;
-      span {
-        display: block;
-        width: 100%;
-        text-align: center;
-        font-size: 14px;
-      }
-      p {
-        width: 100%;
-        text-align: center;
-        font-size: 18px;
-      }
-    }
-  }
-}
-</style>

+ 84 - 33
client/src/views/OaSystem/personnelManagement/dailyCenter/OaCalendar.vue

@@ -10,9 +10,14 @@
       </template>
       <template #date-cell="{ data }">
         <!-- 仅工作日显示角标 -->
-        <div :class="`day-cell ${getDayClass(data.day)}`" v-if="data.type === 'current-month'">
+        <div
+          :class="`day-cell ${getDayClass(data.day)}`"
+          v-if="data.type === 'current-month'"
+          @mouseover="onMouseOver(data)"
+          @mouseout="onMouseOut(data)"
+        >
           <p :class="data.isSelected ? 'is-selected' : ''">
-            {{ data.day.split('-')[2] }}
+            {{ dayReportMap[data.day]?.show }}
           </p>
         </div>
 
@@ -34,6 +39,12 @@
 <script setup lang="ts">
 import request from '@/config/axios'
 import moment from 'moment'
+import { getUserInfo } from '@/utils/tool'
+
+const message = useMessage()
+
+// 获取用户信息
+const userInfo = getUserInfo()
 
 const $emit = defineEmits<{
   (e: 'click', v: string | object): void
@@ -43,12 +54,33 @@ const calendar = ref()
 const todayValue = ref(new Date())
 
 watch(todayValue, () => {
-  $emit('click', dayReportMap.value[moment(todayValue.value).format('YYYY-MM-DD')])
+  // console.log(
+  //   'dayReportMap.value',
+  //   moment(todayValue.value).format('YYYY-MM-DD'),
+  //   dayReportMap.value
+  // )
+  // 如果选中的是今天之后的日期,则不进行点击及跳转
+  const isAfterToday = moment(todayValue.value).isAfter(moment())
+  if (isAfterToday) {
+    todayValue.value = new Date()
+    message.info('仅可对今日及之前的日志进行填报!')
+  } else {
+    $emit('click', dayReportMap.value[moment(todayValue.value).format('YYYY-MM-DD')])
+  }
 })
 
 const selectDate = (val) => {
   if (!calendar.value) return
   calendar.value.selectDate(val)
+  if (val === 'prev-month') {
+    nowMonths.value = moment(nowMonths.value).subtract(1, 'months').format('YYYY-MM')
+  } else if (val === 'next-month') {
+    nowMonths.value = moment(nowMonths.value).add(1, 'months').format('YYYY-MM')
+  }
+  const timer = setTimeout(() => {
+    initDailyReportData()
+    clearTimeout(timer)
+  }, 128)
 }
 
 onMounted(() => {
@@ -56,7 +88,7 @@ onMounted(() => {
   const timer = setTimeout(() => {
     $emit('click', dayReportMap.value[moment(todayValue.value).format('YYYY-MM-DD')])
     clearTimeout(timer)
-  }, 200)
+  }, 128)
 })
 
 interface ItemState {
@@ -90,12 +122,11 @@ const leaveMap = {
 }
 
 const dailyReportAttendances = ref<ItemState[]>([])
-const nowTime: any = ref(moment().format('YYYY-MM'))
-const dailyReportCount = ref<number>(0)
+const nowMonths: any = ref(moment().format('YYYY-MM'))
 
 // const dictMap: any = getDictOptions(DICT_TYPE.ADM_ATTENDANCE_STATUS)
 const getWorkDayList = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
+  const nowTimeObj = moment(nowMonths.value)
   const urlApi = `/adm/workday/list`
   const params = {
     dateDay: [
@@ -105,17 +136,9 @@ const getWorkDayList = async (): Promise<any> => {
   }
   return await request.get({ url: urlApi, params })
 }
-const getDailyReportList = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
-  const urlApi = `/adm/report/query-month`
-  const params = {
-    reportYear: nowTimeObj.format('YYYY'),
-    reportMonth: nowTimeObj.format('MM')
-  }
-  return await request.get({ url: urlApi, params })
-}
+
 const getAttendanceSheetListMine = async (): Promise<any> => {
-  const nowTimeObj = moment(nowTime.value)
+  const nowTimeObj = moment(nowMonths.value)
   const urlApi = `/adm/attendance-sheet/list-me`
   const params = {
     attendanceTime: [
@@ -126,18 +149,27 @@ const getAttendanceSheetListMine = async (): Promise<any> => {
   return await request.get({ url: urlApi, params })
 }
 
+// 日报统计
+const getLogList = async (): Promise<any> => {
+  const nowTimeObj = moment(nowMonths.value)
+  const urlApi = `/adm/report/list`
+  const params = {
+    reportType: 'daily',
+    reportYear: nowTimeObj.format('YYYY'),
+    reportMonth: Number(nowTimeObj.format('MM')),
+    userId: userInfo.id ?? ''
+  }
+  return await request.get({ url: urlApi, params })
+}
+
 const dayReportMap: any = ref({})
 const initDailyReportData = async (): Promise<any> => {
-  //日报统计
-  const dailyReports: [] = await getDailyReportList()
-  const dailyReportMap: Map<string, Map<string, string>> = new Map()
-  dailyReports.forEach((item) => {
-    dailyReportMap[moment(item['fillingDate']).format('YYYY-MM-DD')] = {
-      id: item['id'],
-      statu: '99'
-    }
+  // 获取已填写的日志
+  const logList = await getLogList()
+  const logObj = {}
+  logList?.forEach((item) => {
+    logObj[moment(item.reportStartDate).format('YYYY-MM-DD')] = item
   })
-  dailyReportCount.value = dailyReports.length
   //考勤统计
   const attendances: [] = await getAttendanceSheetListMine()
   const attendanceState: Map<string, string> = new Map()
@@ -148,13 +180,13 @@ const initDailyReportData = async (): Promise<any> => {
     }
   })
   //节假日统计
-  const workdays: [] = await getWorkDayList()
-  const dailyReportList: ItemState[] = []
+  const workdays: any[] = await getWorkDayList()
+  const dailyReportList: any[] = []
   workdays.forEach((item) => {
     const date = moment(item['dateDay']).format('YYYY-MM-DD')
     const _dailyReportMap = dailyReportList[date]
     const _attendanceState = attendanceState[date]
-
+    const isLog = logObj[date] ?? false
     if (_dailyReportMap) {
       dailyReportList.push({
         id: _dailyReportMap['id'],
@@ -164,7 +196,9 @@ const initDailyReportData = async (): Promise<any> => {
         week: item['week'],
         dayOfWeek: item['dayOfWeek'],
         isworkday: item['isworkday'],
-        state: _dailyReportMap['state']
+        state: _dailyReportMap['state'],
+        isLog,
+        holidayRemark: item['holidayRemark']
       })
     } else if (_attendanceState) {
       dailyReportList.push({
@@ -175,7 +209,9 @@ const initDailyReportData = async (): Promise<any> => {
         week: item['week'],
         dayOfWeek: item['dayOfWeek'],
         isworkday: item['isworkday'],
-        state: _attendanceState
+        state: _attendanceState,
+        isLog,
+        holidayRemark: item['holidayRemark']
       })
     } else {
       dailyReportList.push({
@@ -186,13 +222,15 @@ const initDailyReportData = async (): Promise<any> => {
         week: item['week'],
         dayOfWeek: item['dayOfWeek'],
         isworkday: item['isworkday'],
-        state: item['isworkday'] === 0 ? '' : '-1'
+        state: item['isworkday'] === 0 ? '' : '-1',
+        isLog,
+        holidayRemark: item['holidayRemark']
       })
     }
   })
   dailyReportAttendances.value = dailyReportList
   dailyReportList.forEach((item) => {
-    dayReportMap.value[item.date] = item
+    dayReportMap.value[item.date] = { ...item, show: item.date.split('-')[2] }
   })
 }
 
@@ -220,6 +258,19 @@ const getDayClass = (data) => {
   }
   return ''
 }
+
+// 鼠标移入移出事件
+const onMouseOver = (data) => {
+  const isLog = dayReportMap.value[data.day]?.isLog ? true : false
+  if (isLog) {
+    dayReportMap.value[data.day].show = '已填'
+  } else {
+    dayReportMap.value[data.day].show = dayReportMap.value[data.day]?.holidayRemark ?? '未填'
+  }
+}
+const onMouseOut = (data) => {
+  dayReportMap.value[data.day].show = data.day.split('-')[2]
+}
 </script>
 <style lang="scss" scoped>
 .OaCalendar {

+ 0 - 14
client/src/views/OaSystem/personnelManagement/dailyCenter/dailyCenter.vue

@@ -34,20 +34,6 @@ const dateOnChange = (date) => {
   // console.log('dateOnChange', date)
   writeData.value = date
 }
-
-// const state = ref<string>('-1') //-1 未填 99 已填
-// const clickHandle = async (item: ItemState) => {
-//   console.log(item)
-//   if (['-1', '99'].indexOf(item['state']) === -1) return
-//   state.value = item['state']
-//   const urlApi = `/adm/report/query-detail`
-//   const params = {
-//     reportId: ''
-//   }
-//   const result = await request.get({ url: urlApi, params })
-//   console.log('result~~~~~~~~~~~~~~~~~~~~')
-//   console.log(result)
-// }
 </script>
 
 <style lang="scss" scoped>

+ 45 - 20
client/src/views/OaSystem/personnelManagement/dailyCenter/editorDetail.vue

@@ -6,13 +6,18 @@
           <el-col :span="8">
             <el-form-item class="label-item" label="日志日期">
               <div class="write-date">
-                {{ writeData?.date ?? moment().format('YYYY-MM-DD') }}
+                {{ props.writeData?.date ?? moment().format('YYYY-MM-DD') }}
               </div>
             </el-form-item>
           </el-col>
           <el-col :span="16">
             <el-form-item class="label-item" label="接收人" required>
-              <UserSelect construction="tree" :multiple="true" :onChange="getReceiveUserIds" />
+              <UserSelect
+                construction="tree"
+                :multiple="true"
+                :onChange="getReceiveUserIds"
+                :defaultValue="formData.receiveUserIds"
+              />
             </el-form-item>
           </el-col>
         </el-row>
@@ -33,8 +38,15 @@
         </el-row>
       </el-form>
     </div>
-    <AmountOfWork :onChange="getWorkTimeList" />
-    <div class="footBox">
+    <AmountOfWork
+      :onChange="getWorkTimeList"
+      :initialData="formData.weeklyWorkloadList"
+      :nowDate="props.writeData?.date"
+    />
+    <div class="footBox" v-if="isUpDate">
+      <el-button type="primary" @click="sendReportHandle(false)">更新</el-button>
+    </div>
+    <div class="footBox" v-else>
       <el-button type="primary" @click="sendReportHandle(true)">暂存</el-button>
       <el-button type="primary" @click="sendReportHandle(false)">发送</el-button>
     </div>
@@ -52,18 +64,31 @@ defineOptions({ name: 'EditorDetail' })
 interface IProp {
   writeData: any
 }
-const { writeData } = defineProps<IProp>()
-// const logDate = ref(writeDate)
+const props = defineProps<IProp>()
+const { writeData } = toRefs(props)
+
+const isUpDate = ref(false) // 是否是更新日志
+
 watch(
-  () => writeData.date,
+  () => writeData.value?.date,
   () => {
     initLog()
   }
 )
 
-// console.log('writeData', writeData)
 const initLog = () => {
-  // console.log('initLog')
+  if (writeData.value?.isLog) {
+    const { reportContent, workload, receiveIds } = writeData.value.isLog
+    formData.value.reportContent = reportContent
+    formData.value.weeklyWorkloadList = workload
+    formData.value.receiveUserIds = receiveIds
+    isUpDate.value = true
+  } else {
+    formData.value.reportContent = ''
+    formData.value.weeklyWorkloadList = []
+    formData.value.receiveUserIds = []
+    isUpDate.value = false
+  }
 }
 
 const formData = ref<{
@@ -72,7 +97,7 @@ const formData = ref<{
   reportContent: string
   weeklyWorkloadList: any[]
 }>({
-  fillingDate: writeData.date,
+  fillingDate: writeData.value.date,
   receiveUserIds: [],
   reportContent: '',
   weeklyWorkloadList: []
@@ -80,19 +105,16 @@ const formData = ref<{
 
 // 接收人数据改变时触发
 const getReceiveUserIds = (list) => {
-  // console.log('接收人', list)
   formData.value.receiveUserIds = list
 }
 
 // 工作内容改变时触发
 const getReportContent = (val) => {
-  // console.log('工作内容', val)
   formData.value.reportContent = val
 }
 
 // 工作量分配改变时触发
 const getWorkTimeList = (val) => {
-  // console.log('工作量分配', val)
   formData.value.weeklyWorkloadList = val
 }
 
@@ -113,23 +135,26 @@ const sendReportHandle = async (isTemp) => {
   const params = {
     userId: userInfo.id ?? '',
     deptId: userInfo.deptId ?? '',
-    reportStartDate: moment(writeData.date).valueOf(),
-    reportEndDate: moment(writeData.date).valueOf(),
+    reportStartDate: moment(writeData.value.date).valueOf(),
+    reportEndDate: moment(writeData.value.date).valueOf(),
     receiveUserIds: formData.value.receiveUserIds,
+    // receiveUserIds: ['ea81aaf2-74fe-429f-acaa-25a9a898abcf'],
     reportType: 'daily',
     reportContent: formData.value.reportContent,
     isTemp,
     weeklyWorkloadList: formData.value.weeklyWorkloadList,
-    reportYear: writeData.year, // 报告年份
-    reportMonth: writeData.month, // 月份
-    reportWeek: writeData.week, // 周
-    reportDay: writeData.dayOfWeek // 天
+    reportYear: writeData.value.year, // 报告年份
+    reportMonth: writeData.value.month, // 月份
+    reportWeek: writeData.value.week, // 周
+    reportDay: writeData.value.dayOfWeek // 天
   }
-  // console.log('提交(暂存)~~~~~~~~~~~~~~~~~~~', params)
+  // console.log('提交(暂存)~~~~~~~~~~~~~~~~~~~', params, writeData.value.date)
+  // return
   const result = await request.postOriginal({ url: '/adm/report/add-report-info', data: params })
   // console.log('提交(暂存)~~~~~~~result~~~~~~', result)
   if (result?.msg && !isTemp) {
     message.success('日志发送成功')
+    isUpDate.value = true
   } else if (result?.msg && isTemp) {
     message.success('日志暂存成功')
   } else {

+ 128 - 59
client/src/views/OaSystem/personnelManagement/weeklyCenter/AmountOfWork.vue

@@ -9,17 +9,17 @@
           {{ '工作项目' + (defaultTotalTime ? `(总耗时${defaultTotalTime}小时)` : '') }}
         </div>
         <div class="right">
-          <!-- <el-input placeholder="搜索项目" /> -->
+          <el-input
+            ref="searchInputRef"
+            placeholder="搜索项目"
+            v-model="searchValue"
+            @input="searchOnchange"
+            clearable
+          />
         </div>
       </div>
       <ul class="list-ul">
         <li v-for="(item, index) in dataList" :key="index" @click="handleClick(item)">
-          <div class="project-name">
-            <!-- <span>{{
-              popperInfoList[index].count ? `(${popperInfoList[index].count}小时)` : ''
-            }}</span>
-            {{ item['name'] }} -->
-          </div>
           <div class="project-write">
             <el-popover
               ref="popperRef"
@@ -27,13 +27,11 @@
               placement="top-end"
               :width="400"
               trigger="click"
-              :visible="popperInfoList[index].visible"
+              :visible="item.visible"
             >
               <template #reference>
-                <div class="time-select" @click="popperInfoList[index].visible = true">
-                  <span>{{
-                    popperInfoList[index].count ? `(${popperInfoList[index].count}小时)` : ''
-                  }}</span>
+                <div class="time-select" @click="item.visible = true">
+                  <span>{{ item.count ? `(${item.count}小时)` : '' }}</span>
                   {{ item['name'] }}
                 </div>
               </template>
@@ -43,7 +41,7 @@
                   <div class="panel-input-number">
                     输入时间:
                     <el-input-number
-                      v-model="popperInfoList[index].count"
+                      v-model="item.count"
                       class="input-number"
                       :min="0"
                       :max="80"
@@ -54,15 +52,15 @@
                   <div class="panel-numeric-key">
                     <ul>
                       <li
-                        v-for="(item, i) in 40"
+                        v-for="(num, i) in 40"
                         :style="{
-                          background: i + 1 === popperInfoList[index].count ? '#1b80eb' : '#f7f8fa',
-                          color: i + 1 === popperInfoList[index].count ? '#fff' : '#2d333c'
+                          background: i + 1 === item.count ? '#1b80eb' : '#f7f8fa',
+                          color: i + 1 === item.count ? '#fff' : '#2d333c'
                         }"
                         :key="i"
-                        @click="changeCount(item, index)"
+                        @click="changeCount(num, index)"
                       >
-                        <span>{{ item }}</span>
+                        <span>{{ num }}</span>
                       </li>
                     </ul>
                   </div>
@@ -82,6 +80,7 @@
 </template>
 
 <script setup lang="ts">
+/** 周日报相同文件 */
 import request from '@/config/axios'
 import { getUserInfo } from '@/utils/tool'
 // 获取用户信息
@@ -91,19 +90,55 @@ defineOptions({ name: 'WorkHoursSelect' })
 
 interface IProp {
   onChange: (any) => any
+  initialData?: any[] // 初始数据
+  nowDate: string
 }
-const { onChange } = defineProps<IProp>()
-
+const props = defineProps<IProp>()
+const { onChange } = props
+const { initialData, nowDate } = toRefs(props)
 // 默认工作项目总时长
 const defaultTotalTime = ref(0)
 // 工时填写弹框的ref
 const popperRef = ref<any>(null)
-const popperInfoList = ref<any>([])
 // 初始化数据
 const dataList = ref<any[]>([])
-// for (let i = 0; i < 10; i++) {}
+
+const setInitData = () => {
+  if (initialData.value && initialData.value.length > 0) {
+    const initialObj = {}
+    initialData.value.forEach((item) => {
+      initialObj[item.projectId] = item.workTime
+    })
+    const timer = setTimeout(() => {
+      dataList.value = dataList.value.map((item) => {
+        let count = 0
+        if (initialObj[item.id]) {
+          count = initialObj[item.id]
+        }
+        return {
+          ...item,
+          count
+        }
+      })
+      dataList.value.sort((x, y) => y['count'] - x['count'])
+      clearTimeout(timer)
+    }, 0)
+  } else {
+    getAllProject()
+  }
+  getTotalTime()
+}
+
+watch(
+  () => nowDate.value,
+  () => {
+    setInitData()
+  }
+)
+
 onMounted(() => {
   getAllProject()
+  setInitData()
 })
 // 获取任务列表
 const getAllProject = async () => {
@@ -118,17 +153,13 @@ const getAllProject = async () => {
     '/business'
   )
   dataList.value = records.map((item) => {
-    popperInfoList.value.push({
+    return {
       visible: false,
       count: 0,
-      id: item.id
-    })
-    return {
       name: item.xmmc,
       id: item.id
     }
   })
-  // console.log('result', records)
 }
 
 // 临时存储数量
@@ -137,47 +168,92 @@ const tempCount = ref(0)
 // 工时数量
 const changeCount = (val, index) => {
   // 获取临时数量
-  tempCount.value = popperInfoList.value[index].count
-  popperInfoList.value[index].count = val
+  tempCount.value = dataList.value[index].count
+  dataList.value[index].count = val
 }
 
-// 提交工时
-const panelSubmit = (index: number) => {
-  popperInfoList.value[index].visible = false
-  defaultTotalTime.value = popperInfoList.value.reduce((total, item) => {
+// 计算总工时
+const getTotalTime = () => {
+  defaultTotalTime.value = dataList.value.reduce((total, item) => {
     return total + item.count
   }, 0)
+}
+
+// 提交工时
+const panelSubmit = (index: number) => {
+  dataList.value[index].visible = false
+  getTotalTime()
   tempCount.value = 0
   // 提交后进行一下数据排序
-  popperInfoList.value.sort((x, y) => y['count'] - x['count'])
-  dataList.value.sort((a, b) => {
-    const idA = a.id
-    const idB = b.id
-    // 在 popperInfoList 中找到对应的对象,并获取其索引
-    const indexA = popperInfoList.value.findIndex((item) => item.id === idA)
-    const indexB = popperInfoList.value.findIndex((item) => item.id === idB)
-    // 根据 popperInfoList 的顺序对 dataList 进行排序
-    return indexA - indexB
-  })
+  dataList.value.sort((x, y) => y['count'] - x['count'])
+
   // 提交工时后将已填数据传出去
-  const countList = popperInfoList.value
+  const countList = dataList.value
     .filter((item) => item.count > 0)
     .map((item) => ({
       workTime: item.count,
       projectId: item.id
     }))
   onChange(countList)
+
+  // 提交工时后清空搜索框
+  if (tempSearchList.value.length > 0) {
+    searchInputRef.value?.clear()
+  }
 }
 
 // 取消选择
 const panelCancel = (index: number) => {
-  popperInfoList.value[index] = {
+  dataList.value[index] = {
+    ...dataList.value[index],
     visible: false,
     count: tempCount.value
   }
-  defaultTotalTime.value = popperInfoList.value.reduce((total, item) => {
-    return total + item.count
-  }, 0)
+  getTotalTime()
+}
+
+// 搜索内容的临时存储
+const searchInputRef = ref<any>(null)
+const tempSearchList = ref<any[]>([])
+const searchValue = ref('')
+// 搜索内容改变时触发
+const searchOnchange = (val: string) => {
+  // 搜索框第一次搜索时触发
+  if (tempSearchList.value.length < dataList.value.length) {
+    tempSearchList.value = dataList.value
+  }
+  // 搜索内容为空时,清空搜索列表,并显示全部数据
+  if (val.length == 0) {
+    clearSearch()
+    return
+  }
+  // 使用 filter() 方法进行模糊查询
+  const filteredArray = tempSearchList.value.filter((item) => {
+    // 创建正则表达式,忽略大小写,并且匹配关键词
+    const regex = new RegExp(val, 'i')
+    // 使用正则表达式测试数组中的每个元素
+    return regex.test(item.name)
+  })
+  dataList.value = filteredArray
+}
+// 清除内容时触发
+const clearSearch = () => {
+  const countObj = {}
+  dataList.value.forEach((item) => {
+    countObj[item.id] = item.count
+  })
+  tempSearchList.value.forEach((item) => {
+    if (countObj[item.id]) {
+      // 如果有值,则赋值
+      item.count = countObj[item.id]
+    }
+  })
+  // 顺便进行一下数据排序
+  tempSearchList.value.sort((x, y) => y['count'] - x['count'])
+  // 还原全部数据
+  dataList.value = tempSearchList.value
+  tempSearchList.value = []
+  getTotalTime()
 }
 
 interface IProject {
@@ -220,7 +296,7 @@ const handleClick = (val: IProject): void => {
     height: 100%;
     border: 1px solid #dee0e3;
     .title {
-      padding: 8px 24px;
+      padding: 8px 20px;
       background-color: #f7f8fa;
       color: #121518;
       display: flex;
@@ -229,7 +305,7 @@ const handleClick = (val: IProject): void => {
     }
     .list-ul {
       width: 100%;
-      height: calc(100% - 45px);
+      height: calc(100% - 50px);
       overflow-y: scroll;
       text-align: center;
       background-color: #fff;
@@ -237,20 +313,13 @@ const handleClick = (val: IProject): void => {
       li {
         text-align: left;
         color: #2d333c;
-        padding: 10px 15px;
+        padding: 6px 10px;
         cursor: pointer;
-        display: flex;
         justify-content: space-between;
         &:hover {
           background-color: #d3e5ff;
         }
-        .project-name {
-          // flex: 0;
-          // span {
-          //   color: #1b80eb;
-          // }
-          width: 0;
-        }
+
         .project-write {
           width: 100%;
           padding-left: 10px;

+ 141 - 19
client/src/views/OaSystem/personnelManagement/weeklyCenter/WeekCalendar.vue

@@ -2,7 +2,7 @@
   <div class="weeklyCenterBox">
     <div class="selectBox">
       <el-icon class="icon1" @click="clickHandle(0)"><ArrowLeftBold /></el-icon>
-      <p>{{ moment(nowTime).format('YYYY年MM月') }}</p>
+      <p>{{ moment(nowTime).format('YYYY 年 M 月') }}</p>
       <el-icon class="icon1" @click="clickHandle(1)"><ArrowRightBold /></el-icon>
     </div>
     <div class="contentBox">
@@ -12,13 +12,9 @@
         @click="weekOnChange(arr, index)"
         :class="['ulBox', index == checkWeek ? 'check-box' : '']"
       >
-        <p
-          :class="[
-            'title',
-            index > thisWeekNum ? 'color3' : index == thisWeekNum ? 'color2' : 'color1'
-          ]"
-          >第{{ weekNum[index] }}周</p
-        >
+        <p :class="['title', getTitleClass(index)]">
+          第{{ weekNum[index] }}周 {{ getThisWeekLogIsFill(arr) }}
+        </p>
         <ul>
           <li
             v-for="(cItem, cIndex) in arr"
@@ -53,6 +49,7 @@
 import moment from 'moment'
 import request from '@/config/axios'
 import { useComputedDates, isWeekend } from '@/components/Calendar/calendar'
+import { getUserInfo } from '@/utils/tool'
 
 defineOptions({
   name: 'WeekCalendar'
@@ -65,7 +62,21 @@ const { onChange } = defineProps<IProp>()
 
 const checkWeek = ref(0)
 const weekOnChange = (arr, index) => {
-  onChange(arr)
+  const weekDate = [arr[0].dm, arr[6].dm]
+  const dateOfWeek = weekOfYearObj.value[arr[0].dm]
+  const changeData: any = {
+    weekDate,
+    year: dateOfWeek.year,
+    month: dateOfWeek.month,
+    week: dateOfWeek.week,
+    dayOfWeek: dateOfWeek.dayOfWeek,
+    checkDate: arr
+  }
+  const target = arr.find((item) => weekLogObj.value[item.dm])
+  if (target) {
+    changeData.isLog = weekLogObj.value[target.dm]
+  }
+  onChange(changeData)
   checkWeek.value = index
 }
 
@@ -118,12 +129,31 @@ const clickHandle: Function = (type: number): void => {
   const typeStr = type === 0 ? 'subtract' : 'add'
   const time: string = moment(nowTime.value)[typeStr](1, 'months').format('YYYY-MM')
   nowTime.value = moment(time).format('YYYY-MM')
-  sourceList.value = computedDays(useComputedDates(nowTime.value))
+  // sourceList.value = computedDays(useComputedDates(nowTime.value))
+
+  // const timer = setTimeout(() => {
+  setDayOfMonth()
+  //   clearTimeout(timer)
+  // }, 200)
 }
 
 const attendanceStatusObj = ref<any>({}) // 考勤状态
 const thisWeekNum = ref(0) // 当前周数
 onMounted(async () => {
+  await setWeekOfYear()
+  await getLogList()
+  // getMonthWeekGroup()
+  await setDayOfMonth()
+})
+
+watch(
+  () => nowTime.value,
+  async () => {
+    await getLogList()
+  }
+)
+// 设置当月日期
+const setDayOfMonth = async () => {
   await getAttendanceSheetList()
   sourceList.value = await computedDays(useComputedDates(nowTime.value))
   const thisDay = moment().format('YYYY-MM-DD')
@@ -139,17 +169,12 @@ onMounted(async () => {
       sourceList.value[i][j]['pm'] = attendanceStatusObj.value[dm]?.pm
     }
   }
-  // console.log('sourceList.value', thisWeekNum.value, sourceList.value)
-  // console.log('attendanceDataObj.value', attendanceStatusObj.value)
-})
+}
 
 // 获取考勤数据
 const getAttendanceSheetList = async (): Promise<any> => {
-  const startTime = moment()
-    .month(nowTime.value)
-    .startOf('month')
-    .startOf('week')
-    .format('YYYY-MM-DD')
+  const startTime = moment(nowTime.value).startOf('month').startOf('week').format('YYYY-MM-DD')
+
   const attendanceData = await request.get({
     url: `/adm/attendance-sheet/list-me`,
     params: {
@@ -159,7 +184,7 @@ const getAttendanceSheetList = async (): Promise<any> => {
       ]
     }
   })
-  attendanceData.forEach((item) => {
+  attendanceData?.forEach((item) => {
     //	attendanceDate 考勤时间
     //	attendanceType 考勤类型(1:上午;2:下午)
     //	attendanceStatus 考勤状态
@@ -176,6 +201,103 @@ const getAttendanceSheetList = async (): Promise<any> => {
     }
   })
 }
+
+// 获取用户信息
+const userInfo = getUserInfo()
+const weekLogObj = ref({})
+// 周报统计
+const getLogList = async (): Promise<any> => {
+  const urlApi = `/adm/report/list`
+  const params = {
+    reportType: 'weekly',
+    reportYear: moment(nowTime.value).format('YYYY'),
+    reportMonth: moment(nowTime.value).format('M'),
+    userId: userInfo.id ?? ''
+  }
+  const logList = await request.get({ url: urlApi, params })
+  logList.forEach((item: any) => {
+    const data = moment(item.reportStartDate).format('YYYY-MM-DD')
+    weekLogObj.value[data] = item
+  })
+}
+// 获取本周是否已填
+const getThisWeekLogIsFill = (arr) => {
+  const target = arr.find((item) => weekLogObj.value[item.dm])
+  if (target) {
+    return '(已填)'
+  }
+  return ''
+}
+
+watch(
+  () => moment(nowTime.value).format('YYYY'),
+  (year) => {
+    setWeekOfYear(year)
+  }
+)
+
+// 获取周和年的关系
+// 把获取到的周信息汇聚起来
+const weekOfYearObj = ref({})
+const weekOfMonthObj = ref({})
+// 获取日期对应的相关周等信息
+const setWeekOfYear = async (date = moment().format('YYYY')) => {
+  // const year = moment(date).format('YYYY')
+  // const month = moment(date).format('M')
+  const result = await request.get({ url: '/adm/workday/list-week', params: { year: date } })
+  result.forEach((item) => {
+    const date = moment(item.dateDay).format('YYYY-MM-DD')
+    const month = moment(item.dateDay).format('YYYY-MM')
+    weekOfYearObj.value[date] = item
+    if (weekOfMonthObj.value[month]) {
+      weekOfMonthObj.value[month].push(item)
+    } else {
+      weekOfMonthObj.value[month] = [item]
+    }
+  })
+}
+
+// 设置本周title颜色
+const getTitleClass = (index) => {
+  const thisMonth = moment().format('YYYY-MM')
+  const isBefore = moment(nowTime.value).isBefore(thisMonth)
+  const isAfter = moment(nowTime.value).isAfter(thisMonth)
+  if (isBefore) {
+    return 'color1'
+  }
+  if (isAfter) {
+    return 'color3'
+  }
+  if (index > thisWeekNum.value) {
+    return 'color3'
+  } else if (index == thisWeekNum.value) {
+    return 'color2'
+  }
+  return 'color1'
+}
+
+// 获取本月的日期分组
+const getMonthWeekGroup = () => {
+  const thisMonth = moment(nowTime.value).format('YYYY-MM')
+  const monthList = weekOfMonthObj.value[thisMonth].sort((x, y) => x.dateDay - y.dateDay)
+  const weekGroupObj = {}
+  monthList.forEach((item) => {
+    const { week, dateDay } = item
+    if (weekGroupObj[week]) {
+      weekGroupObj[week].push({
+        ...item,
+        day: moment(dateDay).format('YYYY-MM-DD')
+      })
+    } else {
+      weekGroupObj[week] = [
+        {
+          ...item,
+          day: moment(dateDay).format('YYYY-MM-DD')
+        }
+      ]
+    }
+  })
+}
 </script>
 <style lang="scss" scoped>
 .weeklyCenterBox {

+ 0 - 160
client/src/views/OaSystem/personnelManagement/weeklyCenter/editorDetail copy.vue

@@ -1,160 +0,0 @@
-<template>
-  <div class="editorDetailBox">
-    <div class="formBox">
-      <el-form ref="form" :model="formData" label-width="100px">
-        <el-row :gutter="24">
-          <el-col :span="8">
-            <el-form-item label="填写日期">
-              <el-date-picker
-                type="date"
-                placeholder="填写日期"
-                v-model="formData.fillingDate"
-                style="width: 100%"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="16">
-            <el-form-item label="发给谁">
-              <el-tree-select
-                style="width: 100%"
-                v-model="formData.receiveUserId"
-                :data="allUserList"
-                :filter-node-method="filterNodeMethod"
-                :render-after-expand="false"
-                show-checkbox
-                filterable
-                multiple
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row style="height: calc(100% - 120px)">
-          <el-col :span="24" style="height: 100%">
-            <el-form-item label="本周完成工作" style="height: 100%">
-              <el-input type="textarea" v-model="formData.reportContent" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-    </div>
-    <div class="footBox">
-      <div>
-        <div>
-          <WorkProjectList />
-        </div>
-        <div>
-          <WorkHoursSelect :data="5" @select="whSelectHandle" />
-        </div>
-      </div>
-      <div> <el-button type="primary" @click="sendReportHandle">发送</el-button></div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import request from '@/config/axios'
-import { handleTree } from '@/utils/tree'
-import WorkHoursSelect from '../components/WorkHoursSelect.vue'
-import WorkProjectList from '../components/WorkProjectList.vue'
-
-defineOptions({ name: 'EditorDetail' })
-
-const formData = ref<{
-  fillingDate: string
-  receiveUserId: never[]
-  reportContent: string
-  workTime: number
-}>({
-  fillingDate: '',
-  receiveUserId: [],
-  reportContent: '',
-  workTime: 0
-})
-const allUserList = ref<any[]>()
-let sourceAllUserList: any[] = []
-
-const getAllUserSimpleByList = async () => {
-  const urlApi = '/system/dept/list-all-user-simple'
-  const params = {}
-  const result = await request.get({ url: urlApi, params })
-  sourceAllUserList = handleTree(
-    result.map((item) => {
-      return {
-        label: item['name'],
-        value: item['id'],
-        parentId: item['parentId'],
-        children: item['children']
-      }
-    }),
-    'value'
-  )
-  allUserList.value = sourceAllUserList ?? []
-}
-const filterNodeMethod = (value, data) => data.label.includes(value)
-const whSelectHandle = (val: number): void => {
-  formData.value.workTime = val
-}
-const sendReportHandle = async () => {
-  const urlApi = `/adm/report/add-report-info`
-  let receiveUserId: string[] = [].concat(formData.value.receiveUserId)
-  receiveUserId = receiveUserId.map((userId) => userId.replace('user:', ''))
-  const sendData = {
-    projectId: '',
-    receiveUserId,
-    reportType: 'weekly',
-    fillingDate: formData.value['fillingDate'],
-    reportContent: formData.value['reportContent'],
-    workTime: formData.value['workTime']
-  }
-  const result = await request.post({ url: urlApi, data: sendData })
-  console.log('result~~~~~~~~~~~~~~~~~~~~')
-  console.log(result)
-}
-getAllUserSimpleByList()
-</script>
-
-<style lang="scss" scoped>
-.editorDetailBox {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  > .formBox {
-    flex: 1.2;
-    height: 100%;
-    margin-right: 15px;
-    :depp(.el-form) {
-      height: 100%;
-    }
-    :deep(.el-textarea, .el-textarea__inner) {
-      height: 100% !important;
-    }
-  }
-  > .footBox {
-    flex: 1;
-    height: 100%;
-    > div {
-      &:first-child {
-        height: calc(100% - 70px);
-        display: flex;
-        > div {
-          &.title {
-            width: 120px;
-            color: var(--el-text-color-regular);
-            font-size: 14px;
-          }
-          &:nth-child(1) {
-            flex: 2;
-          }
-          &:nth-child(2) {
-            flex: 1;
-          }
-        }
-      }
-      &:last-child {
-        text-align: right;
-        margin-top: 26px;
-      }
-    }
-  }
-}
-</style>

+ 61 - 15
client/src/views/OaSystem/personnelManagement/weeklyCenter/editorDetail.vue

@@ -42,8 +42,15 @@
         </el-row>
       </el-form>
     </div>
-    <AmountOfWork :onChange="getWorkTimeList" />
-    <div class="footBox">
+    <AmountOfWork
+      :onChange="getWorkTimeList"
+      :initialData="formData.weeklyWorkloadList"
+      :nowDate="weekDate[0]"
+    />
+    <div class="footBox" v-if="isUpDate">
+      <el-button type="primary" @click="sendReportHandle(false)">更新</el-button>
+    </div>
+    <div class="footBox" v-else>
       <el-button type="primary" @click="sendReportHandle(true)">暂存</el-button>
       <el-button type="primary" @click="sendReportHandle(false)">发送</el-button>
     </div>
@@ -59,17 +66,50 @@ import { getUserInfo } from '@/utils/tool'
 defineOptions({ name: 'EditorDetail' })
 
 interface IProp {
+  writeData: any
   weekDate: any[]
 }
-const { weekDate } = defineProps<IProp>()
-// console.log('weekDate', weekDate)
+const props = defineProps<IProp>()
+const { writeData, weekDate } = toRefs(props)
+
+const isUpDate = ref(false) // 是否是更新周报
+
+watch(weekDate, () => {
+  initLog()
+})
+
+const initLog = () => {
+  if (writeData.value?.isLog) {
+    const { reportContent, workload, receiveIds } = writeData.value.isLog
+    formData.value.reportContent = reportContent
+    formData.value.weeklyWorkloadList = workload
+    formData.value.receiveUserIds = receiveIds
+    isUpDate.value = true
+  } else {
+    formData.value.reportContent = `星期一
+
+星期二
+
+星期三
+
+星期四
+
+星期五
+
+  `
+    formData.value.weeklyWorkloadList = []
+    formData.value.receiveUserIds = []
+    isUpDate.value = false
+  }
+}
+
 const formData = ref<{
   reportDate: any
   receiveUserIds: string[]
   reportContent: string
   weeklyWorkloadList: any[]
 }>({
-  reportDate: weekDate,
+  reportDate: weekDate.value,
   receiveUserIds: [],
   reportContent: `星期一
 
@@ -109,10 +149,11 @@ const userInfo = getUserInfo()
 // 提交(暂存)
 const message = useMessage()
 const sendReportHandle = async (isTemp) => {
-  if (formData.value.receiveUserIds.length === 0) {
-    message.warning('请选择接收人')
-    return
-  }
+  // if (formData.value.receiveUserIds.length === 0) {
+  //   message.warning('请选择接收人')
+  //   return
+  // }
+
   if (formData.value.weeklyWorkloadList.length === 0) {
     message.warning('请对工作量进行分配')
     return
@@ -120,13 +161,18 @@ const sendReportHandle = async (isTemp) => {
   const params = {
     userId: userInfo.id ?? '',
     deptId: userInfo.deptId ?? '',
-    reportStartDate: moment(weekDate[0]).valueOf(),
-    reportEndDate: moment(weekDate[1]).valueOf(),
-    receiveUserIds: formData.value.receiveUserIds, // ['e1a66d67-38ab-4f07-839f-1042dc3c735d']
+    reportStartDate: moment(weekDate.value[0]).valueOf(),
+    reportEndDate: moment(weekDate.value[1]).valueOf(),
+    receiveUserIds: formData.value.receiveUserIds,
+    // receiveUserIds: ['ea81aaf2-74fe-429f-acaa-25a9a898abcf'],
     reportType: 'weekly',
     reportContent: formData.value.reportContent,
     isTemp,
-    weeklyWorkloadList: formData.value.weeklyWorkloadList
+    weeklyWorkloadList: formData.value.weeklyWorkloadList,
+    reportYear: writeData.value.year, // 报告年份
+    reportMonth: writeData.value.month, // 月份
+    reportWeek: writeData.value.week // 周
+    // reportDay: writeData.value.dayOfWeek // 天
     // [
     //   {
     //     workTime: 1,
@@ -138,12 +184,12 @@ const sendReportHandle = async (isTemp) => {
     //   }
     // ]
   }
-  // return
-  // console.log('提交(暂存)~~~~~~~~~~~~~~~~~~~', params)
+  // console.log('提交(暂存)~~~~~~~~~~~~~~~~~~~', params, weekDate.value)
   const result = await request.postOriginal({ url: '/adm/report/add-report-info', data: params })
   // console.log('提交(暂存)~~~~~~~result~~~~~~', result)
   if (result?.msg && !isTemp) {
     message.success('周报发送成功')
+    isUpDate.value = true
   } else if (result?.msg && isTemp) {
     message.success('周报暂存成功')
   } else {

+ 10 - 8
client/src/views/OaSystem/personnelManagement/weeklyCenter/weeklyCenter.vue

@@ -6,7 +6,7 @@
         <WeekCalendar :onChange="onChange" />
       </div>
       <div class="contentBox">
-        <EditorDetail :weekDate="weekDate" />
+        <EditorDetail :weekDate="writeData.weekDate" :writeData="writeData" />
       </div>
     </div>
   </div>
@@ -16,17 +16,19 @@
 import WeekCalendar from './WeekCalendar.vue'
 import EditorDetail from './editorDetail.vue'
 import moment from 'moment'
+// import request from '@/config/axios'
 
 defineOptions({ name: 'WeeklyCenter' })
 
 // 本周填写的日期
-const weekDate = ref([
-  moment().startOf('isoWeek').format('YYYY-MM-DD'),
-  moment().endOf('isoWeek').format('YYYY-MM-DD')
-])
-const onChange = (date) => {
-  weekDate.value = [date[0].dm, date[6].dm]
-  // console.log('onChange', date, weekDate.value)
+const writeData = ref<any>({
+  weekDate: [
+    moment().startOf('isoWeek').format('YYYY-MM-DD'),
+    moment().endOf('isoWeek').format('YYYY-MM-DD')
+  ]
+})
+const onChange = (data) => {
+  writeData.value = data
 }
 </script>