ソースを参照

Merge branch 'dev-wyf' into 'dev'

密码加密&加水印&跳转外链

See merge request product-group-fe/sfy-safety-group/sfy-safety!295
ai0197(吴云丰) 4 ヶ月 前
コミット
a2d1ec3676

+ 1 - 0
package.json

@@ -40,6 +40,7 @@
     "@wangeditor/editor-for-vue": "5.1.12",
     "animate.css": "4.1.1",
     "axios": "0.27.2",
+    "blueimp-md5": "2.19.0",
     "cropperjs": "1.5.12",
     "dayjs": "1.11.4",
     "echarts": "5.5.0",

+ 7 - 0
public/app.config.js

@@ -5,6 +5,13 @@ window.__PRODUCTION__SKYEYEADMIN__CONF__ = {
   // 接口前缀
   VITE_GLOB_API_URL_PREFIX: './safety_api/api',
 
+  VITE_GLOB_SKYEYE_LOGIN_URL: "/skyeye-login/",
+  VITE_GLOB_SKYEYE_PLATFORM_URL: "/skyeye-pc/",
+  VITE_GLOB_SKYEYE_ADMIN_URL: "/skyeye-admin/",
+  VITE_GLOB_SKYEYE_H5_URL: "/skyeye-h5/",
+
+  VITE_GLOB_TIANSUO_PLATFORM: "/tiansuo/"
+
 };
 
 Object.freeze(window.__PRODUCTION__SKYEYEADMIN__CONF__);

+ 24 - 5
src/App.vue

@@ -1,17 +1,31 @@
 <template>
   <div id="app">
-    <Nav v-if="!isFixedScreen" />
-    <div class="content" :class="{ 'fixed-screen': isFixedScreen }">
-      <router-view />
-    </div>
+    <el-watermark class="viewport-watermark" :content="[username, realname]" :font="font" :width="90" :gap="[200, 200]">
+      <Nav v-if="!isFixedScreen" />
+      <div class="content" :class="{ 'fixed-screen': isFixedScreen }">
+        <router-view />
+      </div>
+    </el-watermark>
   </div>
 </template>
 
 <script setup lang="ts">
   import { useRoute } from 'vue-router';
-  import { computed } from 'vue';
+  import { computed, reactive } from 'vue';
+  import { storeToRefs } from 'pinia';
+  import { useUserStore } from '@/store/modules/user';
   import Nav from '@/components/Nav.vue';
 
+  const userStore = useUserStore();
+  const { getUserInfo } = storeToRefs(userStore);
+
+  const username = computed(() => getUserInfo.value.username);
+  const realname = computed(() => getUserInfo.value.realname);
+
+  const font = reactive({
+    color: 'rgba(0,0,0,.03)',
+  });
+
   const route = useRoute();
   const isFixedScreen = computed(
     () => route.matched.some((r) => r.meta?.fixedScreen === true) || route.path.startsWith('/institute-safety'),
@@ -25,7 +39,12 @@
     width: 100vw;
     height: 100vh;
   }
