角色 保存

This commit is contained in:
zhonghua1
2026-01-02 14:40:14 +08:00
parent f004a75483
commit b607a5980c
5 changed files with 185 additions and 86 deletions

View File

@@ -44,13 +44,14 @@ function isLoginApi(url) {
} }
/** /**
* 设置全局 uni.request 拦截器,自动添加 X-Tenant-Id header * 设置全局 uni.request 拦截器,自动添加 X-Tenant-Id header 和 Authorization token
* 确保每次请求后端都携带 token 进行身份验证
*/ */
function setupRequestInterceptor() { function setupRequestInterceptor() {
// 保存原始的 uni.request // 保存原始的 uni.request
const originalRequest = uni.request const originalRequest = uni.request
// 重写 uni.request自动添加 tenantId // 重写 uni.request自动添加 tenantId 和 token
uni.request = function(options = {}) { uni.request = function(options = {}) {
const { url, header = {}, method = 'GET', ...restOptions } = options const { url, header = {}, method = 'GET', ...restOptions } = options
@@ -81,18 +82,37 @@ function setupRequestInterceptor() {
newHeader['X-Tenant-Id'] = tenantId newHeader['X-Tenant-Id'] = tenantId
} }
// 添加 token如果存在且未设置 // 每次请求都自动添加 token登录接口除外
if (!newHeader['Authorization']) { // 全局拦截器确保所有通过 uni.request 的请求都携带 token
if (!isLoginApi(url)) {
try { try {
const token = uni.getStorageSync('backend-token') || '' const token = uni.getStorageSync('backend-token') || ''
if (token) { if (token) {
// 每次请求都添加 token 到 Authorization header
newHeader['Authorization'] = `Bearer ${token}` newHeader['Authorization'] = `Bearer ${token}`
} else {
// 如果没有 token移除可能存在的旧 Authorization header
delete newHeader['Authorization']
} }
} catch (e) { } catch (e) {
console.error('获取 token 失败:', e) console.error('获取 token 失败:', e)
} }
} }
// 添加 roleName 和 scenario 到 header从登录响应中获取
try {
const roleName = uni.getStorageSync('backend-role-name') || ''
if (roleName) {
newHeader['X-Role-Name'] = roleName
}
const scenario = uni.getStorageSync('backend-scenario') || ''
if (scenario) {
newHeader['X-Scenario'] = scenario
}
} catch (e) {
console.error('获取 roleName 或 scenario 失败:', e)
}
// 统一使用 Promise 方式,确保正确返回响应 // 统一使用 Promise 方式,确保正确返回响应
// 这样无论调用方使用 await 还是回调,都能正常工作 // 这样无论调用方使用 await 还是回调,都能正常工作
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -132,7 +152,7 @@ function setupRequestInterceptor() {
}) })
} }
// 全局请求拦截器已设置,所有 uni.request 调用将自动添加 X-Tenant-Id header // 全局请求拦截器已设置,所有 uni.request 调用将自动添加 X-Tenant-Id header 和 Authorization token
} }
export default async function() { export default async function() {

View File

@@ -61,6 +61,30 @@ function getToken() {
} }
} }
/**
* 获取 roleName从本地存储
*/
function getRoleName() {
try {
return uni.getStorageSync('backend-role-name') || ''
} catch (e) {
console.error('获取 roleName 失败:', e)
return ''
}
}
/**
* 获取 scenario从本地存储
*/
function getScenario() {
try {
return uni.getStorageSync('backend-scenario') || ''
} catch (e) {
console.error('获取 scenario 失败:', e)
return ''
}
}
/** /**
* 统一的请求方法 * 统一的请求方法
* @param {Object} options - uni.request 的配置选项 * @param {Object} options - uni.request 的配置选项
@@ -99,16 +123,29 @@ export function request(options = {}) {
...header ...header
} }
// 添加 token如果需要 // 每次请求都自动添加 token登录接口除外
if (needToken) { // 确保所有后端请求都携带 token 进行身份验证
if (needToken && !isLoginApi(fullUrl)) {
const token = getToken() const token = getToken()
if (token) { if (token) {
// 每次请求都添加 token 到 Authorization header
requestHeader['Authorization'] = `Bearer ${token}` requestHeader['Authorization'] = `Bearer ${token}`
// 或者使用其他 header 名称,根据后端要求调整 } else {
// requestHeader['X-Token'] = token // 如果没有 token移除可能存在的旧 Authorization header
delete requestHeader['Authorization']
} }
} }
// 添加 roleName 和 scenario 到 header从登录响应中获取
const roleName = getRoleName()
if (roleName) {
requestHeader['X-Role-Name'] = roleName
}
const scenario = getScenario()
if (scenario) {
requestHeader['X-Scenario'] = scenario
}
// 处理请求数据 // 处理请求数据
let requestData = { ...data } let requestData = { ...data }

View File

@@ -52,9 +52,6 @@
</view> </view>
<text class="customer-name">{{ item.customerName }}</text> <text class="customer-name">{{ item.customerName }}</text>
</view> </view>
<view class="ai-tag">
<text>以上内容由AI生成</text>
</view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>

View File

@@ -1635,7 +1635,8 @@
// 构建查询参数对象(后端使用 @RequestParam参数需要作为 URL 查询参数传递) // 构建查询参数对象(后端使用 @RequestParam参数需要作为 URL 查询参数传递)
const queryParams = { const queryParams = {
current: this.serviceListPage.current, current: this.serviceListPage.current,
size: this.serviceListPage.size size: this.serviceListPage.size,
serviceStatus: '服务结束' // 默认搜索条件:服务结束
}; };
// 添加查询参数:所属销售姓名和客户姓名 // 添加查询参数:所属销售姓名和客户姓名
@@ -1654,17 +1655,40 @@
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`) .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
.join('&'); .join('&');
// 调试:打印请求参数
console.log('服务记录查询参数:', JSON.stringify(queryParams));
console.log('查询字符串:', queryString);
// 后端使用 @RequestParam参数需要作为 URL 查询参数传递 // 后端使用 @RequestParam参数需要作为 URL 查询参数传递
const baseUrl = getApiUrl('/api/audioManagement/list'); const baseUrl = getApiUrl('/api/audioManagement/list');
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl; const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
// 获取认证信息
let tenantId = '';
let token = '';
try {
tenantId = uni.getStorageSync('backend-tenant-id') || '';
token = uni.getStorageSync('backend-token') || '';
} catch (e) {
console.error('获取认证信息失败:', e);
}
// 构建请求头(参考接待页面的实现方式)
const headers = {
'Content-Type': 'application/json'
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
if (tenantId) {
headers['X-Tenant-Id'] = tenantId;
}
const res = await uni.request({ const res = await uni.request({
url, url,
method: 'POST', method: 'POST',
data: {}, // POST 请求体为空,参数都在 URL 查询字符串中 data: {}, // POST 请求体为空,参数都在 URL 查询字符串中
header: { header: headers,
'Content-Type': 'application/json'
},
timeout: 10000 timeout: 10000
}); });

View File

@@ -75,9 +75,9 @@
}) })
}, },
/** /**
* 密码登录(改为调用后端 /api/sys/auth/login 接口) * 密码登录(调用后端 /api/sys/auth/login 接口)
*/ */
pwdLogin() { async pwdLogin() {
if (!this.password.length) { if (!this.password.length) {
this.focusPassword = true this.focusPassword = true
return uni.showToast({ return uni.showToast({
@@ -98,7 +98,7 @@
return this.$refs.agreements.popup(this.pwdLogin) return this.$refs.agreements.popup(this.pwdLogin)
} }
// 组装后端登录参数(根据后端 LoginRequest 约定,这里假定为 userName + password // 组装后端登录参数
const payload = { const payload = {
userName: this.username, userName: this.username,
password: this.password password: this.password
@@ -109,79 +109,100 @@
mask: true mask: true
}) })
uni.request({ try {
url: getApiUrl('/api/sys/auth/login'), // 使用 uni.request 直接调用登录接口(登录接口不需要 token
method: 'POST', const res = await new Promise((resolve, reject) => {
header: { uni.request({
'Content-Type': 'application/json' url: getApiUrl('/api/sys/auth/login'),
}, method: 'POST',
data: payload, header: {
success: (res) => { 'Content-Type': 'application/json'
const body = res.data || {} },
if (!body.success || !body.data) { data: payload,
return uni.showToast({ success: resolve,
title: body.message || '登录失败', fail: reject
icon: 'none',
duration: 3000
})
}
const loginData = body.data
// 持久化后端登录态,供后续接口使用
try {
uni.setStorageSync('backend-login-response', loginData)
uni.setStorageSync('backend-token', loginData.token || '')
uni.setStorageSync('backend-user-id', loginData.userId)
// 保存 tenantId从 LoginResponse 中获取,后端 UserServiceImpl.login 从 user.getTenantId() 赋值)
// 后续所有请求会自动在 X-Tenant-Id header 中携带此值
if (loginData.tenantId) {
uni.setStorageSync('backend-tenant-id', loginData.tenantId)
console.log('[Login] tenantId 已保存:', loginData.tenantId)
} else {
console.warn('[Login] 登录响应中未包含 tenantId后续请求可能失败')
}
} catch (e) {
console.error('缓存登录信息失败:', e)
}
// 同步更新前端 store保证“我的”页等能识别为已登录状态
try {
mutations.setUserInfo({
username: loginData.userName,
mobile: loginData.phone,
email: loginData.email,
avatar_file: loginData.avatar ? { url: loginData.avatar } : undefined
}, { cover: true })
} catch (e) {
console.error('更新本地用户信息失败:', e)
}
uni.showToast({
title: body.message || '登录成功',
icon: 'none',
duration: 800
}) })
})
// 登录成功后跳转到 tabBar 首页(接待页) const body = res.data || {}
setTimeout(() => { if (!body.success || !body.data) {
uni.switchTab({ return uni.showToast({
url: '/pages/reception/reception' title: body.message || '登录失败',
})
}, 300)
},
fail: (err) => {
console.error('调用登录接口失败:', err)
uni.showToast({
title: '网络异常,登录失败',
icon: 'none', icon: 'none',
duration: 3000 duration: 3000
}) })
},
complete: () => {
uni.hideLoading()
} }
})
const loginData = body.data
// 保存 token重要后续所有请求会自动在 header 中携带此 token
if (loginData.token) {
uni.setStorageSync('backend-token', loginData.token)
console.log('[Login] token 已保存,后续请求将自动在 header 中携带')
} else {
console.warn('[Login] 登录响应中未包含 token')
}
// 持久化其他登录信息
try {
uni.setStorageSync('backend-login-response', loginData)
uni.setStorageSync('backend-user-id', loginData.userId)
// 保存 tenantId后续所有请求会自动在 X-Tenant-Id header 中携带)
if (loginData.tenantId) {
uni.setStorageSync('backend-tenant-id', loginData.tenantId)
console.log('[Login] tenantId 已保存:', loginData.tenantId)
} else {
console.warn('[Login] 登录响应中未包含 tenantId后续请求可能失败')
}
// 保存 roleName 和 scenario后续所有请求会自动在 header 中携带
if (loginData.roleName) {
uni.setStorageSync('backend-role-name', loginData.roleName)
console.log('[Login] roleName 已保存:', loginData.roleName)
}
if (loginData.scenario) {
uni.setStorageSync('backend-scenario', loginData.scenario)
console.log('[Login] scenario 已保存:', loginData.scenario)
}
} catch (e) {
console.error('缓存登录信息失败:', e)
}
// 同步更新前端 store保证"我的"页等能识别为已登录状态
try {
mutations.setUserInfo({
username: loginData.userName,
mobile: loginData.phone,
email: loginData.email,
avatar_file: loginData.avatar ? { url: loginData.avatar } : undefined
}, { cover: true })
} catch (e) {
console.error('更新本地用户信息失败:', e)
}
uni.showToast({
title: body.message || '登录成功',
icon: 'none',
duration: 800
})
// 登录成功后跳转到 tabBar 首页(接待页)
setTimeout(() => {
uni.switchTab({
url: '/pages/reception/reception'
})
}, 300)
} catch (err) {
console.error('调用登录接口失败:', err)
uni.showToast({
title: '网络异常,登录失败',
icon: 'none',
duration: 3000
})
} finally {
uni.hideLoading()
}
}, },
/* 前往注册 */ /* 前往注册 */
toRegister() { toRegister() {