用户权限公共方法方案

开发目标

  1. 低使用门槛
    1. 使用门槛低,使用频率才会上升,也更便于统一维护
    2. 不需要额外约定,符合开发直觉
  2. 通用性、复用性、可维护性
    1. 逻辑颗粒度尽可能低,提高单个逻辑复用性
    2. 逻辑与逻辑间约定统一,实现逻辑组合
    3. 低颗粒度自然就有高可维护性
    4. 一定程度上提高开发成本,但对于一个高复用性功能来说,是可以接受的
  3. 可统一管理
    1. 便于使用,可根据需求把单一逻辑集合成复合逻辑进行使用并管理

实现思路

  1. 权限判断做的功能基本为 成功、失败、回调,几种状态与promise不谋而合,既然已经有了现成且原生的模式,直接套用即可。
  2. 约定统一返回对象,既然已经使用了promise,那不如直接与原有的axios请求数据格式统一,调用时与请求数据完全一致,约定新错误码以对错误进行甄别
  3. 单个组件逻辑单一,一个逻辑单元内只完成一件事
  4. 针对递进的逻辑判断,引用上层逻辑单元后再进行封装
  5. 符合判断逻辑只需进行组合即可
  6. 给promise添加原型方法,添加统一处理错误回调的方法
import useStatusStore from 'stores/status';
import useLogin from 'uses/login';
import ROLE from 'constants/role';
import { ElMessage } from 'element-plus';
import * as statusUtils from 'utils/status';
import { $location, $windowOpen } from 'utils/window';
/**
 * @typedef {*} Code
 * @property {number} [SUCCESS=200] 正确
 * @property {number} [AUTH_ERR=401] 登录错误,跳转至登录页
 * @property {string} [ERROR='Err'] 一般错误,无特殊处理
 */
/**
 * @typedef {object} PromiseResult 权限内统一返回promise数据结构
 * @property {Code} status 数据状态
 * @property {string} msg 错误信息
 * @property {object} data 数据
 */
import { Code } from 'api';
/**
 * @function solve
 * @description promise 扩展通用处理逻辑
 * 1. 捕获catch状态
 * 2. 弹出msg定制错误信息
 * 3. 根据错误码统一处理错误回调
 */
Promise.prototype.solve = function () {
  this.catch((ex) => {
    if (ex.msg) {
      ElMessage({
        type: 'error',
        message: ex.msg
      });
    }
    if (ex.status === Code.AUTH_ERR) {
      let login = useLogin();
      login.toLogin();
    } else if (ex.status === Code.SIGNUP_ERROR || ex.status === Code.PAY_ERROR) {
      $location('/signup');
    } else if (ex.status === Code.TEAM_ERROR) {
      $location('/team');
    }
    return ex;
  });
};
/**
 * @description 获取学生status数据
 * @function
 * @mixes isStudent
 * @return {Promise<PromiseResult>}
 */
export const getStudentStatus = async () => {
  let isStudentRes = await isStudent();
  return new Promise((resolve, reject) => {
    if (isStudentRes.status === Code.SUCCESS) {
      const statusStore = useStatusStore();
      statusStore
        .getStudentStatus()
        .then((res) => {
          resolve({
            status: Code.SUCCESS,
            data: res
          });
        })
        .catch((ex) => {
          reject(ex);
        });
    } else {
      reject(isStudentRes);
    }
  });
};
/**
 * @function
 * @description 获取学生激活数据
 * @mixes getStudentStatus
 * @returns {Promise<PromiseResult>}
 */
export const getStudentActivateMark = async () => {
  let studentStatus = await getStudentStatus();
  return new Promise((resolve, reject) => {
    if (studentStatus.status === Code.SUCCESS) {
      let status = studentStatus.data;
      if (status.activate) {
        resolve({
          status: Code.SUCCESS,
          data: status.activate.status_mark
        });
      } else {
        reject({
          status: Code.SUCCESS,
          msg: '未查找到用户激活信息'
        });
      }
    } else {
      reject(studentStatus);
    }
  });
};
/**
 * @function
 * @description 获取用户套餐数据
 * @mixes getStudentStatus
 * @return {Promise<PromiseResult>}}
 */
export const getStudentApplyPackage = async () => {
  let studentStatus = await getStudentStatus();
  return new Promise((resolve, reject) => {
    if (studentStatus.status === Code.SUCCESS) {
      let status = studentStatus.data;
      if (status.apply_package_status) {
        resolve({
          status: Code.SUCCESS,
          data: status.activate.apply_package_status
        });
      } else {
        reject({
          status: Code.SUCCESS,
          msg: '未查找到用户激活信息'
        });
      }
    } else {
      reject(studentStatus);
    }
  });
};
/**
 * @function
 * @description 获取学生小队数据
 * @mixes isStudent
 * @return {Promise<PromiseResult>}
 */
