瀏覽代碼

fix: 周日报移动端功能优化,周报web端样式重设

qiny 1 年之前
父節點
當前提交
68e480af82

+ 1 - 1
client/src/views/OaSystem/personnelManagement/ProjectStatistics/index.vue

@@ -2,9 +2,9 @@
 /**
  * @description 项目工时统计
  */
-
 import ProjectForm from './projectForm.vue'
 import ProjectTable from './projectTable.vue'
+defineOptions({ name: 'ProjectStatistics' })
 </script>
 <template>
   <div class="oa-sys-list-view">

+ 22 - 9
client/src/views/OaSystem/personnelManagement/ProjectStatistics/projectForm.vue

@@ -82,11 +82,20 @@ onMounted(() => {
 /* 导出 */
 
 // 导出头部
-const tableHead = [['人员', '项目名称', '项目编号', '项目工时(小时)']]
-// const newTableHead = [['公司', '月份', '部门', '人员', '项目编号', '合同编码', '工时']]
+// const tableHead = [['人员', '项目名称', '项目编号', '项目工时(小时)']]
+const newTableHead = [['公司', '月份', '部门', '人员', '项目编号', '合同编码', '工时']]
 // 列宽设置
-const colsWidth = ref([{ wch: 8 }, { wch: 100 }, { wch: 18 }, { wch: 15 }])
-const exportData = ref(tableHead)
+// const colsWidth = ref([{ wch: 8 }, { wch: 100 }, { wch: 18 }, { wch: 15 }])
+const colsWidth = ref([
+  { wch: 35 },
+  { wch: 10 },
+  { wch: 25 },
+  { wch: 12 },
+  { wch: 20 },
+  { wch: 20 },
+  { wch: 8 }
+])
+const exportData = ref(newTableHead)
 
 // 获取所有统计数据
 const getAllData = () => {
@@ -113,12 +122,16 @@ const getAllData = () => {
 // 整合导出表格数据
 const getExportData = (data) => {
   const tableBody = data.map((item) => [
-    item.nickName ?? '',
-    item.xmmc ?? '',
-    item.xmbh ?? '',
-    item.workTime ?? ''
+    '浙江万维空间信息技术有限公司',
+    queryParams.date,
+    item.deptName ?? '', // 部门
+    item.nickName ?? '', // 人员
+    // item.xmmc ?? '', // 项目名称
+    item.xmbh ?? '', // 项目编号
+    item.contractNumber ?? '', // 合同编码
+    item.workTime ?? '' // 项目工时
   ])
-  exportData.value = [...tableHead, ...tableBody]
+  exportData.value = [...newTableHead, ...tableBody]
   // console.log('exportData.value', exportData.value)
 }
 </script>

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

@@ -46,6 +46,9 @@
   </div>
 </template>
 <script setup lang="ts">
+/**
+ * @description 周报组件(已废弃)
+ */
 import moment from 'moment'
 import request from '@/config/axios'
 import { useComputedDates, isWeekend } from '@/components/Calendar/calendar'

+ 16 - 6
client/src/views/OaSystem/personnelManagement/weeklyCenter/service.ts

@@ -23,7 +23,17 @@ export const http = {
     const result: any = await request.get({ url: api.workDayList, params })
     return result ?? []
   },
-
+  // 获取当月日志列表
+  getMonthLogList: async (type: 'weekly' | 'daily', date: string | Date) => {
+    const params = {
+      reportType: type,
+      reportYear: moment(date).format('YYYY'),
+      reportMonth: moment(date).format('M'),
+      userId: userInfo.id ?? ''
+    }
+    const result: any = await request.get({ url: api.logList, params })
+    return result ?? []
+  },
   // 获取近三个月周日报日志列表
   getLogList: async (type: 'weekly' | 'daily', date?) => {
     const nearThreeMonth = service.getNearThreeMonth(date)
@@ -118,15 +128,15 @@ export const service = {
       }
     ]
   },
-  // 返回当前月尾那周周日 到 上个月初那周的周一前一天的日期
-  getMonthRange: () => {
-    const endTime = moment()
+  // 返回当前月尾那周周日 到 上个月初那周的周一前一天的日期
+  getMonthRange: (date: string | Date) => {
+    const endTime = moment(date)
       .endOf('month')
       .endOf('week')
       .add(1, 'day')
       .format('YYYY-MM-DD HH:mm:ss')
-    const startTime = moment()
-      .subtract(2, 'month')
+    const startTime = moment(date)
+      .subtract(1, 'month')
       .startOf('month')
       .startOf('week')
       .format('YYYY-MM-DD HH:mm:ss')

+ 45 - 14
client/src/views/OaSystem/personnelManagement/weeklyCenter/weeklyLogList.vue

@@ -9,12 +9,16 @@
         <el-icon><ArrowRightBold /></el-icon>
       </div>
     </div>
-    <div class="content">
+
+    <div class="content" v-loading="isLoading">
       <div
         v-for="(item, index) in thisMonthLogs"
         :key="item.week"
         class="week-item"
-        :style="{ backgroundColor: item.bgColor }"
+        :style="{
+          backgroundColor: item.bgColor,
+          border: item.endDate == checkItem ? `1.5px solid ${item.color}` : 'none'
+        }"
         @click="goToWeeklyPage(item)"
       >
         <div class="left">
@@ -53,6 +57,7 @@ interface IProp {
 }
 const { onChange } = defineProps<IProp>()
 
+const isLoading = ref<boolean>(false)
 // 所有的周日报和周划分
 // const allWorkDayListAndLogs = ref<any>([])
 // 本月日期
@@ -63,16 +68,16 @@ 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()
+  PubsubService.subscribe('sendWeeklyReportHandle-init', async () => {
+    await initPageList()
   })
 })
 
@@ -92,7 +97,7 @@ const checkMonth = (type: 'prev' | 'next') => {
 }
 // 获取最近三个月的工作日列表详情
 const workDayList = async () => {
-  const monthRange = service.getMonthRange()
+  const monthRange = service.getMonthRange(thisMonth.value)
   const workDays = await http.getWorkDayList(monthRange[0], monthRange[1])
   const workDayObj = service.setWorkDayListToWeek(workDays)
   return workDayObj
@@ -100,12 +105,13 @@ const workDayList = async () => {
 
 // 合并工作日和周报列表并初始化页面
 const initPageList = async () => {
+  isLoading.value = true
   const workObj = await workDayList()
-  const logList = await http.getLogList('weekly', thisMonth.value)
+  const logList = await http.getMonthLogList('weekly', thisMonth.value)
   const allWorkDayListAndLogs = service.mergeWorkDayAndLogs(workObj, logList)
 
   const pointer = moment(thisMonth.value).format('YYYY-M')
-  thisMonthLogs.value = allWorkDayListAndLogs[pointer].map((item: any) => {
+  const thisMonthLog = allWorkDayListAndLogs[pointer].map((item: any) => {
     // 默认未填
     item.type = statusObj[1].type
     item.icon = statusObj[1].icon
@@ -113,15 +119,15 @@ const initPageList = async () => {
     item.bgColor = statusObj[1].bgColor
     // 如果本周
     const startOfWeek = moment().startOf('week')
-    const endOfWeek = moment().endOf('week')
+    const endOfWeek = moment().endOf('week').add(1, 'day')
     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) {
+    // 如果已填,且不是暂存
+    if (item.isLog.length > 0 && !item.isLog[0].isTemp) {
       const isLog = item.isLog[0]
       item.id = isLog.id
       item.icon = statusObj[0].icon
@@ -129,6 +135,11 @@ const initPageList = async () => {
       item.bgColor = statusObj[0].bgColor
       item.type = statusObj[0].type
     }
+    // 如果已填但是是暂存
+    if (item.isLog.length > 0 && item.isLog[0].isTemp) {
+      // 啥也不做
+      item.type = '暂存'
+    }
     // 如果未到
     if (moment(item.startDate).isAfter(moment())) {
       item.icon = statusObj[3].icon
@@ -138,6 +149,21 @@ const initPageList = async () => {
     }
     return item
   })
+
+  isLoading.value = false
+
+  thisMonthLogs.value = thisMonthLog
+
+  const nowLog = thisMonthLog.find((item: any) =>
+    moment(checkItem.value).isBetween(
+      item.startDate,
+      moment(item.endDate).add(1, 'day'),
+      item.endDate
+    )
+  )
+  if (nowLog) {
+    itemOnChange(nowLog)
+  }
 }
 // 颜色列表
 const weekTitleList = ['第一周', '第二周', '第三周', '第四周', '第五周']
@@ -149,21 +175,26 @@ const statusObj = [
 ]
 // 跳转到周报填写或详情页面
 // const { push } = useRouter()
+const checkItem = ref(moment())
 const goToWeeklyPage = (item: any) => {
-  // console.log('click item', item)
   if (item.type == '未到') {
     message.info('还未到这周!')
     return
   }
+  // 修改点击的item
+  checkItem.value = item.endDate
+  itemOnChange(item)
+}
+
+const itemOnChange = (item: any) => {
   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
+    isLog: item.isLog.length > 0 ? item.isLog[0] : false
   }
-  // console.log('changeData', changeData)
   onChange(changeData)
 }
 </script>

+ 5 - 0
client_h5/src/pages/myLogs/Daily/MyLogs.vue

@@ -34,12 +34,17 @@ onMounted(async () => {
 // 格式化日历
 const formatter = (day: any) => {
   const date = moment(day.date).format("YYYY-MM-DD");
+  const dayOfWeek = moment(day.date).day(); // 获取当前日期是星期几,0代表星期日,6代表星期六
+
   if (moment(day.date).isAfter(moment())) {
     // 如果未到,不做处理
     day.topInfo = "";
   } else if (logObj.value[date]) {
     day.topInfo = "已填";
     day.className = "filled-in";
+  } else if ((dayOfWeek === 0 || dayOfWeek === 6) && !logObj.value[date]) {
+    // 如果是周六或周日且未填
+    day.topInfo = "";
   } else {
     day.topInfo = "未填";
     day.className = "not-fill";

+ 14 - 1
client_h5/src/pages/myLogs/Daily/index.vue

@@ -17,7 +17,9 @@
       type="textarea"
       placeholder=""
     />
-    <div class="title">工作量分配</div>
+    <div class="title">
+      工作量分配 {{ totalTime ? `(总耗时${totalTime}小时)` : "" }}
+    </div>
     <ProjectList type="daily" :onChange="projectChange" />
     <div class="title">接收人</div>
     <SelectUser v-model="formData.receiveUserIds" />
@@ -114,6 +116,7 @@ const calendarShow = ref(false);
 // 工作量改变
 const projectChange = (data: any) => {
   formData.weeklyWorkloadList = data;
+  getTotalTime();
 };
 
 // 提交
@@ -157,6 +160,16 @@ const getIsWorkDays = async (date?: string) => {
     formData.reportDay = workDays[0].dayOfWeek;
   }
 };
+
+// 计算总耗时
+const totalTime = ref(0);
+const getTotalTime = () => {
+  let total = 0;
+  formData.weeklyWorkloadList.forEach((item: any) => {
+    total += item.workTime;
+  });
+  totalTime.value = total;
+};
 </script>
 <style lang="scss" scoped>
 @import "../page.scss";

+ 14 - 1
client_h5/src/pages/myLogs/Weekly/index.vue

@@ -23,7 +23,9 @@
       type="textarea"
       placeholder=""
     />
-    <div class="title">工作量分配</div>
+    <div class="title">
+      工作量分配 {{ totalTime ? `(总耗时${totalTime}小时)` : "" }}
+    </div>
     <ProjectList type="weekly" :onChange="projectChange" />
     <div class="title">接收人</div>
     <SelectUser v-model="formData.receiveUserIds" />
@@ -131,6 +133,7 @@ const calendarShow = ref(false);
 // 工作量改变
 const projectChange = (data: any) => {
   formData.weeklyWorkloadList = data;
+  getTotalTime();
 };
 
 // 提交
@@ -172,6 +175,16 @@ const getIsWorkDays = async (date?: string) => {
   formData.reportWeek = workDays[0].week;
   // return workDays[0];
 };
+
+// 计算总耗时
+const totalTime = ref(0);
+const getTotalTime = () => {
+  let total = 0;
+  formData.weeklyWorkloadList.forEach((item: any) => {
+    total += item.workTime;
+  });
+  totalTime.value = total;
+};
 </script>
 <style lang="scss" scoped>
 @import "../page.scss";

+ 59 - 23
client_h5/src/pages/myLogs/components/ProjectList.vue

@@ -1,30 +1,37 @@
 <template>
-  <van-tabs v-model:active="active" class="project-tabs" :show-header="false">
-    <van-tab title="工作项目"
-      ><van-list>
-        <van-cell
-          v-for="item in dataSource"
-          :key="item.projectId"
-          :title="projectTitme(item)"
-          @click="projectClick(item)"
-        /> </van-list
-    ></van-tab>
-    <van-tab title="工作时长"
-      ><van-list>
-        <van-cell
-          v-for="item in workTimeList(type)"
-          :key="item.key"
-          :title="item.title"
-          @click="timerClick(item)"
-        /> </van-list
-    ></van-tab>
-  </van-tabs>
+  <div>
+    <!-- 搜索输入框 -->
+    <van-search v-model="searchQuery" placeholder="搜索项目" />
+    <van-tabs v-model:active="active" class="project-tabs" :show-header="false">
+      <van-tab title="工作项目">
+        <van-list>
+          <van-cell
+            v-for="item in filteredDataSource"
+            :key="item.projectId"
+            :title="projectTitme(item)"
+            @click="projectClick(item)"
+          />
+        </van-list>
+      </van-tab>
+      <van-tab title="工作时长">
+        <van-list>
+          <van-cell
+            v-for="item in workTimeList(type)"
+            :key="item.key"
+            :title="item.title"
+            @click="timerClick(item)"
+          />
+        </van-list>
+      </van-tab>
+    </van-tabs>
+  </div>
 </template>
+
 <script lang="ts" setup>
 /**
- * @description
+ * @description 接收人组件
  */
-import { ref } from "vue";
+import { ref, onMounted } from "vue";
 import { http } from "../http";
 interface IProp {
   type: "weekly" | "daily";
@@ -47,6 +54,7 @@ onMounted(async () => {
         workTimeName: "",
       };
     }) ?? [];
+  filteredDataSource.value = dataSource.value;
 });
 
 // 生成工作时长数据
@@ -60,6 +68,24 @@ const workTimeList = (type: string) => {
     };
   });
 };
+
+// 过滤
+const searchQuery = ref<string>("");
+const filteredDataSource = ref<any[]>([]);
+const setFilteredDataSource = () => {
+  filteredDataSource.value = dataSource.value;
+  if (!searchQuery.value) {
+    return;
+  }
+  filteredDataSource.value = dataSource.value.filter((item) => {
+    // 创建正则表达式,忽略大小写,并且匹配关键词
+    const regex = new RegExp(searchQuery.value, "i");
+    // 使用正则表达式测试数组中的每个元素
+    return regex.test(item.projectName);
+  });
+};
+watch(searchQuery, setFilteredDataSource);
+
 // 设置工作量
 const active = ref(0);
 const activeProject = ref(null);
@@ -83,6 +109,10 @@ const timerClick = (timer: any) => {
       return item;
     })
     .sort((a, b) => b.workTime - a.workTime);
+  // 筛选后
+  searchQuery.value = "";
+  filteredDataSource.value = dataSource.value;
+
   active.value = 0;
   const weeklyWorkloadList = dataSource.value
     .filter((item: any) => item.workTime > 0)
@@ -93,4 +123,10 @@ const timerClick = (timer: any) => {
   onChange(weeklyWorkloadList);
 };
 </script>
-<style scoped lang="scss"></style>
+
+<style scoped lang="scss">
+.project-tabs {
+  max-height: 350px;
+  overflow-y: scroll;
+}
+</style>

+ 1 - 0
client_h5/src/pages/myLogs/page.scss

@@ -56,6 +56,7 @@
     padding-left: 15px;
     max-height: 32vh;
     overflow: scroll;
+    margin-bottom: 50px;
   }
 
   .comment-item {

+ 2 - 1
client_h5/src/utils/tools.ts

@@ -14,5 +14,6 @@ export const getUserInfo = () => {
     deptName: "数智产业研发部",
   };
   // 从localStorage中获取用户信息并返回
-  return JSON.parse(localStorage.getItem("_userInfo") as string) ?? userInfo;
+  return JSON.parse(localStorage.getItem("_userInfo") as string);
+  // return JSON.parse(localStorage.getItem("_userInfo") as string) ?? userInfo;
 };