From 1681cdaa1074f57d49579a6ae2adb0140a166851 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Mon, 29 Sep 2025 16:33:40 +0800
Subject: [PATCH] feat:移动端基础配置调整、登录页基础配置调整

---
 src/config/website.js             |   83 +++++++
 src/api/user/index.js             |   45 +++
 src/pages/login/index.vue         |  259 ++++++++++++----------
 src/utils/request/interceptors.js |  203 ++++++++---------
 env/.env.development              |    2 
 env/.env.test                     |    2 
 package.json                      |    4 
 env/.env.production               |    2 
 env/.env                          |    2 
 pnpm-lock.yaml                    |   14 +
 10 files changed, 381 insertions(+), 235 deletions(-)

diff --git a/env/.env b/env/.env
index d69f69d..4d07c50 100644
--- a/env/.env
+++ b/env/.env
@@ -5,7 +5,7 @@
 VITE_APP_ENV=development
 
 # 接口地址
-VITE_API_BASE_URL=http://localhost:8080
+VITE_API_BASE_URL=https://wrj.shuixiongit.com/api
 
 # 端口号
 VITE_APP_PORT=9527
diff --git a/env/.env.development b/env/.env.development
index c078d37..aaf33b4 100644
--- a/env/.env.development
+++ b/env/.env.development
@@ -2,7 +2,7 @@
 VITE_APP_ENV=development
 
 # 接口地址
-VITE_API_BASE_URL=http://localhost:8080
+VITE_API_BASE_URL=https://wrj.shuixiongit.com/api
 
 # 删除console
 VITE_DROP_CONSOLE=false
diff --git a/env/.env.production b/env/.env.production
index 7ee7743..37d85fa 100644
--- a/env/.env.production
+++ b/env/.env.production
@@ -2,7 +2,7 @@
 VITE_APP_ENV=production
 
 # 接口地址
-VITE_API_BASE_URL=http://localhost:8080/prod
+VITE_API_BASE_URL=https://wrj.shuixiongit.com/api
 
 # 删除console
 VITE_DROP_CONSOLE=true
diff --git a/env/.env.test b/env/.env.test
index 88a6c6f..c4499c7 100644
--- a/env/.env.test
+++ b/env/.env.test
@@ -2,7 +2,7 @@
 VITE_APP_ENV=staging
 
 # 接口地址
-VITE_API_BASE_URL=http://localhost:8080/staging
+VITE_API_BASE_URL=https://wrj.shuixiongit.com/api
 
 # 删除console
 VITE_DROP_CONSOLE=true
diff --git a/package.json b/package.json
index f368bc3..2b08074 100644
--- a/package.json
+++ b/package.json
@@ -84,7 +84,9 @@
     "uview-plus": "^3.5.41",
     "vue": "3.4.21",
     "vue-i18n": "9.1.9",
