feat:添加扫码器/手机设备判断

master
黄伟杰 3 weeks ago
parent fb08eed1d4
commit 60c45a2af0

@ -2,6 +2,7 @@
import { getToken } from '@/utils/auth'
import { initializeLocale, translateLiteral } from '@/locales'
import useUserStore from '@/store/modules/user'
import { initializeTerminalType } from '@/utils/terminal'
let wrapped = false
@ -48,6 +49,7 @@ function wrapUniTextApi() {
export default {
onLaunch: function () {
initializeLocale()
initializeTerminalType()
wrapUniTextApi()
if (getToken()) {
useUserStore().getInfo().catch(() => {})

@ -1,4 +1,5 @@
import request from '@/utils/request'
import { getTerminalType } from '@/utils/terminal'
const permissionInfoCache = new Map()
const permissionInfoPending = new Map()
@ -12,16 +13,35 @@ function normalizePermissionParams(params = {}) {
function createPermissionCacheKey(params = {}) {
const normalizedParams = normalizePermissionParams(params)
const terminalType = getTerminalType()
return JSON.stringify(
Object.keys(normalizedParams)
Object.keys({ ...normalizedParams, terminalType })
.sort()
.reduce((result, key) => {
result[key] = normalizedParams[key]
result[key] = key === 'terminalType' ? terminalType : normalizedParams[key]
return result
}, {})
)
}
function filterPermissionMenus(menus, terminalType) {
if (!Array.isArray(menus)) {
return []
}
return menus.filter((menu) => {
if (!menu || typeof menu !== 'object') {
return false
}
if (menu.terminalType === null || typeof menu.terminalType === 'undefined' || menu.terminalType === '') {
return true
}
return Number(menu.terminalType) === Number(terminalType)
})
}
export function clearPermissionInfoCache() {
permissionInfoCache.clear()
permissionInfoPending.clear()
@ -62,6 +82,7 @@ export function register(data) {
function getPermissionInfo(params = {}) {
const normalizedParams = normalizePermissionParams(params)
const terminalType = getTerminalType()
const cacheKey = createPermissionCacheKey(normalizedParams)
if (permissionInfoCache.has(cacheKey)) {
@ -80,8 +101,15 @@ function getPermissionInfo(params = {}) {
const wrappedPromise = requestPromise
.then((res) => {
permissionInfoCache.set(cacheKey, res)
return res
const nextRes = {
...res,
data: {
...res?.data,
menus: filterPermissionMenus(res?.data?.menus, terminalType)
}
}
permissionInfoCache.set(cacheKey, nextRes)
return nextRes
})
.finally(() => {
permissionInfoPending.delete(cacheKey)

@ -4,10 +4,12 @@
:fixed="true" :placeholder="true" :border="false" @change="handleChange" zIndex="1000">
<up-tabbar-item v-for="(item, index) in tabList" :key="index" :text="item.text" :name="index">
<template #active-icon>
<image :src="item.selectedIcon" class="tabbar-icon" mode="widthFix" />
<uni-icons v-if="item.iconType === 'uni-icons'" :type="item.iconName" size="24" :color="activeColor" />
<image v-else :src="item.selectedIcon" class="tabbar-icon" mode="widthFix" />
</template>
<template #inactive-icon>
<image :src="item.icon" class="tabbar-icon" mode="widthFix" />
<uni-icons v-if="item.iconType === 'uni-icons'" :type="item.iconName" size="24" :color="inactiveColor" />
<image v-else :src="item.icon" class="tabbar-icon" mode="widthFix" />
</template>
</up-tabbar-item>
</up-tabbar>
@ -61,6 +63,14 @@ function normalizeRoute(path = '') {
return String(path || '').trim().replace(/^\/+/, '')
}
function isUniIcon(icon) {
return String(icon || '').startsWith('uni-icons:')
}
function getUniIconName(icon) {
return String(icon || '').replace(/^uni-icons:/, '').trim()
}
function resolveTabIcons(path, index) {
const route = normalizeRoute(path)
if (route === 'pages/index') {
@ -84,6 +94,23 @@ function resolveTabIcons(path, index) {
return dynamicTabIconList[index % dynamicTabIconList.length]
}
function resolveTabIconMeta(menu, index) {
if (isUniIcon(menu?.icon)) {
return {
iconType: 'uni-icons',
iconName: getUniIconName(menu.icon)
}
}
const icons = resolveTabIcons(menu?.path, index)
return {
iconType: 'image',
iconName: '',
icon: icons.icon,
selectedIcon: icons.selectedIcon
}
}
function getCurrentActiveIndex() {
const pages = getCurrentPages()
if (pages && pages.length > 0) {
@ -97,11 +124,13 @@ function getCurrentActiveIndex() {
const tabList = computed(() => {
const dynamicTabList = getTabBarMenus(menus.value)
.map((menu, index) => {
const icons = resolveTabIcons(menu.path, index)
const iconMeta = resolveTabIconMeta(menu, index)
return {
text: String(menu.name || menu.enName || '').trim() || `菜单${index + 1}`,
icon: icons.icon,
selectedIcon: icons.selectedIcon,
icon: iconMeta.icon,
selectedIcon: iconMeta.selectedIcon,
iconType: iconMeta.iconType,
iconName: iconMeta.iconName,
path: menu.path
}
})
@ -112,6 +141,8 @@ const tabList = computed(() => {
text: t('nav.mine'),
icon: mineIcon,
selectedIcon: mineSelectedIcon,
iconType: 'image',
iconName: '',
path: '/pages/mine'
}
]

@ -514,10 +514,16 @@ export default {
setting: {
language: 'System Language',
currentLanguage: 'Current: {language}',
terminalMode: 'Terminal Mode',
currentTerminal: 'Current Terminal: {terminal}',
switchingTerminal: 'Switching terminal...',
terminalSwitched: 'Switched to {terminal}',
switchLanguage: 'Switch Language',
checkUpdate: 'Check Updates',
cleanCache: 'Clear Cache',
logout: 'Log Out',
mobile: 'Mobile',
scanner: 'Scanner',
zhCN: 'Chinese',
enUS: 'English'
},

@ -514,10 +514,16 @@ export default {
setting: {
language: '系统语言',
currentLanguage: '当前语言:{language}',
terminalMode: '终端模式',
currentTerminal: '当前终端:{terminal}',
switchingTerminal: '正在切换终端...',
terminalSwitched: '已切换到{terminal}',
switchLanguage: '切换语言',
checkUpdate: '检查更新',
cleanCache: '清理缓存',
logout: '退出登录',
mobile: '手机',
scanner: '扫码器',
zhCN: '中文',
enUS: '英文'
},

@ -15,6 +15,13 @@
<view>{{ t('mine.changePassword') }}</view>
</view>
</view>
<view class="list-cell list-cell-arrow" @click="handleTerminalChange">
<view class="menu-item-box">
<view class="iconfont icon-phone menu-icon"></view>
<view>{{ t('setting.terminalMode') }}</view>
</view>
<view class="text-grey">{{ t('setting.currentTerminal', { terminal: currentTerminalLabel }) }}</view>
</view>
<view class="list-cell list-cell-arrow" @click="handleToUpgrade">
<view class="menu-item-box">
<view class="iconfont icon-refresh menu-icon"></view>
@ -51,6 +58,7 @@ import { useI18n } from 'vue-i18n'
import useUserStore from '@/store/modules/user'
import { getCurrentLocale, setLocale } from '@/locales'
import NavBar from '@/components/common/NavBar.vue'
import { getTerminalType, setTerminalType, TERMINAL_TYPE_MOBILE, TERMINAL_TYPE_SCANNER } from '@/utils/terminal'
const userStore = useUserStore()
const { t } = useI18n()
@ -59,7 +67,9 @@ const pageTitle = computed(() => t('nav.setting'))
const windowHeight = ref(uni.getSystemInfoSync().windowHeight);
const popup = ref(null);
const currentLocale = ref(getCurrentLocale())
const currentTerminalType = ref(getTerminalType())
const currentLanguageLabel = computed(() => currentLocale.value === 'en-US' ? t('setting.enUS') : t('setting.zhCN'))
const currentTerminalLabel = computed(() => currentTerminalType.value === TERMINAL_TYPE_SCANNER ? t('setting.scanner') : t('setting.mobile'))
function handleToPwd() {
uni.navigateTo({
@ -99,6 +109,46 @@ function handleLanguageChange() {
}
})
}
function handleTerminalChange() {
uni.showActionSheet({
itemList: [t('setting.mobile'), t('setting.scanner')],
success: async ({ tapIndex }) => {
const nextTerminalType = tapIndex === 1 ? TERMINAL_TYPE_SCANNER : TERMINAL_TYPE_MOBILE
if (nextTerminalType === currentTerminalType.value) {
return
}
const previousTerminalType = currentTerminalType.value
setTerminalType(nextTerminalType)
currentTerminalType.value = nextTerminalType
uni.showLoading({
title: t('setting.switchingTerminal')
})
try {
await userStore.refreshPermissionInfo()
uni.showToast({
title: t('setting.terminalSwitched', { terminal: currentTerminalLabel.value }),
icon: 'none',
duration: 1000
})
} catch (error) {
setTerminalType(previousTerminalType)
currentTerminalType.value = previousTerminalType
await userStore.refreshPermissionInfo().catch(() => {})
uni.showToast({
title: t('common.saveFailed'),
icon: 'none',
duration: 1000
})
} finally {
uni.hideLoading()
}
}
})
}
function handleLogout() {
popup.value.open();
};

@ -1,5 +1,6 @@
import { login, logout, getInfo, clearPermissionInfoCache } from "@/api/login";
import { getToken, setToken, removeToken } from "@/utils/auth";
import { removeTerminalType } from "@/utils/terminal";
import defAva from "@/static/images/profile.jpg";
import { defineStore } from "pinia";
import { initAllDict } from "@/utils/dict";
@ -76,12 +77,17 @@ const useUserStore = defineStore("user", {
});
});
},
refreshPermissionInfo() {
clearPermissionInfoCache();
return this.getInfo();
},
// 退出系统
logOut() {
return new Promise<null>((resolve, reject) => {
logout()
.then(() => {
clearPermissionInfoCache();
removeTerminalType();
this.token = "";
this.roles = [];
this.permissions = [];

@ -216,6 +216,10 @@ export function buildPageModules(tabMenu) {
}
export function resolveMenuUrl(menu) {
if (String(menu?.path || '').trim() === '/' || String(menu?.component || '').trim() === '/') {
return '/pages/index'
}
const directRoute = getDirectRoute(menu?.path) || getDirectRoute(menu?.component)
if (directRoute) {
return directRoute

@ -0,0 +1,46 @@
const TerminalTypeKey = 'App-Terminal-Type'
export const TERMINAL_TYPE_MOBILE = 1
export const TERMINAL_TYPE_SCANNER = 2
function normalizeTerminalType(value: unknown) {
return Number(value) === TERMINAL_TYPE_SCANNER ? TERMINAL_TYPE_SCANNER : TERMINAL_TYPE_MOBILE
}
export function detectTerminalType() {
const systemInfo = uni.getSystemInfoSync()
const width = Number(systemInfo.windowWidth || systemInfo.screenWidth || 0)
const height = Number(systemInfo.windowHeight || systemInfo.screenHeight || 0)
if (width === 480 && height === 800) {
return TERMINAL_TYPE_SCANNER
}
return TERMINAL_TYPE_MOBILE
}
export function getTerminalType() {
const storedValue = uni.getStorageSync(TerminalTypeKey)
if (storedValue === '' || storedValue === null || typeof storedValue === 'undefined') {
return TERMINAL_TYPE_MOBILE
}
return normalizeTerminalType(storedValue)
}
export function setTerminalType(value: unknown) {
const terminalType = normalizeTerminalType(value)
uni.setStorageSync(TerminalTypeKey, terminalType)
return terminalType
}
export function removeTerminalType() {
uni.removeStorageSync(TerminalTypeKey)
}
export function initializeTerminalType() {
const storedValue = uni.getStorageSync(TerminalTypeKey)
if (storedValue === '' || storedValue === null || typeof storedValue === 'undefined') {
return setTerminalType(detectTerminalType())
}
return normalizeTerminalType(storedValue)
}
Loading…
Cancel
Save