export const getStudentTeamStatus = async () => {
  let isStudentRes = await isStudent();
  return new Promise((resolve, reject) => {
    if (isStudentRes.status === Code.SUCCESS) {
      const statusStore = useStatusStore();
      statusStore
        .getStudentTeamStatus()
        .then((res) => {
          resolve({
            status: Code.SUCCESS,
            data: res
          });
        })
        .catch((ex) => {
          reject(ex);
        });
    } else {
      reject(isStudentRes);
    }
  });
};
/**
 * @description 是否登录
 * @function
 * @throws {Code} status - Code.AUTH_ERR
 * @throws {string} msg - 请重新登录!
 * @returns {Promise<PromiseResult>}
 */
export const isLogin = () =>
  new Promise((resolve, reject) => {
    const login = useLogin();
    if (login.isLogin.value) {
      resolve({
        status: Code.SUCCESS
      });
    } else {
      reject({
        status: Code.AUTH_ERR,
        msg: '请重新登录!'
      });
    }
  });
/**
 * @description 是否学生账号
 * @function
 * @mixes isLogin
 * @throws {Code} status - Code.AUTH_ERR
 * @throws {string} msg - 不是学生
 * @returns {Promise<PromiseResult>}
 */
export const isStudent = async () => {
  let isLoginRes = await isLogin();
  return new Promise((resolve, reject) => {
    if (isLoginRes.status === Code.SUCCESS) {
      let login = useLogin();
      let role = login.role.value;
      if (role === ROLE.STUDENT) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.AUTH_ERR,
          msg: '不是学生'
        });
      }
    } else {
      reject(isLoginRes);
    }
  });
};
/**
 * @description 是否学校账号
 * @function
 * @mixes isLogin
 * @throws {Code} status - Code.AUTH_ERR
 * @throws {string} msg - 不是学校
 * @returns {Promise<PromiseResult>}
 */
export const isSchool = async () => {
  let isLoginRes = await isLogin();
  return new Promise((resolve, reject) => {
    if (isLoginRes.status === Code.SUCCESS) {
      let login = useLogin();
      let role = login.role.value;
      if (role === ROLE.SCHOOL) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.AUTH_ERR,
          msg: '不是学校'
        });
      }
    } else {
      reject(isLoginRes);
    }
  });
};
/**
 * @description 是否教练账号
 * @function
 * @mixes isLogin
 * @throws {Code} status - Code.AUTH_ERR
 * @throws {string} msg - 不是教练
 * @returns {Promise<PromiseResult>}
 */
export const isCoach = async () => {
  let isLoginRes = await isLogin();
  return new Promise((resolve, reject) => {
    if (isLoginRes.status === Code.SUCCESS) {
      let login = useLogin();
      let role = login.role.value;
      if (role === ROLE.COACH) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.AUTH_ERR,
          msg: '不是教练'
        });
      }
    } else {
      reject(isLoginRes);
    }
  });
};
/**
 * @description 是否社团账号
 * @function
 * @mixes isLogin
 * @throws {Code} status - Code.AUTH_ERR
 * @throws {string} msg - 不是社团
 * @returns {Promise<PromiseResult>}
 */
export const isLeague = async () => {
  let isLoginRes = await isLogin();
  return new Promise((resolve, reject) => {
    if (isLoginRes.status === Code.SUCCESS) {
      let login = useLogin();
      let role = login.role.value;
      if (role === ROLE.LEAGUE) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.AUTH_ERR,
          msg: '不是社团'
        });
      }
    } else {
      reject(isLoginRes);
    }
  });
};
/**
 * @description 是否已支付
 * @function
 * @mixes isSignup
 * @mixes getStudentStatus
 * @throws {Code} status - Code.PAY_ERROR
 * @throws {string} msg - 仅付费用户查看
 * @returns {Promise<PromiseResult>}
 */
export const isPaid = async () => {
  return new Promise((resolve, reject) => {
    Promise.all([isSignup(), getStudentStatus()])
      .then((res) => {
        let studentStatus = res[1];
        if (statusUtils.isPaid(studentStatus.data)) {
          resolve({
            status: Code.SUCCESS
          });
        } else {
          reject({
            status: Code.PAY_ERROR,
            msg: '仅付费用户查看'
          });
        }
      })
      .catch((ex) => reject(ex));
  });
};
/**
 * @function
 * @description 是否支付或免费用户
 * @mixes isFree
 * @mixes isPaid
 * @return {Promise<PromiseResult>}
 */