+  .viewport-watermark {
+    width: 100%;
+    height: 100%;
+  }
   .content {
+    height: 100%;
     flex: 1;
     overflow-y: auto;
     overflow-x: hidden;

+ 4 - 0
src/components/Login/components/BaseLogin.vue

@@ -55,8 +55,11 @@
   import { ref, reactive } from 'vue';
   import { ElMessage } from 'element-plus';
   import type { FormInstance } from 'element-plus';
+  import md5 from 'blueimp-md5';
   import exitIcon from 'assets/svg/exit.svg';
   import { useUserStore } from '@/store/modules/user';
+  import { PWD_KEY } from '@/utils/pwd';
+
   const props = defineProps<{ title: string }>();
 
   const userStore = useUserStore();
@@ -73,6 +76,7 @@
     formRef.value.validate((valid: boolean) => {
       if (valid) {
         console.log('valid', formValue);
+        formValue.password = md5(PWD_KEY + formValue.password);
         userStore
           .login(formValue)
           .then(() => {

+ 27 - 8
src/components/Nav.vue

@@ -13,15 +13,9 @@
         <span>{{ item.meta?.title }}</span>
       </div>
     </nav>
+
     <SwitchTenant v-if="userStore.info.tenantId === SYS_TENANT_ID" />
     <div class="platform__right">
-      <div class="platform__right__search">
-        <el-input v-model="searchValue" placeholder="搜索您想了解的" class="input-with-icon" clearable>
-          <template #prepend>
-            <img :src="searchIcon" alt="search" class="search-icon" @click="handleSearch" />
-          </template>
-        </el-input>
-      </div>
       <div class="platform__right__login">
         <span @click="userStore.showLogin = true" v-if="!userStore.info?.id">登录</span>
         <UserInfo v-else />
@@ -63,7 +57,11 @@
   const currentRoute = useRoute();
   const { title } = useGlobSetting();
 
-  const handleNavClick = (item: { name: string; path: string }) => {
+  const handleNavClick = (item: { name: string; path: string; isRedrect?: boolean }) => {
+    if (item.isRedrect) {
+      window.open(item.path, '_blank');
+      return;
+    }
     if (!item.path) {
       router.replace({ name: 'StayTune' });
       // ElMessage.warning({ message: `${item.name}功能建设中,暂无法访问`, offset: 100, grouping: true });
@@ -86,11 +84,13 @@
     height: 78cpx;
     background: url('assets/images/home/nav-bg@1X.png') no-repeat center center / cover;
     z-index: 2;
+
     &__nav {
       @include flex-center;
       gap: 20cpx;
       height: 100%;
       margin-left: 32cpx;
+
       &--item {
         @include flex-center;
         height: 45cpx;
@@ -102,6 +102,7 @@
         cursor: pointer;
         border: 1px solid transparent;
         border-radius: 4px;
+
         // transition: all 0.3s ease-in-out;
         &.active,
         &:hover {
@@ -111,22 +112,26 @@
       }
     }
   }
+
   .header__logo {
     width: 34cpx;
     height: 34cpx;
     margin-left: 38cpx;
   }
+
   .platform-name {
     font-size: 18cpx;
     font-weight: 550;
     margin-left: 9cpx;
   }
+
   .platform__right {
     @include flex-center;
     position: absolute;
     top: 0;
     right: 0;
     height: 73cpx;
+
     &__search {
       @include flex-center;
       width: 210cpx;
@@ -134,6 +139,7 @@
       padding: 28cpx 26cpx;
       background: rgba($white-color, 0.4);
     }
+
     &__login {
       @include flex-center;
       gap: 10cpx;
@@ -144,6 +150,7 @@
       cursor: pointer;
     }
   }
+
   .input-with-icon {
     :deep(.el-input__wrapper),
     :deep(.el-input-group__prepend) {
@@ -151,58 +158,70 @@
       box-shadow: none;
       padding: 0;
     }
+
     :deep(.el-input__inner) {
       width: 120cpx;
       margin-left: 5cpx;
       font-size: 16cpx;
       color: #909399;
     }
+
     .search-icon {
       width: 28cpx;
       height: 28cpx;
       cursor: pointer;
     }
   }
+
   /* 使用 px 的样式覆盖(用于固定画布布局) */
   .header.use-px {
     height: 78px;
   }
+
   .header.use-px .header__nav {
     gap: 14px;
     margin-left: 32px;
   }
+
   .header.use-px .header__nav--item {
     height: 45px;
     padding: 10px 20px;
     font-size: 18px;
     border-radius: 4px;
   }
+
   .header.use-px .header__logo {
     width: 34px;
     height: 34px;
     margin-left: 38px;
   }
+
   .header.use-px .platform-name {
     font-size: 18px;
     margin-left: 9px;
   }
+
   .header.use-px .platform__right {
     height: 73px;
   }
+
   .header.use-px .platform__right__search {
     width: 210px;
     padding: 28px 26px;
   }
+
   .header.use-px .platform__right__login {
     gap: 10px;
     padding: 27px 40px 26px 40px;
     font-size: 18px;
   }
+
   .header.use-px .input-with-icon :deep(.el-input__inner) {
     width: 120px;
     margin-left: 5px;
     font-size: 16px;
   }
+
   .header.use-px .input-with-icon .search-icon {
     width: 28px;
     height: 28px;

+ 19 - 2
src/components/UpdatePwd.vue

@@ -67,6 +67,8 @@
   import exitIcon from 'assets/svg/exit.svg';
   import { useUserStore } from '@/store/modules/user';
   import router from '@/router';
+  import md5 from 'blueimp-md5';
+  import { checkPwdRegexp, PWD_KEY, PWD_MESSAGE } from '@/utils/pwd';
 
   const userStore = useUserStore();
 
@@ -102,6 +104,16 @@
     showOverlay.value = false;
   };
 
+  const validateNewPassword = (rule: any, value: string, callback: any) => {
+    if (value.length < 6) {
+      callback(new Error('密码长度不能小于6位'));
+    } else if (!checkPwdRegexp(value)) {
+      callback(new Error(PWD_MESSAGE));
+    } else {
+      callback();
+    }
+  };
+
   const validateConfirmPassword = (rule: any, value: string, callback: any) => {
     if (value !== formValue.newPwd) {
       callback(new Error('两次输入密码不一致'));
@@ -114,7 +126,8 @@
     oldPwd: [{ required: true, message: '原密码不能为空', trigger: 'blur' }],
     newPwd: [
       { required: true, message: '新密码不能为空', trigger: 'blur' },
-      { min: 6, message: '密码长度不能小于6位', trigger: 'blur' },
+      { validator: validateNewPassword, trigger: 'blur' },
+      // { min: 6, message: '密码长度不能小于6位', trigger: 'blur' },
     ],
     confirmPwd: [
       { required: true, message: '请确认新密码', trigger: 'blur' },
@@ -128,7 +141,11 @@
       if (valid) {
         startLoadingAnimation();
         userStore
-          .changePassword(formValue)
+          .changePassword({
+            userId: userStore.getUserInfo().id,
+            newPwd: md5(PWD_KEY + formValue.newPwd),
+            oldPwd: md5(PWD_KEY + formValue.oldPwd),
+          })
           .then(() => {
             emit('close');
             setTimeout(() => {

+ 156 - 0
src/components/Waterwrapper.vue

@@ -0,0 +1,156 @@
+<template>
+  <!-- 水印容器:根据传入的 props 适配全局/局部水印 -->
+  <div 
+    class="watermark-wrapper"
+    :style="{
+      position: position,
+      top: 0,
+      left: 0,
+      width: width,
+      height: height,
+      zIndex: zIndex,
+      pointerEvents: 'none' // 核心:不遮挡交互
+    }"
+  ></div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted, watch } from 'vue';
+// import {useUserInfoHook} from '@/hooks/useUserInfoHook'
+
+// 定义组件 props
+const props = defineProps({
+  // 定位方式:fixed(全局)/ absolute(局部)
+  position: {
+    type: String,
+    default: 'fixed',
+    validator: (val) => ['fixed', 'absolute'].includes(val)
+  },
+  // 宽度:全局用 100vw,局部用 100%
+  width: {
+    type: String,
+    default: '100vw'
+  },
+  // 高度:全局用 100vh,局部用 100%
+  height: {
+    type: String,
+    default: '100vh'
+  },
+  // 层级:默认 999(低于 el-dialog 的 2000)
+  zIndex: {
+    type: Number,
+    default: 999
+  },
+  // 是否固定屏幕模式(适配你的业务逻辑)
+  isFixedScreen: {
+    type: Boolean,
+    default: false
+  },
+  username:{
+    type: String,
+  },
+    realname:{
+    type: String,
+  }
+});
+
+// 移除水印的方法引用
+let removeWatermarkFn = null;
+
+// 获取用户仓库
+
+// const {realname,staffNo} = useUserInfoHook();
+// 生成水印的核心方法
+const createWatermark = () => {
+  
+  // 未登录/无用户信息时不生成水印
+  if (!props.username || !props.realname) return;
+
+  // 拼接水印文本
+  const watermarkText = `${props.username}-${props.realname}`;
+
+  // 1. 创建 Canvas 绘制水印
+  const canvas = document.createElement('canvas');
+  const ctx = canvas.getContext('2d');
+  if (!ctx) return;
+
+  // 配置水印样式
+  const font = '16px Microsoft YaHei';
+  const color = 'rgba(64, 158, 255, 0.15)';
+  const rotate = -15;
+
+  // 计算文本尺寸
+  ctx.font = font;
+  const textWidth = ctx.measureText(watermarkText).width;
+  canvas.width = textWidth + 120; // 水平间距
+  canvas.height = textWidth + 80; // 垂直间距
+
+  // 绘制水印
+  ctx.font = font;
+  ctx.fillStyle = color;
+  ctx.rotate((rotate * Math.PI) / 180); // 角度转弧度
+  ctx.fillText(watermarkText, 0, canvas.height / 2);
+
+  // 2. 生成 Base64 图片
+  const watermarkBase64 = canvas.toDataURL('image/png');
+
+  // 3. 给水印容器设置背景
+  const wrapper = document.querySelector('.watermark-wrapper');
+  if (wrapper) {
+    wrapper.style.backgroundImage = `url(${watermarkBase64})`;
+    wrapper.style.backgroundRepeat = 'repeat';
+    wrapper.style.backgroundSize = `${canvas.width}px ${canvas.height}px`;
+  }
+};
+
+// 移除水印
+const removeWatermark = () => {
+  const wrapper = document.querySelector('.watermark-wrapper');
+  if (wrapper) {
+    wrapper.style.backgroundImage = 'none';
+  }
+};
+
+// 监听用户信息变化(登录/退出时重新生成水印)
+// watch(
+//   () => userId,
+//   () => {
+//     removeWatermark();
+//     createWatermark();
+//   },
+//   { immediate: true, deep: true }
+// );
+
+// 监听 isFixedScreen 变化,适配布局
+// watch(
+//   () => props.isFixedScreen,
+//   () => {
+//     removeWatermark();
+//     createWatermark();
+//   }
+// );
+
+// 页面挂载时生成水印
+onMounted(() => {
+  createWatermark();
+});
+
+// 页面销毁时移除水印
+onUnmounted(() => {
+  removeWatermark();
+  if (removeWatermarkFn) {
+    removeWatermarkFn();
+  }
+});
+</script>
+
+<style scoped>
+.watermark-wrapper {
+    width: 100vw;
+    height: 100vh;
+  margin: 0;
+  padding: 0;
+  border: none;
+  background: transparent;
+}
+</style>

+ 18 - 1
src/constant/nav.ts

@@ -3,7 +3,8 @@
  */
 
 import { HOME_PAGE } from '@/router/full-routes';
-
+import { useGlobSetting } from '@/hooks/setting';
+const { skyeyePlatformHost, tiansuoHost } = useGlobSetting();
 // 首页导航列表 根据后端返回权限控制(首页永远存在)
 export const NAV_LIST = [
   {
@@ -58,4 +59,20 @@ export const NAV_LIST = [
       title: '平台管理',
     },
   },
+  {
+    name: 'Skyeye',
+    path: skyeyePlatformHost,
+    isRedrect: true,
+    meta: {
+      title: '实时监控',
+    },
+  },
+  {
+    name: 'Tiansuo',
+    path: tiansuoHost,
+    isRedrect: true,
+    meta: {
+      title: '物联集成',
+    },
+  },
 ];

+ 20 - 1
src/hooks/setting/index.ts

@@ -4,7 +4,17 @@ import { warn } from '@/utils/log';
 import { getAppEnvConfig } from '@/utils/env';
 
 export const useGlobSetting = (): Readonly<GlobConfig> => {
-  const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_DRILL_SIGN_URL } = getAppEnvConfig();
+  const {
+    VITE_GLOB_APP_TITLE,
+    VITE_GLOB_API_URL_PREFIX,
+    VITE_GLOB_DRILL_SIGN_URL,
+    // VITE_GLOB_TENANT_CODE,
+    VITE_GLOB_SKYEYE_LOGIN_URL,
+    VITE_GLOB_SKYEYE_PLATFORM_URL,
+    VITE_GLOB_SKYEYE_ADMIN_URL,
+    VITE_GLOB_SKYEYE_H5_URL,
+    VITE_GLOB_TIANSUO_PLATFORM,
+  } = getAppEnvConfig();
 
   // Take global configuration
   const glob: Readonly<GlobConfig> = {
@@ -13,6 +23,15 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
     urlPrefix: VITE_GLOB_API_URL_PREFIX || '',
 
     drillSignUrl: VITE_GLOB_DRILL_SIGN_URL || '',
+
+    // tenantCode: VITE_GLOB_TENANT_CODE,
+
+    skyeyeLoginHost: VITE_GLOB_SKYEYE_LOGIN_URL,
+    skyeyePlatformHost: VITE_GLOB_SKYEYE_PLATFORM_URL,
+    skyeyeAdminHost: VITE_GLOB_SKYEYE_ADMIN_URL,
+    skyeyeH5Host: VITE_GLOB_SKYEYE_H5_URL,
+
+    tiansuoHost: VITE_GLOB_TIANSUO_PLATFORM,
   };
   return glob as Readonly<GlobConfig>;
 };

+ 3 - 1
src/main.ts

@@ -18,10 +18,12 @@ dayjs.locale('zh-cn');
 
 async function bootstrap() {
   const app = createApp(App);
+  
   app.use(notivue);
-
+   
   // 全局完整引入 element 组件
   setupElement(app);
+
   app.component('BreadcrumbBack', BreadcrumbBack); //全局注册面包屑返回按钮
 
   // 注册全局自定义指令,如:v-permission权限指令

+ 1 - 1
src/utils/env.ts

@@ -16,8 +16,8 @@ export function getStorageShortName() {
 
 export function getAppEnvConfig() {
   const ENV_NAME = '__PRODUCTION__SKYEYEADMIN__CONF__';
-
   const ENV = window[ENV_NAME as any] as unknown as GlobEnvConfig;
+
   if (!ENV) {
     throw new Error('config not found');
   }

+ 12 - 0
src/utils/pwd.ts

@@ -0,0 +1,12 @@
+const PWD_KEY = 'NavieAdmin_';
+
+// 中密码正则(字母+数字,可含特殊字符)
+// const PWD_REGEXP = /^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z0-9!@#$%^&*`~()-+=]{6,18}$/;
+// 强密码:大小写+数字+特殊字符,长度≥6
+// const PWD_REGEXP = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,12}$/;
+const PWD_REGEXP = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[#@$!%*?&])[a-zA-Z\d#@$!%*?&]{6,12}$/;
+
+const PWD_MESSAGE = '密码6-12位包含 数字 字母 特殊字符(#@$!%*?&)';
+const checkPwdRegexp = (pwd: string) => PWD_REGEXP.test(pwd);
+
+export { PWD_KEY, PWD_REGEXP, checkPwdRegexp, PWD_MESSAGE };

+ 50 - 51
src/views/system/user/ResetCodeDrawer.vue

@@ -1,22 +1,11 @@
 <template>
   <el-drawer v-model="isDrawer" :size="width" :title="props.title" @close="handleReset">
-    <el-form
-      :model="formParams"
-      :rules="rules"
-      ref="formRef"
-      label-placement="left"
-      :label-width="80"
-    >
+    <el-form :model="formParams" :rules="rules" ref="formRef" label-placement="left" :label-width="80">
       <el-form-item label="登录账号" prop="username">
         <el-input placeholder="请输入登录账号" v-model="formParams.username" disabled />
       </el-form-item>
       <el-form-item label="新密码" prop="password">
-        <el-input
-          type="password"
-          show-password-on="mousedown"
-          placeholder="请输入密码"
-          v-model="formParams.password"
-        />
+        <el-input type="password" show-password-on="mousedown" placeholder="请输入密码" v-model="formParams.password" />
       </el-form-item>
       <el-form-item label="确认密码" prop="passwordRe">
         <el-input
@@ -40,25 +29,40 @@
 <script lang="ts" setup>
   import { ref } from 'vue';
   import { FormRules, ElMessage } from 'element-plus';
-  import { cloneDeep } from 'lodash-es';
+  import type { FormInstance } from 'element-plus';
+  // import { cloneDeep } from 'lodash-es';
   import { UserType, resetCode } from '@/api/system/user-operate';
+  import md5 from 'blueimp-md5';
+  import { checkPwdRegexp, PWD_KEY, PWD_MESSAGE } from '@/utils/pwd';
+
+  const validateNewPassword = (rule: any, value: string, callback: any) => {
+    if (value.length < 6) {
+      callback(new Error('密码长度不能小于6位'));
+    } else if (!checkPwdRegexp(value)) {
+      callback(new Error(PWD_MESSAGE));
+    } else {
+      callback();
+    }
+  };
+
+  const validateConfirmPassword = (rule: any, value: string, callback: any) => {
+    if (value !== formParams.value.password) {
+      callback(new Error('两次输入密码不一致'));
+    } else {
+      callback();
+    }
+  };
 
   const rules: FormRules = {
-    username: {
-      required: true,
-      message: '登录账号不能为空',
-      trigger: 'blur',
-    },
-    password: {
-      required: true,
-      message: '密码不能为空',
-      trigger: 'blur',
-    },
-    passwordRe: {
-      required: true,
-      message: '密码不能为空',
-      trigger: 'blur',
-    },
+    username: [{ required: true, message: '登录账号不能为空', trigger: 'blur' }],
+    password: [
+      { required: true, message: '新密码不能为空', trigger: 'blur' },
+      { validator: validateNewPassword, trigger: 'blur' },
+    ],
+    passwordRe: [
+      { required: true, message: '请确认新密码', trigger: 'blur' },
+      { validator: validateConfirmPassword, trigger: 'blur' },
+    ],
   };
   const emit = defineEmits(['change']);
 
@@ -79,13 +83,13 @@
   });
 
   const message = ElMessage;
-  const formRef: any = ref(null);
+  const formRef = ref<FormInstance>();
   const isDrawer = ref(false);
   const subLoading = ref(false);
 
   const formParams = ref<UserType>(defaultValueRef());
 
-  async function openDrawer(username?, userId? ) {
+  async function openDrawer(username?, userId?) {
     formParams.value.username = username;
     formParams.value.userId = userId;
     isDrawer.value = true;
@@ -96,31 +100,26 @@
   }
 
   function formSubmit() {
-    formRef.value.validate((valid) => {
-      if (!valid) {
-        return message.error('请填写完整信息');
-      }
-      // 克隆
-      const params = cloneDeep(formParams.value);
-      if (params.password != params.passwordRe) {
-        return message.error('两次密码不一致');
-      }
-      const addData = {
-        newPwd: formParams.value.password as string,
-        userId: Number(formParams.value.userId),
-      };
-      resetCode(addData).then(() => {
-        emit('change');
-        handleReset();
-        closeDrawer();
-        ElMessage.success('重置成功');
-      });
+    if (!formRef.value) return;
+    formRef.value.validate((valid: boolean) => {
+      if (valid) {
+        const addData = {
+          userId: Number(formParams.value.userId),
+          newPwd: md5(PWD_KEY + formParams.value.password),
+        };
 
-      //然后进行调接口
+        resetCode(addData).then(() => {
+          emit('change');
+          handleReset();
+          closeDrawer();
+          ElMessage.success('重置成功');
+        });
+      }
     });
   }
 
   function handleReset() {
+    if (!formRef.value) return;
     formRef.value.resetFields();
     formParams.value = Object.assign(formParams.value, defaultValueRef());
   }

+ 23 - 0
types/config.d.ts

@@ -56,6 +56,18 @@ export interface GlobConfig {
   urlPrefix: string;
   // 签到二维码地址
   drillSignUrl: string;
+
+  // 租户code
+  // tenantCode?: string;
+
+  // 天眼外链地址
+  skyeyeLoginHost: string | undefined;
+  skyeyePlatformHost: string | undefined;
+  skyeyeAdminHost: string | undefined;
+  skyeyeH5Host: string | undefined;
+
+  // 天梭外链地址
+  tiansuoHost: string | undefined;
 }
 
 export interface GlobEnvConfig {
@@ -65,6 +77,17 @@ export interface GlobEnvConfig {
   VITE_GLOB_API_URL_PREFIX: string;
   // 签到二维码地址
   VITE_GLOB_DRILL_SIGN_URL: string;
+  // 租户code
+  VITE_GLOB_TENANT_CODE: string;
+
+  // 天眼外链地址
+  VITE_GLOB_SKYEYE_LOGIN_URL: string;
+  VITE_GLOB_SKYEYE_PLATFORM_URL: string;
+  VITE_GLOB_SKYEYE_ADMIN_URL: string;
+  VITE_GLOB_SKYEYE_H5_URL: string;
+
+  // 天梭外链地址
+  VITE_GLOB_TIANSUO_PLATFORM: string;
 }
 
 // export interface GlobConfig {

+ 7 - 0
utils/devProxy/staff/app.config.js

@@ -5,6 +5,13 @@ window.__PRODUCTION__SKYEYEADMIN__CONF__ = {
   // 接口前缀
   VITE_GLOB_API_URL_PREFIX: './safety_api/api',
 
+  VITE_GLOB_SKYEYE_LOGIN_URL: "/skyeye-login/",
+  VITE_GLOB_SKYEYE_PLATFORM_URL: "/skyeye-pc/",
+  VITE_GLOB_SKYEYE_ADMIN_URL: "/skyeye-admin/",
+  VITE_GLOB_SKYEYE_H5_URL: "/skyeye-h5/",
+
+  VITE_GLOB_TIANSUO_PLATFORM: "/tiansuo/"
+
 };
 
 Object.freeze(window.__PRODUCTION__SKYEYEADMIN__CONF__);

+ 5 - 3
utils/devProxy/staff/proxy.ts

@@ -4,9 +4,11 @@ import path from 'path';
 // staff环境
 const proxyStaff: PROXY_TYPE = {
   serverHost: 'http://192.168.13.68:8802/',
-  // serverHost: 'http://192.168.22.121:8802/',
-  // serverHost: 'http://192.168.21.223:8802/',
-  loginHost: 'http://192.168.13.68:7200/login/#/',
+  skyeyeLoginHost: 'http://192.168.13.68:7000/skyeye-login/#/',
+  skyeyePlatformHost: 'http://192.168.13.68:7000/skyeye-pc/#/',
+  skyeyeAdminHost: 'http://192.168.13.68:7000/skyeye-admin/#/',
+  skyeyeH5Host: 'http://192.168.13.68:7000/skyeye-h5/#/',
+  tiansuoHost: 'http://192.168.6.33:91/',
   fileUploadHost: 'http://192.168.13.102:9000/',
   violation_src: 'http://192.168.13.102:62/violation_src',
   push_stream_host: 'http://192.168.13.68:7000/skyeye-admin/push_stream_host/',

+ 10 - 1
utils/devProxy/types.ts

@@ -2,8 +2,17 @@ export interface PROXY_TYPE {
   /** 后端服务的地址 */
   serverHost: string;
 
+  /** 天眼地址 */
+  skyeyeLoginHost: string;
+  skyeyePlatformHost: string;
+  skyeyeAdminHost: string;
+  skyeyeH5Host: string;
+
+  /** 天梭地址 */
+  tiansuoHost: string;
+
   /** 登录地址 */
-  loginHost: string;
+  // loginHost: string;
   /** 文件存储服务minio */
   fileUploadHost: string;
   /** 流媒体服务 */

+ 5 - 0
utils/devProxy/utils.ts

@@ -7,6 +7,11 @@ export const createProxyList = (devProxy: PROXY_TYPE) =>
   [
     ['/ws_api_bak/', devProxy.serverHost],
     ['/safety_api/', devProxy.serverHost],
+    ['/skyeye-login/', devProxy.skyeyeLoginHost],
+    ['/skyeye-pc/', devProxy.skyeyePlatformHost],
+    ['/skyeye-admin/', devProxy.skyeyeAdminHost],
+    ['/skyeye-h5/', devProxy.skyeyeH5Host],
+    ['/tiansuo/', devProxy.tiansuoHost],
     ['/skyeye-file-upload/', devProxy.fileUploadHost],
     ['/push_stream_host/', devProxy.push_stream_host],
     ['/violation_src/', devProxy.violation_src],