first commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Emoji处理工具函数
|
||||
*/
|
||||
|
||||
// 将emoji代码转换为Unicode字符
|
||||
export function parseEmoji(text) {
|
||||
// 这里可以添加具体的emoji解析逻辑
|
||||
// 例如将 :smile: 转换为 😊
|
||||
return text;
|
||||
}
|
||||
|
||||
// 将Unicode字符转换为emoji代码
|
||||
export function encodeEmoji(text) {
|
||||
// 这里可以添加具体的emoji编码逻辑
|
||||
return text;
|
||||
}
|
||||
|
||||
// 检查文本中是否包含emoji
|
||||
export function containsEmoji(text) {
|
||||
// 基本的emoji Unicode范围检查
|
||||
const emojiRegex = /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/gu;
|
||||
return emojiRegex.test(text);
|
||||
}
|
||||
|
||||
export default {
|
||||
parseEmoji,
|
||||
encodeEmoji,
|
||||
containsEmoji
|
||||
};
|
||||
@@ -0,0 +1,165 @@
|
||||
// 常用emoji表情数据
|
||||
export const emojis = [
|
||||
// 笑脸和情感
|
||||
{ id: 'smile', unicode: '😊', name: '微笑' },
|
||||
{ id: 'laugh', unicode: '😄', name: '大笑' },
|
||||
{ id: 'grin', unicode: '😁', name: ' grin' },
|
||||
{ id: 'tears_of_joy', unicode: '😂', name: '笑哭' },
|
||||
{ id: 'wink', unicode: '😉', name: '眨眼' },
|
||||
{ id: 'blush', unicode: '😊', name: '脸红' },
|
||||
{ id: 'innocent', unicode: '😇', name: '天使' },
|
||||
{ id: 'heart_eyes', unicode: '😍', name: '花痴' },
|
||||
{ id: 'kissing_heart', unicode: '😘', name: '飞吻' },
|
||||
{ id: 'kissing_closed_eyes', unicode: '😚', name: '闭眼亲亲' },
|
||||
{ id: 'yum', unicode: '😋', name: '好吃' },
|
||||
{ id: 'stuck_out_tongue_winking_eye', unicode: '😜', name: '吐舌头眨眼' },
|
||||
{ id: 'sunglasses', unicode: '😎', name: '酷' },
|
||||
{ id: 'smirk', unicode: '😏', name: '得意' },
|
||||
{ id: 'expressionless', unicode: '😑', name: '面无表情' },
|
||||
{ id: 'neutral_face', unicode: '😐', name: '中性' },
|
||||
|
||||
// 手势和身体部位
|
||||
{ id: 'thumbsup', unicode: '👍', name: '赞' },
|
||||
{ id: 'thumbsdown', unicode: '👎', name: '踩' },
|
||||
{ id: 'ok_hand', unicode: '👌', name: 'OK' },
|
||||
{ id: 'fist', unicode: '✊', name: '拳头' },
|
||||
{ id: 'v', unicode: '✌️', name: '胜利' },
|
||||
{ id: 'wave', unicode: '👋', name: '挥手' },
|
||||
{ id: 'clap', unicode: '👏', name: '鼓掌' },
|
||||
{ id: 'muscle', unicode: '💪', name: '肌肉' },
|
||||
{ id: 'pray', unicode: '🙏', name: '祈祷' },
|
||||
|
||||
// 动物和自然
|
||||
{ id: 'dog', unicode: '🐶', name: '狗' },
|
||||
{ id: 'cat', unicode: '🐱', name: '猫' },
|
||||
{ id: 'pig', unicode: '🐷', name: '猪' },
|
||||
{ id: 'rabbit', unicode: '🐰', name: '兔子' },
|
||||
{ id: 'koala', unicode: '🐨', name: '考拉' },
|
||||
{ id: 'tiger', unicode: '🐯', name: '老虎' },
|
||||
{ id: 'horse', unicode: '🐴', name: '马' },
|
||||
{ id: 'cow', unicode: '🐮', name: '牛' },
|
||||
{ id: 'panda_face', unicode: '🐼', name: '熊猫' },
|
||||
{ id: 'pig_nose', unicode: '🐽', name: '猪鼻子' },
|
||||
{ id: 'feet', unicode: '🐾', name: '爪子' },
|
||||
{ id: 'turtle', unicode: '🐢', name: '乌龟' },
|
||||
{ id: 'hatching_chick', unicode: '🐣', name: '孵化' },
|
||||
{ id: 'baby_chick', unicode: '🐤', name: '小鸡' },
|
||||
{ id: 'hatched_chick', unicode: '🐥', name: '雏鸡' },
|
||||
{ id: 'bird', unicode: '🐦', name: '鸟' },
|
||||
|
||||
// 食物和饮料
|
||||
{ id: 'grapes', unicode: '🍇', name: '葡萄' },
|
||||
{ id: 'melon', unicode: '🍈', name: '甜瓜' },
|
||||
{ id: 'watermelon', unicode: '🍉', name: '西瓜' },
|
||||
{ id: 'tangerine', unicode: '🍊', name: '橘子' },
|
||||
{ id: 'lemon', unicode: '🍋', name: '柠檬' },
|
||||
{ id: 'banana', unicode: '🍌', name: '香蕉' },
|
||||
{ id: 'pineapple', unicode: '🍍', name: '菠萝' },
|
||||
{ id: 'apple', unicode: '🍎', name: '苹果' },
|
||||
{ id: 'green_apple', unicode: '🍏', name: '青苹果' },
|
||||
{ id: 'cherries', unicode: '🍒', name: '樱桃' },
|
||||
{ id: 'strawberry', unicode: '🍓', name: '草莓' },
|
||||
{ id: 'hamburger', unicode: '🍔', name: '汉堡' },
|
||||
{ id: 'pizza', unicode: '🍕', name: '披萨' },
|
||||
{ id: 'meat_on_bone', unicode: '🍖', name: '排骨' },
|
||||
{ id: 'poultry_leg', unicode: '🍗', name: '鸡腿' },
|
||||
{ id: 'rice_cracker', unicode: '🍘', name: '米饼' },
|
||||
|
||||
// 活动和运动
|
||||
{ id: 'soccer', unicode: '⚽', name: '足球' },
|
||||
{ id: 'basketball', unicode: '🏀', name: '篮球' },
|
||||
{ id: 'football', unicode: '🏈', name: '橄榄球' },
|
||||
{ id: 'baseball', unicode: '⚾', name: '棒球' },
|
||||
{ id: 'tennis', unicode: '🎾', name: '网球' },
|
||||
{ id: 'golf', unicode: '⛳', name: '高尔夫' },
|
||||
{ id: 'ski', unicode: '🎿', name: '滑雪' },
|
||||
{ id: 'snowboarder', unicode: '🏂', name: '滑雪板' },
|
||||
{ id: 'swimmer', unicode: '🏊', name: '游泳' },
|
||||
{ id: 'surfer', unicode: '🏄', name: '冲浪' },
|
||||
{ id: 'cyclist', unicode: '🚴', name: '骑车' },
|
||||
{ id: 'runner', unicode: '🏃', name: '跑步' },
|
||||
{ id: 'dancer', unicode: '💃', name: '跳舞' },
|
||||
{ id: 'guitar', unicode: '🎸', name: '吉他' },
|
||||
{ id: 'musical_keyboard', unicode: '🎹', name: '键盘' },
|
||||
{ id: 'violin', unicode: '🎻', name: '小提琴' },
|
||||
|
||||
// 旅行和地点
|
||||
{ id: 'rocket', unicode: '🚀', name: '火箭' },
|
||||
{ id: 'helicopter', unicode: '🚁', name: '直升机' },
|
||||
{ id: 'steam_locomotive', unicode: '🚂', name: '火车头' },
|
||||
{ id: 'railway_car', unicode: '🚃', name: '车厢' },
|
||||
{ id: 'bullettrain_side', unicode: '🚄', name: '高铁' },
|
||||
{ id: 'bullettrain_front', unicode: '🚅', name: '子弹头' },
|
||||
{ id: 'train2', unicode: '🚆', name: '火车' },
|
||||
{ id: 'metro', unicode: '🚇', name: '地铁' },
|
||||
{ id: 'light_rail', unicode: '🚈', name: '轻轨' },
|
||||
{ id: 'station', unicode: '🚉', name: '车站' },
|
||||
{ id: 'tram', unicode: '🚊', name: '电车' },
|
||||
{ id: 'bus', unicode: '🚌', name: '公交车' },
|
||||
{ id: 'blue_car', unicode: '🚙', name: '汽车' },
|
||||
{ id: 'car', unicode: '🚗', name: '轿车' },
|
||||
{ id: 'taxi', unicode: '🚕', name: '出租车' },
|
||||
{ id: 'truck', unicode: '🚚', name: '卡车' },
|
||||
|
||||
// 符号和标志
|
||||
{ id: 'heart', unicode: '❤️', name: '爱心' },
|
||||
{ id: 'broken_heart', unicode: '💔', name: '心碎' },
|
||||
{ id: 'heartpulse', unicode: '💗', name: '心动' },
|
||||
{ id: 'sparkling_heart', unicode: '💖', name: '闪心' },
|
||||
{ id: 'cupid', unicode: '💘', name: '丘比特' },
|
||||
{ id: 'gift_heart', unicode: '💝', name: '礼盒心' },
|
||||
{ id: 'heart_decoration', unicode: '💟', name: '心装饰' },
|
||||
{ id: 'purple_heart', unicode: '💜', name: '紫心' },
|
||||
{ id: 'yellow_heart', unicode: '💛', name: '黄心' },
|
||||
{ id: 'green_heart', unicode: '💚', name: '绿心' },
|
||||
{ id: 'blue_heart', unicode: '💙', name: '蓝心' },
|
||||
{ id: 'star', unicode: '⭐', name: '星星' },
|
||||
{ id: 'sparkles', unicode: '✨', name: '闪亮' },
|
||||
{ id: 'zap', unicode: '⚡', name: '闪电' },
|
||||
{ id: 'fire', unicode: '🔥', name: '火' },
|
||||
{ id: 'boom', unicode: '💥', name: '爆炸' }
|
||||
];
|
||||
|
||||
// 将emoji按类别分组
|
||||
export const emojiCategories = [
|
||||
{
|
||||
id: 'people',
|
||||
name: '笑脸和情感',
|
||||
emojis: emojis.slice(0, 16)
|
||||
},
|
||||
{
|
||||
id: 'hands',
|
||||
name: '手势和身体',
|
||||
emojis: emojis.slice(16, 25)
|
||||
},
|
||||
{
|
||||
id: 'animals',
|
||||
name: '动物和自然',
|
||||
emojis: emojis.slice(25, 41)
|
||||
},
|
||||
{
|
||||
id: 'food',
|
||||
name: '食物和饮料',
|
||||
emojis: emojis.slice(41, 57)
|
||||
},
|
||||
{
|
||||
id: 'activity',
|
||||
name: '活动和运动',
|
||||
emojis: emojis.slice(57, 73)
|
||||
},
|
||||
{
|
||||
id: 'travel',
|
||||
name: '旅行和地点',
|
||||
emojis: emojis.slice(73, 89)
|
||||
},
|
||||
{
|
||||
id: 'symbols',
|
||||
name: '符号和标志',
|
||||
emojis: emojis.slice(89, 105)
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
emojis,
|
||||
emojiCategories
|
||||
};
|
||||
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* 通用工具函数
|
||||
*/
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
* @param {Date|string|number} date 时间
|
||||
* @param {string} format 格式 'YYYY-MM-DD HH:mm:ss'
|
||||
*/
|
||||
export function formatTime(date, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
if (!date) return ''
|
||||
|
||||
const d = new Date(date)
|
||||
if (isNaN(d.getTime())) return ''
|
||||
|
||||
const year = d.getFullYear()
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
const hours = String(d.getHours()).padStart(2, '0')
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(d.getSeconds()).padStart(2, '0')
|
||||
|
||||
return format
|
||||
.replace('YYYY', year)
|
||||
.replace('MM', month)
|
||||
.replace('DD', day)
|
||||
.replace('HH', hours)
|
||||
.replace('mm', minutes)
|
||||
.replace('ss', seconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化相对时间
|
||||
* @param {Date|string|number} date 时间
|
||||
*/
|
||||
export function formatRelativeTime(date) {
|
||||
if (!date) return ''
|
||||
|
||||
const now = new Date()
|
||||
const target = new Date(date)
|
||||
const diff = now.getTime() - target.getTime()
|
||||
|
||||
const minute = 60 * 1000
|
||||
const hour = 60 * minute
|
||||
const day = 24 * hour
|
||||
const week = 7 * day
|
||||
const month = 30 * day
|
||||
|
||||
if (diff < minute) {
|
||||
return '刚刚'
|
||||
} else if (diff < hour) {
|
||||
return `${Math.floor(diff / minute)}分钟前`
|
||||
} else if (diff < day) {
|
||||
return `${Math.floor(diff / hour)}小时前`
|
||||
} else if (diff < week) {
|
||||
return `${Math.floor(diff / day)}天前`
|
||||
} else if (diff < month) {
|
||||
return `${Math.floor(diff / week)}周前`
|
||||
} else {
|
||||
return formatTime(target, 'YYYY-MM-DD')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化金额
|
||||
* @param {number} amount 金额
|
||||
* @param {string} currency 货币符号
|
||||
*/
|
||||
export function formatMoney(amount, currency = '¥') {
|
||||
if (amount === null || amount === undefined || isNaN(amount)) return '0'
|
||||
return `${currency}${Number(amount).toLocaleString()}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
* @param {number} bytes 字节数
|
||||
*/
|
||||
export function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 B'
|
||||
|
||||
const k = 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param {Function} func 要防抖的函数
|
||||
* @param {number} delay 延迟时间
|
||||
*/
|
||||
export function debounce(func, delay = 300) {
|
||||
let timeoutId
|
||||
return function (...args) {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = setTimeout(() => func.apply(this, args), delay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* @param {Function} func 要节流的函数
|
||||
* @param {number} delay 延迟时间
|
||||
*/
|
||||
export function throttle(func, delay = 300) {
|
||||
let lastCall = 0
|
||||
return function (...args) {
|
||||
const now = Date.now()
|
||||
if (now - lastCall >= delay) {
|
||||
lastCall = now
|
||||
return func.apply(this, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝
|
||||
* @param {any} obj 要拷贝的对象
|
||||
*/
|
||||
export function deepClone(obj) {
|
||||
if (obj === null || typeof obj !== 'object') return obj
|
||||
if (obj instanceof Date) return new Date(obj.getTime())
|
||||
if (obj instanceof Array) return obj.map(item => deepClone(item))
|
||||
if (typeof obj === 'object') {
|
||||
const clonedObj = {}
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
clonedObj[key] = deepClone(obj[key])
|
||||
}
|
||||
}
|
||||
return clonedObj
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一ID
|
||||
*/
|
||||
export function generateId() {
|
||||
return Date.now().toString(36) + Math.random().toString(36).substr(2)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机号
|
||||
* @param {string} phone 手机号
|
||||
*/
|
||||
export function validatePhone(phone) {
|
||||
const reg = /^1[3-9]\d{9}$/
|
||||
return reg.test(phone)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邮箱
|
||||
* @param {string} email 邮箱
|
||||
*/
|
||||
export function validateEmail(email) {
|
||||
const reg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return reg.test(email)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证身份证号
|
||||
* @param {string} idCard 身份证号
|
||||
*/
|
||||
export function validateIdCard(idCard) {
|
||||
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
|
||||
return reg.test(idCard)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取URL参数
|
||||
* @param {string} name 参数名
|
||||
* @param {string} url URL地址
|
||||
*/
|
||||
export function getUrlParam(name, url = window.location.href) {
|
||||
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
|
||||
const r = url.match(reg)
|
||||
if (r != null) return decodeURIComponent(r[2])
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储到本地
|
||||
* @param {string} key 键
|
||||
* @param {any} value 值
|
||||
*/
|
||||
export function setStorage(key, value) {
|
||||
try {
|
||||
uni.setStorageSync(key, JSON.stringify(value))
|
||||
} catch (error) {
|
||||
console.error('存储失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地获取
|
||||
* @param {string} key 键
|
||||
* @param {any} defaultValue 默认值
|
||||
*/
|
||||
export function getStorage(key, defaultValue = null) {
|
||||
try {
|
||||
const value = uni.getStorageSync(key)
|
||||
return value ? JSON.parse(value) : defaultValue
|
||||
} catch (error) {
|
||||
console.error('获取存储失败:', error)
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除本地存储
|
||||
* @param {string} key 键
|
||||
*/
|
||||
export function removeStorage(key) {
|
||||
try {
|
||||
uni.removeStorageSync(key)
|
||||
} catch (error) {
|
||||
console.error('删除存储失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示加载提示
|
||||
* @param {string} title 提示文字
|
||||
*/
|
||||
export function showLoading(title = '加载中...') {
|
||||
uni.showLoading({
|
||||
title,
|
||||
mask: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏加载提示
|
||||
*/
|
||||
export function hideLoading() {
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示成功提示
|
||||
* @param {string} title 提示文字
|
||||
*/
|
||||
export function showSuccess(title) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误提示
|
||||
* @param {string} title 提示文字
|
||||
*/
|
||||
export function showError(title) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示普通提示
|
||||
* @param {string} title 提示文字
|
||||
*/
|
||||
export function showToast(title) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示确认对话框
|
||||
* @param {string} content 内容
|
||||
* @param {string} title 标题
|
||||
*/
|
||||
export function showConfirm(content, title = '提示') {
|
||||
return new Promise((resolve) => {
|
||||
uni.showModal({
|
||||
title,
|
||||
content,
|
||||
success: (res) => {
|
||||
resolve(res.confirm)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面跳转
|
||||
* @param {string} url 页面路径
|
||||
* @param {object} params 参数
|
||||
*/
|
||||
export function navigateTo(url, params = {}) {
|
||||
const query = Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&')
|
||||
const fullUrl = query ? `${url}?${query}` : url
|
||||
|
||||
uni.navigateTo({
|
||||
url: fullUrl,
|
||||
fail: (error) => {
|
||||
console.error('页面跳转失败:', error)
|
||||
showError('页面跳转失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面重定向
|
||||
* @param {string} url 页面路径
|
||||
* @param {object} params 参数
|
||||
*/
|
||||
export function redirectTo(url, params = {}) {
|
||||
const query = Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&')
|
||||
const fullUrl = query ? `${url}?${query}` : url
|
||||
|
||||
uni.redirectTo({
|
||||
url: fullUrl,
|
||||
fail: (error) => {
|
||||
console.error('页面重定向失败:', error)
|
||||
showError('页面重定向失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换Tab页面
|
||||
* @param {string} url 页面路径
|
||||
*/
|
||||
export function switchTab(url) {
|
||||
uni.switchTab({
|
||||
url,
|
||||
fail: (error) => {
|
||||
console.error('Tab切换失败:', error)
|
||||
showError('页面切换失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回上一页
|
||||
* @param {number} delta 返回层数
|
||||
*/
|
||||
export function navigateBack(delta = 1) {
|
||||
uni.navigateBack({
|
||||
delta,
|
||||
fail: (error) => {
|
||||
console.error('返回失败:', error)
|
||||
showError('返回失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import { useAuthStore } from '../store/authStore.js'
|
||||
|
||||
// 需要登录的页面路径
|
||||
const authRequiredPages = [
|
||||
'/pages/index/index',
|
||||
'/pages/profile/profile',
|
||||
'/pages/function/function',
|
||||
'/pages/message/message',
|
||||
'/pages/tasks/index'
|
||||
]
|
||||
|
||||
// 登录页面路径
|
||||
const loginPage = '/pages/login/index'
|
||||
|
||||
// 首页路径
|
||||
const homePage = '/pages/index/index'
|
||||
|
||||
/**
|
||||
* 检查当前页面是否需要登录
|
||||
* @param {string} currentPath 当前页面路径
|
||||
* @returns {boolean} 是否需要登录
|
||||
*/
|
||||
export function isAuthRequired(currentPath) {
|
||||
return authRequiredPages.includes(currentPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由守卫 - 检查登录状态
|
||||
* @param {string} toPath 目标页面路径
|
||||
* @returns {boolean} 是否允许访问
|
||||
*/
|
||||
export function checkAuthGuard(toPath) {
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// 如果是登录页面,直接允许访问
|
||||
if (toPath === loginPage) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查是否需要登录
|
||||
if (isAuthRequired(toPath)) {
|
||||
// 检查是否已登录
|
||||
if (!authStore.isAuthenticated) {
|
||||
// 跳转到登录页面
|
||||
uni.reLaunch({
|
||||
url: loginPage
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化路由守卫
|
||||
*/
|
||||
export function initRouteGuard() {
|
||||
// 监听页面跳转
|
||||
uni.addInterceptor('navigateTo', {
|
||||
invoke(args) {
|
||||
const toPath = args.url.split('?')[0] // 移除查询参数
|
||||
if (!checkAuthGuard(toPath)) {
|
||||
return false // 阻止跳转
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
uni.addInterceptor('redirectTo', {
|
||||
invoke(args) {
|
||||
const toPath = args.url.split('?')[0]
|
||||
if (!checkAuthGuard(toPath)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
uni.addInterceptor('switchTab', {
|
||||
invoke(args) {
|
||||
const toPath = args.url.split('?')[0]
|
||||
if (!checkAuthGuard(toPath)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
uni.addInterceptor('reLaunch', {
|
||||
invoke(args) {
|
||||
const toPath = args.url.split('?')[0]
|
||||
if (!checkAuthGuard(toPath)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后跳转
|
||||
* @param {string} redirectPath 重定向路径,默认为首页
|
||||
*/
|
||||
export function redirectAfterLogin(redirectPath = homePage) {
|
||||
uni.reLaunch({
|
||||
url: redirectPath
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出后跳转
|
||||
*/
|
||||
export function redirectAfterLogout() {
|
||||
uni.reLaunch({
|
||||
url: loginPage
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* 启动画面管理器
|
||||
*/
|
||||
|
||||
// 启动画面配置
|
||||
export const splashConfig = {
|
||||
// 最小显示时间(毫秒)
|
||||
minDisplayTime: 2000,
|
||||
// 最大显示时间(毫秒)
|
||||
maxDisplayTime: 5000,
|
||||
// 是否已显示过启动画面
|
||||
hasShown: false,
|
||||
// 启动时间戳
|
||||
startTime: null
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化启动画面
|
||||
*/
|
||||
export function initSplash() {
|
||||
splashConfig.startTime = Date.now()
|
||||
splashConfig.hasShown = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否应该显示启动画面
|
||||
*/
|
||||
export function shouldShowSplash() {
|
||||
// 如果已经显示过,不再显示
|
||||
if (splashConfig.hasShown) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查是否在冷启动状态
|
||||
const isColdStart = !getApp().globalData?.isWarmStart
|
||||
|
||||
return isColdStart
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记启动画面已显示
|
||||
*/
|
||||
export function markSplashShown() {
|
||||
splashConfig.hasShown = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取启动画面显示时长
|
||||
*/
|
||||
export function getSplashDuration() {
|
||||
if (!splashConfig.startTime) {
|
||||
return splashConfig.minDisplayTime
|
||||
}
|
||||
|
||||
const elapsed = Date.now() - splashConfig.startTime
|
||||
return Math.max(splashConfig.minDisplayTime - elapsed, 500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动画面加载步骤配置
|
||||
*/
|
||||
export const loadingSteps = [
|
||||
{
|
||||
text: '正在初始化...',
|
||||
duration: 800,
|
||||
action: 'init'
|
||||
},
|
||||
{
|
||||
text: '加载用户数据...',
|
||||
duration: 1000,
|
||||
action: 'loadUserData'
|
||||
},
|
||||
{
|
||||
text: '同步工作数据...',
|
||||
duration: 800,
|
||||
action: 'syncWorkData'
|
||||
},
|
||||
{
|
||||
text: '准备就绪...',
|
||||
duration: 600,
|
||||
action: 'ready'
|
||||
}
|
||||
]
|
||||
|
||||
/**
|
||||
* 执行启动步骤
|
||||
*/
|
||||
export async function executeLoadingStep(step) {
|
||||
try {
|
||||
switch (step.action) {
|
||||
case 'init':
|
||||
await initializeApp()
|
||||
break
|
||||
case 'loadUserData':
|
||||
await loadUserData()
|
||||
break
|
||||
case 'syncWorkData':
|
||||
await syncWorkData()
|
||||
break
|
||||
case 'ready':
|
||||
await prepareReady()
|
||||
break
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error(`启动步骤 ${step.action} 执行失败:`, error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化应用
|
||||
*/
|
||||
async function initializeApp() {
|
||||
// 模拟初始化过程
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
|
||||
// 这里可以添加实际的初始化逻辑
|
||||
// 例如:检查网络状态、初始化全局配置等
|
||||
console.log('应用初始化完成')
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载用户数据
|
||||
*/
|
||||
async function loadUserData() {
|
||||
// 模拟加载用户数据
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
|
||||
// 这里可以添加实际的用户数据加载逻辑
|
||||
// 例如:从本地存储加载用户信息、验证登录状态等
|
||||
console.log('用户数据加载完成')
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步工作数据
|
||||
*/
|
||||
async function syncWorkData() {
|
||||
// 模拟同步工作数据
|
||||
await new Promise(resolve => setTimeout(resolve, 400))
|
||||
|
||||
// 这里可以添加实际的工作数据同步逻辑
|
||||
// 例如:同步待办事项、考勤数据、消息等
|
||||
console.log('工作数据同步完成')
|
||||
}
|
||||
|
||||
/**
|
||||
* 准备就绪
|
||||
*/
|
||||
async function prepareReady() {
|
||||
// 模拟准备就绪过程
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
|
||||
// 这里可以添加最后的准备逻辑
|
||||
// 例如:预加载关键数据、设置全局状态等
|
||||
console.log('应用准备就绪')
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动画面完成回调
|
||||
*/
|
||||
export function onSplashComplete() {
|
||||
// 标记应用为热启动
|
||||
if (getApp().globalData) {
|
||||
getApp().globalData.isWarmStart = true
|
||||
}
|
||||
|
||||
// 标记启动画面已显示
|
||||
markSplashShown()
|
||||
|
||||
console.log('启动画面完成')
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置启动状态(用于测试)
|
||||
*/
|
||||
export function resetSplashState() {
|
||||
splashConfig.hasShown = false
|
||||
splashConfig.startTime = null
|
||||
if (getApp().globalData) {
|
||||
getApp().globalData.isWarmStart = false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user