Browse Source

Merge remote-tracking branch 'origin/master'

jzh 1 year ago
parent
commit
4e5840fee1

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

@@ -170,6 +170,9 @@ const changeCount = (val, index) => {
   // 获取临时数量
   tempCount.value = dataList.value[index].count
   dataList.value[index].count = val
+  if (index || index === 0) {
+    panelSubmit(index)
+  }
 }
 
 // 计算总工时

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

@@ -0,0 +1,259 @@
+<script lang="ts" setup>
+import moment from 'moment'
+import request from '@/config/axios'
+import { getUserInfo } from '@/utils/tool'
+interface IProp {
+  detail: any
+}
+const { detail } = defineProps<IProp>()
+
+const emojiList = ['赞!👍', '写的太棒了!👏', '学习了🌹', '感谢你的分享🙏', '加油💪', '早点休息😴']
+
+const message = useMessage()
+const userInfo = getUserInfo()
+// 评论字段
+interface IComment {
+  reportId: string // 报告id
+  commentUserId: string // 评论人用户id
+  commentContent: string // 评论内容
+  commentDate?: string // 评论时间
+  replyToUserid?: string // 被回复人用户ID
+}
+// 提交评论
+const submitComment = async (content?) => {
+  if (!content && commentInput.value == '') {
+    message.info('评论内容不能为空!')
+    return
+  }
+  const data = {
+    reportId: detail.id,
+    commentUserId: userInfo.id ?? '',
+    commentContent: content ?? commentInput.value
+  }
+  const result: any = await request.postOriginal({ url: '/adm/reportComment/send', data })
+  if (result.msg == 'success') {
+    getCommentList()
+    message.success('评论成功!')
+    // 清空输入框
+    if (!content) {
+      commentInput.value = ''
+    }
+  } else {
+    message.error('评论失败,请稍后再试')
+  }
+}
+const commentList = ref<any[]>(detail?.comments ?? [])
+// 获取报告被评论列表
+const getCommentList = async () => {
+  const result = await request.get({
+    url: '/adm/reportComment/getList',
+    params: { reportId: detail?.id, uId: detail?.userId }
+  })
+  commentList.value = result
+}
+const commentInput = ref('')
+
+onMounted(() => {
+  getCommentList()
+})
+</script>
+<template>
+  <div class="detail-box">
+    <div class="form-box">
+      <el-form ref="form" label-width="100px">
+        <el-row :gutter="24">
+          <el-col :span="8">
+            <el-form-item class="label-item" label="日志日期">
+              <div class="write-date">
+                {{ moment(detail.reportStartDate).format('YYYY-MM-DD') }}
+              </div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="16">
+            <el-form-item class="label-item" label="接收人">
+              <div class="tag-list">
+                <el-tag
+                  type="info"
+                  effect="light"
+                  v-for="(item, index) in detail.receiveNames"
+                  :key="index"
+                  >{{ item }}</el-tag
+                >
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24" style="height: 100%">
+            <el-form-item class="label-item" label="今日工作">
+              <div
+                class="text-area"
+                v-html="detail?.reportContent?.replace(/(\r\n|\n|\r)/gm, '<br />')"
+              >
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24" style="height: 100%">
+            <el-form-item class="label-item" label="工作量分配">
+              <div class="text-area area2">
+                <div v-for="(item, index) in detail.workload" :key="index">
+                  <span class="work-time">{{ `(${item.workTime}小时)` }}</span>
+                  <span>{{ item.projectName }}</span>
+                </div>
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </div>
+    <div class="comment-box">
+      <div class="comment-list">
+        <div v-if="commentList.length === 0" class="not-comment">
+          <el-empty description="暂无评论" image-size="35" />
+        </div>
+        <div v-else v-for="(item, index) in commentList" :key="index" class="item">
+          <div class="left">
+            <span>{{ item.commentUserName.substr(-2) }}</span>
+          </div>
+          <div class="right">
+            <div class="title">
+              {{
+                `${item.commentUserName} ${moment(item.commentDate).format('YYYY-MM-DD HH:mm:ss')}`
+              }}
+              <span>删除</span>
+            </div>
+            <div>{{ item.commentContent }}</div>
+          </div>
+        </div>
+      </div>
+      <div class="comment-emoji">
+        <span v-for="(item, index) in emojiList" :key="index" @click="submitComment(item)">{{
+          item
+        }}</span>
+      </div>
+      <div class="comment-input">
+        <el-input v-model="commentInput" placeholder="请输入评论内容" />
+        <el-button class="submit" type="primary" @click="submitComment()">发表评价</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+<style scoped lang="scss">
+.detail-box {
+  width: 100%;
+  height: 100%;
+  .form-box {
+    width: 100%;
+    .label-item {
+      .el-form-item__label {
+        font-weight: 400 !important;
+        font-size: 16px !important;
+      }
+      .write-date {
+        width: 100px;
+        border: 1px solid #dee0e3;
+        border-radius: 4px;
+        text-align: center;
+        background: #f9f9f9;
+      }
+      .text-area {
+        width: 100%;
+        height: 132px;
+        overflow-y: scroll;
+        background: #f9f9f9;
+        border-radius: 4px 4px 4px 4px;
+        border: 1px solid #c7ceda;
+        padding: 5px 10px;
+      }
+      .area2 {
+        height: 90px;
+        .work-time {
+          font-weight: bold;
+          font-size: 14px;
+          color: #1b80eb;
+        }
+      }
+      .tag-list {
+        width: 100%;
+        max-height: 65px;
+        overflow-y: scroll;
+        .el-tag {
+          margin-right: 8px;
+        }
+      }
+    }
+  }
+  .comment-box {
+    width: 100%;
+    padding-left: 100px;
+    .comment-list {
+      height: 180px;
+      overflow-y: scroll;
+      background: #f7f8fa;
+      border-radius: 4px 4px 4px 4px;
+      border: 1px solid #eef2f9;
+      padding: 10px;
+      .item {
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        border-bottom: 1px solid #e3eaf5;
+        height: 85px;
+        .left {
+          width: 80px;
+          text-align: center;
+          span {
+            display: inline-block;
+            width: 44px;
+            height: 44px;
+            line-height: 44px;
+            color: #ffffff;
+            background-color: #5a99e3;
+            font-size: 14px;
+            font-weight: 400;
+            border-radius: 50%;
+          }
+        }
+        .right {
+          font-weight: 400;
+          font-size: 14px;
+          color: #121518;
+          line-height: 16px;
+          .title {
+            font-weight: 400;
+            font-size: 14px;
+            color: #8a94a4;
+            margin-bottom: 8px;
+            span {
+              color: #1b80eb;
+              margin-left: 15px;
+              cursor: pointer;
+            }
+          }
+        }
+      }
+    }
+    .comment-emoji {
+      height: 50px;
+      line-height: 50px;
+      display: flex;
+      justify-content: space-between;
+      font-size: 14px;
+      color: #626b70;
+      span {
+        cursor: pointer;
+      }
+    }
+    .comment-input {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      .submit {
+        margin-left: 10px;
+      }
+    }
+  }
+}
+</style>

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

