yanghao 1 mês atrás
pai
commit
68b12c541b

+ 13 - 0
src/api/user.ts

@@ -151,6 +151,19 @@ export const getSRMTasks = async (params) => {
   });
 };
 
+// EHR 待办任务
+export const getEHRTasks = async (params) => {
+  return await request.get({
+    url:
+      "/admin-api/portal/todo/ehr?workcode=" +
+      params.id +
+      "&pageNo=" +
+      params.pageNum +
+      "&pageSize=" +
+      params.pageSize,
+  });
+};
+
 // CMR消息通知
 export const getNotifyMessages = async (id) => {
   return await request.get({

+ 9 - 0
src/router/index.ts

@@ -124,6 +124,15 @@ const routes: RouteRecordRaw[] = [
     },
   },
 
+  {
+    path: "/ehr-todo-list",
+    name: "EHRTodoList",
+    component: () => import("@/views/flow/ehrTodoList.vue"),
+    meta: {
+      title: "DeepOil 智慧经营平台 | EHR待办列表",
+    },
+  },
+
   {
     path: "/drive",
     name: "Drive",

+ 485 - 0
src/views/flow/ehrTodoList.vue

@@ -0,0 +1,485 @@
+<template>
+  <div class="todo-list">
+    <Header />
+
+    <div class="content-wrapper mt-15 max-w-[1200px] mx-auto">
+      <div class="nav flex gap-5 items-center mb-4 py-2 pl-4 rounded-sm">
+        <p class="flex items-center text-var(--text-primary)">
+          <Icon
+            icon="mynaui:arrow-up-down"
+            class="icon pr-1 h-8 w-8"
+            color="#014099"
+          />EHR待办任务列表
+        </p>
+
+        <el-button
+          type="primary"
+          round
+          size="small"
+          color="#02409b"
+          @click="router.back()"
+          ><Icon
+            icon="mynaui:corner-up-left"
+            class="icon pr-1"
+            width="20"
+            height="20"
+          />&#36820;&#22238;</el-button
+        >
+      </div>
+      <div v-loading="loading" class="table-wrapper">
+        <el-table
+          v-loading="loading"
+          :data="oaTasks"
+          style="width: 100%"
+          stripe
+          height="70vh"
+          element-loading-text="加载中..."
+          :empty-text="loading ? '' : '暂无数据'"
+          :header-cell-style="{
+            backgroundColor: 'var(--bg-table-head) !important',
+            color: 'var(--text-primary)',
+            fontWeight: '400',
+          }"
+        >
+          <el-table-column
+            type="index"
+            label="&#24207;&#21495;"
+            width="80"
+            fixed="left"
+            align="center"
+            :index="getIndex"
+          />
+          <el-table-column prop="title" label="请求标题" align="center" />
+
+          <el-table-column
+            prop="createTime"
+            label="&#21019;&#24314;&#26102;&#38388;"
+            align="center"
+          />
+
+          <el-table-column
+            label="&#25805;&#20316;"
+            width="120"
+            fixed="right"
+            align="center"
+          >
+            <template #default="scope">
+              <span
+                class="text-[#1e90ff] cursor-pointer text-[13px]"
+                @click="goBackPage(scope.row)"
+                >&#22788;&#29702;</span
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="pagination.pageNum"
+          v-model:page-size="pagination.pageSize"
+          :total="pagination.total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next"
+          background
+          @current-change="handleCurrentChange"
+          @size-change="handleSizeChange"
+        />
+      </div>
+    </div>
+
+    <Footer />
+  </div>
+</template>
+
+<script setup>
+import Header from "@components/home/header.vue";
+import * as dd from "dingtalk-jsapi";
+import { ref, onMounted } from "vue";
+import { getEHRTasks, ehrLogin } from "@/api/user";
+import { useUserStore } from "@/stores/useUserStore";
+import { Icon } from "@iconify/vue";
+import router from "@/router";
+const userStore = useUserStore();
+import { ElLoading, ElMessage } from "element-plus";
+
+const oaTasks = ref([]);
+const loading = ref(false);
+
+const pagination = ref({
+  pageNum: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+const goBackPage = async (row) => {
+  const res = await ehrLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const ua = window.navigator.userAgent; // const ua = navigator.userAgent;
+    const isDesktop =
+      ua.includes("DingTalk") &&
+      (ua.includes("Windows") || ua.includes("Macintosh"));
+
+    let ua2 = navigator.userAgent.toLowerCase();
+    var isMobile = ua2.indexOf("dingtalk") > -1;
+    if (ua2.includes("dingtalk") || ua2.includes("dingtalkwork")) {
+      if (isMobile && !isDesktop) {
+        dd.biz.util.openLink({
+          url: `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=/proxy/h5/home`,
+
+          onSuccess: () => {
+            setTimeout(() => {
+              dd.biz.util.openLink({
+                url: `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=${row.h5_url}`,
+              });
+            }, 500);
+          },
+        });
+      } else if (isDesktop) {
+        const newTab = window.open("", "_blank");
+        newTab.location.href = `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=${res.redirect}`;
+
+        setTimeout(function () {
+          newTab.location.href = `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=${row.web_url}`;
+          setTimeout(() => {}, 500);
+        }, 500);
+      }
+    } else {
+      const newTab = window.open("", "_blank");
+      newTab.location.href = `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=${res.redirect}`;
+
+      setTimeout(function () {
+        newTab.location.href = `${res.ehrUrl}/gateway/login/free?loginfree_licence=${res.licence}&signature=${res.sign}&redirect_url=${row.web_url}`;
+        setTimeout(() => {}, 500);
+      }, 500);
+    }
+  }
+};
+
+const handleCurrentChange = async (page) => {
+  pagination.value.pageNum = page;
+  try {
+    const res = await getEHRTasks({
+      id: userStore.getUser.username,
+      pageNum: pagination.value.pageNum,
+      pageSize: pagination.value.pageSize,
+    });
+    oaTasks.value = res.todoList;
+    pagination.value.total = Number(res.todoCount);
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleSizeChange = async (size) => {
+  pagination.value.pageSize = size;
+  pagination.value.pageNum = 1;
+
+  try {
+    const res = await getEHRTasks({
+      id: userStore.getUser.username,
+      pageNum: pagination.value.pageNum,
+      pageSize: pagination.value.pageSize,
+    });
+    oaTasks.value = res.todoList;
+    pagination.value.total = Number(res.todoCount);
+  } finally {
+    loading.value = false;
+  }
+};
+
+onMounted(async () => {
+  if (userStore.getUser.username) {
+    loading.value = true;
+    try {
+      const res = await getEHRTasks({
+        id: userStore.getUser.username,
+        pageNum: pagination.value.pageNum,
+        pageSize: pagination.value.pageSize,
+      });
+      oaTasks.value = res.todoList;
+      pagination.value.total = Number(res.todoCount);
+    } finally {
+      loading.value = false;
+    }
+  }
+});
+</script>
+
+<style scoped>
+.todo-list {
+  --portal-text: #17345f;
+  --portal-text-muted: #5f6f83;
+  --portal-text-soft: #7f8fa6;
+  --portal-title: #163867;
+  --portal-subtitle: rgba(61, 92, 135, 0.86);
+  --portal-line: rgba(126, 156, 201, 0.24);
+  --portal-card: rgba(255, 255, 255, 0.82);
+  --portal-card-2: rgba(248, 251, 255, 0.94);
+  --portal-card-3: rgba(240, 246, 255, 0.88);
+  --portal-card-4: rgba(231, 239, 251, 0.92);
+  --portal-nav-bg: rgba(255, 255, 255, 0.72);
+  --portal-nav-hover: rgba(219, 232, 252, 0.8);
+  --portal-input-bg: rgba(255, 255, 255, 0.7);
+  --portal-input-hover: rgba(255, 255, 255, 0.92);
+  --portal-shadow: 0 18px 40px rgba(23, 52, 95, 0.12);
+  --portal-shadow-strong: 0 24px 60px rgba(23, 52, 95, 0.16);
+  --portal-accent: #245edb;
+  --portal-accent-2: #4e8cff;
+  --portal-accent-soft: rgba(36, 94, 219, 0.14);
+  --portal-todo-bg: rgba(242, 247, 255, 0.94);
+  --portal-todo-hover: rgba(228, 238, 252, 0.95);
+  --portal-number-todo: #e15a5a;
+  --portal-number-done: #2da04d;
+  color: var(--portal-text);
+  background:
+    radial-gradient(
+      circle at 18% 12%,
+      rgba(83, 126, 255, 0.14),
+      transparent 22%
+    ),
+    radial-gradient(
+      circle at 82% 20%,
+      rgba(71, 148, 255, 0.14),
+      transparent 20%
+    ),
+    radial-gradient(
+      circle at 50% 100%,
+      rgba(97, 142, 247, 0.12),
+      transparent 28%
+    ),
+    linear-gradient(180deg, #eef3f9 0%, #f7faff 46%, #eef3f9 100%);
+}
+
+:global([data-theme="dark"] .todo-list) {
+  --portal-text: #eaf1ff;
+  --portal-text-muted: rgba(234, 241, 255, 0.95);
+  --portal-text-soft: #8a9ab0;
+  --portal-title: #f4f7ff;
+  --portal-subtitle: rgba(188, 205, 255, 0.82);
+  --portal-line: rgba(97, 129, 206, 0.28);
+  --portal-card: rgba(10, 19, 43, 0.8);
+  --portal-card-2: rgba(12, 24, 52, 0.92);
+  --portal-card-3: rgba(17, 25, 48, 0.8);
+  --portal-card-4: rgba(15, 24, 45, 0.82);
+  --portal-nav-bg: rgba(10, 19, 43, 0.8);
+  --portal-nav-hover: rgba(28, 40, 72, 0.8);
+  --portal-input-bg: rgba(255, 255, 255, 0.08);
+  --portal-input-hover: rgba(255, 255, 255, 0.12);
+  --portal-shadow: 0 16px 34px rgba(0, 0, 0, 0.22);
+  --portal-shadow-strong: 0 24px 60px rgba(0, 0, 0, 0.38);
+  --portal-accent: #6e7dff;
+  --portal-accent-2: #8d4dff;
+  --portal-accent-soft: rgba(110, 125, 255, 0.16);
+  --portal-todo-bg: #070e20;
+  --portal-todo-hover: rgba(28, 40, 72, 0.8);
+  --portal-number-todo: #f56c6c;
+  --portal-number-done: #ffffff;
+  --bg-table: #091126;
+  color: var(--portal-text);
+  background:
+    radial-gradient(
+      circle at 18% 12%,
+      rgba(79, 82, 221, 0.34),
+      transparent 22%
+    ),
+    radial-gradient(circle at 82% 20%, rgba(28, 95, 255, 0.2), transparent 20%),
+    radial-gradient(
+      circle at 50% 100%,
+      rgba(103, 46, 255, 0.16),
+      transparent 28%
+    ),
+    linear-gradient(180deg, #040814 0%, #060d1d 46%, #040814 100%);
+}
+
+.nav {
+  background-color: var(--bg-table);
+}
+.todo-list {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.content {
+  padding: 16px 20px;
+  margin-top: 100px;
+}
+
+.pagination-wrap {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 16px;
+}
+
+.news-container {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f7fa;
+}
+
+.content-wrapper {
+  flex: 1;
+  max-width: 1200px;
+  /* margin: 0 auto; */
+  padding: 20px;
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.page-title {
+  margin-bottom: 20px;
+  color: #303133;
+  border-left: 5px solid #409eff;
+  padding-left: 10px;
+}
+
+.table-wrapper {
+  min-height: 400px;
+  background: #fff;
+  padding: 20px;
+  border-radius: 4px;
+}
+
+.table-title {
+  font-weight: 500;
+  color: #303133;
+}
+
+.table-summary {
+  color: #606266;
+  font-size: 13px;
+}
+
+.pagination-container {
+  display: flex;
+  justify-content: center;
+  margin-top: 0px;
+  padding: 20px 0;
+}
+
+:deep(.el-table) {
+  background-color: var(--bg-table) !important;
+  color: var(--text-primary) !important;
+}
+
+:deep(.table-wrapper) {
+  background: var(--bg-table) !important;
+}
+
+:deep(.el-table__header-wrapper thead) {
+  background: var(--bg-table-head) !important;
+  color: var(--text-primary) !important;
+}
+
+:deep(.el-table__header-wrapper .el-table__header) {
+  border-bottom: none;
+  background: var(--bg-table-head) !important;
+}
+:deep(.el-table__inner-wrapper) {
+  background: var(--bg-table) !important;
+  color: var(--text-primary) !important;
+}
+:deep(.el-table__body-wrapper .el-table__row) {
+  background: var(--bg-table);
+  color: var(--text-primary) !important;
+}
+
+:deep(.el-table__body-wrapper .el-table__row .hover-row) {
+  background: var(--bg-table) !important;
+  color: var(--text-primary) !important;
+}
+
+:deep(.el-table__body-wrapper .el-table__row .el-table__cell) {
+  background: var(--bg-table) !important;
+  color: var(--text-primary) !important;
+  border-bottom: 1px solid var(--border-color) !important;
+}
+
+:deep(.el-loading-mask) {
+  background-color: var(--bg-table) !important; /* 半透明深色遮罩 */
+}
+
+:deep(.el-table__body-wrapper .el-table__row .el-table__cell) {
+  border-bottom: 1px solid #313849;
+}
+
+:deep(.el-pagination is-background) {
+  background: var(--bg-table) !important;
+}
+
+:deep(.el-pagination .el-pager li) {
+  background: var(--bg-table) !important;
+  color: var(--text-tertiary) !important;
+}
+
+:deep(.el-pagination .el-pager li.is-active) {
+  /* background: #2d8cf0 !important; */
+  color: var(--portal-accent) !important;
+}
+
+:deep(.el-select .el-select__wrapper) {
+  background: var(--bg-table) !important;
+  border: 1px solid #313849 !important;
+  outline: none !important;
+}
+
+:deep(.el-input) {
+  border: 1px solid #313849 !important;
+  outline: none !important;
+}
+
+:deep(.btn-next) {
+  background: var(--bg-table) !important;
+  color: var(--text-tertiary) !important;
+}
+
+:deep(.btn-prev) {
+  background: var(--bg-table) !important;
+  color: var(--text-tertiary) !important;
+}
+
+/* 下拉菜单弹出层的背景 */
+:deep(.el-select-dropdown) {
+  background-color: var(--bg-table) !important;
+  border: 1px solid #313849 !important;
+}
+
+/* 下拉菜单项 */
+:deep(.el-select-dropdown__item) {
+  color: var(--bg-table) !important;
+}
+
+:deep(.el-select-dropdown__item.hover),
+:deep(.el-select-dropdown__item:hover) {
+  background-color: var(--bg-table) !important; /* 悬停深色背景 */
+}
+
+/* 关键:修复下拉选择框 (PageSize) 的白色边框/背景 */
+:deep(.el-pagination .el-select .el-select__wrapper) {
+  background-color: var(--bg-table) !important;
+  box-shadow: none !important; /* 去掉可能的阴影 */
+  border: 1px solid #313849 !important; /* 统一边框颜色 */
+}
+
+/* 去掉聚焦时的白色/蓝色轮廓 */
+:deep(.el-pagination .el-select .el-select__wrapper.is-focused),
+:deep(.el-pagination .el-select .el-select__wrapper:hover) {
+  box-shadow: none !important;
+  border-color: #409eff !important; /* 聚焦时变为主题蓝,或者保持 #313849 */
+}
+
+/* 通用输入框边框修复 (如果其他地方也有) */
+:deep(.el-input__wrapper) {
+  background-color: var(--bg-table) !important;
+  box-shadow: none !important; /* 去掉默认的白色/灰色阴影边框 */
+  border: 1px solid #313849 !important;
+}
+
+:deep(.el-input__inner) {
+  color: var(--bg-primary) !important;
+}
+</style>

+ 20 - 1
src/views/flow/index.vue

@@ -227,6 +227,7 @@ import {
   getOATasks,
   getCRMTasks,
   getSRMTasks,
+  getEHRTasks,
 } from "@/api/user";
 import { useUserStore } from "@/stores/useUserStore";
 import { useThemeStore } from "@/stores/useThemeStore";
@@ -653,12 +654,20 @@ const handleDetailClick = (task, categoryTitle) => {
         query: { type: task.name.toLowerCase() },
       });
     }
+
+    if (task.name === "EHR" && categoryTitle === "我的待办") {
+      router.push({
+        path: "/ehr-todo-list",
+        query: { type: task.name.toLowerCase() },
+      });
+    }
   }
 };
 
 let oaTasks = ref([]);
 let crmTasks = ref([]);
 let srmTasks = ref([]);
+let ehrTasks = ref([]);
 const statsLoading = ref(true);
 
 const stats = ref([
@@ -728,14 +737,24 @@ onMounted(async () => {
 
       srmTasks.value = srmRes;
 
+      const ehrRes = await getEHRTasks({
+        id: userStore.getUser.username,
+        pageNum: 1,
+        pageSize: 10,
+      });
+
+      ehrTasks.value = ehrRes;
+
       stats.value[0].number =
         Number(oaTasks.value.todoCount) +
         Number(crmTasks.value.todoCount) +
-        Number(srmTasks.value.todoCount);
+        Number(srmTasks.value.todoCount) +
+        Number(ehrTasks.value.todoCount);
       todoCount.value = [
         { name: "OA", value: oaTasks.value.todoCount ?? 0 },
         { name: "CRM", value: crmTasks.value.todoCount ?? 0 },
         { name: "SRM", value: srmTasks.value.todoCount ?? 0 },
+        { name: "EHR", value: ehrTasks.value.todoCount ?? 0 },
       ];
 
       // *****************已办事项统计*************************

+ 63 - 32
src/views/index.vue

@@ -119,23 +119,30 @@
                 <template #dropdown>
                   <el-dropdown-menu>
                     <el-dropdown-item command="todo-oa">
-                      <div class="p-2 flex items-center gap-3 text-[#e43c2f]!">
+                      <div class="p-2 flex items-center gap-3 text-[#e26669]!">
                         <span>OA</span>
                         <span>{{ oatodo }}</span>
                       </div>
                     </el-dropdown-item>
                     <el-dropdown-item command="todo-crm">
-                      <div class="p-2 flex items-center gap-3 text-[#e43c2f]!">
+                      <div class="p-2 flex items-center gap-3 text-[#e26669]!">
                         <span>CRM</span>
                         <span>{{ crmtodo }}</span>
                       </div>
                     </el-dropdown-item>
                     <el-dropdown-item command="todo-srm">
-                      <div class="p-2 flex items-center gap-3 text-[#e43c2f]!">
+                      <div class="p-2 flex items-center gap-3 text-[#e26669]!">
                         <span>SRM</span>
                         <span>{{ srmtodo }}</span>
                       </div>
                     </el-dropdown-item>
+
+                    <el-dropdown-item command="todo-ehr">
+                      <div class="p-2 flex items-center gap-3 text-[#e26669]!">
+                        <span>EHR</span>
+                        <span>{{ ehrtodo }}</span>
+                      </div>
+                    </el-dropdown-item>
                   </el-dropdown-menu>
                 </template>
               </el-dropdown>
@@ -403,6 +410,15 @@
                           <span>{{ srmtodo }}</span>
                         </div>
                       </el-dropdown-item>
+
+                      <el-dropdown-item command="todo-ehr">
+                        <div
+                          class="p-2 flex items-center gap-3 text-[#e26669]!"
+                        >
+                          <span>EHR</span>
+                          <span>{{ ehrtodo }}</span>
+                        </div>
+                      </el-dropdown-item>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -570,6 +586,7 @@ import {
   getOATasks,
   getCRMTasks,
   getSRMTasks,
+  getEHRTasks,
   getNotices,
   getRedHeadFiles,
   getNews,
@@ -751,6 +768,7 @@ const handleQuickAccessCommand = (command: string) => {
     "done-crm": "/crm-done-list?type=crm",
     "todo-srm": "/srm-todo-list?type=srm",
     "done-srm": "/srm-done-list?type=srm",
+    "todo-ehr": "/ehr-todo-list?type=ehr",
   };
 
   const routeMap2: Record<string, string> = {
@@ -903,42 +921,54 @@ let crmtodo = ref(0);
 let crmdone = ref(0);
 let srmtodo = ref(0);
 let srmdone = ref(0);
+
+let ehrtodo = ref(0);
 const loadHomeData = async () => {
   await loadNoticeList(activeNoticeTab.value);
 
   if (!userStore.getUser.username) return;
 
-  const [oaRes, crmRes, crmDoneRes, srmRes, newsRes] = await Promise.all([
-    getOATasks({
-      id: userStore.getUser.username,
-      pageNum: 1,
-      pageSize: 10,
-    }),
-    await getCRMTasks({
-      id: userStore.getUser.username,
-      type: "pending",
-      pageNum: 1,
-      pageSize: 10,
-    }),
-    await getCRMTasks({
-      id: userStore.getUser.username,
-      type: "approved",
-      pageNum: 1,
-      pageSize: 10,
-    }),
-    await getSRMTasks({
-      id: userStore.getUser.username,
-      pageNum: 1,
-      pageSize: 10,
-    }),
-    getNews({
-      pageNum: 1,
-      pageSize: 10,
-    }),
-  ]);
+  const [oaRes, crmRes, crmDoneRes, srmRes, ehrRes, newsRes] =
+    await Promise.all([
+      getOATasks({
+        id: userStore.getUser.username,
+        pageNum: 1,
+        pageSize: 10,
+      }),
+      await getCRMTasks({
+        id: userStore.getUser.username,
+        type: "pending",
+        pageNum: 1,
+        pageSize: 10,
+      }),
+      await getCRMTasks({
+        id: userStore.getUser.username,
+        type: "approved",
+        pageNum: 1,
+        pageSize: 10,
+      }),
+      await getSRMTasks({
+        id: userStore.getUser.username,
+        pageNum: 1,
+        pageSize: 10,
+      }),
+      await getEHRTasks({
+        id: userStore.getUser.username,
+        pageNum: 1,
+        pageSize: 10,
+      }),
+      getNews({
+        pageNum: 1,
+        pageSize: 10,
+      }),
+    ]);
 
   oaTasks.value = oaRes.todoList.slice(0, 3);
-  todo.value = Number(oaRes.todoCount) + crmRes.todoCount + srmRes.todoCount;
+  todo.value =
+    Number(oaRes.todoCount) +
+    crmRes.todoCount +
+    srmRes.todoCount +
+    ehrRes.todoCount;
   done.value =
     Number(oaRes.doneCount) + crmDoneRes.todoCount + srmRes.doneCount;
 
@@ -948,6 +978,7 @@ const loadHomeData = async () => {
   crmdone.value = crmDoneRes.todoCount;
   srmtodo.value = srmRes.todoCount;
   srmdone.value = srmRes.doneCount;
+  ehrtodo.value = ehrRes.todoCount;
   newsList.value = newsRes.list.slice(0, 3);
 };
 

+ 2 - 2
src/views/login.vue

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