Files
xlxumu/mini_program/App.vue

758 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view id="app">
<!-- 应用根组件 -->
</view>
</template>
<script>
import { onLaunch, onShow, onHide, onError } from '@dcloudio/uni-app'
import { useUserStore } from '@/common/store/modules/user.js'
import { createLogger } from '@/common/utils/logger.js'
import { CONFIG } from '@/common/config/app.config.js'
const logger = createLogger('App')
export default {
name: 'App',
setup() {
const userStore = useUserStore()
onLaunch((options) => {
logger.info('Application launched', {
scene: options.scene,
query: options.query,
referrerInfo: options.referrerInfo
})
// 初始化应用
initializeApp(options)
})
onShow((options) => {
logger.info('Application shown', {
scene: options.scene,
query: options.query
})
// 应用显示时的处理
handleAppShow(options)
})
onHide(() => {
logger.info('Application hidden')
// 应用隐藏时的处理
handleAppHide()
})
onError((error) => {
logger.error('Application error', null, new Error(error))
})
/**
* 初始化应用
*/
const initializeApp = async (options) => {
try {
// 检查登录状态
await checkLoginStatus()
// 处理启动参数
handleLaunchOptions(options)
// 初始化全局数据
await initializeGlobalData()
logger.info('App initialization completed')
} catch (error) {
logger.error('App initialization failed', null, error)
}
}
/**
* 检查登录状态
*/
const checkLoginStatus = async () => {
try {
const token = uni.getStorageSync('token')
if (token) {
// 验证 token 并获取用户信息
await userStore.getCurrentUser()
logger.info('User login status verified')
}
} catch (error) {
logger.warn('Login status check failed', null, error)
// 清除无效的登录信息
uni.removeStorageSync('token')
uni.removeStorageSync('userInfo')
}
}
/**
* 处理启动参数
*/
const handleLaunchOptions = (options) => {
// 处理分享参数
if (options.query && Object.keys(options.query).length > 0) {
logger.info('Launch with query parameters', options.query)
// 保存启动参数供后续使用
uni.setStorageSync('launchQuery', options.query)
}
// 处理场景值
switch (options.scene) {
case 1001: // 发现栏小程序主入口
case 1019: // 微信钱包
case 1020: // 公众号 profile 页相关小程序列表
logger.info('Launched from WeChat discovery')
break
case 1007: // 单人聊天会话中的小程序消息卡片
case 1008: // 群聊会话中的小程序消息卡片
logger.info('Launched from chat message')
break
case 1011: // 扫描二维码
logger.info('Launched from QR code scan')
break
default:
logger.info('Launched from scene', { scene: options.scene })
}
}
/**
* 初始化全局数据
*/
const initializeGlobalData = async () => {
try {
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
// 设置全局变量
getApp().globalData = {
systemInfo,
userInfo: userStore.userInfo,
config: CONFIG,
version: CONFIG.APP_VERSION || '1.0.0'
}
// 设置导航栏标题
uni.setNavigationBarTitle({
title: CONFIG.APP_NAME || '畜牧管理系统'
})
logger.info('Global data initialized', {
platform: systemInfo.platform,
version: systemInfo.version
})
} catch (error) {
logger.error('Failed to initialize global data', null, error)
}
}
/**
* 应用显示处理
*/
const handleAppShow = (options) => {
// 检查网络状态
uni.getNetworkType({
success: (res) => {
if (res.networkType === 'none') {
uni.showToast({
title: '网络连接不可用',
icon: 'none',
duration: 3000
})
}
}
})
// 刷新用户信息(如果已登录)
if (userStore.isLoggedIn) {
userStore.refreshUserInfo().catch(error => {
logger.warn('Failed to refresh user info', null, error)
})
}
// 处理从后台切换回前台的逻辑
const lastHideTime = uni.getStorageSync('lastHideTime')
if (lastHideTime) {
const hideTime = Date.now() - lastHideTime
// 如果后台时间超过30分钟重新验证登录状态
if (hideTime > 30 * 60 * 1000 && userStore.isLoggedIn) {
checkLoginStatus()
}
uni.removeStorageSync('lastHideTime')
}
}
/**
* 应用隐藏处理
*/
const handleAppHide = () => {
// 记录隐藏时间
uni.setStorageSync('lastHideTime', Date.now())
// 清理临时数据
cleanupTempData()
// 保存重要数据
saveImportantData()
}
/**
* 清理临时数据
*/
const cleanupTempData = () => {
try {
// 清理临时文件
const tempFiles = uni.getStorageSync('tempFiles') || []
tempFiles.forEach(filePath => {
uni.removeSavedFile({
filePath,
complete: () => {
logger.debug('Temp file removed', { filePath })
}
})
})
// 清理临时存储
uni.removeStorageSync('tempFiles')
uni.removeStorageSync('tempData')
logger.debug('Temp data cleaned up')
} catch (error) {
logger.error('Failed to cleanup temp data', null, error)
}
}
/**
* 保存重要数据
*/
const saveImportantData = () => {
try {
// 保存用户偏好设置
if (userStore.userInfo) {
uni.setStorageSync('userPreferences', {
theme: userStore.userInfo.theme || 'light',
language: userStore.userInfo.language || 'zh-CN',
notifications: userStore.userInfo.notifications || true
})
}
// 保存应用状态
const currentPages = getCurrentPages()
if (currentPages.length > 0) {
const currentPage = currentPages[currentPages.length - 1]
uni.setStorageSync('lastPage', {
route: currentPage.route,
options: currentPage.options
})
}
logger.debug('Important data saved')
} catch (error) {
logger.error('Failed to save important data', null, error)
}
}
return {}
}
}
</script>
<style lang="scss">
/**
* 全局样式
*/
// 导入基础样式
@import '@/common/styles/base.scss';
@import '@/common/styles/variables.scss';
@import '@/common/styles/mixins.scss';
// 应用根样式
#app {
font-family: $font-family-base;
font-size: $font-size-base;
line-height: $line-height-base;
color: $text-color-primary;
background-color: $background-color-base;
}
// 全局重置样式
* {
box-sizing: border-box;
}
// 页面基础样式
page {
background-color: $background-color-base;
font-size: $font-size-base;
line-height: $line-height-base;
}
// 通用工具类
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-primary {
color: $color-primary;
}
.text-success {
color: $color-success;
}
.text-warning {
color: $color-warning;
}
.text-error {
color: $color-error;
}
.text-info {
color: $color-info;
}
.text-muted {
color: $text-color-secondary;
}
.bg-primary {
background-color: $color-primary;
}
.bg-success {
background-color: $color-success;
}
.bg-warning {
background-color: $color-warning;
}
.bg-error {
background-color: $color-error;
}
.bg-info {
background-color: $color-info;
}
// 间距工具类
@for $i from 0 through 10 {
.m-#{$i} {
margin: #{$i * 8}rpx;
}
.mt-#{$i} {
margin-top: #{$i * 8}rpx;
}
.mr-#{$i} {
margin-right: #{$i * 8}rpx;
}
.mb-#{$i} {
margin-bottom: #{$i * 8}rpx;
}
.ml-#{$i} {
margin-left: #{$i * 8}rpx;
}
.mx-#{$i} {
margin-left: #{$i * 8}rpx;
margin-right: #{$i * 8}rpx;
}
.my-#{$i} {
margin-top: #{$i * 8}rpx;
margin-bottom: #{$i * 8}rpx;
}
.p-#{$i} {
padding: #{$i * 8}rpx;
}
.pt-#{$i} {
padding-top: #{$i * 8}rpx;
}
.pr-#{$i} {
padding-right: #{$i * 8}rpx;
}
.pb-#{$i} {
padding-bottom: #{$i * 8}rpx;
}
.pl-#{$i} {
padding-left: #{$i * 8}rpx;
}
.px-#{$i} {
padding-left: #{$i * 8}rpx;
padding-right: #{$i * 8}rpx;
}
.py-#{$i} {
padding-top: #{$i * 8}rpx;
padding-bottom: #{$i * 8}rpx;
}
}
// 弹性布局工具类
.d-flex {
display: flex;
}
.flex-row {
flex-direction: row;
}
.flex-column {
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-nowrap {
flex-wrap: nowrap;
}
.justify-start {
justify-content: flex-start;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.justify-between {
justify-content: space-between;
}
.justify-around {
justify-content: space-around;
}
.align-start {
align-items: flex-start;
}
.align-end {
align-items: flex-end;
}
.align-center {
align-items: center;
}
.align-stretch {
align-items: stretch;
}
.flex-1 {
flex: 1;
}
.flex-auto {
flex: auto;
}
.flex-none {
flex: none;
}
// 显示隐藏工具类
.d-none {
display: none;
}
.d-block {
display: block;
}
.d-inline {
display: inline;
}
.d-inline-block {
display: inline-block;
}
// 位置工具类
.position-relative {
position: relative;
}
.position-absolute {
position: absolute;
}
.position-fixed {
position: fixed;
}
.position-sticky {
position: sticky;
}
// 圆角工具类
.rounded {
border-radius: $border-radius-base;
}
.rounded-sm {
border-radius: $border-radius-sm;
}
.rounded-lg {
border-radius: $border-radius-lg;
}
.rounded-circle {
border-radius: 50%;
}
// 阴影工具类
.shadow-sm {
box-shadow: $box-shadow-sm;
}
.shadow {
box-shadow: $box-shadow-base;
}
.shadow-lg {
box-shadow: $box-shadow-lg;
}
// 边框工具类
.border {
border: 1rpx solid $border-color-base;
}
.border-top {
border-top: 1rpx solid $border-color-base;
}
.border-right {
border-right: 1rpx solid $border-color-base;
}
.border-bottom {
border-bottom: 1rpx solid $border-color-base;
}
.border-left {
border-left: 1rpx solid $border-color-base;
}
.border-0 {
border: 0;
}
// 溢出处理
.overflow-hidden {
overflow: hidden;
}
.overflow-auto {
overflow: auto;
}
.overflow-scroll {
overflow: scroll;
}
// 文本溢出
.text-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-ellipsis-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.text-ellipsis-3 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}
// 字体大小工具类
.font-xs {
font-size: $font-size-xs;
}
.font-sm {
font-size: $font-size-sm;
}
.font-base {
font-size: $font-size-base;
}
.font-lg {
font-size: $font-size-lg;
}
.font-xl {
font-size: $font-size-xl;
}
// 字体粗细
.font-light {
font-weight: 300;
}
.font-normal {
font-weight: 400;
}
.font-medium {
font-weight: 500;
}
.font-semibold {
font-weight: 600;
}
.font-bold {
font-weight: 700;
}
// 宽高工具类
.w-full {
width: 100%;
}
.h-full {
height: 100%;
}
.w-auto {
width: auto;
}
.h-auto {
height: auto;
}
// 最小高度
.min-h-screen {
min-height: 100vh;
}
// 清除浮动
.clearfix::after {
content: '';
display: table;
clear: both;
}
// 禁用选择
.user-select-none {
user-select: none;
}
// 指针样式
.cursor-pointer {
cursor: pointer;
}
.cursor-not-allowed {
cursor: not-allowed;
}
// 透明度
.opacity-0 {
opacity: 0;
}
.opacity-25 {
opacity: 0.25;
}
.opacity-50 {
opacity: 0.5;
}
.opacity-75 {
opacity: 0.75;
}
.opacity-100 {
opacity: 1;
}
// 过渡动画
.transition {
transition: all 0.3s ease;
}
.transition-fast {
transition: all 0.15s ease;
}
.transition-slow {
transition: all 0.5s ease;
}
// 变换
.transform {
transform: translateZ(0);
}
.scale-95 {
transform: scale(0.95);
}
.scale-100 {
transform: scale(1);
}
.scale-105 {
transform: scale(1.05);
}
// 响应式断点(小程序中主要用于不同屏幕尺寸适配)
@media screen and (max-width: 750rpx) {
.hidden-xs {
display: none;
}
}
@media screen and (min-width: 751rpx) {
.hidden-sm {
display: none;
}
}
</style>