@@ -17,7 +17,10 @@
           @mouseout="onMouseOut(data)"
         >
           <p :class="data.isSelected ? 'is-selected' : ''">
-            {{ dayReportMap[data.day]?.show }}
+            <span v-if="getDayClass(data.day) == 'square-leave'" class="glary">{{
+              dayReportMap[data.day]?.show
+            }}</span>
+            <span v-else>{{ dayReportMap[data.day]?.show }}</span>
           </p>
         </div>
 
@@ -31,6 +34,7 @@
           <el-icon v-if="getDayClass(data.day) == 'square-unfilled'"><CloseBold /></el-icon>
           <el-icon v-if="getDayClass(data.day) == 'square-today'"><EditPen /></el-icon>
           <el-icon v-if="getDayClass(data.day) == 'square-future'"><MoreFilled /></el-icon>
+          <span v-if="getDayClass(data.day) == 'square-leave'">假</span>
         </div>
       </template>
     </el-calendar>
@@ -54,16 +58,17 @@ const calendar = ref()
 const todayValue = ref(new Date())
 
 watch(todayValue, () => {
-  // console.log(
-  //   'dayReportMap.value',
-  //   moment(todayValue.value).format('YYYY-MM-DD'),
-  //   dayReportMap.value
-  // )
-  // 如果选中的是今天之后的日期,则不进行点击及跳转
+  // 1、如果请假,则不进行跳转
+  const today = moment(todayValue.value).format('YYYY-MM-DD')
+  const { isworkday = 0, state = '' } = dayReportMap.value[today] ?? {}
+  // 2、如果选中的是今天之后的日期,则不进行点击及跳转
   const isAfterToday = moment(todayValue.value).isAfter(moment())
   if (isAfterToday) {
     todayValue.value = new Date()
     message.info('仅可对今日及之前的日志进行填报!')
+  } else if (isworkday && leaveList.includes(state)) {
+    todayValue.value = new Date()
+    message.info('请假当天日志不需要填报!')
   } else {
     $emit('click', dayReportMap.value[moment(todayValue.value).format('YYYY-MM-DD')])
   }
@@ -114,12 +119,14 @@ const leaveMap = {
   13: '婚假',
   14: '产假',
   15: '陪产假',
-  19: '丧假',
   16: '工伤',
   17: '年假',
   18: '调休',
+  19: '丧假',
   20: '其他'
 }
+// 所有请假的代码,参考leaveMap
+const leaveList = ['5', '11', '12', '13', '14', '15', '16', '17', '18', '19']
 
 const dailyReportAttendances = ref<ItemState[]>([])
 const nowMonths: any = ref(moment().format('YYYY-MM'))
@@ -179,6 +186,7 @@ const initDailyReportData = async (): Promise<any> => {
         item['attendanceStatus']
     }
   })
