vue做任务工具方法的实现

需求:须有普通任务(在其他页面完成指定操作,如点赞、转发等后提示完成)和浏览任务指定浏览秒数。

实现:因全局有多处时候封装成一个工具方法,且一次只能进行一个任务,设置一个开始任务类型,完成操作的时候判断改类型任务是否进行中,如果是则调用完成方法;浏览任务为设置当前任务待开始,进入指定浏览页面后判断当前待开始的任务是否数据当前浏览任务,是则开始倒计时,中途离开则中断倒计时,倒计时完成则自动调用完成方方达。当前任务进行中点击了别的任务开始则进行类型覆盖

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()
   }
相关推荐
mayaairi2 小时前
Vue2 事件绑定完全指南:从入门到原理
前端·javascript·vue.js
ℋᙚᵐⁱᒻᵉ鲸落8 小时前
移动端滑动手势冲突:overflow: auto导致外层横向滑动失效
前端·javascript·css·vue.js·html
默_笙9 小时前
🎃 前端学了 Next.js,后端该学啥?NestJS 就是 Node 版的蜜雪冰城
前端·javascript
前端snow10 小时前
ai agent --- 实现 openclaw 定时间效果
前端
码云之上10 小时前
换模型之后,Chatbot 为什么要自己做 compact?
前端·agent·前端工程化
এ慕ོ冬℘゜10 小时前
navigator 导航对象 BOM制作方法
javascript
星栈11 小时前
自定义 UI-UX-Pro-Max 的 CSV 知识库,把 AI 生成的后台拉回行业该有的样子
前端·agent·weui
研☆香11 小时前
简单的图片上传 删除 预览
前端
ITresearchGuest11 小时前
我用 AI 一小时写了一个世界杯数据可视化平台|前端 VibeCoding 初体验
前端·人工智能·信息可视化
慧一居士12 小时前
Vite项目中使用Less步骤,详细使用示例
前端·css