-    "z-paging": "^2.8.8"
+    "z-paging": "^2.8.8",
+    "js-md5": "^0.7.3",
+    "js-base64": "^3.7.4"
   },
   "devDependencies": {
     "@antfu/eslint-config": "5.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b52026d..4377ecf 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -59,6 +59,12 @@
   dayjs:
     specifier: ^1.11.18
     version: 1.11.18
+  js-base64:
+    specifier: ^3.7.4
+    version: 3.7.4
+  js-md5:
+    specifier: ^0.7.3
+    version: 0.7.3
   leaflet:
     specifier: ^1.9.4
     version: 1.9.4
@@ -7795,6 +7801,14 @@
     resolution: {integrity: sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==}
     dev: false
 
+  /js-base64@3.7.4:
+    resolution: {integrity: sha512-wpM/wi20Tl+3ifTyi0RdDckS4YTD4Lf953mBRrpG8547T7hInHNPEj8+ck4gB8VDcGyeAWFK++Wb/fU1BeavKQ==}
+    dev: false
+
+  /js-md5@0.7.3:
+    resolution: {integrity: sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==}
+    dev: false
+
   /js-tokens@4.0.0:
     resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
 
diff --git a/src/api/user/index.js b/src/api/user/index.js
index 0d1f16b..43c60a9 100644
--- a/src/api/user/index.js
+++ b/src/api/user/index.js
@@ -1,14 +1,51 @@
-import { get, post } from "@/utils/request"
+import {
+  get,
+  post,
+  request
+} from "@/utils/request"
+
+import website from '@/config/website'
 
 /** 获取用户信息 */
-export const profile = params => get("/user/profile", { params })
+export const profile = params => get("/user/profile", {
+  params
+})
 
 /** 登录 */
 export const login = data =>
-  post("/user/login", { data, custom: { auth: false } })
+  post("/user/login", {
+    data,
+    custom: {
+      auth: false
+    }
+  })
 
 /** 验证码登录 */
-export const loginByCode = data => post("/user/loginByCode", { data })
+export const loginByCode = data => post("/user/loginByCode", {
+  data
+})
 
 /** 退出登录 */
 export const logout = () => post("/user/logout")
+
+// 用户登录接口
+export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) =>
+  request({
+    url: '/blade-auth/oauth/token',
+    method: 'post',
+    header: {
+      'Tenant-Id': tenantId,
+      'Dept-Id': website.switchMode ? deptId : '',
+      'Role-Id': website.switchMode ? roleId : '',
+      'Captcha-Key': key,
+      'Captcha-Code': code,
+    },
+    params: {
+      tenantId,
+      username,
+      password,
+      grant_type: 'password',
+      scope: 'all',
+      type,
+    },
+  })
diff --git a/src/config/website.js b/src/config/website.js
new file mode 100644
index 0000000..53305b7
--- /dev/null
+++ b/src/config/website.js
@@ -0,0 +1,83 @@
+/**
+ * 全局配置文件
+ */
+export default {
+	title: '',
+	logo: 'S',
+	key: 'saber', //配置主键,目前用于存储
+	indexTitle: 'BladeX 微服务平台',
+	clientId: 'drone', // 客户端id
+	clientSecret: 'drone_secret', // 客户端密钥
+	tenantMode: false, // 是否开启租户模式
+	tenantId: '000000', // 管理组租户编号
+	captchaMode: false, // 是否开启验证码模式
+	switchMode: false, // 是否开启登录切换角色部门
+	lockPage: '/lock',
+	tokenTime: 3000,
+	tokenHeader: 'Blade-Auth',
+	//HTTP状态码白名单
+	statusWhiteList: [],
+	//配置首页不可关闭
+	setting: {
+		sidebar: 'vertical',
+		tag: true,
+		debug: true,
+		collapse: true,
+		search: true,
+		color: true,
+		lock: true,
+		screenshot: true,
+		fullscreen: true,
+		theme: true,
+		menu: true,
+	},
+	//首页配置
+	fistPage: {
+		// name: '首页',
+		// path: '/wel/index',
+		name: '门户页',
+		path: '/wel/gatewayPage',
+	},
+	//配置菜单的属性
+	menu: {
+		iconDefault: 'icon-caidan',
+		label: 'name',
+		path: 'path',
+		icon: 'source',
+		children: 'children',
+		query: 'query',
+		href: 'path',
+		meta: 'meta',
+	},
+	//水印配置
+	watermark: {
+		mode: false,
+		text: 'BladeX',
+	},
+	//oauth2配置
+	oauth2: {
+		// 是否开启注册功能
+		registerMode: true,
+		// 使用后端工程 @org.springblade.test.Sm2KeyGenerator 获取
+		publicKey: '请配置国密sm2公钥',
+		// 第三方系统授权地址
+		authUrl: 'http://localhost/blade-auth/oauth/render',
+		// 单点登录系统认证
+		ssoMode: false, // 是否开启单点登录功能
+		ssoBaseUrl: 'http://localhost:8100', // 单点登录系统地址(cloud端口为8100,boot端口为80)
+		ssoAuthUrl: '/oauth/authorize?client_id=saber3&response_type=code&redirect_uri=', // 单点登录授权地址
+		ssoLogoutUrl: '/oauth/authorize/logout?redirect_uri=', // 单点登录退出地址
+		redirectUri: 'http://localhost:2888/login', // 单点登录回调地址(Saber服务的登录界面地址)
+	},
+	//设计器配置
+	design: {
+		// 流程设计器类型(true->nutflow,false->flowable)
+		designMode: true,
+		// 流程设计器地址(flowable模式)
+		designUrl: 'http://localhost:9999',
+		// 报表设计器地址(cloud端口为8108,boot端口为80)
+		reportUrl: 'http://localhost:8108/ureport',
+		// 规则设计引擎地址
+		edgeUrl: 'http://localhost:1880',
+	},
+}
diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue
index 403ee91..9ef666e 100644
--- a/src/pages/login/index.vue
+++ b/src/pages/login/index.vue
@@ -3,19 +3,9 @@
   <view>
     <view class="login-form-wrap">
       <view class="title"> 欢迎登录 </view>
-      <input
-        v-model="tel"
-        class="u-border-bottom"
-        type="number"
-        placeholder="请输入手机号"
-      />
+      <input v-model="tel" class="u-border-bottom" type="number" placeholder="请输入手机号" />
       <view class="u-border-bottom my-40rpx flex">
