Bladeren bron

Merge remote-tracking branch 'origin/master'

hotchicken1996 1 maand geleden
bovenliggende
commit
1a8a1177ab

BIN
client/src/assets/imgs/OA/news_icon.png


BIN
client/src/assets/imgs/OA/notify_icon.png


+ 8 - 0
client/src/router/modules/remaining.ts

@@ -168,6 +168,14 @@ const remainingRouter: AppRouteRecordRaw[] = [
           title: '报表打印'
         }
       },
+      {
+        path: 'dailyNotify',
+        component: () => import('@/views/OaSystem/newsCenter/dailyNotify/index.vue'),
+        name: 'dailyNotify',
+        meta: {
+          title: '每日速递'
+        }
+      },
       {
         path: 'newsEditor',
         component: () => import('@/views/OaSystem/newsCenter/newsSetting/editor.vue'),

+ 447 - 0
client/src/views/OaSystem/newsCenter/dailyNotify/index.vue

@@ -0,0 +1,447 @@
+<template>
+  <div class="daily_notify_box">
+    <div class="top_box">
+      <div class="filter_tags">
+        <span
+          v-for="(item, index) in tabs"
+          :key="index"
+          :class="{ active: currentTab === item['index'] }"
+          @click="switchTabHandle(item)"
+          >{{ item['title'] }}({{ item['num'] }})</span
+        >
+      </div>
+      <el-button type="primary" @click="onOperateHandle('add')">新增</el-button>
+    </div>
+    <div class="table" ref="tableRef">
+      <el-table
+        stripe
+        :data="tableData"
+        :header-cell-style="{
+          background: '#E5F0FB',
+          color: '#233755',
+          height: '50px'
+        }"
+      >
+        <el-table-column label="序号" width="80">
+          <template #default="scope">{{ scope.$index + 1 }}</template>
+        </el-table-column>
+        <el-table-column prop="nickname" label="发布人" width="320" />
+        <el-table-column prop="createTime" label="发布时间" width="280">
+          <template #default="scope">
+            <span>{{ scope.row.createTime }}</span>
+            <span class="news" v-if="currentTab !== '1' && scope.row['isToday']"
+              ><img src="../../../../assets/imgs/OA/news_icon.png"
+            /></span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="content" label="发布内容" />
+
+        <el-table-column label="操作" width="180" align="center">
+          <template #default="scope">
+            <div class="operateBtn">
+              <span @click="onOperateHandle('look', scope.row)">查看</span>
+              <span v-if="currentTab === '3'" @click="onOperateHandle('editor', scope.row)"
+                >编辑</span
+              >
+              <dialog-confirm
+                title="确定要删除该条数据?"
+                width="280px"
+                v-if="currentTab === '3'"
+                @confirm="onDeleteHandle(scope.row)"
+              >
+                <template #reference>
+                  <span class="delete">删除</span>
+                </template>
+              </dialog-confirm>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="pageBox" v-if="currentTab == '2'">
+      <el-pagination
+        v-model:current-page="pageData.pageNo"
+        :page-size="pageData.pageSize"
+        background
+        layout="total, prev, pager, next, jumper"
+        :total="pageData.total"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+    <el-dialog
+      v-model="dialogVisible"
+      width="600px"
+      :close-on-click-modal="false"
+      :title="
+        '每日速递' + (operateType === 'add' ? '新增' : operateType === 'editor' ? '编辑' : '查看')
+      "
+    >
+      <div class="dailyNotifyDetail" v-if="operateType === 'look'">
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><UserFilled /></el-icon>
+            发布人:
+          </span>
+          <span>{{ formData.nickname }}</span>
+        </div>
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><BellFilled /></el-icon>
+            发布时间:
+          </span>
+          <span>{{ formData.createTime }}</span>
+        </div>
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><Comment /></el-icon>
+            发布内容:
+          </span>
+          <span>{{ formData.content }}</span>
+        </div>
+      </div>
+      <div v-else class="dailyNotifyDetail">
+        <el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
+          <el-form-item label="发布人:">
+            <template #label>
+              <span class="dialog_label_icon">
+                <el-icon class="icon" size="18"><UserFilled /></el-icon>
+                发布人:
+              </span>
+            </template>
+            <span>{{ formData.nickname }}</span>
+          </el-form-item>
+          <template v-if="operateType !== 'look'">
+            <el-form-item label="发布内容:" prop="content">
+              <template #label>
+                <span class="dialog_label_icon">
+                  <el-icon class="icon" size="18"><Comment /></el-icon>
+                  发布内容:
+                </span>
+              </template>
+              <el-input
+                v-model="formData.content"
+                maxlength="200"
+                placeholder="请输入您的发布内容,最多200字"
+                show-word-limit
+                :rows="8"
+                type="textarea"
+              />
+            </el-form-item>
+          </template>
+          <template v-else>
+            <el-form-item label="发布内容:">
+              <span>{{ formData.content }}</span>
+            </el-form-item>
+          </template>
+        </el-form>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="dialogVisible = false" v-if="operateType === 'look'">
+            关闭
+          </el-button>
+          <el-button type="primary" @click="onSubmitHandle" v-if="operateType !== 'look'">
+            保存
+          </el-button>
+          <el-button @click="dialogVisible = false" v-if="operateType !== 'look'"> 取消 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup lang="ts">
+import request from '@/config/axios'
+import { ElMessage } from 'element-plus'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+defineOptions({ name: 'ProjectBook' })
+const tableRef: any = ref(null)
+
+interface TabType {
+  title: string
+  index: string
+  num: number
+}
+const currentTab = ref<string>('0')
+const switchTabHandle = (item: TabType) => {
+  currentTab.value = item.index
+  if (currentTab.value === '2') {
+    queryDailyNotifyByPage()
+  } else {
+    tableData.value = listMap.value[currentTab.value]
+  }
+}
+const tabs = ref<TabType[]>([
+  {
+    title: '近三日',
+    index: '0',
+    num: 0
+  },
+  {
+    title: '今日',
+    index: '1',
+    num: 0
+  },
+  {
+    title: '所有',
+    index: '2',
+    num: 0
+  },
+  {
+    title: '我的',
+    index: '3',
+    num: 0
+  }
+])
+const queryDailyNotifyTotal = async () => {
+  const sendData = {
+    type: 3,
+    readType: 2
+  }
+  const urlApi = `/adm/noticeAndLearn/query/total`
+  const result = await request.post({ url: urlApi, data: sendData })
+  tabs.value = result
+}
+const pageData = ref<{
+  pageNo: number
+  pageSize: number
+  total?: number
+}>({
+  pageNo: 1,
+  pageSize: 10,
+  total: 0
+})
+const tableData = ref<Array<any>>([])
+const total = ref<number>()
+const queryDailyNotifyByPage = async (): Promise<void> => {
+  const urlApi = `/adm/noticeAndLearn/query/page`
+  const sendData = {
+    type: 3,
+    readType: 2,
+    ...pageData.value
+  }
+  const result = await request.post({ url: urlApi, data: sendData })
+  tableData.value = result['list']
+  total.value = result['total']
+}
+const handleCurrentChange = () => {}
+/**
+ * 数据列表分组
+ */
+const listMap = ref<any>({})
+const queryDailyNotifyGroup = async () => {
+  const sendData = {
+    type: 3,
+    readType: 2
+  }
+  const result = await request.post({
+    url: '/adm/noticeAndLearn/query/group',
+    data: sendData
+  })
+  const resultData = result
+  if (resultData) {
+    listMap.value = resultData
+  }
+}
+const initDailyNotifyData = () => {
+  currentTab.value = '0'
+  queryDailyNotifyGroup()
+  queryDailyNotifyByPage()
+  queryDailyNotifyTotal()
+}
+initDailyNotifyData()
+/**
+ * 速递查看、编辑、删除
+ */
+const dialogVisible = ref<boolean>(false)
+const formData = ref({
+  id: '',
+  nickname: '',
+  createTime: '',
+  content: ''
+})
+const { wsCache } = useCache()
+const user = wsCache.get(CACHE_KEY.USER)
+const operateType = ref('add')
+const onOperateHandle = (type: string, item = null): void => {
+  dialogVisible.value = true
+  operateType.value = type
+  formData.value['id'] = ''
+  if (type !== 'add' && item) {
+    formData.value['id'] = item['id']
+    formData.value['nickname'] = item?.['nickname']
+    formData.value['createTime'] = item?.['createTime']
+    formData.value['content'] = item?.['content']
+  } else {
+    formData.value['nickname'] = `${user.user.deptName}-${user.user.nickname}`
+    formData.value['content'] = ''
+    formData.value['createTime'] = ''
+  }
+}
+const isDisabled = ref(false)
+const rules = reactive({
+  content: [{ required: true, message: '内容不能为空!', trigger: 'blur' }]
+})
+const formRef = ref<any>(null)
+const onSubmitHandle = async () => {
+  if (!formRef.value) return
+  await formRef.value.validate(async (valid, fields) => {
+    if (valid) {
+      const urlApi = formData.value.id ? '/adm/noticeAndLearn/update' : '/adm/noticeAndLearn/add'
+      const sendData = {
+        type: '3',
+        nickname: formData.value.nickname,
+        content: formData.value.content
+      }
+      if (formData.value.id) {
+        sendData['id'] = formData.value.id
+      }
+      isDisabled.value = true
+      const result = await request.post({ url: urlApi, data: sendData })
+      if (result) {
+        ElMessage({
+          type: 'success',
+          message: '保存成功!'
+        })
+        initDailyNotifyData()
+        isDisabled.value = false
+        dialogVisible.value = false
+      }
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+const onDeleteHandle = async (item: any) => {
+  const result = await request.get({ url: `/adm/noticeAndLearn/delete?id=${item.id}` })
+  if (result) {
+    initDailyNotifyData()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+:deep(.el-dialog) {
+  border-radius: 10px;
+  overflow: hidden;
+  .el-dialog__header {
+    background: #f3f7fe;
+    margin-right: 0px;
+    padding: 15px 20px;
+    > span {
+      font-weight: bold;
+    }
+  }
+  .el-form-item__label,
+  .el-form-item__content {
+    font-size: 17px;
+  }
+  .el-form-item__label:before {
+    display: none;
+  }
+}
+.dailyNotifyDetail {
+  padding: 0px 20px;
+  padding-bottom: 20px;
+  .dialog_label_icon {
+    display: inline-block;
+    width: 120px;
+    display: flex;
+    align-items: center;
+    > .icon {
+      color: #0079ee;
+      margin-right: 4px;
+    }
+  }
+  > div {
+    padding: 8px;
+    display: flex;
+    align-items: flex-start;
+    > span {
+      color: #333;
+      font-size: 17px;
+      &:nth-child(2) {
+        flex: 1;
+      }
+    }
+  }
+}
+.daily_notify_box {
+  height: 100%;
+  display: flex;
+  margin-top: 20px;
+  padding: 20px;
+  flex-direction: column;
+  background: #fff;
+  > .top_box {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 15px;
+    > .filter_tags {
+      display: inline-block;
+      background-color: #fff;
+      border: 1px solid #dfe0e4;
+      border-radius: 4px;
+      width: max-content;
+      margin-right: 10px;
+      > span {
+        display: inline-block;
+        color: #111;
+        font-size: 13px;
+        padding: 8px 15px;
+        cursor: pointer;
+        &:not(:first-child) {
+          border-left: 1px solid #dfe0e4;
+          border-right: 1px solid transparent;
+        }
+        &:first-child {
+          border-left: 1px solid transparent;
+        }
+        &.active {
+          color: #2b82f1;
+          border: 1px solid #2b82f1;
+          border-radius: 4px;
+        }
+      }
+    }
+  }
+  > .table {
+    width: 100%;
+    flex: 1;
+    > .table {
+      width: 100%;
+    }
+  }
+  > .pageBox {
+    padding: 20px 0px 10px 0px;
+    display: flex;
+    justify-content: right;
+  }
+}
+.operateBtn {
+  > span {
+    margin: 0px 10px;
+    cursor: pointer;
+    &:nth-child(1),
+    &:nth-child(2) {
+      color: #2e77e6;
+    }
+    &:nth-child(3) {
+      color: red;
+    }
+  }
+}
+
+.news {
+  > img {
+    height: 20px;
+    margin-left: 4px;
+    margin-top: -2px;
+    vertical-align: middle;
+  }
+}
+:deep(.el-radio) {
+  margin-right: 10px;
+}
+</style>

+ 2 - 2
client/src/views/OaSystem/newsCenter/newsLook/index.vue

@@ -15,7 +15,7 @@
     <div class="pageBox">
       <el-pagination
         v-model:current-page="pageNo"
-        :page-size="8"
+        :page-size="9"
         background
         layout="total, prev, pager, next"
         :total="total"
@@ -36,7 +36,7 @@ const queryArticleByPage = async (): Promise<void> => {
   const urlApi = `/adm/article/query/page`
   const sendData = {
     pageNo: pageNo.value,
-    pageSize: 8,
+    pageSize: 9,
     title: '',
     isPub: 1,
     status: 1

+ 198 - 0
client/src/views/OaSystem/oaLayout/header.vue

@@ -3,6 +3,19 @@
     <div class="header-left">
       <img src="@/assets/imgs/OA/zdww.png" alt="" />
       <p>{{ titleName }} </p>
+      <div class="tips">
+        <div class="left">
+          <img src="../../../assets/imgs/OA/notify_icon.png" />
+          <div>
+            <ul :class="`scroll_ani${dailyNotifyList.length}`">
+              <li v-for="(item, index) in dailyNotifyList" :key="index" @click="onLookDetail(item)">
+                {{ item['content'] }}
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="more" @click="toMoreHandle">更多<span class="arrow">></span></div>
+      </div>
     </div>
     <div class="header-right">
       <Weather />
@@ -16,12 +29,43 @@
         <img src="@/assets/imgs/OA/offLogin.png" alt="" />
       </div>
     </div>
+    <el-dialog v-model="dialogVisible" width="500px" title="每日速递详情">
+      <div class="dailyNotifyDetail">
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><UserFilled /></el-icon>
+            发布人:
+          </span>
+          <span>{{ formData.nickname }}</span>
+        </div>
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><BellFilled /></el-icon>
+            发布时间:
+          </span>
+          <span>{{ formData.createTime }}</span>
+        </div>
+        <div>
+          <span class="dialog_label_icon">
+            <el-icon class="icon" size="18"><Comment /></el-icon>
+            发布内容:
+          </span>
+          <span>{{ formData.content }}</span>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="dialogVisible = false"> 关闭 </el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 <script setup lang="ts">
 import { ElMessageBox } from 'element-plus'
 import { useAppStore } from '@/store/modules/app'
 import { useUserStore } from '@/store/modules/user'
+import request from '@/config/axios'
 import Cookies from 'js-cookie'
 import Weather from './weather.vue'
 const { replace } = useRouter()
@@ -51,10 +95,61 @@ const removeCokLog = () => {
     Cookies.remove(cookiesAll[i])
   }
 }
+const dailyNotifyList = ref([])
+async function queryNotifyByNewThree() {
+  const urlApi = `/adm/noticeAndLearn/query/page`
+  const sendData = {
+    pageNo: 1,
+    pageSize: 3,
+    type: 3,
+    nickname: '',
+    title: '',
+    readType: 2
+  }
+  const result = await request.post({ url: urlApi, data: sendData })
+  if (result) {
+    dailyNotifyList.value = result.list
+  }
+}
+queryNotifyByNewThree()
+const formData = ref({
+  id: '',
+  nickname: '',
+  createTime: '',
+  content: ''
+})
+const dialogVisible = ref(false)
+const onLookDetail = (item) => {
+  if (item) {
+    formData.value['id'] = item['id']
+    formData.value['nickname'] = item?.['nickname']
+    formData.value['createTime'] = item?.['createTime']
+    formData.value['content'] = item?.['content']
+    dialogVisible.value = true
+  }
+}
+const router = useRouter()
+const toMoreHandle = () => {
+  router.push({
+    path: '/dailyNotify'
+  })
+}
 /** 初始化 **/
 onMounted(() => {})
 </script>
 <style lang="scss" scoped>
+:deep(.el-dialog) {
+  border-radius: 10px;
+  overflow: hidden;
+  .el-dialog__header {
+    background: #f3f7fe;
+    margin-right: 0px;
+    padding: 15px 20px;
+    > span {
+      font-weight: bold;
+    }
+  }
+}
 .header {
   width: calc(100%);
   height: 60px;
@@ -68,6 +163,83 @@ onMounted(() => {})
     display: flex;
     align-items: center;
     min-width: 466px;
+    > .tips {
+      background: rgba(255, 255, 255, 0.6);
+      border-radius: 10px;
+      display: flex;
+      align-items: center;
+      padding: 5px 10px;
+      margin-left: 20px;
+      > .left {
+        display: flex;
+        align-items: center;
+        color: #0e1f38;
+        font-size: 14px;
+        > img {
+          width: 15px;
+          height: 15px;
+          margin-right: 4px;
+        }
+        > div {
+          height: 22px;
+          overflow: hidden;
+          > ul {
+            &.scroll_ani2 {
+              animation: scroll2 6s infinite;
+            }
+            &.scroll_ani3 {
+              animation: scroll3 9s infinite;
+            }
+            > li {
+              max-width: 460px;
+              white-space: nowrap;
+              text-overflow: ellipsis;
+              overflow: hidden;
+              cursor: pointer;
+            }
+          }
+        }
+        @keyframes scroll2 {
+          0%,
+          37% {
+            transform: translateY(0);
+          }
+          50%,
+          87% {
+            transform: translateY(-20px);
+          }
+          100% {
+            transform: translateY(0);
+          }
+        }
+        @keyframes scroll3 {
+          0%,
+          25% {
+            transform: translateY(0);
+          }
+          33.33%,
+          58.33% {
+            transform: translateY(-20px);
+          }
+          66.66%,
+          91.66% {
+            transform: translateY(-41px);
+          }
+          100% {
+            transform: translateY(0);
+          }
+        }
+      }
+      > .more {
+        margin-left: 20px;
+        font-size: 12px;
+        color: #333333;
+        cursor: pointer;
+        > .arrow {
+          margin-left: 3px;
+        }
+      }
+    }
     img {
       width: 48px;
       height: 48px;
@@ -103,4 +275,30 @@ onMounted(() => {})
     }
   }
 }
+.dailyNotifyDetail {
+  padding: 0px 20px;
+  padding-bottom: 20px;
+  .dialog_label_icon {
+    display: inline-block;
+    width: 120px;
+    display: flex;
+    align-items: center;
+    > .icon {
+      color: #0079ee;
+      margin-right: 4px;
+    }
+  }
+  > div {
+    padding: 8px;
+    display: flex;
+    align-items: flex-start;
+    > span {
+      color: #333;
+      font-size: 17px;
+      &:nth-child(2) {
+        flex: 1;
+      }
+    }
+  }
+}
 </style>

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

@@ -128,7 +128,7 @@ const setRateData = (rateTree) => {
           deptId: item.deptId
         })
       }
-    } else if (data.deptName === '北京分公司') {
+    } else if (['北京分公司', '杭州万维点石科技有限公司'].includes(data.deptName)) {
       // 因为北京分公司暂无下属部门,以防后期添加,先这样处理
       rataData.push({
         ...data,

+ 5 - 1
client_h5/src/pages/dailyNotify/detail.vue

@@ -3,6 +3,7 @@
   <div class="dailyNotifyDetail">
     <div class="box">
       <div class="userInfo">发布人:<span>{{ detailData['nickname'] }}</span></div>
+      <div class="createTime">发布时间:<span>{{ detailData['createTime'] }}</span></div>
       <div class="content">
         {{ detailData['content'] }}
       </div>
@@ -56,12 +57,15 @@ const onBackHandle = ()=>{
     background: #fff;
     border-radius: 5px;
     padding: 15px;
-    >.userInfo {
+    >.userInfo,>.createTime {
       color: #111;
       font-size: 15px;
       padding-bottom: 12px;
       border-bottom: 1px solid #EFF1F5;
     }
+    >.createTime {
+      padding: 12px 0px;
+    }
     >.content {
       color: #111;
       font-size: 15px;

+ 15 - 5
client_h5/src/pages/dailyNotify/index.vue

@@ -96,7 +96,6 @@ const queryDailyNotifyTotal = () => {
     }
   });
 }
-queryDailyNotifyTotal()
 
 const loading = ref(false);
 const finished = ref(false);
@@ -115,7 +114,7 @@ const pageData = ref<{
   total?: number
 }>({
   pageNo: 0,
-  pageSize: 10,
+  pageSize: 8,
   total: 0
 })
 /**
@@ -133,14 +132,17 @@ const queryDailyNotifyByPage = (isPull = false) => {
     readType: 2,
     ...pageData.value
   }
+  if(pageData.value.pageNo === 1) noticeLists.value = []
   reqest.post('/admin-api/adm/noticeAndLearn/query/page', sendData).then((result: any) => { 
     const resultData = result.data;
     if (resultData) {
       if (resultData && resultData.list) {
-        isPull ? noticeLists.value = resultData.list : noticeLists.value?.push(...resultData.list) 
+        (isPull) ? noticeLists.value = resultData.list : noticeLists.value?.push(...resultData.list) 
       }
       if (isPull) {
         refreshing.value = false
+      } else {
+        loading.value = false
       }
       /** 用来解决tab切换时,容器高度发生变化自动触发loading事件 */
       const time = setTimeout(() => {
@@ -173,7 +175,15 @@ const queryDailyNotifyGroup = () => {
     }
   });
 }
-queryDailyNotifyGroup();
+const initDailyNotifyData = () => {
+  pageData.value.pageNo = 0
+  loading.value = false
+  finished.value = false
+  refreshing.value = false
+  queryDailyNotifyTotal()
+  queryDailyNotifyGroup()
+}
+initDailyNotifyData()
 const router = useRouter()
 const clickHandler = (item: any) => {
   router.push({
@@ -193,7 +203,7 @@ const onDeleteHandle = (item: any) => {
         duration: 800,
         position: 'top',
         onOpened() {
-          queryDailyNotifyGroup();
+          initDailyNotifyData();
         }
       });
     }