export const isPaidOrFree = async () => {
  return new Promise((resolve, reject) => {
    Promise.any([isFree(), isPaid()])
      .then(() => {
        resolve({
          status: Code.SUCCESS
        });
      })
      .catch((ex) => {
        const errors = ex.errors;
        reject(errors[0]);
      });
  });
};
/**
 * @description 是否已注册
 * @function
 * @mixes getStudentStatus
 * @throws {Code} status - Code.SIGNUP_ERROR
 * @throws {string} msg - 你还未报名 CTB 2022-23
 * @returns {Promise<PromiseResult>}
 */
export const isSignup = async () => {
  let studentStatus = await getStudentStatus();
  return new Promise((resolve, reject) => {
    if (studentStatus.status === Code.SUCCESS) {
      if (statusUtils.isSignup(studentStatus.data)) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.SIGNUP_ERROR,
          msg: '你还未报名 CTB 2022-23'
        });
      }
    } else {
      reject(studentStatus);
    }
  });
};
/**
 * @description 是否有小队
 * @function
 * @mixes getStudentTeamStatus
 * @mixes isPaid
 * @throws {Code} status - Code.TEAM_ERROR
 * @throws {string} msg - 组队用户方可参加
 * @returns {Promise<PromiseResult>}
 */
export const haveTeam = async () => {
  return new Promise((resolve, reject) => {
    Promise.all([getStudentTeamStatus(), isPaid()])
      .then((res) => {
        const data = res[0].data;
        if (statusUtils.haveTeam(data)) {
          resolve({
            status: Code.SUCCESS
          });
        } else {
          reject({
            status: Code.TEAM_ERROR,
            msg: '组队用户方可参加'
          });
        }
      })
      .catch((ex) => {
        reject(ex);
      });
  });
};
/**
 * @function
 * @description 用户套餐是否符合
 * @param {string} packageName - 套餐名称(free/standard/guided)
 * @param {boolean} [meet=true] - 是否当前套餐大于指定套餐等级
 * @mixes isSignup
 * @mixes getStudentStatus
 * @throws {Code} status - Code.ERROR
 * @throws {string} msg - 用户套餐不符合
 * @returns {Promise<PromiseResult>}
 */
export const isStudentPackage = async (packageName, meet = true) => {
  return new Promise((resolve, reject) => {
    Promise.all([isSignup(), getStudentStatus()])
      .then((res) => {
        const studentStatus = res[1].data;
        let result = statusUtils.isStudentPackage(studentStatus, packageName, meet);
        if (result) {
          resolve({
            status: Code.SUCCESS
          });
        } else {
          reject({
            status: Code.ERROR,
            msg: '用户套餐不符合'
          });
        }
      })
      .catch((ex) => reject(ex));
  });
};
/**
 * @function
 * @mixes isSignup
 * @mixes isStudentPackage
 * @description 是否免费用户
 * @throws {Code} status - Code.PAY_ERROR
 * @throws {Code} msg - 用户权限不足
 * @return {Promise<PromiseResult>}
 */
export const isFree = async () => {
  let isSignupRes = await isSignup();
  return new Promise((resolve, reject) => {
    if (isSignupRes.status === Code.SUCCESS) {
      isStudentPackage('free', false)
        .then(() => {
          resolve({
            status: Code.SUCCESS
          });
        })
        .catch(() =>
          reject({
            status: Code.PAY_ERROR,
            msg: '用户权限不足'
          })
        );
    } else {
      reject(isSignupRes);
    }
  });
};
/**
 * @function
 * @description 用户是否完成实名认证
 * @mixes getStudentStatus
 * @throws {Code} status - Code.ERROR
 * @throws {string} msg - 尚未完成实名认证
 * @return {Promise<PromiseResult>}
 */
export const haveFinishInformation = async () => {
  let studentStatus = await getStudentStatus();
  return new Promise((resolve, reject) => {
    if (studentStatus.status === Code.SUCCESS) {
      if (statusUtils.haveFinishInformation(studentStatus.data)) {
        resolve({
          status: Code.SUCCESS
        });
      } else {
        reject({
          status: Code.INFORMATION_ERROR,
          msg: '尚未完成实名认证'
        });
      }
    } else {
      reject(studentStatus);
    }
  });
};
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容