需求:须有普通任务(在其他页面完成指定操作,如点赞、转发等后提示完成)和浏览任务指定浏览秒数。
实现:因全局有多处时候封装成一个工具方法,且一次只能进行一个任务,设置一个开始任务类型,完成操作的时候判断改类型任务是否进行中,如果是则调用完成方法;浏览任务为设置当前任务待开始,进入指定浏览页面后判断当前待开始的任务是否数据当前浏览任务,是则开始倒计时,中途离开则中断倒计时,倒计时完成则自动调用完成方方达。当前任务进行中点击了别的任务开始则进行类型覆盖
js
// src/stores/taskStore.ts
import { defineStore } from 'pinia';
interface TaskConfig {
type: LifeTaskType;
duration?: number; // 倒计时持续时间(毫秒)
onCompleted?: () => void;
onInterrupted?: () => void;
}
interface RunningTask extends TaskConfig {
startTime: number;
timerId?: number;
}
interface TaskState {
runningTask: RunningTask | null; // 只允许一个任务运行
pendingTask: RunningTask | null; // 待开始的任务
}
export enum LifeTaskType {
Browse = 'browse',//浏览
Share = 'share',//分享
Comment = 'comment',//评论
Publish = 'publish',//发布
Like = 'like',//点赞
}
export const useTaskStore = defineStore('task', {
state: (): TaskState => ({
runningTask: null,
pendingTask: null // 待开始的任务
}),
getters: {
// 检查指定任务类型是否正在运行
isTaskRunning: (state) => (taskType: string): boolean => {
return state.runningTask !== null && state.runningTask.type === taskType;
},
// 获取当前运行的任务类型
getCurrentTaskType: (state) => (): string | null => {
return state.runningTask ? state.runningTask.type : null;
},
// 获取剩余时间
getRemainingTime: (state) => (): number | null => {
const task = state.runningTask;
if (!task || !task.duration) {
return null;
}
const elapsed = Date.now() - task.startTime;
return Math.max(0, task.duration * 1000 - elapsed);
},
},
actions: {
/**
* 开始一个任务,会停止之前运行的任务
*/
startTask(config: TaskConfig): boolean {
// 先停止当前运行的任务
if (this.runningTask) {
this.interruptCurrentTask(true);
}
const task: RunningTask = {
...config,
startTime: Date.now(),
};
// 对于需要倒计时的浏览任务,先放入待开始队列
if (config.duration) {
// 设置为待开始状态,等待用户确认开始后才启动倒计时
this.pendingTask = task;
return true;
}
// 非浏览任务直接开始
this.runningTask = task;
return true;
},
//启动待开始的任务(开始倒计时)
startPendingTask(): boolean {
if (!this.pendingTask) {
console.warn('No pending task to start');
return false;
}
const task = this.pendingTask;
// 创建倒计时
if (task.duration) {
const timerId = setTimeout(() => {
this.completeTask();
}, task.duration * 1000);
task.timerId = timerId as unknown as number;
}
console.log('开始任务', task.type)
// 将待开始任务转为运行中任务
this.runningTask = task;
this.pendingTask = null;
return true;
},
//获取待开始的任务
getPendingTaskType(): LifeTaskType | null {
return this.pendingTask?.type || null;
},
/**
* 完成当前任务
*/
async completeTask() {
const task = this.runningTask;
if (!task) {
console.warn('No task is currently running');
return false;
}
try {
//这里调用完成方法
uni.showToast({
title: '恭喜你,任务完成',
icon: 'success',
duration: 3000,
});
// 清理定时器
if (task.timerId) {
clearTimeout(task.timerId);
}
// 执行完成回调
task.onCompleted?.();
this.pendingTask = null;
this.runningTask = null;
} catch (error) {
console.error('Failed to complete task:', error);
}
},
/**
* 中断当前任务
*/
interruptCurrentTask(isNewTask = false): boolean {
const task = this.runningTask;
if (!task) {
console.warn('No task is currently running');
return false;
}
console.log('中断任务', task.type)
// 清理定时器
if (task.timerId) {
clearTimeout(task.timerId);
}
//如果不是浏览任务或新任务,清除待开始任务,保留浏览类型的浏览任务
if (!(task.type === LifeTaskType.Browse || isNewTask) {
task.onInterrupted?.();
this.pendingTask = null;
this.runningTask = null;
}
// 执行中断回调
return true;
},
/**
* 清除当前任务
*/
clearCurrentTask() {
const task = this.runningTask;
if (task) {
if (task.timerId) {
clearTimeout(task.timerId);
}
task.onInterrupted?.();
this.pendingTask = null;
this.runningTask = null;
}
}
}
});
这里是调用:
js
//开始浏览任务
startTask({ type: 'browse', duration: 60 })
//开始普通任务
startTask({ type: 'like' })
//判断当前页面进行中的任务,并在完成操作后调用
if (isTaskRunning('like')) {
completeTask()
}