+
   //节假日统计
   const workdays: any[] = await getWorkDayList()
   const dailyReportList: any[] = []
@@ -237,21 +245,24 @@ const initDailyReportData = async (): Promise<any> => {
 /**
  * 日报样式设置
  * 1、已填,绿色三角+对勾 square-filled
- *    state == 99
+ *    isworkday == 1, isLog
  * 2、未填,红色三角+错号 square-unfilled
- *    state == -1
+ *    isworkday == 0, isLog == false
  * 3、当天,蓝色三角+画笔 square-today
  * 4、未到,灰色三角+省略 square-future
+ * 5、请假,橙色三角+假   square-leave
  */
 const getDayClass = (data) => {
-  const { isworkday = 0, state = '', date = '' } = dayReportMap.value[data] ?? {}
+  const { isworkday = 0, state = '', date = '', isLog } = dayReportMap.value[data] ?? {}
   const isFuture = moment(date).isAfter(moment())
   if (date == moment().format('YYYY-MM-DD')) {
     return `square-today`
   }
-  if (isworkday && state != -1 && !isFuture) {
+  if (isworkday && isLog && !isFuture) {
     return `square-filled`
-  } else if (isworkday && !isFuture) {
+  } else if (isworkday && leaveList.includes(state) && !isFuture) {
+    return `square-leave`
+  } else if (isworkday && !isLog && !isFuture) {
     return `square-unfilled`
   } else if (isworkday && isFuture) {
     return `square-future`
@@ -322,6 +333,10 @@ const onMouseOut = (data) => {
         top: 0;
         right: 0;
       }
+
+      .glary {
+        color: #ccc;
+      }
     }
     .square-filled {
       ::before {
@@ -343,6 +358,11 @@ const onMouseOut = (data) => {
         border-right: 30px solid #c9cdd8;
       }
     }
+    .square-leave {
+      ::before {
+        border-right: 30px solid #f1a256;
+      }
+    }
     .is-selected {
       color: #1989fa;
     }

+ 5 - 2
client/src/views/OaSystem/personnelManagement/dailyCenter/dailyCenter.vue

@@ -5,7 +5,10 @@
       <div class="calendarBox">
         <OaCalendar @click="dateOnChange" />
       </div>
-      <div class="contentBox">
+      <div class="contentBox" v-if="writeData.isLog">
+        <DetailBox :detail="writeData.isLog" />
+      </div>
+      <div class="contentBox" v-else>
         <EditorDetail :writeData="writeData" />
       </div>
     </div>
@@ -14,6 +17,7 @@
 
 <script setup lang="ts">
 import OaCalendar from './OaCalendar.vue'
+import DetailBox from './DetailBox.vue'
 import EditorDetail from './editorDetail.vue'
 import moment from 'moment'
 defineOptions({ name: 'DailyCenter' })
@@ -31,7 +35,6 @@ const writeData = ref<any>({
   date: moment().format('YYYY-MM-DD')
 })
 const dateOnChange = (date) => {
-  // console.log('dateOnChange', date)
   writeData.value = date
 }
 </script>

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

@@ -72,7 +72,6 @@ watch(
   () => writeData.value?.date,
   () => {
     initLog()
-    console.log('writeData', writeData.value)
   }
 )
 

+ 4 - 3
client/src/views/OaSystem/personnelManagement/dailyDetail/DetailBox.vue

@@ -7,9 +7,6 @@ interface IProp {
 }
 const { detail } = defineProps<IProp>()
 
-// onMounted(() => {
-//   console.log('detail', detail)
-// })
 // const emojiObj = {
 //   'emoji-good': '赞!👍',
 //   'emoji-very-good': '写的太棒了!👏',
@@ -64,6 +61,10 @@ const getCommentList = async () => {
   commentList.value = result
 }
 const commentInput = ref('')
+
+onMounted(() => {
+  getCommentList()
+})
 </script>
 <template>
   <div class="detail-box">

+ 11 - 5
client/src/views/OaSystem/personnelManagement/dailyDetail/OaCalendar.vue

@@ -29,6 +29,7 @@
           <el-icon v-if="getDayClass(data.day) == 'square-unfilled'"><CloseBold /></el-icon>
           <!-- <el-icon v-if="getDayClass(data.day) == 'square-today'"><EditPen /></el-icon> -->
           <el-icon v-if="getDayClass(data.day) == 'square-future'"><MoreFilled /></el-icon>
+          <span v-if="getDayClass(data.day) == 'square-leave'">假</span>
         </div>
       </template>
     </el-calendar>
@@ -88,6 +89,8 @@ const leaveMap = {
   18: '调休',
   20: '其他'
 }
+// 所有请假的代码,参考leaveMap
+const leaveList = ['5', '11', '12', '13', '14', '15', '16', '17', '18', '19']
 
 const dailyReportAttendances = ref<ItemState[]>([])
 const nowMonths: any = ref(moment(detailTime).format('YYYY-MM'))
@@ -205,21 +208,24 @@ const initDailyReportData = async (): Promise<any> => {
 /**
  * 日报样式设置
  * 1、已填,绿色三角+对勾 square-filled
- *    state == 99
+ *    isworkday == 1, isLog
  * 2、未填,红色三角+错号 square-unfilled
- *    state == -1
+ *    isworkday == 0, isLog == false
  * 3、当天,蓝色三角+画笔 square-today
  * 4、未到,灰色三角+省略 square-future
+ * 5、请假,橙色三角+假   square-leave
  */
 const getDayClass = (data) => {
-  const { isworkday = 0, state = '', date = '' } = dayReportMap.value[data] ?? {}
+  const { isworkday = 0, state = '', date = '', isLog } = dayReportMap.value[data] ?? {}
   const isFuture = moment(date).isAfter(moment())
   // if (date == moment().format('YYYY-MM-DD')) {
   //   return `square-today`
   // }
-  if (isworkday && state != -1 && !isFuture) {
+  if (isworkday && isLog && !isFuture) {
     return `square-filled`
-  } else if (isworkday && !isFuture) {
+  } else if (isworkday && leaveList.includes(state) && !isFuture) {
+    return `square-leave`
+  } else if (isworkday && !isLog && !isFuture) {
     return `square-unfilled`
   } else if (isworkday && isFuture) {
     return `square-future`

+ 259 - 0
client/src/views/OaSystem/personnelManagement/weeklyCenter/DetailBox.vue

@@ -0,0 +1,259 @@
+<script lang="ts" setup>
+import moment from 'moment'
+import request from '@/config/axios'
+import { getUserInfo } from '@/utils/tool'
+interface IProp {
+  detail: any
+}
+const { detail } = defineProps<IProp>()
+
+const emojiList = ['赞!👍', '写的太棒了!👏', '学习了🌹', '感谢你的分享🙏', '加油💪', '早点休息😴']
+
+const message = useMessage()
+const userInfo = getUserInfo()
+// 评论字段
+interface IComment {
+  reportId: string // 报告id
+  commentUserId: string // 评论人用户id
+  commentContent: string // 评论内容
+  commentDate?: string // 评论时间
+  replyToUserid?: string // 被回复人用户ID
+}
+// 提交评论
+const submitComment = async (content?) => {
+  if (!content && commentInput.value == '') {
+    message.info('评论内容不能为空!')
+    return
+  }
+  const data = {
+    reportId: detail.id,
+    commentUserId: userInfo.id ?? '',
+    commentContent: content ?? commentInput.value
+  }
+  const result: any = await request.postOriginal({ url: '/adm/reportComment/send', data })
+  if (result.msg == 'success') {
+    getCommentList()
+    message.success('评论成功!')
+    // 清空输入框
+    if (!content) {
+      commentInput.value = ''
+    }
+  } else {
+    message.error('评论失败,请稍后再试')
+  }
+}
+const commentList = ref<any[]>(detail?.comments ?? [])
+// 获取报告被评论列表
+const getCommentList = async () => {
+  const result = await request.get({
+    url: '/adm/reportComment/getList',
+    params: { reportId: detail?.id, uId: detail?.userId }
+  })
+  commentList.value = result
+}
+const commentInput = ref('')
+
+onMounted(() => {
+  getCommentList()
+})
+</script>
+<template>
+  <div class="detail-box">
+    <div class="form-box">
+      <el-form ref="form" label-width="100px">
+        <el-row :gutter="24">
+          <el-col :span="8">
+            <el-form-item class="label-item" label="日志日期">
+              <div class="write-date">
+                {{ moment(detail.reportStartDate).format('YYYY-MM-DD') }}
+              </div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="16">
+            <el-form-item class="label-item" label="接收人">
+              <div class="tag-list">
+                <el-tag
+                  type="info"
+                  effect="light"
+                  v-for="(item, index) in detail.receiveNames"
+                  :key="index"
+                  >{{ item }}</el-tag
+                >
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24" style="height: 100%">
+            <el-form-item class="label-item" label="今日工作">
+              <div
+                class="text-area"
+                v-html="detail?.reportContent?.replace(/(\r\n|\n|\r)/gm, '<br />')"
+              >
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24" style="height: 100%">
+            <el-form-item class="label-item" label="工作量分配">
+              <div class="text-area area2">
+                <div v-for="(item, index) in detail.workload" :key="index">
+                  <span class="work-time">{{ `(${item.workTime}小时)` }}</span>
+                  <span>{{ item.projectName }}</span>
+                </div>
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </div>
+    <div class="comment-box">
+      <div class="comment-list">
+        <div v-if="commentList.length === 0" class="not-comment">
+          <el-empty description="暂无评论" image-size="35" />
+        </div>
+        <div v-else v-for="(item, index) in commentList" :key="index" class="item">
+          <div class="left">
+            <span>{{ item.commentUserName.substr(-2) }}</span>
+          </div>
+          <div class="right">
+            <div class="title">
+              {{
+                `${item.commentUserName} ${moment(item.commentDate).format('YYYY-MM-DD HH:mm:ss')}`
+              }}
+              <span>删除</span>
+            </div>
+            <div>{{ item.commentContent }}</div>
+          </div>
+        </div>
+      </div>
+      <div class="comment-emoji">
+        <span v-for="(item, index) in emojiList" :key="index" @click="submitComment(item)">{{
+          item
+        }}</span>
+      </div>
+      <div class="comment-input">
+        <el-input v-model="commentInput" placeholder="请输入评论内容" />
+        <el-button class="submit" type="primary" @click="submitComment()">发表评价</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+<style scoped lang="scss">
+.detail-box {
+  width: 100%;
+  height: 100%;
+  .form-box {
+    width: 100%;
+    .label-item {
+      .el-form-item__label {
+        font-weight: 400 !important;
+        font-size: 16px !important;
+      }
+      .write-date {
+        width: 100px;
+        border: 1px solid #dee0e3;
+        border-radius: 4px;
+        text-align: center;
+        background: #f9f9f9;
+      }
+      .text-area {
+        width: 100%;
+        height: 132px;
+        overflow-y: scroll;
+        background: #f9f9f9;
+        border-radius: 4px 4px 4px 4px;
+        border: 1px solid #c7ceda;
+        padding: 5px 10px;
+      }
+      .area2 {
+        height: 90px;
+        .work-time {
+          font-weight: bold;
+          font-size: 14px;
+          color: #1b80eb;
+        }
+      }
+      .tag-list {
+        width: 100%;
+        max-height: 65px;
+        overflow-y: scroll;
+        .el-tag {
+          margin-right: 8px;
+        }
+      }
+    }
+  }
+  .comment-box {
+    width: 100%;
+    padding-left: 100px;
+    .comment-list {
+      height: 180px;
+      overflow-y: scroll;
+      background: #f7f8fa;
+      border-radius: 4px 4px 4px 4px;
+      border: 1px solid #eef2f9;
+      padding: 10px;
+      .item {
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        border-bottom: 1px solid #e3eaf5;
+        height: 85px;
+        .left {
+          width: 80px;
+          text-align: center;
+          span {
+            display: inline-block;
+            width: 44px;
+            height: 44px;
+            line-height: 44px;
+            color: #ffffff;
+            background-color: #5a99e3;
+            font-size: 14px;
+            font-weight: 400;
+            border-radius: 50%;
+          }
+        }
+        .right {
+          font-weight: 400;
+          font-size: 14px;
+          color: #121518;
+          line-height: 16px;
+          .title {
+            font-weight: 400;
+            font-size: 14px;
+            color: #8a94a4;
+            margin-bottom: 8px;
+            span {
+              color: #1b80eb;
+              margin-left: 15px;
+              cursor: pointer;
+            }
+          }
+        }
+      }
+    }
+    .comment-emoji {
+      height: 50px;
+      line-height: 50px;
+      display: flex;
+      justify-content: space-between;
+      font-size: 14px;
+      color: #626b70;
+      span {
+        cursor: pointer;
+      }
+    }
+    .comment-input {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      .submit {
+        margin-left: 10px;
+      }
+    }
+  }
+}
+</style>

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

@@ -5,7 +5,10 @@
       <div class="calendarBox">
         <WeekCalendar :onChange="onChange" />
       </div>
-      <div class="contentBox">
+      <div class="contentBox" v-if="writeData.isLog">
+        <DetailBox :detail="writeData.isLog" />
+      </div>
+      <div class="contentBox" v-else>
         <EditorDetail :weekDate="writeData.weekDate" :writeData="writeData" />
       </div>
     </div>
@@ -14,6 +17,7 @@
 
 <script setup lang="ts">
 import WeekCalendar from './WeekCalendar.vue'
+import DetailBox from './DetailBox.vue'
 import EditorDetail from './editorDetail.vue'
 import moment from 'moment'
 // import request from '@/config/axios'