Browse Source

Merge branch 'flow' of ruiqigogs/yf-portal-vue into master

yanghao 1 ngày trước cách đây
mục cha
commit
72d3d2d345

+ 5 - 0
components.d.ts

@@ -12,6 +12,7 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     CardItem: typeof import('./src/components/home/CardItem.vue')['default']
+    ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
@@ -21,7 +22,11 @@ declare module 'vue' {
     ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
+    ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']

+ 28 - 0
src/api/user.ts

@@ -98,3 +98,31 @@ export const getOATasks = async (id) => {
     url: "/admin-api/portal/todo/oa?workcode=" + id,
   });
 };
+
+// crm待办任务
+export const getCRMTasks = async (id) => {
+  return await request.get({
+    url: "/admin-api/portal/todo/crm?workcode=" + id,
+  });
+};
+
+// 消息通知
+export const getNotifyMessages = async (id) => {
+  return await request.get({
+    url: "/admin-api/portal/todo/crm/notice?workcode=" + id,
+  });
+};
+
+// 消息列表
+export const getNotifyMessageList = async (id) => {
+  return await request.get({
+    url: "/admin-api/portal/todo/crm/notice/self?workcode=" + id,
+  });
+};
+
+// 标记消息为已读
+export const markMessageAsRead = async (id) => {
+  return await request.get({
+    url: "/admin-api/portal/todo/crm/notice/readed?workcode=" + id,
+  });
+};

+ 128 - 45
src/components/home/header.vue

@@ -30,36 +30,71 @@
       <div class="hidden lg:flex items-center gap-3 h-full">
         <!-- 消息中心 -->
         <el-dropdown trigger="click" placement="bottom-end">
-          <div class="flex items-center gap-2 cursor-pointer pr-2">
+          <div class="flex items-center gap-2 cursor-pointer pr-6 pt-2">
+            <el-badge
+              :value="unreadMessageCount"
+              class="item"
+              v-if="hasUnreadMessages"
+            >
+              <Icon
+                icon="mdi:bell"
+                class="w-5 h-5 text-gray-600 hover:text-[#409EFF]"
+              />
+            </el-badge>
             <Icon
+              v-else
               icon="mdi:bell"
               class="w-5 h-5 text-gray-600 hover:text-[#409EFF]"
             />
-            <span class="text-sm text-gray-600">消息代办</span>
           </div>
           <template #dropdown>
             <el-dropdown-menu class="notification-dropdown">
               <div class="notification-tabs pl-2">
                 <el-tabs v-model="activeTab" class="demo-tabs">
-                  <el-tab-pane label="消息中心" name="messages">
+                  <el-tab-pane label="CRM" name="messages">
+                    <template #label>
+                      <span class="custom-tabs-label">
+                        <span>CRM</span>
+                        <el-badge
+                          :value="unreadMessageCount"
+                          class="item ml-1"
+                          v-if="hasUnreadMessages"
+                        ></el-badge>
+                      </span>
+                    </template>
                     <div class="tab-content">
                       <!-- 消息中心内容 -->
+                      <div>
+                        <span
+                          v-if="hasUnreadMessages"
+                          class="cursor-pointer text-blue-500"
+                          @click="markAllAsRead"
+                          >全部标为已读</span
+                        >
+
+                        <span v-else class="cursor-pointer text-[#b2aaaa]"
+                          >全部已读</span
+                        >
+                      </div>
                       <div
                         class="message-item"
                         v-for="(item, index) in messages"
                         :key="index"
                       >
-                        <div class="message-icon">
-                          <Icon
-                            :icon="item.icon"
-                            class="w-5 h-5"
-                            :class="item.typeClass"
-                          />
-                        </div>
+                        <div class="message-icon"></div>
                         <div class="message-text">
