Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation
This project
Loading...
Sign in
陈岩
/
CvaYap-app
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 9e4b3e50
authored
Dec 11, 2025
by
陈岩
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
feat: 完成保持登录功能
1 parent
32b9de45
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
320 additions
and
66 deletions
manifest.json
pages/home/index.nvue
pages/login/index.vue
uni_modules/wczd-app-update/js_sdk/app-update.js
utils/request copy.js
utils/request.js
manifest.json
View file @
9e4b3e5
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
"name"
:
"CVA YAP"
,
"name"
:
"CVA YAP"
,
"appid"
:
"__UNI__C2F3380"
,
"appid"
:
"__UNI__C2F3380"
,
"description"
:
""
,
"description"
:
""
,
"versionName"
:
"1.0.2
0
"
,
"versionName"
:
"1.0.2
1
"
,
"versionCode"
:
3
0
,
"versionCode"
:
3
1
,
"transformPx"
:
false
,
"transformPx"
:
false
,
/*
h
5
代理方式
*/
/*
h
5
代理方式
*/
"h5"
:
{
"h5"
:
{
...
@@ -220,12 +220,12 @@
...
@@ -220,12 +220,12 @@
"androidStyle"
:
"default"
,
"androidStyle"
:
"default"
,
"useOriginalMsgbox"
:
false
,
"useOriginalMsgbox"
:
false
,
"android"
:
{
"android"
:
{
"hdpi"
:
"/Users/yuki/vion_app/
pmi
/android/480x762-1.9.png"
,
"hdpi"
:
"/Users/yuki/vion_app/
CVA YAP
/android/480x762-1.9.png"
,
"xhdpi"
:
"/Users/yuki/vion_app/
pmi
/android/720x1242-1.9.png"
,
"xhdpi"
:
"/Users/yuki/vion_app/
CVA YAP
/android/720x1242-1.9.png"
,
"xxhdpi"
:
"/Users/yuki/vion_app/
pmi
/android/1080x1882-1.9.png"
"xxhdpi"
:
"/Users/yuki/vion_app/
CVA YAP
/android/1080x1882-1.9.png"
},
},
"ios"
:
{
"ios"
:
{
"storyboard"
:
"/Users/yuki/vion_app/
pmi/ios/ios
.zip"
"storyboard"
:
"/Users/yuki/vion_app/
CVA YAP/ios/ios_screen
.zip"
}
}
},
},
"icons"
:
{
"icons"
:
{
...
...
pages/home/index.nvue
View file @
9e4b3e5
...
@@ -112,6 +112,7 @@
...
@@ -112,6 +112,7 @@
getAppVersionApi,
getAppVersionApi,
getUserStoreEquipmentNumApi,
getUserStoreEquipmentNumApi,
getMessageListApi,
getMessageListApi,
bindClientIdApi
} from '@/api'
} from '@/api'
import appUpdate from '@/uni_modules/wczd-app-update/js_sdk/app-update.js'
import appUpdate from '@/uni_modules/wczd-app-update/js_sdk/app-update.js'
...
@@ -262,7 +263,7 @@
...
@@ -262,7 +263,7 @@
const modalRef = ref(null)
const modalRef = ref(null)
onMounted(() => {
onMounted(
async
() => {
// #ifdef APP-PLUS
// #ifdef APP-PLUS
checkAppUpdate()
checkAppUpdate()
// #endif
// #endif
...
@@ -277,6 +278,17 @@
...
@@ -277,6 +278,17 @@
})
})
// #endif
// #endif
getUserStoreEquipmentNum()
getUserStoreEquipmentNum()
// #ifdef APP-PLUS
const clientInfo = uni.getDeviceInfo()
await bindClientIdApi({
clientId: uni.getStorageSync('clientId'),
clientType: clientInfo.osName, // ios or android
deviceInfo: JSON.stringify(clientInfo), // 备用传值
language: uni.getStorageSync('lang') || '',
status: 1 // 是否有效 1:有效 0: 无效
})
// #endif
})
})
/********** 统计相关 ***********/
/********** 统计相关 ***********/
...
...
pages/login/index.vue
View file @
9e4b3e5
...
@@ -90,8 +90,8 @@
...
@@ -90,8 +90,8 @@
<!-- <view v-if="!isLoginSuccess" class="login-info-tips">用户名或密码有误,登录失败!</view> -->
<!-- <view v-if="!isLoginSuccess" class="login-info-tips">用户名或密码有误,登录失败!</view> -->
<view
class=
"remember-password"
>
<view
class=
"remember-password"
>
<uv-checkbox-group
v-model=
"rememberValue"
shape=
"square"
>
<uv-checkbox-group
v-model=
"rememberValue"
shape=
"square"
>
<uv-checkbox
shape=
"circle"
activeColor=
"#387CF5"
size=
"15"
labelSize=
"26rpx"
labelColor=
"#90949D"
name=
"remember"
<uv-checkbox
shape=
"circle"
activeColor=
"#387CF5"
size=
"15"
labelSize=
"26rpx"
labelColor=
"#90949D"
:label=
"t('login.rememberPw')"
></uv-checkbox>
name=
"remember"
:label=
"t('login.rememberPw')"
></uv-checkbox>
</uv-checkbox-group>
</uv-checkbox-group>
</view>
</view>
<view
class=
"forget-password-text"
@
click=
"handleForgetPwd"
>
{{ t('login.forgotPassword') }}?
</view>
<view
class=
"forget-password-text"
@
click=
"handleForgetPwd"
>
{{ t('login.forgotPassword') }}?
</view>
...
@@ -397,13 +397,24 @@
...
@@ -397,13 +397,24 @@
if
(
code
===
200
)
{
if
(
code
===
200
)
{
uni
.
hideLoading
()
uni
.
hideLoading
()
}
}
const
{
const
{
atoken
,
atoken
,
rtoken
,
user
user
}
=
data
}
=
data
uni
.
setStorageSync
(
'Authorization'
,
atoken
)
uni
.
setStorageSync
(
'Authorization'
,
atoken
)
uni
.
setStorageSync
(
'rtoken'
,
rtoken
)
uni
.
setStorageSync
(
'user'
,
JSON
.
stringify
(
user
))
uni
.
setStorageSync
(
'user'
,
JSON
.
stringify
(
user
))
// uni.setStorageSync('Authorization', '165af547-08ba-4ddf-9286-bc8ce37cca39')
// uni.setStorageSync('rtoken', '61b5b0ca-5a0c-40df-8068-d5b390eef072')
const
{
const
{
data
:
accountList
data
:
accountList
}
=
await
getUserAccountsApi
({
}
=
await
getUserAccountsApi
({
...
...
uni_modules/wczd-app-update/js_sdk/app-update.js
View file @
9e4b3e5
...
@@ -317,7 +317,7 @@ function download(updateInfo) {
...
@@ -317,7 +317,7 @@ function download(updateInfo) {
let
platform
=
updateInfo
.
platform
||
'android'
let
platform
=
updateInfo
.
platform
||
'android'
if
(
updateInfo
.
downUrl
)
{
if
(
updateInfo
.
downUrl
)
{
if
(
platform
==
'ios'
)
{
if
(
platform
==
'ios'
)
{
plus
.
runtime
.
openURL
(
updateInfo
.
downUrl
)
plus
.
runtime
.
openURL
(
'https://apps.apple.com/cn/app/id6752882316'
)
}
}
if
(
platform
==
'android'
)
{
if
(
platform
==
'android'
)
{
plus
.
runtime
.
openURL
(
'https://play.google.com/store/apps/details?id=com.viontech.app.pmistore'
)
plus
.
runtime
.
openURL
(
'https://play.google.com/store/apps/details?id=com.viontech.app.pmistore'
)
...
...
utils/request copy.js
0 → 100755
View file @
9e4b3e5
import
host
from
'@/utils/ip-config.js'
;
import
{
t
}
from
'@/plugins/index.js'
let
requestFlag
=
true
// 请求封装
export
default
function
request
(
options
,
ipType
=
'ip'
)
{
// 根据不同的类型选择不同的ip
// // #ifdef APP-PLUS
// const ipTypeMap = {
// ip: uni.getStorageSync('serverIp'),
// assetsIp: `${uni.getStorageSync('serverIp')}/images`
// }
// // #endif
// // #ifndef APP-PLUS
// const ipTypeMap = {
// ip: host.ip,
// assetsIp: host.assetsIp
// }
// // #endif
// 声明部分接口必须要用store.keliuyun.com服务
const
ipTypeMap
=
{
ip
:
host
.
ip
,
assetsIp
:
host
.
assetsIp
}
// const url = (ipType === 'store.keliuyun' ? host.ip : ipTypeMap[ipType]) + options.url
const
url
=
ipTypeMap
[
ipType
]
+
options
.
url
return
new
Promise
((
resolve
,
reject
)
=>
{
const
systemInfo
=
uni
.
getSystemInfoSync
()
// 请求方式
const
method
=
options
.
method
?.
toUpperCase
()
||
'GET'
;
// 根据method类型调整header,GET为?a=x&b=y,POST为json
const
headerContentType
=
method
===
'GET'
?
'application/x-www-form-urlencoded'
:
'application/json'
;
const
_data
=
Array
.
isArray
(
options
.
data
)
?
options
.
data
:
{
...(
options
.
data
||
{}),
};
// const _data = {
// ...(options.data || {}),
// // _t:Date.now()
// }
const
languageObj
=
{
'mall_CN'
:
'zh-CN,zh;q=0.9'
,
'zh_CN'
:
'zh-CN,zh;q=0.9'
,
'en_US'
:
'en-US,en;q=0.5'
,
'zh_TW'
:
'zh-TW,zh;q=0.3'
,
'ja_JP'
:
'ja-JP,ja;q=0.9'
}
const
lang
=
uni
.
getStorageSync
(
'lang'
)
||
host
.
defaultLang
const
setting
=
{
url
,
data
:
_data
,
method
,
timeout
:
60
*
1000
,
header
:
{
'content-type'
:
headerContentType
,
// 请求体中添加设备信息
'Device-OS'
:
systemInfo
.
platform
||
'unknown'
,
// 直接使用同步获取的信息
'Device-Model'
:
systemInfo
.
model
||
'unknown'
,
'Authorization'
:
uni
.
getStorageSync
(
'Authorization'
)
||
''
,
'Accept-Language'
:
languageObj
[
lang
]
||
'en-US,en;q=0.5'
,
},
success
(
res
)
{
// 如果是静态资源,直接返回
if
(
ipType
===
'assetsIp'
)
{
resolve
(
res
.
data
);
return
;
}
// 否则判断res.data内部的code
if
(
res
.
data
.
ecode
===
401
&&
ipType
!==
'store.keliuyun'
)
{
console
.
log
(
1
);
if
(
requestFlag
)
{
requestFlag
=
false
uni
.
showModal
({
title
:
t
(
'message.prompt'
),
showCancel
:
false
,
content
:
t
(
'Message.atokeIsDisabled'
),
confirmText
:
t
(
'app.login.reLogin'
),
success
:
function
(
resModal
)
{
if
(
resModal
.
confirm
)
{
requestFlag
=
true
uni
.
removeStorageSync
(
'Authorization'
)
// uni.clearStorageSync()
uni
.
reLaunch
({
url
:
'/pages/login/index'
})
}
else
if
(
resModal
.
cancel
)
{
console
.
log
(
'用户点击取消'
);
}
}
})
}
}
else
if
(
res
.
data
.
code
!==
200
)
{
if
(
!
options
.
hiddenMsg
){
uni
.
showToast
({
icon
:
'none'
,
title
:
res
?.
data
?.
msg
||
'Error'
})
}
reject
(
res
?.
data
?.
msg
||
'Error'
)
}
else
{
resolve
(
res
.
data
);
}
},
fail
(
err
)
{
uni
.
showToast
({
icon
:
'none'
,
title
:
t
(
'app.login.networkError'
)
})
reject
(
err
);
},
}
if
(
options
.
header
)
{
setting
.
header
=
Object
.
assign
(
setting
.
header
,
options
.
header
);
}
uni
.
request
(
setting
);
})
}
utils/request.js
View file @
9e4b3e5
import
host
from
'@/utils/ip-config.js'
;
import
host
from
'@/utils/ip-config.js'
;
import
{
t
}
from
'@/plugins/index.js'
import
{
t
}
from
'@/plugins/index.js'
import
{
getStageObj
}
from
'@/utils/index.js'
let
requestFlag
=
true
let
requestFlag
=
true
// 请求封装
let
isRefreshing
=
false
// 是否正在刷新token
export
default
function
request
(
options
,
ipType
=
'ip'
)
{
let
refreshSubscribers
=
[]
// 重试队列
// 添加订阅
function
addSubscriber
(
callback
)
{
refreshSubscribers
.
push
(
callback
)
}
// 执行订阅的回调
function
executeSubscribers
(
newToken
)
{
refreshSubscribers
.
forEach
(
callback
=>
callback
(
newToken
))
refreshSubscribers
=
[]
}
// 刷新token的函数
async
function
refreshToken
(
hostUrlIp
)
{
if
(
isRefreshing
)
{
// 如果已经在刷新,返回一个Promise等待刷新完成
return
new
Promise
((
resolve
)
=>
{
addSubscriber
(
resolve
)
})
}
isRefreshing
=
true
try
{
const
rtoken
=
uni
.
getStorageSync
(
'rtoken'
)
if
(
!
rtoken
)
{
throw
new
Error
(
'No refresh token'
)
}
const
userInfoStage
=
getStageObj
(
'user'
)
// 使用原生uni.request,避免使用封装的request导致循环调用
const
refreshResult
=
await
new
Promise
((
resolve
,
reject
)
=>
{
uni
.
request
({
url
:
hostUrlIp
+
`/report/auth/api/v1/auth/users/
${
userInfoStage
.
unid
}
/atoken`
,
// 根据你的实际接口调整
method
:
'GET'
,
header
:
{
'Authorization'
:
rtoken
},
success
:
(
res
)
=>
{
if
(
res
.
data
.
atoken
)
{
resolve
(
res
.
data
.
atoken
)
}
else
{
handleAuthFailure
(
'登录已失效,请重新登录'
)
reject
(
new
Error
(
res
.
data
.
msg
||
'刷新token失败'
))
}
},
fail
:
(
err
)
=>
{
reject
(
err
)
}
})
})
// 存储新的Authorization
uni
.
setStorageSync
(
'Authorization'
,
refreshResult
)
isRefreshing
=
false
// 执行所有等待的回调
executeSubscribers
(
refreshResult
)
return
refreshResult
}
catch
(
error
)
{
console
.
error
(
'刷新token失败:'
,
error
)
isRefreshing
=
false
refreshSubscribers
=
[]
// 清空队列
throw
error
}
}
// 请求封装
export
default
function
request
(
options
,
ipType
=
'ip'
)
{
// 根据不同的类型选择不同的ip
// 根据不同的类型选择不同的ip
// // #ifdef APP-PLUS
// const ipTypeMap = {
// ip: uni.getStorageSync('serverIp'),
// assetsIp: `${uni.getStorageSync('serverIp')}/images`
// }
// // #endif
// // #ifndef APP-PLUS
// const ipTypeMap = {
// ip: host.ip,
// assetsIp: host.assetsIp
// }
// // #endif
// 声明部分接口必须要用store.keliuyun.com服务
const
ipTypeMap
=
{
const
ipTypeMap
=
{
ip
:
host
.
ip
,
ip
:
host
.
ip
,
assetsIp
:
host
.
assetsIp
assetsIp
:
host
.
assetsIp
}
}
// const url = (ipType === 'store.keliuyun' ? host.ip : ipTypeMap[ipType]) + options.url
const
url
=
ipTypeMap
[
ipType
]
+
options
.
url
const
url
=
ipTypeMap
[
ipType
]
+
options
.
url
console
.
log
(
url
,
'=s=s'
);
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
systemInfo
=
uni
.
getSystemInfoSync
()
const
systemInfo
=
uni
.
getSystemInfoSync
()
// 请求方式
const
method
=
options
.
method
?.
toUpperCase
()
||
'GET'
;
const
method
=
options
.
method
?.
toUpperCase
()
||
'GET'
;
// 根据method类型调整header,GET为?a=x&b=y,POST为json
const
headerContentType
=
method
===
'GET'
?
'application/x-www-form-urlencoded'
:
'application/json'
;
const
headerContentType
=
method
===
'GET'
?
'application/x-www-form-urlencoded'
:
'application/json'
;
const
_data
=
{
const
_data
=
Array
.
isArray
(
options
.
data
)
?
options
.
data
:
{
...(
options
.
data
||
{}),
...(
options
.
data
||
{}),
};
}
// const _data = {
// ...(options.data || {}),
// // _t:Date.now()
// }
const
languageObj
=
{
const
languageObj
=
{
'mall_CN'
:
'zh-CN,zh;q=0.9'
,
'mall_CN'
:
'zh-CN,zh;q=0.9'
,
'zh_CN'
:
'zh-CN,zh;q=0.9'
,
'zh_CN'
:
'zh-CN,zh;q=0.9'
,
'en_US'
:
'en-US,en;q=0.5'
,
'en_US'
:
'en-US,en;q=0.5'
,
'zh_TW'
:
'zh-TW,zh;q=0.3'
,
'zh_TW'
:
'zh-TW,zh;q=0.3'
,
'ja_JP'
:
'ja-JP,ja;q=0.9'
}
}
const
lang
=
uni
.
getStorageSync
(
'lang'
)
||
host
.
defaultLang
const
lang
=
uni
.
getStorageSync
(
'lang'
)
||
host
.
defaultLang
const
setting
=
{
const
createRequestConfig
=
(
authorization
=
null
)
=>
{
const
authToken
=
authorization
||
uni
.
getStorageSync
(
'Authorization'
)
||
''
return
{
url
,
url
,
data
:
_data
,
data
:
_data
,
method
,
method
,
timeout
:
60
*
1000
,
timeout
:
60
*
1000
,
header
:
{
header
:
{
'content-type'
:
headerContentType
,
'content-type'
:
headerContentType
,
// 请求体中添加设备信息
'Device-OS'
:
systemInfo
.
platform
||
'unknown'
,
'Device-OS'
:
systemInfo
.
platform
||
'unknown'
,
// 直接使用同步获取的信息
'Device-Model'
:
systemInfo
.
model
||
'unknown'
,
'Device-Model'
:
systemInfo
.
model
||
'unknown'
,
'Authorization'
:
uni
.
getStorageSync
(
'Authorization'
)
||
''
,
'Authorization'
:
authToken
,
'Accept-Language'
:
languageObj
[
lang
]
||
'en-US,en;q=0.5
'
,
'Accept-Language'
:
languageObj
[
lang
]
||
'zh-CN,zh;q=0.9
'
,
},
},
success
(
res
)
{
}
}
// 执行请求
const
executeRequest
=
(
authorization
=
null
)
=>
{
let
setting
=
createRequestConfig
(
authorization
)
if
(
options
.
header
)
{
setting
.
header
=
Object
.
assign
(
setting
.
header
,
options
.
header
);
}
uni
.
request
({
...
setting
,
success
:
async
(
res
)
=>
{
// 如果是静态资源,直接返回
// 如果是静态资源,直接返回
if
(
ipType
===
'a
ssetsIp'
)
{
if
(
ipType
===
'assetsIp'
||
ipType
===
'StoreA
ssetsIp'
)
{
resolve
(
res
.
data
);
resolve
(
res
.
data
);
return
;
return
;
}
}
// 否则判断res.data内部的code
// 处理401状态码
if
(
res
.
data
.
ecode
===
401
&&
ipType
!==
'store.keliuyun'
)
{
if
(
res
.
data
.
ecode
===
401
&&
ipType
!==
'store.keliuyun'
)
{
// 如果是刷新token的接口本身返回401,直接跳转登录
if
(
options
.
url
===
'/report/auth/api'
)
{
handleAuthFailure
(
res
?.
data
?.
enote
||
t
(
'Message.authLoginError'
));
return
;
}
try
{
// 尝试刷新token
const
newToken
=
await
refreshToken
(
host
.
ip
)
console
.
log
(
newToken
);
// 使用新token重试当前请求
executeRequest
(
newToken
)
}
catch
(
error
)
{
// 刷新token失败,跳转登录
handleAuthFailure
(
t
(
'Message.authLoginError'
));
}
return
;
}
else
if
(
res
.
data
.
code
!==
200
)
{
handleRequestError
(
res
,
options
,
reject
);
}
else
{
resolve
(
res
.
data
);
}
},
fail
(
err
)
{
console
.
log
(
'err'
,
err
);
uni
.
showToast
({
icon
:
'none'
,
title
:
t
(
err
.
errMsg
||
'app.login.networkError'
)
})
reject
(
err
);
},
});
}
// 开始第一次请求
executeRequest
();
})
}
// 处理认证失败
function
handleAuthFailure
(
message
)
{
if
(
requestFlag
)
{
if
(
requestFlag
)
{
requestFlag
=
false
requestFlag
=
false
uni
.
showModal
({
uni
.
showModal
({
title
:
t
(
'message.prompt'
),
title
:
t
(
'message.prompt'
),
showCancel
:
false
,
showCancel
:
false
,
content
:
t
(
'Message.atokeIsDisabled'
)
,
content
:
message
,
confirmText
:
t
(
'app.login.reLogin'
),
confirmText
:
t
(
'app.login.reLogin'
),
success
:
function
(
resModal
)
{
success
:
function
(
resModal
)
{
if
(
resModal
.
confirm
)
{
if
(
resModal
.
confirm
)
{
requestFlag
=
true
requestFlag
=
true
uni
.
removeStorageSync
(
'Authorization'
)
uni
.
removeStorageSync
(
'Authorization'
)
uni
.
removeStorageSync
(
'rtoken'
)
// uni.clearStorageSync()
// uni.clearStorageSync()
uni
.
reLaunch
({
uni
.
reLaunch
({
url
:
'/pages/login/index'
url
:
'/pages/login/index'
...
@@ -92,31 +204,27 @@ export default function request(options, ipType = 'ip') {
...
@@ -92,31 +204,27 @@ export default function request(options, ipType = 'ip') {
}
}
})
})
}
}
}
}
else
if
(
res
.
data
.
code
!==
200
)
{
if
(
!
options
.
hiddenMsg
){
// 处理请求错误
function
handleRequestError
(
res
,
options
,
reject
)
{
const
errorMsg
=
res
?.
data
?.
msg
||
'Error'
if
(
!
options
.
hiddenMsg
)
{
uni
.
showToast
({
uni
.
showToast
({
icon
:
'none'
,
icon
:
'none'
,
title
:
res
?.
data
?.
msg
||
'Error'
title
:
errorMsg
})
})
}
}
reject
(
res
?.
data
?.
msg
||
'Error'
)
// 针对登录接口 单独修改报错返回信息
}
else
{
if
(
options
.
url
===
'/report/users/login'
)
{
resolve
(
res
.
data
);
if
([
'用户名/密码错误'
,
'Username/Password Incorrect'
,
'用戶名/密碼錯誤'
].
includes
(
errorMsg
))
{
reject
(
'U/P Error'
)
}
}
// 如果是502 提示默认密码 需要修改 同时传递atoken过去
},
if
(
res
.
data
.
code
===
502
)
{
fail
(
err
)
{
reject
(
`P Reset`
+
'*$*'
+
`
${
res
?.
data
?.
data
?.
atoken
||
''
}
`)
uni
.
showToast
({
icon
:
'none'
,
title
:
t
(
'app.login.networkError'
)
})
reject
(
err
);
},
}
}
if
(
options
.
header
)
{
setting
.
header
=
Object
.
assign
(
setting
.
header
,
options
.
header
);
}
}
uni
.
request
(
setting
);
reject(errorMsg)
})
}
}
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment