فهرست منبع

值班管理 值班日历

Hwf 10 ماه پیش
والد
کامیت
758dbee17d

+ 1 - 1
src/components/Calendar/index.vue

@@ -143,7 +143,7 @@ onMounted(() => {
 </script>
 <style lang="scss" scoped>
 .calendar {
-  width: 355px;
+  width: 100%;
   user-select: none;
   background-color: #ffffff;
   color: #414f64;

+ 2 - 2
src/components/Tabbar/index.vue

@@ -78,9 +78,9 @@ watch(() => useUserStore().roles, () => {
       {
         icon: 'contact',
         iconActive: 'contactActive',
-        title: "通讯录",
+        title: "值班管理",
         to: {
-          name: "AddressBook"
+          name: "Duty"
         }
       },
       {

+ 27 - 60
src/router/routes.ts

@@ -140,58 +140,6 @@ export const constantRoutes: Array<RouteRecordRaw> = [
       noCache: true
     }
   },
-  {
-    path: "/worker",
-    name: "Worker",
-    component: Layout,
-    redirect: { name: "WorkerIndex" },
-    children: [
-      {
-        path: "index2",
-        name: "WorkerIndex",
-        component: () => import("@/views/worker/index.vue"),
-        meta: {
-          title: "首页"
-        }
-      },
-      {
-        path: "event",
-        name: "Event",
-        component: () => import("@/views/event/detail.vue"),
-        meta: {
-          title: "事件管理",
-          noCache: true
-        }
-      },
-      {
-        path: "duty",
-        name: "DutyIndex",
-        component: () => import("@/views/duty/index.vue"),
-        meta: {
-          title: "值班管理",
-          noCache: true
-        }
-      },
-      {
-        path: "about2",
-        name: "About",
-        component: () => import("@/views/about/index.vue"),
-        meta: {
-          title: "我的",
-          noCache: true
-        }
-      },
-      {
-        path: "inspectionWork",
-        name: "inspectionWork",
-        component: () => import("@/views/worker/inspectionWork/index.vue"),
-        meta: {
-          title: "巡查工作",
-          noCache: true
-        }
-      }
-    ]
-  },
   {
     path: "/event/index",
     name: "EventList",
@@ -240,14 +188,6 @@ export const constantRoutes: Array<RouteRecordRaw> = [
     meta: {
       title: "风险防控"
     }
-  },
-  {
-    path: "/test",
-    name: "test",
-    component: () => import("@/views/test.vue"),
-    meta: {
-      title: "测试"
-    }
   }
 ];
 
@@ -331,6 +271,33 @@ export const workerRoute = [
           title: "首页",
           noCache: true
         }
+      },
+      {
+        path: "event",
+        name: "Event2",
+        component: () => import("@/views/event/detail.vue"),
+        meta: {
+          title: "事件管理",
+          noCache: true
+        }
+      },
+      {
+        path: "inspectionWork",
+        name: "inspectionWork",
+        component: () => import("@/views/worker/inspectionWork/index.vue"),
+        meta: {
+          title: "巡查工作",
+          noCache: true
+        }
+      },
+      {
+        path: "duty",
+        name: "Duty",
+        component: () => import("@/views/duty/index.vue"),
+        meta: {
+          title: "值班管理",
+          noCache: true
+        }
       }
     ]
   }

+ 175 - 0
src/views/duty/dutyCalendar.vue

@@ -0,0 +1,175 @@
+<template>
+  <div class="calendar-container">
+    <Calendar ref="calendarRef" :current="current" :dotDays="dutyData.dateList" @change="handleChange" />
+    <div class="duty-card">
+      <div class="duty-header">当天值班:{{ parseTime(current, '{y}年{m}月{d}日') }}</div>
+      <div class="duty-content">
+        <div class="duty-item">
+          <div class="item-left">
+            <i class="icon" />
+            <div>带班领导</div>
+          </div>
+          <div class="item-label">{{ dutyData.data1 }}</div>
+        </div>
+        <div class="duty-item">
+          <div class="item-left">
+            <i class="icon" />
+            <div>主班</div>
+          </div>
+          <div class="item-label">{{ dutyData.data2 }}</div>
+        </div>
+        <div class="duty-item">
+          <div class="item-left">
+            <i class="icon" />
+            <div>副班</div>
+          </div>
+          <div class="item-label">{{ dutyData.data3 }}</div>
+        </div>
+        <div class="duty-item">
+          <div class="item-left">
+            <i class="icon" />
+            <div>备班</div>
+          </div>
+          <div class="item-label">{{ dutyData.data4 }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="duty-card">
+      <div class="duty-header">提醒事项</div>
+      <div class="duty-content">
+        <div v-for="(item, index) in dutyData.dataList2" :key="index" class="duty-item2">
+          <div class="text1">{{ item.time }}</div>
+          <div class="text2">{{ item.text }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="duty-card">
+      <div class="duty-header">待办事项</div>
+      <div class="duty-content">
+        <div v-for="(item, index) in dutyData.dataList3" :key="index" class="duty-item2">
+          <div class="text1">{{ item.time }}</div>
+          <div class="text2">{{ item.text }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="footer">
+      <div class="confirm-btn" @click="handleToShiftChange">去交班</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import {onMounted, ref} from "vue";
+import {parseTime} from "@/utils/ruoyi";
+
+let calendarRef = ref();
+const current = ref('');
+const dutyData  = ref({
+  data1: '张珊珊1',
+  data2: '张珊珊2',
+  data3: '张珊珊3',
+  data4: '张珊珊4',
+  dateList: [
+    { date: '2024-10-19', color: '#a2d7f1' },
+    { date: '2024-10-18', color: '#ffd5d8' },
+    { date: '2024-10-17', color: '#ffefcc' },
+    { date: '2024-10-16', color: '#dfdfdf' }
+  ],
+  dataList2: [
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况1。', time: '2024-10-20 11:43:00' },
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况2。', time: '2024-10-20 11:43:00' },
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况3。', time: '2024-10-20 11:43:00' }
+  ],
+  dataList3: [
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作1。', time: '2024-10-20 11:43:00' },
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作2。', time: '2024-10-20 11:43:00' },
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作3。', time: '2024-10-20 11:43:00' }
+  ]
+})
+
+const handleChange = (date) => {
+  current.value = date.value;
+  console.log(current.value)
+}
+
+const initData = () => {
+  current.value = parseTime(new Date(), '{y}-{m}-{d}');
+};
+const emits = defineEmits(['changIndex']);
+const handleToShiftChange = () => {
+  emits('changIndex', 'shiftChange');
+}
+onMounted(() => {
+  initData();
+})
+</script>
+
+<style lang="scss" scoped>
+.calendar-container {
+  .duty-card {
+    margin-top: 16px;
+    width: 100%;
+    background-color: #fff;
+    border-radius: 4px;
+    .duty-header {
+      padding: 10px;
+      font-size: 16px;
+      font-weight: bold;
+      border-bottom: 1px solid #f0f1f1;
+    }
+    .duty-content {
+      padding: 10px;
+      .duty-item {
+        padding: 3px 0;
+        display: flex;
+        justify-content: space-between;
+        align-items: flex-start;
+        font-size: 14px;
+        .item-left {
+          display: flex;
+          align-items: center;
+          .icon {
+            display: inline-block;
+          }
+        }
+      }
+      .duty-item2 {
+        padding: 5px;
+        font-size: 14px;
+        background-color: #f2f2f2;
+        border-radius: 4px;
+        margin-top: 10px;
+        &:first-child {
+          margin-top: 0;
+        }
+        .text1 {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.45);
+        }
+      }
+    }
+  }
+}
+.footer {
+  position: fixed;
+  bottom: 55px;
+  left: 0;
+  width: 100%;
+  height: 55px;
+  background: #FFFFFF;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .confirm-btn {
+    width: 110px;
+    height: 40px;
+    background: #2C81FF;
+    border-radius: 2px;
+    font-size: 16px;
+    color: #FFFFFF;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+</style>

+ 73 - 3
src/views/duty/index.vue

@@ -1,5 +1,75 @@
-<script setup lang="ts" name="About"></script>
-
 <template>
-  <div>值班管理</div>
+  <div class="container">
+    <div class="tabs">
+      <div v-for="item in tabs" :key="item.id" class="tab" @click="handleClickTab(item.id)">
+        <i :class="item.icon" />
+        <div :class="activeIndex === item.id ? 'tab-text text-active' : 'tab-text'">{{ item.name }}</div>
+      </div>
+    </div>
+    <div class="content">
+      <duty-calendar v-show="activeIndex === 'calendar'" @changIndex="handleClickTab" />
+      <shift-change v-show="activeIndex === 'shiftChange'" />
+    </div>
+  </div>
 </template>
+
+<script lang="ts" setup>
+import { ref } from "vue";
+import DutyCalendar from "@/views/duty/dutyCalendar.vue";
+import ShiftChange from "@/views/duty/shiftChange.vue";
+
+let activeIndex = ref('calendar');
+let tabs = ref([
+  { id: 'calendar', name: '值班日历', icon: 'icon1' },
+  { id: 'shiftChange', name: '面对面换班', icon: 'icon2' },
+  { id: 'rota', name: '值班表', icon: 'icon3' },
+]);
+
+// 点击tab
+const handleClickTab = (id) => {
+  activeIndex.value = id;
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  height: calc(100vh - 55px);
+  padding-top: 12px;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  .tabs {
+    height: 90px;
+    flex-shrink: 0;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 16px;
+    .tab {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      .icon1, .icon2, .icon3 {
+        display: inline-block;
+        width: 48px;
+        height: 48px;
+        background-color: #9d9d9d;
+      }
+      .tab-text {
+        color: #414F64;
+        font-size: 14px;
+        margin-top: 8px;
+      }
+      .text-active {
+        color: #2C81FF;
+      }
+    }
+  }
+  .content {
+    margin-top: 10px;
+    height: calc(100vh - 230px);
+    overflow-y: auto;
+  }
+}
+</style>

+ 152 - 0
src/views/duty/shiftChange.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="change-container">
+    <div class="duty-card">
+      <div class="duty-header">
+        <div>提醒事项</div>
+        <div class="add-text" @click="handleShowAdd('1')">新增事项</div>
+      </div>
+      <div class="duty-content">
+        <div v-for="(item, index) in dutyData.dataList2" :key="index" class="duty-item2">
+          <div class="text1">{{ item.time }}</div>
+          <div class="text2">{{ item.text }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="duty-card">
+      <div class="duty-header">
+        <div>待办事项</div>
+        <div class="add-text" @click="handleShowAdd('2')">新增事项</div>
+      </div>
+      <div class="duty-content">
+        <div v-for="(item, index) in dutyData.dataList3" :key="index" class="duty-item2">
+          <div class="text1">{{ item.time }}</div>
+          <div class="text2">{{ item.text }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="footer">
+      <div class="confirm-btn" @click="handleToShiftChange">确认交班</div>
+    </div>
+    <van-dialog
+        v-model:show="show"
+        class="custom-dialog"
+        :title="eventKey === '1' ? '新增提醒事项' : '新增待办事项'"
+        confirmButtonText="确认点名"
+        @confirm="handleConfirm"
+    >
+      <van-field v-model="content" :placeholder="eventKey === '1' ? '请输入提醒事项' : '请输入待办事项'" />
+    </van-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup name="shiftChange">
+import {ref} from "vue";
+
+let show = ref(false);
+let eventKey = ref('');
+let content = ref('');
+const dutyData  = ref({
+  dataList2: [
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况1。', time: '2024-10-20 11:43:00' },
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况2。', time: '2024-10-20 11:43:00' },
+    { text: '台风生成期间,请密切关注台风路径及等级变化情况3。', time: '2024-10-20 11:43:00' }
+  ],
+  dataList3: [
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作1。', time: '2024-10-20 11:43:00' },
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作2。', time: '2024-10-20 11:43:00' },
+    { text: '台风即将登录,请通知相关单位人员下午2:00到现场开展台风联合值守工作3。', time: '2024-10-20 11:43:00' }
+  ]
+});
+const handleShowAdd = (key) => {
+  eventKey.value = key;
+  show.value = true;
+}
+const handleToShiftChange = () => {
+
+}
+// 新增
+const handleConfirm = () => {
+
+}
+</script>
+
+<style lang="scss" scoped>
+.change-container {
+  .duty-card {
+    margin-top: 16px;
+    width: 100%;
+    background-color: #fff;
+    border-radius: 4px;
+    &:first-child {
+      margin-top: 0;
+    }
+    .duty-header {
+      padding: 10px;
+      font-size: 16px;
+      font-weight: bold;
+      border-bottom: 1px solid #f0f1f1;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .add-text {
+        font-size: 14px;
+        color: #2C81FF;
+        cursor: pointer;
+      }
+    }
+    .duty-content {
+      padding: 10px;
+      .duty-item {
+        padding: 3px 0;
+        display: flex;
+        justify-content: space-between;
+        align-items: flex-start;
+        font-size: 14px;
+        .item-left {
+          display: flex;
+          align-items: center;
+          .icon {
+            display: inline-block;
+          }
+        }
+      }
+      .duty-item2 {
+        padding: 5px;
+        font-size: 14px;
+        background-color: #f2f2f2;
+        border-radius: 4px;
+        margin-top: 10px;
+        &:first-child {
+          margin-top: 0;
+        }
+        .text1 {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.45);
+        }
+      }
+    }
+  }
+}
+.footer {
+  position: fixed;
+  bottom: 55px;
+  left: 0;
+  width: 100%;
+  height: 55px;
+  background: #FFFFFF;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .confirm-btn {
+    width: 110px;
+    height: 40px;
+    background: #2C81FF;
+    border-radius: 2px;
+    font-size: 16px;
+    color: #FFFFFF;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+</style>

+ 5 - 0
src/views/event/index.vue

@@ -38,6 +38,7 @@
       error-text="请求失败,点击重新加载"
       :finished="finished"
       finished-text="没有更多事件了"
+      class="list"
       @load="getList"
     >
       <div
@@ -326,6 +327,10 @@ const handleCloseEvent = item => {
 </script>
 
 <style lang="scss" scoped>
+.list {
+  height: calc(100vh - 102px);
+  overflow-y: auto;
+}
 .van-doc-block__title {
   color: var(--van-doc-text-color-4);
   margin: 0;

+ 0 - 37
src/views/test.vue

@@ -1,37 +0,0 @@
-<template>
-<div class="container">
-  <div @click="show = true">
-    巡查日历
-  </div>
-  <Calendar v-show="show" ref="calendarRef" :current="current" :dotDays="data" @change="handleChange" />
-</div>
-</template>
-
-<script lang="ts" setup>
-import {reactive, ref} from "vue";
-import { onClickOutside } from "@vueuse/core";
-
-let show = ref(false);
-let calendarRef = ref();
-const current = ref('2024-10-02');
-const data = reactive([
-    { date: '2024-10-19', color: '#a2d7f1' },
-    { date: '2024-10-18', color: '#ffd5d8' },
-    { date: '2024-10-17', color: '#ffefcc' },
-    { date: '2024-10-16', color: '#dfdfdf' }
-])
-onClickOutside(calendarRef, event => {
-  show.value = false;
-});
-const handleChange = (date) => {
-  current.value = date;
-  show.value = false;
-  console.log(current.value)
-}
-</script>
-
-<style lang="scss" scoped>
-.container {
-  margin: 0 auto;
-}
-</style>