408 lines
12 KiB
Vue
408 lines
12 KiB
Vue
<script>
|
||
import initApp from '@/common/appInit.js';
|
||
import openApp from '@/common/openApp.js';
|
||
// #ifdef H5
|
||
openApp() //创建在h5端全局悬浮引导用户下载app的功能
|
||
// #endif
|
||
import checkIsAgree from '@/pages/uni-agree/utils/uni-agree.js';
|
||
import uniIdPageInit from '@/uni_modules/uni-id-pages/init.js';
|
||
import { store } from '@/uni_modules/uni-id-pages/common/store.js';
|
||
|
||
export default {
|
||
globalData: {
|
||
searchText: '',
|
||
appVersion: {},
|
||
config: {},
|
||
$i18n: {},
|
||
$t: {}
|
||
},
|
||
onLaunch: async function() {
|
||
console.log('App Launch')
|
||
this.globalData.$i18n = this.$i18n
|
||
this.globalData.$t = str => this.$t(str)
|
||
initApp();
|
||
await uniIdPageInit()
|
||
|
||
// #ifdef H5
|
||
this.hideEduTabIfNeed() // 初始化尝试隐藏教务 tab(非教务角色)
|
||
uni.$on('tabbar:refresh', this.hideEduTabIfNeed) // 登录后触发
|
||
// #endif
|
||
|
||
// 设置全局路由拦截,检查登录状态
|
||
this.setupRouteInterceptor()
|
||
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序:先快速检查登录状态,如果未登录则立即跳转,避免首页闪烁
|
||
// 延迟一小段时间确保页面栈已初始化
|
||
setTimeout(() => {
|
||
if (!this.isLoggedIn()) {
|
||
this.redirectToLogin()
|
||
} else {
|
||
// 已登录,检查当前页面
|
||
this.checkCurrentPageLogin()
|
||
}
|
||
}, 300)
|
||
// #endif
|
||
// #ifndef MP-WEIXIN
|
||
// 其他平台:延迟检查登录状态
|
||
setTimeout(() => {
|
||
this.checkCurrentPageLogin()
|
||
}, 100)
|
||
// #endif
|
||
|
||
// #ifdef APP
|
||
//checkIsAgree(); APP端暂时先用原生默认生成的。目前,自定义方式启动vue界面时,原生层已经请求了部分权限这并不符合国家的法规
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// checkIsAgree(); // 默认不开启。目前全球,仅欧盟国家有网页端同意隐私权限的需要。如果需要可以自己去掉注视后生效
|
||
// #endif
|
||
|
||
// #ifdef APP-PLUS
|
||
//idfa有需要的用户在应用首次启动时自己获取存储到storage中
|
||
/*var idfa = '';
|
||
var manager = plus.ios.invoke('ASIdentifierManager', 'sharedManager');
|
||
if(plus.ios.invoke(manager, 'isAdvertisingTrackingEnabled')){
|
||
var identifier = plus.ios.invoke(manager, 'advertisingIdentifier');
|
||
idfa = plus.ios.invoke(identifier, 'UUIDString');
|
||
plus.ios.deleteObject(identifier);
|
||
}
|
||
plus.ios.deleteObject(manager);
|
||
console.log('idfa = '+idfa);*/
|
||
// #endif
|
||
},
|
||
onShow: function() {
|
||
console.log('App Show')
|
||
// 每次应用显示时也检查当前页面是否需要登录
|
||
this.checkCurrentPageLogin()
|
||
|
||
// #ifdef H5
|
||
// 返回前台时再尝试隐藏一次
|
||
this.hideEduTabIfNeed()
|
||
// #endif
|
||
},
|
||
onHide: function() {
|
||
console.log('App Hide')
|
||
},
|
||
methods: {
|
||
// #ifdef H5
|
||
/**
|
||
* H5 平台:根据当前登录角色,动态控制原生 tabbar 可见项
|
||
*
|
||
* 规则:
|
||
* - admin:不限制,所有 tab 都显示
|
||
* - speaking_training_teacher:仅显示【教务、语音、表达、我的】
|
||
* - speaking_training_students:仅显示【作业、语音、表达、我的】
|
||
* - 其他角色:隐藏【作业、教务、语音、表达】
|
||
*/
|
||
hideEduTabIfNeed() {
|
||
try {
|
||
const normalize = (val) =>
|
||
typeof val === 'string'
|
||
? val
|
||
.split(',')
|
||
.map((s) => s.trim().toLowerCase())
|
||
.filter(Boolean)
|
||
: [];
|
||
const storedRole = uni.getStorageSync('backend-role-name') || '';
|
||
const loginResp = uni.getStorageSync('backend-login-response') || {};
|
||
const respRole = loginResp.roleName || '';
|
||
const roles = [...normalize(storedRole), ...normalize(respRole)];
|
||
const isTeacher = roles.includes('speaking_training_teacher');
|
||
const isStudent = roles.includes('speaking_training_students');
|
||
const isAdmin = roles.includes('admin');
|
||
const isMeetingAdmin = roles.includes('meeting_admin');
|
||
const isAdminFurniture = roles.includes('admin_furniture');
|
||
|
||
// 检查是否有任何角色名等于 "furniture" 字符串(精确匹配)
|
||
const hasFurnitureRole = roles.includes('furniture');
|
||
|
||
// 会议相关的tab标签
|
||
const meetingTabLabels = ['总结和统计'];
|
||
|
||
const teacherAllowed = ['我的'];
|
||
const studentAllowed = ['我的'];
|
||
const otherHidden = ['作业', '教务', '语音', '表达'];
|
||
|
||
// tabBar 顺序(根据 pages.json 中的 tabBar.list 顺序)
|
||
// 0: 接待, 1: 客户, 2: 团队
|
||
// 3: 总结和统计, 4: 接待(furniture_reception), 5: 开始接待(common_begin_reception), 6: 客户(furniture_customer), 7: 销冠(furniture_top_sales), 8: 我的(ucenter)
|
||
const meetingTabIndices = [3]; // 会议相关tab的索引位置
|
||
const furnitureTabIndices = [4, 6, 7]; // 家具相关tab的索引位置(接待、客户、销冠)
|
||
const ucenterIndex = 8; // "我的"(ucenter)的索引位置
|
||
|
||
const shouldShow = (label, index) => {
|
||
// 任何角色都应该能看到"我的"(ucenter,索引8)
|
||
if (label === '我的') {
|
||
return true;
|
||
}
|
||
|
||
// admin_furniture 和 furniture 角色:显示 furniture_reception, furniture_customer, furniture_top_sales 和 ucenter
|
||
if (isAdminFurniture || hasFurnitureRole) {
|
||
// 显示家具相关的tab(索引4, 6, 7)和"我的"(索引8)
|
||
return furnitureTabIndices.includes(index) || index === ucenterIndex;
|
||
}
|
||
|
||
// 隐藏"接待"和"客户"这两个tab(索引0和1)
|
||
if (label === '接待' || label === '客户') {
|
||
return false;
|
||
}
|
||
|
||
// meeting_admin 角色:显示会议相关的tab和"我的"
|
||
if (isMeetingAdmin) {
|
||
return meetingTabIndices.includes(index);
|
||
}
|
||
|
||
// 非 meeting_admin 角色:隐藏所有会议相关的tab和家具相关的tab
|
||
if (meetingTabIndices.includes(index) || furnitureTabIndices.includes(index)) {
|
||
return false;
|
||
}
|
||
|
||
// 对于非会议相关的tab,按角色判断
|
||
if (isAdmin) return true;
|
||
if (isTeacher) return teacherAllowed.includes(label);
|
||
if (isStudent) return studentAllowed.includes(label);
|
||
// 其他角色:只隐藏指定的几个,其余保留
|
||
return !otherHidden.includes(label);
|
||
};
|
||
|
||
// 延迟+多次尝试,等待原生 tabbar DOM 渲染
|
||
let attempts = 0;
|
||
const maxAttempts = 15;
|
||
const timer = setInterval(() => {
|
||
attempts += 1;
|
||
const items = Array.from(document.querySelectorAll('.uni-tabbar .uni-tabbar__item'));
|
||
if (items && items.length) {
|
||
items.forEach((el, index) => {
|
||
const label = (el.textContent || '').trim();
|
||
const show = shouldShow(label, index);
|
||
|
||
if (show) {
|
||
el.style.display = '';
|
||
el.style.flex = '';
|
||
el.style.width = '';
|
||
el.style.padding = '';
|
||
} else {
|
||
el.style.display = 'none';
|
||
el.style.flex = '0 0 0';
|
||
el.style.width = '0';
|
||
el.style.padding = '0';
|
||
}
|
||
});
|
||
console.log('[TabBar][H5 role-hide] roles:', roles, 'isAdmin:', isAdmin, 'isTeacher:', isTeacher, 'isStudent:', isStudent, 'items:', items.length, 'attempt:', attempts);
|
||
clearInterval(timer);
|
||
}
|
||
if (attempts >= maxAttempts) {
|
||
clearInterval(timer);
|
||
}
|
||
}, 200);
|
||
} catch (e) {
|
||
console.warn('[TabBar][H5 hide] failed:', e);
|
||
}
|
||
},
|
||
// #endif
|
||
/**
|
||
* 设置全局路由拦截
|
||
*/
|
||
setupRouteInterceptor() {
|
||
const app = this
|
||
|
||
// 拦截路由跳转(适用于所有平台)
|
||
uni.addInterceptor('navigateTo', {
|
||
invoke: (options) => {
|
||
if (app.shouldRedirectToLogin(options.url)) {
|
||
app.redirectToLogin()
|
||
return false // 阻止跳转
|
||
}
|
||
}
|
||
})
|
||
|
||
uni.addInterceptor('redirectTo', {
|
||
invoke: (options) => {
|
||
if (app.shouldRedirectToLogin(options.url)) {
|
||
app.redirectToLogin()
|
||
return false // 阻止跳转
|
||
}
|
||
}
|
||
})
|
||
|
||
uni.addInterceptor('switchTab', {
|
||
invoke: (options) => {
|
||
if (app.shouldRedirectToLogin(options.url)) {
|
||
app.redirectToLogin()
|
||
return false // 阻止跳转
|
||
}
|
||
}
|
||
})
|
||
|
||
uni.addInterceptor('reLaunch', {
|
||
invoke: (options) => {
|
||
if (app.shouldRedirectToLogin(options.url)) {
|
||
app.redirectToLogin()
|
||
return false // 阻止跳转
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 判断是否需要跳转到登录页
|
||
*/
|
||
shouldRedirectToLogin(url) {
|
||
if (!url) return false
|
||
|
||
// 排除登录相关页面
|
||
const excludePaths = [
|
||
'/uni_modules/uni-id-pages/pages/login',
|
||
'/uni_modules/uni-id-pages/pages/register',
|
||
'/uni_modules/uni-id-pages/pages/retrieve'
|
||
]
|
||
|
||
// 检查是否在排除列表中
|
||
for (let excludePath of excludePaths) {
|
||
if (url.includes(excludePath)) {
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 检查登录状态
|
||
return !this.isLoggedIn()
|
||
},
|
||
|
||
/**
|
||
* 检查是否已登录
|
||
*/
|
||
isLoggedIn() {
|
||
// 优先检查后端登录态
|
||
const backendToken = uni.getStorageSync('backend-token')
|
||
if (backendToken) {
|
||
return true
|
||
}
|
||
|
||
// 其次检查 uni-id 的登录态
|
||
return store.hasLogin
|
||
},
|
||
|
||
/**
|
||
* 跳转到登录页
|
||
*/
|
||
redirectToLogin() {
|
||
const loginPage = '/uni_modules/uni-id-pages/pages/login/login-withpwd'
|
||
const pages = getCurrentPages()
|
||
|
||
// 如果当前已经在登录页,不重复跳转
|
||
if (pages.length > 0) {
|
||
const currentPage = pages[pages.length - 1]
|
||
if (currentPage.route && currentPage.route.includes('login')) {
|
||
return
|
||
}
|
||
}
|
||
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序:登录页在subPackage中,必须使用reLaunch
|
||
// redirectTo不能用于跳转到subPackage页面,只能用于主包页面
|
||
uni.reLaunch({
|
||
url: loginPage,
|
||
success: () => {
|
||
console.log('跳转登录页成功')
|
||
},
|
||
fail: (err) => {
|
||
console.error('跳转登录页失败:', err)
|
||
// 如果reLaunch失败,可能是路径问题,尝试不带前导斜杠
|
||
const loginPageWithoutSlash = loginPage.startsWith('/') ? loginPage.substring(1) : loginPage
|
||
uni.reLaunch({
|
||
url: loginPageWithoutSlash,
|
||
fail: (err2) => {
|
||
console.error('跳转登录页失败(重试):', err2)
|
||
}
|
||
})
|
||
}
|
||
})
|
||
// #endif
|
||
|
||
// #ifndef MP-WEIXIN
|
||
// 其他平台使用reLaunch
|
||
uni.reLaunch({
|
||
url: loginPage,
|
||
fail: (err) => {
|
||
console.error('跳转登录页失败:', err)
|
||
}
|
||
})
|
||
// #endif
|
||
},
|
||
|
||
/**
|
||
* 判断是否为tabBar页面
|
||
*/
|
||
isTabBarPage(route) {
|
||
if (!route) return false
|
||
const tabBarPages = [
|
||
'pages/reception/reception',
|
||
'pages/customer/customer',
|
||
'pages/team/team',
|
||
'pages/meeting_summary/meeting_summary',
|
||
'pages/furniture_reception/furniture_reception',
|
||
'pages/furniture_reception/common_begin_reception',
|
||
'pages/furniture_customer/furniture_customer',
|
||
'pages/furniture_top_sales/furniture_top_sales',
|
||
'pages/ucenter/ucenter'
|
||
]
|
||
return tabBarPages.includes(route)
|
||
},
|
||
|
||
/**
|
||
* 检查当前页面是否需要登录
|
||
*/
|
||
checkCurrentPageLogin() {
|
||
const pages = getCurrentPages()
|
||
if (pages.length === 0) {
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序:如果页面栈为空,延迟重试
|
||
setTimeout(() => {
|
||
this.checkCurrentPageLogin()
|
||
}, 200)
|
||
// #endif
|
||
return
|
||
}
|
||
|
||
const currentPage = pages[pages.length - 1]
|
||
if (!currentPage || !currentPage.route) {
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序:如果页面信息不完整,延迟重试
|
||
setTimeout(() => {
|
||
this.checkCurrentPageLogin()
|
||
}, 200)
|
||
// #endif
|
||
return
|
||
}
|
||
|
||
const currentRoute = '/' + currentPage.route
|
||
|
||
// 排除登录相关页面
|
||
if (currentRoute.includes('/uni_modules/uni-id-pages/pages/login') ||
|
||
currentRoute.includes('/uni_modules/uni-id-pages/pages/register') ||
|
||
currentRoute.includes('/uni_modules/uni-id-pages/pages/retrieve')) {
|
||
return
|
||
}
|
||
|
||
// 如果未登录,跳转到登录页
|
||
if (!this.isLoggedIn()) {
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序:确保页面已完全加载后再跳转,使用setTimeout代替$nextTick
|
||
setTimeout(() => {
|
||
this.redirectToLogin()
|
||
}, 100)
|
||
// #endif
|
||
// #ifndef MP-WEIXIN
|
||
this.redirectToLogin()
|
||
// #endif
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
/*每个页面公共css */
|
||
</style>
|