开发目标
- 低使用门槛
- 使用门槛低,使用频率才会上升,也更便于统一维护
- 不需要额外约定,符合开发直觉
- 通用性、复用性、可维护性
- 逻辑颗粒度尽可能低,提高单个逻辑复用性
- 逻辑与逻辑间约定统一,实现逻辑组合
- 低颗粒度自然就有高可维护性
- 一定程度上提高开发成本,但对于一个高复用性功能来说,是可以接受的
- 可统一管理
- 便于使用,可根据需求把单一逻辑集合成复合逻辑进行使用并管理
实现思路
- 权限判断做的功能基本为 成功、失败、回调,几种状态与promise不谋而合,既然已经有了现成且原生的模式,直接套用即可。
- 约定统一返回对象,既然已经使用了promise,那不如直接与原有的axios请求数据格式统一,调用时与请求数据完全一致,约定新错误码以对错误进行甄别
- 单个组件逻辑单一,一个逻辑单元内只完成一件事
- 针对递进的逻辑判断,引用上层逻辑单元后再进行封装
- 符合判断逻辑只需进行组合即可
- 给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);
}
});
};