first commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
// 状态
|
||||
const userInfo = ref(null)
|
||||
const token = ref(null)
|
||||
const isLoggedIn = ref(false)
|
||||
|
||||
// 计算属性
|
||||
const isAuthenticated = computed(() => {
|
||||
return isLoggedIn.value && token.value && userInfo.value
|
||||
})
|
||||
|
||||
// 登录
|
||||
const login = (userData, authToken) => {
|
||||
userInfo.value = userData
|
||||
token.value = authToken
|
||||
isLoggedIn.value = true
|
||||
|
||||
// 保存到本地存储
|
||||
uni.setStorageSync('userInfo', userData)
|
||||
uni.setStorageSync('token', authToken)
|
||||
uni.setStorageSync('isLoggedIn', true)
|
||||
}
|
||||
|
||||
// 登出
|
||||
const logout = () => {
|
||||
userInfo.value = null
|
||||
token.value = null
|
||||
isLoggedIn.value = false
|
||||
|
||||
// 清除本地存储
|
||||
uni.removeStorageSync('userInfo')
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('isLoggedIn')
|
||||
|
||||
console.log('用户已登出')
|
||||
}
|
||||
|
||||
// 初始化认证状态(从本地存储恢复)
|
||||
const initAuth = () => {
|
||||
try {
|
||||
const savedUserInfo = uni.getStorageSync('userInfo')
|
||||
const savedToken = uni.getStorageSync('token')
|
||||
const savedIsLoggedIn = uni.getStorageSync('isLoggedIn')
|
||||
|
||||
if (savedUserInfo && savedToken && savedIsLoggedIn) {
|
||||
userInfo.value = savedUserInfo
|
||||
token.value = savedToken
|
||||
isLoggedIn.value = savedIsLoggedIn
|
||||
console.log('从本地存储恢复用户状态')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化认证状态失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查登录状态
|
||||
const checkAuth = () => {
|
||||
return isAuthenticated.value
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
const updateUserInfo = (newUserInfo) => {
|
||||
userInfo.value = { ...userInfo.value, ...newUserInfo }
|
||||
uni.setStorageSync('userInfo', userInfo.value)
|
||||
}
|
||||
|
||||
return {
|
||||
// 状态
|
||||
userInfo,
|
||||
token,
|
||||
isLoggedIn,
|
||||
|
||||
// 计算属性
|
||||
isAuthenticated,
|
||||
|
||||
// 方法
|
||||
login,
|
||||
logout,
|
||||
initAuth,
|
||||
checkAuth,
|
||||
updateUserInfo
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,276 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
export const useTaskStore = defineStore('task', () => {
|
||||
// 状态
|
||||
const tasks = ref([])
|
||||
const currentFilter = ref('all') // all, pending, completed, overdue
|
||||
const currentSort = ref('dueDate') // dueDate, priority, created
|
||||
const searchKeyword = ref('')
|
||||
|
||||
// 计算属性
|
||||
const filteredTasks = computed(() => {
|
||||
let filtered = tasks.value
|
||||
|
||||
// 按状态过滤
|
||||
if (currentFilter.value === 'pending') {
|
||||
filtered = filtered.filter(task => !task.completed)
|
||||
} else if (currentFilter.value === 'completed') {
|
||||
filtered = filtered.filter(task => task.completed)
|
||||
} else if (currentFilter.value === 'overdue') {
|
||||
const now = new Date()
|
||||
filtered = filtered.filter(task =>
|
||||
!task.completed &&
|
||||
task.dueDate &&
|
||||
new Date(task.dueDate) < now
|
||||
)
|
||||
}
|
||||
|
||||
// 按关键词搜索
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
filtered = filtered.filter(task =>
|
||||
task.title.toLowerCase().includes(keyword) ||
|
||||
task.description.toLowerCase().includes(keyword) ||
|
||||
task.tags.some(tag => tag.toLowerCase().includes(keyword))
|
||||
)
|
||||
}
|
||||
|
||||
// 排序
|
||||
filtered.sort((a, b) => {
|
||||
switch (currentSort.value) {
|
||||
case 'priority':
|
||||
const priorityOrder = { high: 3, medium: 2, low: 1 }
|
||||
return (priorityOrder[b.priority] || 0) - (priorityOrder[a.priority] || 0)
|
||||
case 'created':
|
||||
return new Date(b.createdAt) - new Date(a.createdAt)
|
||||
case 'dueDate':
|
||||
default:
|
||||
if (!a.dueDate && !b.dueDate) return 0
|
||||
if (!a.dueDate) return 1
|
||||
if (!b.dueDate) return -1
|
||||
return new Date(a.dueDate) - new Date(b.dueDate)
|
||||
}
|
||||
})
|
||||
|
||||
return filtered
|
||||
})
|
||||
|
||||
const taskStats = computed(() => {
|
||||
const total = tasks.value.length
|
||||
const completed = tasks.value.filter(task => task.completed).length
|
||||
const pending = total - completed
|
||||
const overdue = tasks.value.filter(task =>
|
||||
!task.completed &&
|
||||
task.dueDate &&
|
||||
new Date(task.dueDate) < new Date()
|
||||
).length
|
||||
|
||||
return {
|
||||
total,
|
||||
completed,
|
||||
pending,
|
||||
overdue,
|
||||
completionRate: total > 0 ? Math.round((completed / total) * 100) : 0
|
||||
}
|
||||
})
|
||||
|
||||
// 方法
|
||||
const addTask = (taskData) => {
|
||||
const newTask = {
|
||||
id: Date.now().toString(),
|
||||
title: taskData.title,
|
||||
description: taskData.description || '',
|
||||
priority: taskData.priority || 'medium',
|
||||
dueDate: taskData.dueDate || null,
|
||||
tags: taskData.tags || [],
|
||||
completed: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
tasks.value.unshift(newTask)
|
||||
saveToStorage()
|
||||
return newTask
|
||||
}
|
||||
|
||||
const updateTask = (id, updates) => {
|
||||
const index = tasks.value.findIndex(task => task.id === id)
|
||||
if (index !== -1) {
|
||||
tasks.value[index] = {
|
||||
...tasks.value[index],
|
||||
...updates,
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
saveToStorage()
|
||||
return tasks.value[index]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const deleteTask = (id) => {
|
||||
const index = tasks.value.findIndex(task => task.id === id)
|
||||
if (index !== -1) {
|
||||
tasks.value.splice(index, 1)
|
||||
saveToStorage()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const toggleTask = (id) => {
|
||||
const task = tasks.value.find(task => task.id === id)
|
||||
if (task) {
|
||||
task.completed = !task.completed
|
||||
task.updatedAt = new Date().toISOString()
|
||||
saveToStorage()
|
||||
return task
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const setFilter = (filter) => {
|
||||
currentFilter.value = filter
|
||||
}
|
||||
|
||||
const setSort = (sort) => {
|
||||
currentSort.value = sort
|
||||
}
|
||||
|
||||
const setSearchKeyword = (keyword) => {
|
||||
searchKeyword.value = keyword
|
||||
}
|
||||
|
||||
const clearCompleted = () => {
|
||||
tasks.value = tasks.value.filter(task => !task.completed)
|
||||
saveToStorage()
|
||||
}
|
||||
|
||||
const getTaskById = (id) => {
|
||||
return tasks.value.find(task => task.id === id)
|
||||
}
|
||||
|
||||
const getTasksByTag = (tag) => {
|
||||
return tasks.value.filter(task => task.tags.includes(tag))
|
||||
}
|
||||
|
||||
const getOverdueTasks = () => {
|
||||
const now = new Date()
|
||||
return tasks.value.filter(task =>
|
||||
!task.completed &&
|
||||
task.dueDate &&
|
||||
new Date(task.dueDate) < now
|
||||
)
|
||||
}
|
||||
|
||||
const getTodayTasks = () => {
|
||||
const today = new Date().toDateString()
|
||||
return tasks.value.filter(task =>
|
||||
!task.completed &&
|
||||
task.dueDate &&
|
||||
new Date(task.dueDate).toDateString() === today
|
||||
)
|
||||
}
|
||||
|
||||
// 本地存储
|
||||
const saveToStorage = () => {
|
||||
try {
|
||||
uni.setStorageSync('tasks', JSON.stringify(tasks.value))
|
||||
} catch (error) {
|
||||
console.error('保存任务数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const loadFromStorage = () => {
|
||||
try {
|
||||
const stored = uni.getStorageSync('tasks')
|
||||
if (stored) {
|
||||
tasks.value = JSON.parse(stored)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载任务数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化示例数据
|
||||
const initSampleData = () => {
|
||||
if (tasks.value.length === 0) {
|
||||
const sampleTasks = [
|
||||
{
|
||||
id: '1',
|
||||
title: '完成项目需求分析',
|
||||
description: '分析用户需求,制定详细的功能规格说明',
|
||||
priority: 'high',
|
||||
dueDate: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tags: ['工作', '项目'],
|
||||
completed: false,
|
||||
createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
updatedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: '准备会议材料',
|
||||
description: '准备下周团队会议的PPT和资料',
|
||||
priority: 'medium',
|
||||
dueDate: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tags: ['工作', '会议'],
|
||||
completed: false,
|
||||
createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
updatedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: '购买生活用品',
|
||||
description: '去超市购买日用品和食材',
|
||||
priority: 'low',
|
||||
dueDate: null,
|
||||
tags: ['生活', '购物'],
|
||||
completed: true,
|
||||
createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
updatedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: '学习新技术',
|
||||
description: '学习Vue 3和Pinia状态管理',
|
||||
priority: 'medium',
|
||||
dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tags: ['学习', '技术'],
|
||||
completed: false,
|
||||
createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
updatedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString()
|
||||
}
|
||||
]
|
||||
tasks.value = sampleTasks
|
||||
saveToStorage()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// 状态
|
||||
tasks,
|
||||
currentFilter,
|
||||
currentSort,
|
||||
searchKeyword,
|
||||
|
||||
// 计算属性
|
||||
filteredTasks,
|
||||
taskStats,
|
||||
|
||||
// 方法
|
||||
addTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
toggleTask,
|
||||
setFilter,
|
||||
setSort,
|
||||
setSearchKeyword,
|
||||
clearCompleted,
|
||||
getTaskById,
|
||||
getTasksByTag,
|
||||
getOverdueTasks,
|
||||
getTodayTasks,
|
||||
loadFromStorage,
|
||||
initSampleData
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,205 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
// 用户基本信息
|
||||
userInfo: {
|
||||
name: '张三',
|
||||
avatar: '/static/avatar/user.png',
|
||||
department: '技术部',
|
||||
employeeId: 'EMP001',
|
||||
position: '高级工程师',
|
||||
phone: '138****8888',
|
||||
email: 'zhangsan@company.com'
|
||||
},
|
||||
|
||||
// 登录状态
|
||||
token: '',
|
||||
isLoggedIn: true,
|
||||
|
||||
// 用户权限
|
||||
permissions: [
|
||||
'attendance:view',
|
||||
'attendance:checkin',
|
||||
'leave:apply',
|
||||
'leave:view',
|
||||
'reimbursement:apply',
|
||||
'reimbursement:view',
|
||||
'task:view',
|
||||
'task:create',
|
||||
'meeting:book',
|
||||
'customer:view',
|
||||
'file:view'
|
||||
],
|
||||
|
||||
// 用户设置
|
||||
settings: {
|
||||
theme: 'light', // light, dark, auto
|
||||
messageEnabled: true,
|
||||
nightMode: false,
|
||||
language: 'zh-CN'
|
||||
},
|
||||
|
||||
// 工作数据
|
||||
workData: {
|
||||
attendanceRate: 98,
|
||||
completedTasks: 15,
|
||||
pendingTasks: 3,
|
||||
pendingApproval: 2,
|
||||
pendingAmount: 2580,
|
||||
thisMonthLeave: 2,
|
||||
thisMonthOvertime: 8
|
||||
},
|
||||
|
||||
// 最近使用功能
|
||||
recentFunctions: [
|
||||
{ icon: 'calendar', color: '#FF6B6B', label: '请假', action: 'leave' },
|
||||
{ icon: 'rmb-circle', color: '#4ECDC4', label: '报销', action: 'reimbursement' },
|
||||
{ icon: 'clock', color: '#45B7D1', label: '打卡', action: 'checkin' }
|
||||
],
|
||||
|
||||
// 快捷操作配置
|
||||
quickActions: [
|
||||
{ icon: 'calendar', color: '#FF6B6B', label: '请假', action: 'leave' },
|
||||
{ icon: 'rmb-circle', color: '#4ECDC4', label: '报销', action: 'reimbursement' },
|
||||
{ icon: 'clock', color: '#45B7D1', label: '打卡', action: 'checkin' },
|
||||
{ icon: 'calendar', color: '#96CEB4', label: '会议', action: 'meeting' },
|
||||
{ icon: 'account', color: '#FECA57', label: '客户', action: 'customer' }
|
||||
]
|
||||
}),
|
||||
|
||||
getters: {
|
||||
// 获取用户显示名称
|
||||
getUserName: (state) => state.userInfo?.name || '未登录用户',
|
||||
|
||||
// 获取用户头像
|
||||
getUserAvatar: (state) => state.userInfo?.avatar || '/static/avatar/default.png',
|
||||
|
||||
// 获取用户部门
|
||||
getUserDepartment: (state) => state.userInfo?.department || '',
|
||||
|
||||
// 检查是否有特定权限
|
||||
hasPermission: (state) => (permission) => {
|
||||
return state.permissions.includes(permission)
|
||||
},
|
||||
|
||||
// 获取工作数据概览
|
||||
getWorkOverview: (state) => ({
|
||||
attendanceRate: state.workData.attendanceRate,
|
||||
completedTasks: state.workData.completedTasks,
|
||||
pendingTasks: state.workData.pendingTasks,
|
||||
pendingApproval: state.workData.pendingApproval,
|
||||
pendingAmount: state.workData.pendingAmount
|
||||
}),
|
||||
|
||||
// 获取当前主题
|
||||
getCurrentTheme: (state) => state.settings.theme,
|
||||
|
||||
// 获取消息设置
|
||||
getMessageSettings: (state) => ({
|
||||
enabled: state.settings.messageEnabled,
|
||||
nightMode: state.settings.nightMode
|
||||
})
|
||||
},
|
||||
|
||||
actions: {
|
||||
// 设置用户信息
|
||||
setUserInfo(info) {
|
||||
this.userInfo = { ...this.userInfo, ...info }
|
||||
this.isLoggedIn = true
|
||||
},
|
||||
|
||||
// 设置token
|
||||
setToken(token) {
|
||||
this.token = token
|
||||
},
|
||||
|
||||
// 更新用户设置
|
||||
updateSettings(settings) {
|
||||
this.settings = { ...this.settings, ...settings }
|
||||
},
|
||||
|
||||
// 更新工作数据
|
||||
updateWorkData(data) {
|
||||
this.workData = { ...this.workData, ...data }
|
||||
},
|
||||
|
||||
// 添加最近使用功能
|
||||
addRecentFunction(func) {
|
||||
const existingIndex = this.recentFunctions.findIndex(item => item.action === func.action)
|
||||
if (existingIndex > -1) {
|
||||
this.recentFunctions.splice(existingIndex, 1)
|
||||
}
|
||||
this.recentFunctions.unshift(func)
|
||||
if (this.recentFunctions.length > 5) {
|
||||
this.recentFunctions.pop()
|
||||
}
|
||||
},
|
||||
|
||||
// 更新快捷操作
|
||||
updateQuickActions(actions) {
|
||||
this.quickActions = actions
|
||||
},
|
||||
|
||||
// 添加权限
|
||||
addPermission(permission) {
|
||||
if (!this.permissions.includes(permission)) {
|
||||
this.permissions.push(permission)
|
||||
}
|
||||
},
|
||||
|
||||
// 移除权限
|
||||
removePermission(permission) {
|
||||
const index = this.permissions.indexOf(permission)
|
||||
if (index > -1) {
|
||||
this.permissions.splice(index, 1)
|
||||
}
|
||||
},
|
||||
|
||||
// 登出
|
||||
logout() {
|
||||
this.userInfo = {
|
||||
name: '',
|
||||
avatar: '',
|
||||
department: '',
|
||||
employeeId: '',
|
||||
position: '',
|
||||
phone: '',
|
||||
email: ''
|
||||
}
|
||||
this.token = ''
|
||||
this.isLoggedIn = false
|
||||
this.permissions = []
|
||||
this.workData = {
|
||||
attendanceRate: 0,
|
||||
completedTasks: 0,
|
||||
pendingTasks: 0,
|
||||
pendingApproval: 0,
|
||||
pendingAmount: 0,
|
||||
thisMonthLeave: 0,
|
||||
thisMonthOvertime: 0
|
||||
}
|
||||
this.recentFunctions = []
|
||||
this.quickActions = []
|
||||
},
|
||||
|
||||
// 重置设置
|
||||
resetSettings() {
|
||||
this.settings = {
|
||||
theme: 'light',
|
||||
messageEnabled: true,
|
||||
nightMode: false,
|
||||
language: 'zh-CN'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
persist: {
|
||||
key: 'user-store',
|
||||
storage: {
|
||||
getItem: (key) => uni.getStorageSync(key),
|
||||
setItem: (key, value) => uni.setStorageSync(key, value),
|
||||
removeItem: (key) => uni.removeStorageSync(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user