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