-                          <p class="message-title">{{ item.title }}</p>
-                          <p class="message-desc">{{ item.desc }}</p>
-                          <p class="message-time">{{ item.time }}</p>
+                          <!-- 未读就显示小红点 -->
+
+                          <p class="message-title flex items-center gap-5">
+                            <span
+                              v-if="item.status === '0'"
+                              class="w-2 h-2 bg-[#f56c6c] rounded-full"
+                            ></span
+                            >{{ item.contentMajor }}
+                          </p>
+                          <p class="message-desc">
+                            {{ timestampToDateTime(item.createTime) }}
+                          </p>
                         </div>
                       </div>
                       <div v-if="!messages.length" class="no-messages">
@@ -67,25 +102,38 @@
                       </div>
                     </div>
                   </el-tab-pane>
-                  <el-tab-pane label="待办任务" name="tasks">
+                  <el-tab-pane label="OA" name="tasks">
                     <div class="tab-content">
-                      <!-- 待办任务内容 -->
+                      <!-- <div>
+                        <span
+                          class="cursor-pointer text-blue-500"
+                          @click="markAllAsRead"
+                          >全部标为已读</span
+                        >
+                      </div> -->
+                      <!-- OA消息 -->
                       <div
                         class="task-item"
-                        v-for="(task, index) in tasks"
+                        v-for="(task, index) in oaMessagesList"
                         :key="index"
                       >
                         <div class="task-info">
-                          <p class="task-title">{{ task.title }}</p>
-                          <p class="task-desc">{{ task.desc }}</p>
-                          <p class="task-time">截止时间: {{ task.dueTime }}</p>
+                          <p class="task-title">
+                            <span
+                              class="w-3 h-3 bg-[#f56c6c] rounded-full"
+                            ></span
+                            >{{ task.contentMajor }}
+                          </p>
+                          <p class="message-desc">
+                            {{ timestampToDateTime(task.createTime) }}
+                          </p>
                         </div>
                         <el-tag :type="task.priorityTag" size="small">{{
                           task.priorityText
                         }}</el-tag>
                       </div>
-                      <div v-if="!tasks.length" class="no-tasks">
-                        暂无待办任务
+                      <div v-if="!oaMessagesList.length" class="no-tasks">
+                        暂无新消息
                       </div>
                     </div>
                   </el-tab-pane>
@@ -289,12 +337,17 @@
 
 <script setup lang="ts">
 import { Icon } from "@iconify/vue";
-import { ref, computed } from "vue";
+import { ref, computed, onMounted } from "vue";
 import { useRouter } from "vue-router";
 import logo from "@/assets/images/logo.png";
 import person from "@/assets/images/person.png";
 import { useUserStoreWithOut } from "@/stores/useUserStore";
 const userStore = useUserStoreWithOut();