-        <input
-          v-model="code"
-          class="flex-1"
-          type="number"
-          placeholder="请输入验证码"
-        />
+        <input v-model="code" class="flex-1" type="number" placeholder="请输入验证码" />
         <view>
           <u-code ref="uCodeRef" @change="codeChange" />
           <u-button :text="tips" type="success" size="mini" @click="getCode" />
@@ -55,133 +45,166 @@
 </template>
 
 <script setup>
-import {
-  HOME_PATH,
-  isTabBarPath,
-  LOGIN_PATH,
-  removeQueryString,
-} from "@/router";
-import { setToken } from "@/utils/auth";
-// import { useUserStore } from '@/store';
+  import md5 from 'js-md5'
+  import {
+    loginByUsername
+  } from '@/api/user/index.js'
+  import {
+    HOME_PATH,
+    isTabBarPath,
+    LOGIN_PATH,
+    removeQueryString,
+  } from "@/router";
+  import {
+    setToken
+  } from "@/utils/auth";
+  // import { useUserStore } from '@/store';
 
-// const userStore = useUserStore();
-const tel = ref("18502811111");
-const code = ref("1234");
-const tips = ref();
-const uCodeRef = ref(null);
-let redirect = HOME_PATH;
+  // const userStore = useUserStore();
+  const tel = ref("18502811111");
+  const code = ref("1234");
+  const tips = ref();
+  const uCodeRef = ref(null);
+  let redirect = HOME_PATH;
 
-const inputStyle = computed(() => {
-  const style = {};
-  if (tel.value && code.value) {
-    style.color = "#fff";
-    style.backgroundColor = uni.$u.color.warning;
+  const inputStyle = computed(() => {
+    const style = {};
+    if (tel.value && code.value) {
+      style.color = "#fff";
+      style.backgroundColor = uni.$u.color.warning;
+    }
+    return style;
+  });
+
+  function codeChange(text) {
+    tips.value = text;
   }
-  return style;
-});
 
-function codeChange(text) {
-  tips.value = text;
-}
-
-function getCode() {
-  if (uCodeRef.value?.canGetCode) {
-    // 模拟向后端请求验证码
-    uni.showLoading({
-      title: "正在获取验证码",
-    });
+  function getCode() {
+    if (uCodeRef.value?.canGetCode) {
+      // 模拟向后端请求验证码
+      uni.showLoading({
+        title: "正在获取验证码",
+      });
+      setTimeout(() => {
+        uni.hideLoading();
+        uni.$u.toast("验证码已发送");
+        // 通知验证码组件内部开始倒计时
+        uCodeRef.value?.start();
+      }, 1000);
+    } else {
+      uni.$u.toast("倒计时结束后再发送");
+    }
+  }
+  async function submit() {
+    if (!uni.$u.test.mobile(Number(tel.value))) {
+      uni.$u.toast("请输入正确的手机号");
+      return;
+    }
+    if (!code.value) {
+      uni.$u.toast("请输入验证码");
+      return;
+    }
+    // 登录请求
+    // const res = await userStore.login({ phone: tel.value, code: code.value }).catch(() => {
+    //   uni.$u.toast('登录失败');
+    // });
+    // if (!res) return;
+    setToken("1234567890");
     setTimeout(() => {
-      uni.hideLoading();
-      uni.$u.toast("验证码已发送");
-      // 通知验证码组件内部开始倒计时
-      uCodeRef.value?.start();
-    }, 1000);
-  } else {
-    uni.$u.toast("倒计时结束后再发送");
-  }
-}
-async function submit() {
-  if (!uni.$u.test.mobile(Number(tel.value))) {
-    uni.$u.toast("请输入正确的手机号");
-    return;
-  }
-  if (!code.value) {
-    uni.$u.toast("请输入验证码");
-    return;
-  }
-  // 登录请求
-  // const res = await userStore.login({ phone: tel.value, code: code.value }).catch(() => {
-  //   uni.$u.toast('登录失败');
-  // });
-  // if (!res) return;
-  setToken("1234567890");
-  setTimeout(() => {
-    uni.$u.route({
-      type: isTabBarPath(redirect) ? "switchTab" : "redirectTo",
-      url: redirect,
-    });
-  }, 800);
-}
+      uni.$u.route({
+        type: isTabBarPath(redirect) ? "switchTab" : "redirectTo",
+        url: redirect,
+      });
+    }, 800);
 
