yanghao 2 tygodni temu
rodzic
commit
6beb288e15

+ 3 - 0
components.d.ts

@@ -22,6 +22,9 @@ declare module 'vue' {
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTag: typeof import('element-plus/es')['ElTag']
     Footer: typeof import('./src/components/home/Footer.vue')['default']
     Header: typeof import('./src/components/home/header.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
     "@iconify/vue": "^5.0.0",
     "@types/qs": "^6.14.0",
     "axios": "^1.13.1",
+    "dingtalk-jsapi": "^3.2.5",
     "element-plus": "^2.11.7",
     "jsencrypt": "^3.5.4",
     "motion-v": "^1.7.4",

+ 15 - 0
pnpm-lock.yaml

@@ -20,6 +20,9 @@ importers:
       axios:
         specifier: ^1.13.1
         version: 1.13.1
+      dingtalk-jsapi:
+        specifier: ^3.2.5
+        version: 3.2.5
       element-plus:
         specifier: ^2.11.7
         version: 2.11.7(vue@3.5.22(typescript@5.9.3))
@@ -914,6 +917,9 @@ packages:
     resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
     engines: {node: '>=8'}
 
+  dingtalk-jsapi@3.2.5:
+    resolution: {integrity: sha512-GHtDTmilJQhr07GNarjlzhvgUkPWc0+52zbN2ToW+JzkydaOwmhiJCTO42+BI+onAlhdfLUbtUnGsjQNDTrM1w==}
+
   dunder-proto@1.0.1:
     resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
     engines: {node: '>= 0.4'}
@@ -1358,6 +1364,9 @@ packages:
     resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
     engines: {node: ^10 || ^12 || >=14}
 
+  promise-polyfill@7.1.2:
+    resolution: {integrity: sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==}
+
   proxy-from-env@1.1.0:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 
@@ -2426,6 +2435,10 @@ snapshots:
 
   detect-libc@2.1.2: {}
 
+  dingtalk-jsapi@3.2.5:
+    dependencies:
+      promise-polyfill: 7.1.2
+
   dunder-proto@1.0.1:
     dependencies:
       call-bind-apply-helpers: 1.0.2
@@ -2817,6 +2830,8 @@ snapshots:
       picocolors: 1.1.1
       source-map-js: 1.2.1
 
+  promise-polyfill@7.1.2: {}
+
   proxy-from-env@1.1.0: {}
 
   qs@6.14.0:

BIN
src/assets/images/youcnag.png


+ 35 - 30
src/components/home/CardItem.vue

@@ -103,6 +103,7 @@ import thinkimage from "@/assets/images/think.png"; // 智能决策
 import aiimage from "@/assets/images/ai.png"; // AI大模型
 import agentimage from "@/assets/images/agent.jpeg"; // ai智能体
 import videoimage from "@/assets/images/video.png"; // ai智能体
+import youimage from "@/assets/images/youcnag.png"; // ai智能体
 
 const userStore = useUserStore();
 const router = useRouter();
@@ -131,37 +132,38 @@ const props = defineProps<{
 
 // 创建图标映射表
 const iconMap: Record<string, string> = {
-  "办公系统(OA)": oaimage,
-  "经营驾驶舱(OC)": driveimage,
-  "战略解码与执行(SDM)": zhanlueimage,
+  OA办公: oaimage,
+  "经营驾驶舱(MC)": driveimage,
+  战略解码与执行: zhanlueimage,
   "财务管理(FM)": erpimage,
-  "技术研发管理(RD)": jishuimage,
+  技术研发管理: jishuimage,
   "客户管理(CRM)": crmimage,
   "人力资源(EHR)": ehrimage,
-  "供应链管理(SCM)": scmimage,
-  "组织资产管理(AM)": zuzhiimage,
-  "风控合规管理(ECM)": safeimage,
-  "中航北斗(ZH)": zhonghangimage,
+  "供应商管理(SRM)": scmimage,
+  组织资产管理: zuzhiimage,
+  风控合规管理: safeimage,
+  中航北斗: zhonghangimage,
   "视频中心(VCS)": videoimage,
-  "智能钻井系统(IDS)": zuanjingimage,
-  "智能压裂系统(IFS)": yalieimage,
-  "智能注气系统(IGIS)": zhuqiimage,
-  "智能连油系统(ICOTS)": lianyouimage,
-  "安全应急(QHSE)": qhseimage,
-  "设备管理系统 (PMS)": pmsimage,
-  "项目管理 (PM)": pmimage,
-  "全局数据治理(DG)": dataimage,
-  "智能决策(DI)": thinkimage,
-  "行业AI大模型(LM)": aiimage,
-  "AI智能体(Agent)": agentimage,
+  智能钻井: zuanjingimage,
+  智慧压裂: yalieimage,
+  智慧注气: zhuqiimage,
+  智慧连油: lianyouimage,
+  "质量安全管理(QHSE)": qhseimage,
+  "设备管理(PMS)": pmsimage,
+  "项目管理(PM)": pmimage,
+  "全局数据治理(数据中台)": dataimage,
+  智能决策: thinkimage,
+  行业AI大模型: aiimage,
+  "AI智能体(智能交互)": agentimage,
+  数字油藏: youimage,
 };
 const isSpecialSystem = (label: string) => {
   const specialSystems = [
-    "办公系统(OA)",
+    "OA办公",
     "客户管理(CRM)",
-    "设备管理系统 (PMS)",
-    "中航北斗智慧管理系统",
-    "智能连油系统",
+    "设备管理(PMS)",
+    "中航北斗",
+    "智慧连油",
   ];
   return specialSystems.includes(label);
 };
@@ -182,7 +184,7 @@ const goDetail = () => {
 
 // 处理查看按钮点击事件
 const handleView = async (item: Item) => {
-  if (item.label === "办公系统(OA)") {
+  if (item.label === "OA办公") {
     if (userStore.getUser.username && getAccessToken()) {
       const res = await ssoLogin({
         username: userStore.getUser.username,
@@ -199,7 +201,7 @@ const handleView = async (item: Item) => {
     }
   }
 
-  if (item.label === "设备管理系统 (PMS)") {
+  if (item.label === "设备管理(PMS)") {
     if (userStore.getUser.username && getAccessToken()) {
       window.open(
         import.meta.env.VITE_PMS_URL +
@@ -212,7 +214,7 @@ const handleView = async (item: Item) => {
     }
   }
 
-  if (item.label === "中航北斗(ZH)") {
+  if (item.label === "中航北斗") {
     // window.open("https://zhbdgps.cn", "_blank");
     if (userStore.getUser.username && getAccessToken()) {
       window.open("https://zhbdgps.cn", "_blank");
@@ -222,15 +224,18 @@ const handleView = async (item: Item) => {
   }
 
   if (item.label === "客户管理(CRM)") {
-    // window.open("https://www.xiaoshouyi.com/sfa", "_blank");
     if (userStore.getUser.username && getAccessToken()) {
-      window.open("https://www.xiaoshouyi.com/sfa", "_blank");
+      window.open(
+        "https://crm-tencent.xiaoshouyi.com/global/sso/callback/00APEB9EEEA9B2E338B686B7ECFA8585808C.action?token=" +
+          getAccessToken(),
+        "_blank",
+      );
     } else {
       router.push({ path: "/login" });
     }
   }
 
-  if (item.label === "智能连油系统(ICOTS)") {
+  if (item.label === "智慧连油") {
     const extraParam = "source=zhly";
     if (userStore.getUser.username && getAccessToken()) {
       window.open(
@@ -246,7 +251,7 @@ const handleView = async (item: Item) => {
     }
   }
 
-  if (item.label === "智能注气系统(IGIS)") {
+  if (item.label === "智慧注气") {
     const extraParam = "source=znzq";
     if (userStore.getUser.username && getAccessToken()) {
       window.open(

+ 214 - 4
src/components/home/header.vue

@@ -24,10 +24,71 @@
       </nav>
 
       <div class="hidden lg:flex items-center gap-3 h-full">
-        <div class="flex items-center gap-2 cursor-pointer">
-          <Icon icon="mdi:server" class="w-4 h-4" />
-          <span class="text-sm">控制台</span>
-        </div>
+        <!-- 消息中心 -->
+        <el-dropdown trigger="click" placement="bottom-end">
+          <div class="flex items-center gap-2 cursor-pointer pr-2">
+            <Icon
+              icon="mdi:bell"
+              class="w-5 h-5 text-gray-600 hover:text-[#409EFF]"
+            />
+          </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">
+                    <div class="tab-content">
+                      <!-- 消息中心内容 -->
+                      <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-text">
+                          <p class="message-title">{{ item.title }}</p>
+                          <p class="message-desc">{{ item.desc }}</p>
+                          <p class="message-time">{{ item.time }}</p>
+                        </div>
+                      </div>
+                      <div v-if="!messages.length" class="no-messages">
+                        暂无新消息
+                      </div>
+                    </div>
+                  </el-tab-pane>
+                  <el-tab-pane label="待办任务" name="tasks">
+                    <div class="tab-content">
+                      <!-- 待办任务内容 -->
+                      <div
+                        class="task-item"
+                        v-for="(task, index) in tasks"
+                        :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>
+                        </div>
+                        <el-tag :type="task.priorityTag" size="small">{{
+                          task.priorityText
+                        }}</el-tag>
+                      </div>
+                      <div v-if="!tasks.length" class="no-tasks">
+                        暂无待办任务
+                      </div>
+                    </div>
+                  </el-tab-pane>
+                </el-tabs>
+              </div>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
 
         <template v-if="isLoggedIn">
           <el-dropdown @command="onUserCommand" trigger="click">
@@ -202,6 +263,56 @@ import person from "@/assets/images/person.png";
 import { useUserStoreWithOut } from "@/stores/useUserStore";
 const userStore = useUserStoreWithOut();
 
+// 新增消息中心状态
+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 tasks = ref([
+  {
+    title: "审批申请",
+    desc: "部门采购申请等待您审批",
+    dueTime: "今天 17:00",
+    priorityText: "高",
+    priorityTag: "danger",
+  },
+  {
+    title: "项目汇报",
+    desc: "月度项目进度报告待提交",
+    dueTime: "明天",
+    priorityText: "中",
+    priorityTag: "warning",
+  },
+  {
+    title: "会议安排",
+    desc: "准备下周团队会议材料",
+    dueTime: "后天",
+    priorityText: "低",
+    priorityTag: "info",
+  },
+]);
+
 const isLoggedIn = computed(
   () => !!userStore.isSetUser || !!userStore.user?.id,
 );
@@ -273,4 +384,103 @@ const onUserCommand = async (command: string) => {
     opacity: 0;
   }
 }
+
+.notification-dropdown {
+  width: 400px !important;
+  max-height: 500px;
+  overflow: hidden;
+}
+
+.notification-tabs .el-tabs__header {
+  margin-bottom: 0;
+  padding: 10px;
+  background-color: #f8f9fa;
+}
+
+.tab-content {
+  max-height: 400px;
+  overflow-y: auto;
+  padding: 10px;
+}
+
+.message-item {
+  display: flex;
+  align-items: flex-start;
+  padding: 12px 8px;
+  border-bottom: 1px solid #eee;
+}
+
+.message-item:last-child {
+  border-bottom: none;
+}
+
+.message-icon {
+  margin-right: 12px;
+  display: flex;
+  align-items: center;
+}
+
+.message-text {
+  flex: 1;
+}
+
+.message-title {
+  font-weight: 500;
+  color: #303133;
+  margin-bottom: 4px;
+}
+
+.message-desc {
+  font-size: 13px;
+  color: #909399;
+  line-height: 1.4;
+  margin-bottom: 4px;
+}
+
+.message-time {
+  font-size: 12px;
+  color: #c0c4cc;
+}
+
+.no-messages,
+.no-tasks {
+  text-align: center;
+  padding: 20px;
+  color: #909399;
+  font-style: italic;
+}
+
+.task-item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 12px 8px;
+  border-bottom: 1px solid #eee;
+}
+
+.task-item:last-child {
+  border-bottom: none;
+}
+
+.task-info {
+  flex: 1;
+}
+
+.task-title {
+  font-weight: 500;
+  color: #303133;
+  margin-bottom: 4px;
+}
+
+.task-desc {
+  font-size: 13px;
+  color: #909399;
+  line-height: 1.4;
+  margin-bottom: 4px;
+}
+
+.task-time {
+  font-size: 12px;
+  color: #c0c4cc;
+}
 </style>

+ 20 - 20
src/views/index.vue

@@ -93,18 +93,19 @@ const cards: Card[] = [
     id: "management",
     bg: img1,
     items: [
-      { label: "办公系统(OA)" },
+      { label: "OA办公" },
       { label: "客户管理(CRM)" },
       { label: "人力资源(EHR)" },
-      { label: "供应链管理(SCM)" },
+      { label: "供应商管理(SRM)" },
       { label: "财务管理(FM)" },
-      { label: "经营驾驶舱(OC)", tag: "新" },
-      { label: "战略解码与执行(SDM)" },
+      { label: "经营驾驶舱(MC)", tag: "新" },
+      { label: "项目管理 (PM)" },
 
-      { label: "技术研发管理(RD)" },
+      { label: "技术研发管理" },
 
-      { label: "组织资产管理(AM)" },
-      { label: "风控、合规管理(ECM)" },
+      { label: "组织资产管理" },
+      { label: "风控合规管理" },
+      { label: "战略解码与执行" },
     ],
   },
   {
@@ -114,16 +115,15 @@ const cards: Card[] = [
     id: "command",
     bg: img2,
     items: [
-      { label: "设备管理系统 (PMS)" },
-      { label: "中航北斗(ZH)" },
-      { label: "智能连油系统(ICOTS)" },
-      { label: "安全应急(QHSE)" },
+      { label: "设备管理(PMS)" },
+      { label: "中航北斗" },
+      { label: "质量安全管理(QHSE)" },
+      { label: "智慧连油" },
+      { label: "智慧注气" },
+      { label: "智能钻井" },
+      { label: "智慧压裂" },
+      { label: "数字油藏" },
       { label: "视频中心(VCS)" },
-      { label: "智能钻井系统(IDS)", tag: "热" },
-      { label: "智能压裂系统(IFS)" },
-      { label: "智能注气系统(IGIS)" },
-
-      { label: "项目管理 (PM)" },
     ],
   },
   {
@@ -133,10 +133,10 @@ const cards: Card[] = [
     id: "chatbi",
     bg: img3,
     items: [
-      { label: "全局数据治理(DG)", tag: "热" },
-      { label: "智能决策(DI)" },
-      { label: "行业AI大模型(LM)", tag: "新" },
-      { label: "AI智能体(Agent)", tag: "新" },
+      { label: "全局数据治理(数据中台)", tag: "热" },
+      { label: "智能决策" },
+      { label: "行业AI大模型", tag: "新" },
+      { label: "AI智能体(智能交互)", tag: "新" },
     ],
   },
 ];

+ 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">