+import {
+  getNotifyMessages,
+  getNotifyMessageList,
+  markMessageAsRead,
+} from "@api/user";
 
 import {
   getAccessToken,
@@ -307,29 +360,7 @@ import { deleteUserCache } from "@hooks/useCache";
 
 // 新增消息中心状态
 const activeTab = ref("messages");
-const messages = ref([
-  {
-    title: "系统通知",
-    desc: "您的账户已成功激活",
-    time: "10分钟前",
-    icon: "mdi:message-text-outline",
-    typeClass: "text-blue-500",
-  },
-  {
-    title: "安全提醒",
-    desc: "检测到异地登录行为",
-    time: "30分钟前",
-    icon: "mdi:security",
-    typeClass: "text-red-500",
-  },
-  {
-    title: "更新提示",
-    desc: "系统将于今晚进行维护升级",
-    time: "1小时前",
-    icon: "mdi:update",
-    typeClass: "text-green-500",
-  },
-]);
+const messages = ref([]);
 
 const tasks = ref([
   {
@@ -361,9 +392,61 @@ const isLoggedIn = computed(
 const userAvatar = computed(() => userStore.user?.avatar || "");
 const userName = computed(() => userStore.user?.nickname || "");
 
+// 是否有未读消息
+const hasUnreadMessages = computed(() => {
+  return messages.value.some((msg) => msg.status === "0");
+});
+
+// 未读消息数量
+const unreadMessageCount = computed(() => {
+  return messages.value.filter((msg) => msg.status === "0").length;
+});
+
+// oa未读
+const oaMessagesList = ref([]);
+onMounted(async () => {
+  if (isLoggedIn) {
+    await getNotifyMessages(userStore.getUser.username);
+
+    const messageList = await getNotifyMessageList(userStore.getUser.username);
+    messages.value = messageList;
+
+    console.log("消息中心数据:", messages.value);
+  }
+});
+
+function timestampToDateTime(timestamp) {
+  // 兼容 10位(秒) / 13位(毫秒)
+  const len = String(timestamp).length;
+  const date = new Date(Number(timestamp) * (len === 10 ? 1000 : 1));
+
+  // 年
+  const year = date.getFullYear();
+  // 月(0~11 → +1)
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  // 日
+  const day = String(date.getDate()).padStart(2, "0");
+  // 时
+  const hours = String(date.getHours()).padStart(2, "0");
+  // 分
+  const minutes = String(date.getMinutes()).padStart(2, "0");
+  // 秒
+  const seconds = String(date.getSeconds()).padStart(2, "0");
+
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
 const router = useRouter();
 const drawer = ref(false);
 
+// 全部标为已读
+const markAllAsRead = async () => {
+  await markMessageAsRead(userStore.getUser.username);
+  // 刷新消息列表
+  const messageList = await getNotifyMessageList(userStore.getUser.username);
+  messages.value = messageList;
+};
+
 const goHome = () => {
   router.push({ path: "/" });
 };

+ 18 - 0
src/router/index.ts

@@ -38,6 +38,24 @@ const routes: RouteRecordRaw[] = [
       title: "DeepOil 智慧经营平台 | 流程门户",
     },
   },
+
+  {
+    path: "/todo-list",
+    name: "TodoList",
+    component: () => import("@/views/flow/todoList.vue"),
+    meta: {
+      title: "DeepOil 智慧经营平台 | 待办列表",
+    },
+  },
+
+  {
+    path: "/crm-todo-list",
+    name: "CRMTodoList",
+    component: () => import("@/views/flow/crmTodoList.vue"),
+    meta: {
+      title: "DeepOil 智慧经营平台 | CRM待办列表",
+    },
+  },
 ];
 
 const router = createRouter({

+ 169 - 0
src/views/flow/crmTodoList.vue

@@ -0,0 +1,169 @@
+<template>
+  <div class="todo-list">
+    <Header />
+
+    <div class="content mt-15">
+      <div class="flex gap-5 items-center mb-4 bg-[#f9f9f9] py-2">
+        <p class="flex items-center">
+          <Icon
+            icon="mynaui:arrow-up-down"
+            class="icon pr-1 h-6 w-6"
+            color="#014099"
+          />CRM待办任务列表
+        </p>
+
+        <el-button
+          type="primary"
+          round
+          size="default"
+          color="#02409b"
+          @click="router.back()"
+          ><Icon
+            icon="mynaui:corner-up-left"
+            class="icon pr-1"
+            width="20"
+            height="20"
+          />返回</el-button
+        >
+      </div>
+      <el-table
+        :data="oaTasks"
+        style="width: 100%"
+        :empty-text="loading ? '加载中...' : '暂无数据'"
+        height="80vh"
+        :header-cell-style="{
+          backgroundColor: '#e9f7ff',
+          color: 'black',
+          fontWeight: '400',
+        }"
+        :cell-style="{
+          color: 'black',
+        }"
+      >
+        <el-table-column
+          type="index"
+          label="序号"
+          width="80"
+          fixed="left"
+          align="center"
+        />
+        <el-table-column
+          prop="instTitle"
+          label="流程标题"
+          min-width="220"
+          fixed="left"
+          align="center"
+        />
+        <el-table-column
+          prop="entityTypeId"
+          label="业务类型"
+          width="140"
+          align="center"
+        />
+        <el-table-column
+          prop="priority"
+          label="优先级别"
+          width="100"
+          align="center"
+        />
+
+        <el-table-column
+          prop="createAt"
+          label="任务创建时间"
+          width="180"
+          align="center"
+        />
+
+        <el-table-column
+          prop="endAt"
+          label="任务完成时间"
+          width="180"
+          align="center"
+        />
+
+        <el-table-column
+          prop="submitterId"
+          label="任务提交人"
+          width="120"
+          align="center"
+        />
+
+        <el-table-column
+          prop="status"
+          label="任务状态"
+          width="100"
+          align="center"
+        />
+
+        <el-table-column label="操作" width="120" fixed="right" align="center">
+          <template #default="scope">
+            <span
+              class="text-[#02409b] cursor-pointer"
+              @click="goBackPage(scope.row)"
+              >处理</span
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <Footer />
+  </div>
+</template>
+
+<script setup>
+import Header from "@components/home/header.vue";
+import { ref, onMounted } from "vue";
+import { getCRMTasks, ssoLogin } from "@/api/user";
+import { useUserStore } from "@/stores/useUserStore";
+import { Icon } from "@iconify/vue";
+import router from "@/router";
+const userStore = useUserStore();
+
+const oaTasks = ref([]);
+const loading = ref(false);
+
+const goBackPage = async (row) => {
+  const res = await ssoLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const newTab = window.open("", "_blank");
+
+    newTab.location.href =
+      "https://yfoa.keruioil.com/wui/index.html" +
+      "?ssoToken=" +
+      res +
+      "#/main";
+
+    setTimeout(function () {
+      newTab.location.href = `https://yfoa.keruioil.com/spa/workflow/static4form/index.html?_rdm=1776063595284#/main/workflow/req?requestid=${row.requestId}`;
+    }, 0);
+  }
+};
+onMounted(async () => {
+  if (userStore.getUser.username) {
+    loading.value = true;
+    try {
+      const res = await getCRMTasks(userStore.getUser.username);
+      oaTasks.value = res.todoList;
+    } finally {
+      loading.value = false;
+    }
+  }
+});
+</script>
+
+<style scoped>
+.todo-list {
+  display: flex;
+  flex-direction: column;
+  min-height: 100%;
+}
+
+.content {
+  padding: 16px 20px;
+  margin-top: 100px;
+}
+</style>

+ 216 - 47
src/views/flow/index.vue

@@ -3,9 +3,10 @@
     <Header />
     <section class="hero">
       <div class="hero-inner">
-        <h1 class="hero-title">下午好,晓华</h1>
+        <h1 class="hero-title">下午好,{{ userStore.getUser.nickname }}</h1>
         <p class="hero-desc">
-          今天是 {{ new Date().toLocaleDateString() }}。您有 5 条流程待处理。
+          今天是 {{ new Date().toLocaleDateString() }}。您有
+          {{ stats[0].number }}条流程待处理。
         </p>
       </div>
       <div class="opration">
@@ -24,16 +25,43 @@
     <!-- 任务统计 -->
     <section class="total">
       <div class="total-card" v-for="(item, index) in stats" :key="index">
-        <div class="card-icon" :style="{ backgroundColor: item.bgcolor }">
-          <Icon :icon="item.icon" :color="item.color" />
-        </div>
-        <div class="card-content">
-          <p class="card-title">{{ item.title }}</p>
-          <p class="card-number">{{ oaTasks.todoCount }}</p>
-        </div>
-        <div v-if="item.extra" class="card-extra">
-          {{ item.extra }}
-        </div>
+        <el-popover
+          placement="top"
+          :width="200"
+          trigger="hover"
+          popper-class="glass-popover"
+          :disabled="getDetailList(index).length === 0"
+          raw-content
+          transition="el-zoom-in-top"
+        >
+          <template #reference>
+            <div class="card-wrapper">
+              <!-- ... 图标和内容 ... -->
+              <div class="card-icon" :style="{ backgroundColor: item.bgcolor }">
+                <Icon :icon="item.icon" :color="item.color" />
+              </div>
+              <div class="card-content">
+                <p class="card-title">{{ item.title }}</p>
+                <p class="card-number">{{ item.number }}</p>
+              </div>
+            </div>
+          </template>
+
+          <div class="detail-list">
+            <div
+              v-for="(task, idx) in getDetailList(index)"
+              :key="idx"
+              class="detail-item"
+              @click="handleDetailClick(task, item.title)"
+            >
+              <span class="detail-name">{{ task.name }}</span>
+              <span class="detail-val">{{ task.value }}</span>
+            </div>
+            <div v-if="getDetailList(index).length === 0" class="empty-tip">
+              暂无详细数据
+            </div>
+          </div>
+        </el-popover>
       </div>
     </section>
 
@@ -101,10 +129,12 @@ import Header from "@components/home/header.vue";
 import Footer from "@components/home/Footer.vue";
 import { computed, ref, onMounted, onBeforeUnmount, nextTick } from "vue";
 import { Icon } from "@iconify/vue";
-import { getFlows, ssoLogin, getOATasks } from "@/api/user";
+import { getFlows, ssoLogin, getOATasks, getCRMTasks } from "@/api/user";
 import { useUserStore } from "@/stores/useUserStore";
 import { getAccessToken } from "@/utils/auth";
 import * as echarts from "echarts";
+import { useRouter } from "vue-router";
+const router = useRouter();
 
 const userStore = useUserStore();
 
@@ -158,6 +188,20 @@ const pieChartData = {
   ],
 };
 
+const getDetailList = (index) => {
+  switch (index) {
+    case 0: // 我的待办
+      return todoCount.value;
+    case 1: // 已办事项
+      return doneCount.value;
+    case 2: // 发起流程
+      return startCount.value;
+    case 3: // 草稿箱
+      return drafts.value;
+    default:
+      return [];
+  }
+};
 // 初始化图表
 const initLineChart = () => {
   const chartDom = lineChartRef.value;
@@ -289,39 +333,6 @@ const activeTab = computed(() => {
   );
 });
 
-const stats = [
-  {
-    icon: "mdi:clock-outline",
-    title: "我的待办",
-    number: "05",
-    extra: "+2 今日",
-    bgcolor: "#fff7ed",
-    color: "#f59e0b",
-  },
-  {
-    icon: "mdi:check-circle-outline",
-    title: "已办事项",
-    number: "128",
-    bgcolor: "#eff6ff",
-    color: "#2563eb",
-  },
-  {
-    icon: "mdi:arrow-right-bold-box-outline",
-    title: "发起流程",
-    number: "42",
-    extra: "85% 准时",
-    bgcolor: "#eff6ff",
-    color: "#2563eb",
-  },
-  {
-    icon: "mdi:file-document-outline",
-    title: "草箱箱",
-    number: "03",
-    bgcolor: "#f8fafc",
-    color: "#475569",
-  },
-];
-
 const getAll = async () => {
   const res = await getFlows({
     pageNo: 1,
@@ -374,7 +385,83 @@ const go = async (item) => {
   }
 };
 
+const handleDetailClick = (task, categoryTitle) => {
+  console.log(`点击了 ${categoryTitle} 中的 ${task.name}: ${task.value}`);
+  // 示例:根据类型跳转
+  if (task.name === "OA" && categoryTitle === "我的待办") {
+    router.push({
+      path: "/todo-list",
+      query: { type: task.name.toLowerCase() },
+    });
+  }
+
+  if (task.name === "CRM" && categoryTitle === "我的待办") {
+    router.push({
+      path: "/crm-todo-list",
+      query: { type: task.name.toLowerCase() },
+    });
+  }
+};
+
 let oaTasks = ref([]);
+let crmTasks = ref([]);
+
+const stats = ref([
+  {
+    icon: "mdi:clock-outline",
+    title: "我的待办",
+    number: 0,
+    extra: "+2 今日",
+    bgcolor: "#fff7ed",
+    color: "#f59e0b",
+  },
+  {
+    icon: "mdi:check-circle-outline",
+    title: "已办事项",
+    number: 0,
+    bgcolor: "#eff6ff",
+    color: "#2563eb",
+  },
+  {
+    icon: "mdi:arrow-right-bold-box-outline",
+    title: "发起流程",
+    number: 0,
+    extra: "85% 准时",
+    bgcolor: "#eff6ff",
+    color: "#2563eb",
+  },
+  {
+    icon: "mdi:file-document-outline",
+    title: "草稿箱",
+    number: 0,
+    bgcolor: "#f8fafc",
+    color: "#475569",
+  },
+]);
+
+const todoCount = ref([
+  { name: "OA", value: 0 },
+  { name: "CRM", value: 0 },
+]);
+
+// 已办事项
+const doneCount = ref([
+  { name: "OA", value: 0 },
+  { name: "CRM", value: 0 },
+]);
+
+// 发起流程
+const startCount = ref([
+  { name: "OA", value: 0 },
+  { name: "CRM", value: 0 },
+]);
+
+// 草稿箱
+const drafts = ref([
+  { name: "OA", value: 0 },
+  { name: "CRM", value: 0 },
+]);
+
 onMounted(async () => {
   getAll();
   // 等待 DOM 与样式生效,避免移动端首屏尺寸为 0
@@ -396,7 +483,18 @@ onMounted(async () => {
   if (userStore.getUser.username) {
     const res = await getOATasks(userStore.getUser.username);
     oaTasks.value = res;
+
+    const crmRes = await getCRMTasks(userStore.getUser.username);
+    crmTasks.value = crmRes;
   }
+
+  stats.value[0].number =
+    Number(oaTasks.value.todoCount) + Number(crmTasks.value.todoCount);
+
+  todoCount.value = [
+    { name: "OA", value: oaTasks.value.todoCount },
+    { name: "CRM", value: crmTasks.value.todoCount },
+  ];
 });
 
 // 组件卸载时移除监听,防止内存泄漏
@@ -710,11 +808,13 @@ onBeforeUnmount(() => {
   cursor: pointer;
   /* border: 1px solid #e5e7eb; */
   /* border-top: solid 5px #02409b; */
+  overflow: visible;
 }
 
 .total-card:hover {
   transform: translateY(-4px);
   box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
+  color: #02409b !important;
 }
 
 .card-icon {
@@ -748,7 +848,7 @@ onBeforeUnmount(() => {
 .card-number {
   font-size: 28px;
   font-weight: 600;
-  color: #111827;
+  /* color: #111827; */
 }
 
 .card-extra {
@@ -780,4 +880,73 @@ onBeforeUnmount(() => {
   overflow: hidden;
   position: relative;
 }
+
+:global(.glass-popover) {
+  background: rgba(0, 0, 0, 0.6) !important;
+  backdrop-filter: blur(10px);
+  -webkit-backdrop-filter: blur(10px);
+  height: 200px !important;
+  width: 100px !important;
+  overflow-y: auto !important;
+  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1) !important;
+  border-radius: 8px !important;
+  padding: 10px !important;
+  color: #fff !important;
+  z-index: 2000 !important; /* 确保在最上层 */
+  top: 15% !important; /* 根据需要调整位置 */
+}
+
+:global(.glass-popover .el-popper__arrow::before) {
+  background: transparent !important;
+  /* border: 1px solid rgba(255, 255, 255, 0.1); */
+  border: none !important;
+}
+
+.detail-list {
+  padding: 5px 0;
+}
+
+.detail-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 8px;
+  font-size: 14px;
+  color: #e0e0e0; /* 浅色文字 */
+  line-height: 1.5;
+  padding: 6px 8px;
+  border-radius: 4px;
+  cursor: pointer; /* 鼠标变成手型 */
+  transition: background-color 0.2s ease;
+}
+
+.detail-item:last-child {
+  margin-bottom: 0;
+}
+
+/* 鼠标悬浮背景变灰 */
+.detail-item:hover {
+  background-color: rgba(
+    255,
+    255,
+    255,
+    0.15
+  ); /* 半透明白色,视觉上为灰色高亮 */
+}
+
+.detail-name {
+  color: #ccc;
+}
+
+.detail-val {
+  font-weight: bold;
+  color: #fff;
+}
+
+.empty-tip {
+  text-align: center;
+  color: #aaa;
+  font-size: 12px;
+  padding: 10px 0;
+}
 </style>

+ 199 - 0
src/views/flow/todoList.vue

@@ -0,0 +1,199 @@
+<template>
+  <div class="todo-list">
+    <Header />
+
+    <div class="content mt-15">
+      <div class="flex gap-5 items-center mb-4 bg-[#f9f9f9] py-2">
+        <p class="flex items-center">
+          <Icon
+            icon="mynaui:arrow-up-down"
+            class="icon pr-1 h-6 w-6"
+            color="#014099"
+          />待办任务列表
+        </p>
+
+        <el-button
+          type="primary"
+          round
+          size="default"
+          color="#02409b"
+          @click="router.back()"
+          ><Icon
+            icon="mynaui:corner-up-left"
+            class="icon pr-1"
+            width="20"
+            height="20"
+          />返回</el-button
+        >
+      </div>
+      <el-table
+        :data="oaTasks"
+        style="width: 100%"
+        :empty-text="loading ? '加载中...' : '暂无数据'"
+        height="80vh"
+        :header-cell-style="{
+          backgroundColor: '#e9f7ff',
+          color: 'black',
+          fontWeight: '400',
+        }"
+        :cell-style="{
+          color: 'black',
+        }"
+      >
+        <el-table-column
+          type="index"
+          label="序号"
+          width="80"
+          fixed="left"
+          align="center"
+        />
+        <el-table-column
+          prop="requestName"
+          label="请求标题"
+          min-width="220"
+          fixed="left"
+          align="center"
+        />
+        <el-table-column
+          prop="workflowBaseInfo.workflowTypeName"
+          label="流程类型"
+          width="140"
+          align="center"
+        />
+        <el-table-column
+          prop="requestLevel"
+          label="紧急程度"
+          width="100"
+          align="center"
+        />
+        <el-table-column
+          prop="status"
+          label="路径状态"
+          width="100"
+          align="center"
+        />
+        <el-table-column
+          prop="sysName"
+          label="系统名称"
+          width="140"
+          align="center"
+        />
+        <el-table-column
+          prop="createTime"
+          label="创建时间"
+          width="180"
+          align="center"
+        />
+
+        <el-table-column
+          prop="creatorName"
+          label="创建人名称"
+          width="120"
+          align="center"
+        />
+
+        <el-table-column
+          prop="currentNodeName"
+          label="当前节点名称"
+          width="140"
+          align="center"
+        />
+        <el-table-column
+          prop="lastOperateTime"
+          label="最后操作时间"
+          width="180"
+          align="center"
+        />
+
+        <el-table-column
+          prop="lastOperatorName"
+          label="最后操作人名称"
+          width="140"
+          align="center"
+        />
+        <el-table-column
+          prop="receiveTime"
+          label="接收时间"
+          width="180"
+          align="center"
+        />
+
+        <el-table-column
+          prop="workflowBaseInfo.workflowName"
+          label="流程名称"
+          min-width="200"
+          align="center"
+        />
+
+        <el-table-column label="操作" width="120" fixed="right" align="center">
+          <template #default="scope">
+            <span
+              class="text-[#02409b] cursor-pointer"
+              @click="goBackPage(scope.row)"
+              >处理</span
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <Footer />
+  </div>
+</template>
+
+<script setup>
+import Header from "@components/home/header.vue";
+import { ref, onMounted } from "vue";
+import { getOATasks, ssoLogin } from "@/api/user";
+import { useUserStore } from "@/stores/useUserStore";
+import { Icon } from "@iconify/vue";
+import router from "@/router";
+const userStore = useUserStore();
+
+const oaTasks = ref([]);
+const loading = ref(false);
+
+const goBackPage = async (row) => {
+  const res = await ssoLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const newTab = window.open("", "_blank");
+
+    newTab.location.href =
+      "https://yfoa.keruioil.com/wui/index.html" +
+      "?ssoToken=" +
+      res +
+      "#/main";
+
+    setTimeout(function () {
+      newTab.location.href = `https://yfoa.keruioil.com/spa/workflow/static4form/index.html?_rdm=1776063595284#/main/workflow/req?requestid=${row.requestId}`;
+    }, 0);
+  }
+};
+onMounted(async () => {
+  if (userStore.getUser.username) {
+    loading.value = true;
+    try {
+      const res = await getOATasks(userStore.getUser.username);
+      oaTasks.value = res.todoList;
+    } finally {
+      loading.value = false;
+    }
+  }
+});
+</script>
+
+<style scoped>
+.todo-list {
+  display: flex;
+  flex-direction: column;
+  min-height: 100%;
+}
+
+.content {
+  padding: 16px 20px;
+  margin-top: 100px;
+}
+</style>

+ 15 - 27
src/views/index.vue

@@ -9,39 +9,27 @@
 
       <div
         class="absolute inset-0 flex transition-transform duration-700 ease-in-out"
-        :style="{ transform: `translateX(-${currentBgIndex * 100}%)` }"
       >
-        <div
-          v-for="(img, index) in bgImages"
-          :key="index"
-          class="min-w-full h-full bg-cover bg-center"
-          :style="{ backgroundImage: `url(${img})` }"
-        ></div>
+        <div class="min-w-full h-full relative">
+          <video
+            class="absolute inset-0 w-full h-full object-cover"
+            autoplay
+            muted
+            loop
+            playsinline
+            :src="bgvideo"
+          >
+            您的浏览器不支持 HTML5 视频。
+          </video>
+        </div>
       </div>
 
-      <!-- 指示器 -->
       <div
-        class="absolute bottom-4 left-1/2 transform -translate-x-1/2 z-20 flex gap-2"
-      >
-        <span
-          v-for="(img, index) in bgImages"
-          :key="index"
-          class="block w-2 h-2 rounded-full cursor-pointer transition-all duration-300"
-          :class="
-            currentBgIndex === index
-              ? 'bg-[#0644a1] w-6'
-              : 'bg-white/50 hover:bg-white/80'
-          "
-          @click="currentBgIndex = index"
-        ></span>
-      </div>
-
-      <!-- <div
         class="relative z-10 w-full mx-auto h-full px-20 flex items-center mt-5 pt-10"
       >
         <div class="max-w-4xl">
           <h1
-            class="text-2xl md:text-4xl pt-2 font-bold leading-tight slide-up-fade-in"
+            class="text-2xl md:text-4xl text-white/90 pt-2 font-bold leading-tight slide-up-fade-in"
           >
             山东科瑞石油技术门户网站 · DeepOil 智慧经营平台
           </h1>
@@ -68,7 +56,7 @@
             </a>
           </div>
         </div>
-      </div> -->
+      </div>
     </section>
 
     <section
@@ -109,7 +97,7 @@ import img3 from "@/assets/images/3.jpg";
 import caiwu from "@/assets/images/caiwu.png";
 import banner1 from "@/assets/images/banner1.jpg";
 import banner2 from "@/assets/images/model.jpeg";
-
+import bgvideo from "@/assets/bg.mp4";
 import bg2 from "@/assets/images/e4.png";
 import g1 from "@/assets/images/g1.png";
 import { useRouter } from "vue-router";

+ 2 - 2
src/views/login.vue

@@ -21,7 +21,7 @@
         <h1 class="text-2xl font-bold text-center">登录</h1>
 
         <!-- 用户名密码登陆 -->
-        <!-- <div>
+        <div>
           <el-form
             :model="form"
             :rules="rules"
@@ -62,7 +62,7 @@
               >
             </div>
           </div>
-        </div> -->
+        </div>
 
         <!-- 钉钉登陆 -->
         <div class="text-center">