-onLoad((options) => {
-  if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) {
-    redirect = decodeURIComponent(options.redirect);
+    let userInfo = {
+      "tenantId": "000000",
+      "deptId": "",
+      "roleId": "",
+      "username": "shuishen",
+      "password": "Dashabi....",
+      "type": "account",
+      "code": "",
+      "key": "",
+      "image": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
+    }
+
+    loginByUsername(
+      userInfo.tenantId,
+      userInfo.deptId,
+      userInfo.roleId,
+      userInfo.username,
+      md5(userInfo.password),
+      userInfo.type,
+      userInfo.key,
+      userInfo.code
+    ).then(res => {
+      uni.switchTab({
+        url: '/pages/map/index'
+      })
+    })
   }
-});
+
+  onLoad((options) => {
+    if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) {
+      redirect = decodeURIComponent(options.redirect);
+    }
+  });
 </script>
 
 <style lang="scss" scoped>
-.login-form-wrap {
-  @apply mt-80rpx mx-auto mb-0 w-600rpx;
+  .login-form-wrap {
+    @apply mt-80rpx mx-auto mb-0 w-600rpx;
 
-  .title {
-    @apply mb-100rpx text-60rpx text-left font-500;
-  }
+    .title {
+      @apply mb-100rpx text-60rpx text-left font-500;
+    }
 
-  input {
-    @apply pb-6rpx mb-10rpx text-left;
-  }
+    input {
+      @apply pb-6rpx mb-10rpx text-left;
+    }
 
-  .tips {
-    @apply mt-8rpx mb-60rpx;
+    .tips {
+      @apply mt-8rpx mb-60rpx;
 
-    color: $u-info;
-  }
+      color: $u-info;
+    }
 
-  .login-btn {
-    @apply flex items-center justify-center py-12rpx px-0 text-30rpx bg-#fdf3d0 border-none;
+    .login-btn {
+      @apply flex items-center justify-center py-12rpx px-0 text-30rpx bg-#fdf3d0 border-none;
 
-    color: $u-tips-color;
+      color: $u-tips-color;
 
-    &::after {
-      @apply border-none;
+      &::after {
+        @apply border-none;
+      }
+    }
+
+    .alternative {
+      @apply flex justify-between mt-30rpx;
+
+      color: $u-tips-color;
     }
   }
 
-  .alternative {
-    @apply flex justify-between mt-30rpx;
+  .login-type-wrap {
+    @apply flex justify-between pt-350rpx px-150rpx pb-150rpx;
+
+    .item {
+      @apply flex items-center flex-col text-28rpx;
+
+      color: $u-content-color;
+    }
+  }
+
+  .hint {
+    @apply px-40rpx py-20rpx text-24rpx;
 
     color: $u-tips-color;
+
+    .link {
+      color: $u-warning;
+    }
   }
-}
-
-.login-type-wrap {
-  @apply flex justify-between pt-350rpx px-150rpx pb-150rpx;
-
-  .item {
-    @apply flex items-center flex-col text-28rpx;
-
-    color: $u-content-color;
-  }
-}
-
-.hint {
-  @apply px-40rpx py-20rpx text-24rpx;
-
-  color: $u-tips-color;
-
-  .link {
-    color: $u-warning;
-  }
-}
 </style>
diff --git a/src/utils/request/interceptors.js b/src/utils/request/interceptors.js
index 5984c15..0a45b3b 100644
--- a/src/utils/request/interceptors.js
+++ b/src/utils/request/interceptors.js
@@ -1,8 +1,17 @@
-import { useUserStore } from "@/store"
-import { getToken } from "@/utils/auth"
+import {
+  useUserStore
+} from "@/store"
+import {
+  getToken
+} from "@/utils/auth"
 import storage from "@/utils/storage"
-import { showMessage } from "./status"
-
+import {
+  showMessage
+} from "./status"
+import website from '@/config/website'
+import {
+  Base64
+} from 'js-base64'
 // 重试队列,每一项将是一个待执行的函数形式
 let requestQueue = []
 
@@ -10,10 +19,8 @@
 const repeatSubmit = config => {
   const requestObj = {
     url: config.url,
-    data:
-      typeof config.data === "object"
-        ? JSON.stringify(config.data)
-        : config.data,
+    data: typeof config.data === "object" ?
+      JSON.stringify(config.data) : config.data,
     time: new Date().getTime()
   }
   const sessionObj = storage.getJSON("sessionObj")
@@ -66,106 +73,86 @@
   })
 }
 
-function requestInterceptors (http) {
-  /**
-   * 请求拦截
-   * @param {object} http
-   */
-  http.interceptors.request.use(
-    config => {
-      // 可使用async await 做异步操作
-      // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
-      config.data = config.data || {}
-      // 自定义参数
-      const custom = config?.custom
-
-      // 是否需要设置 token
-      const isToken = custom?.auth === false
-      if (getToken() && !isToken && config.header) {
-        // token设置
-        config.header.token = getToken()
-      }
-
-      // 是否显示 loading
-      if (custom?.loading) {
-        uni.showLoading({
-          title: "加载中",
-          mask: true
-        })
-      }
-
-      // 是否需要防止数据重复提交
-      const isRepeatSubmit = custom?.repeatSubmit === false
-      if (
-        !isRepeatSubmit &&
-        (config.method === "POST" || config.method === "UPLOAD")
-      ) {
-        repeatSubmit(config)
-      }
-      return config
-    },
-    (
-      config // 可使用async await 做异步操作
-    ) => Promise.reject(config)
-  )
-}
-function responseInterceptors (http) {
-  /**
-   * 响应拦截
-   * @param {object} http
-   */
-  http.interceptors.response.use(
-    response => {
-      /* 对响应成功做点什么 可使用async await 做异步操作 */
-      const data = response.data
-      // 配置参数
-      const config = response.config
-      // 自定义参数
-      const custom = config?.custom
-
-      // 登录状态失效,重新登录
-      if (data.code === 401) {
-        return refreshToken(http, config)
-      }
-
-      // 隐藏loading
-      if (custom?.loading) {
-        uni.hideLoading()
-      }
-
-      // 请求成功则返回结果
-      if (data.code === 200) {
-        return response || {}
-      }
-
-      // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
-      if (custom?.toast !== false) {
-        uni.$u.toast(data.message)
-      }
-
-      // 请求失败则抛出错误
-      return Promise.reject(data)
-    },
-    response => {
-      // 自定义参数
-      const custom = response.config?.custom
-
-      // 隐藏loading
-      if (custom?.loading !== false) {
-        uni.hideLoading()
-      }
-
-      // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
-      if (custom?.toast !== false) {
-        const message = response.statusCode
-          ? showMessage(response.statusCode)
-          : "网络连接异常,请稍后再试!"
-        uni.$u.toast(message)
-      }
-
-      return Promise.reject(response)
+function requestInterceptors(http) {
+  http.interceptors.request.use((config) => { // 可使用async await 做异步操作
+    // 假设有token值需要在头部需要携带
+    let accessToken = uni.getStorageSync('accessToken');
+    if (accessToken) {
+      config.header['Blade-Auth'] = 'bearer ' + accessToken;
     }
-  )
+
+    // 安全请求header
+    config.header['Blade-Requested-With'] = 'BladeHttpRequest';
+    // 客户端认证参数
+    config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret);
+
+    // #ifndef H5
+    let url = config.url
+    if (process.env.NODE_ENV == 'development' && !url.startsWith("http")) {
+      url = url.substring(url.indexOf('/api') + 4)
+      config.url = url
+    }
+    // #endif
+
+    // 额外参数
+    // config.data = config.data || {};
+    // config.data.pf = uni.getSystemInfoSync().platform;
+    // config.data.sys = uni.getSystemInfoSync().system;
+
+    // 演示custom 用处
+    // if (config.custom.auth) {
+    //   config.header.token = 'token'
+    // }
+    // if (config.custom.loading) {
+    //  uni.showLoading()
+    // }
+    /**
+     /* 演示
+     if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求
+        return Promise.reject(config)
+      }
+     **/
+    return config
+  }, config => { // 可使用async await 做异步操作
+    return Promise.reject(config)
+  })
 }
 
-export { requestInterceptors, responseInterceptors }
+function responseInterceptors(http) {
+  http.interceptors.response.use((response) => {
+    console.log(response, 2222)
+    // 若有数据返回则通过
+    if (response.data.access_token || response.data.key) {
+      return response.data
+    }
+    // 服务端返回的状态码不等于200,则reject()
+    if (response.data.code !== 200) {
+      uni.showToast({
+        title: response.data.msg,
+        icon: 'none'
+      });
+      return Promise.reject(response);
+    }
+    return response.data;
+  }, (response) => {
+    console.log(response, 111)
+    /*  对响应错误做点什么 (statusCode !== 200)*/
+    uni.showToast({
+      title: response.data.msg,
+      icon: 'none'
+    });
+    if (response.statusCode == 401) {
+      const pages = getCurrentPages()
+      const currentPage = pages[pages.length - 1]
+      uni.redirectTo({
+        url: `/pages/login/login-account?redirect=/${currentPage.route}`
+      })
+    }
+    return Promise.reject(response)
+  })
+}
+
+export {
+  requestInterceptors,
+  responseInterceptors
+}

--
Gitblit v1.9.3