From b2acb41d36f533efdf825dd17a26966f7764e2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=94=AF?= <997132391@qq.com> Date: Tue, 17 Nov 2020 10:22:55 +0800 Subject: [PATCH] =?UTF-8?q?refactor(api):=20=E9=87=8D=E6=9E=84=E7=BD=91?= =?UTF-8?q?=E7=BB=9C=E8=AF=B7=E6=B1=82=E6=A8=A1=E5=9D=97=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=20vuex=20=E6=A8=A1=E5=9D=97=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @types/index.d.ts | 116 +++++++++++++++++++- src/api/apiList.ts | 53 --------- src/api/axios.ts | 61 ++++++++--- src/api/common.ts | 17 +++ src/api/manage.ts | 130 ++++++++++++++++++++++ src/api/team.ts | 155 ++++++++++++++++++++++++++ src/api/user.ts | 162 +++++++++++++++++++++++----- src/store/modules/user/actions.ts | 25 +++++ src/store/modules/user/getters.ts | 3 + src/store/modules/user/mutations.ts | 5 + src/store/modules/user/state.ts | 29 +++++ src/store/utils.ts | 5 +- 12 files changed, 661 insertions(+), 100 deletions(-) delete mode 100644 src/api/apiList.ts create mode 100644 src/api/common.ts create mode 100644 src/api/manage.ts create mode 100644 src/api/team.ts create mode 100644 src/store/modules/user/actions.ts create mode 100644 src/store/modules/user/getters.ts create mode 100644 src/store/modules/user/mutations.ts create mode 100644 src/store/modules/user/state.ts diff --git a/@types/index.d.ts b/@types/index.d.ts index e986d69..e7b9547 100644 --- a/@types/index.d.ts +++ b/@types/index.d.ts @@ -1,8 +1,13 @@ import { AppStateType } from '@/store/modules/app/state' import { ConsoleStateType } from '@/store/modules/console/state' +import { UserStateType } from '@/store/modules/user/state' // vuex模块的类型 -type ModuleType = { app: AppStateType; console: ConsoleStateType } +type ModuleType = { + app: AppStateType + console: ConsoleStateType + user: UserStateType +} // 所有的StateType export type StateType = ModuleType @@ -30,8 +35,111 @@ export type IconType = 'icon' | 'iconfont' export type ModalOpenMode = 'edit' | 'add' | 'other' export interface BasicUserType { + id: number + name?: string + avatar?: string + role?: string + department?: string + code?: string + createTime?: string + description?: string + email?: string + lastLoginTime?: string + modifyTime?: string + modifyUser?: number + nickName?: string + phone?: string + roleId?: number + roleName?: string + status?: number + tenantId?: number + type?: string + userId?: number + username?: string +} + +export interface ListParamType { + id: number + pageSize: number + pageNum: number +} + +// 接口响应通过格式 +export interface HttpResponse { + status: number + statusText: string + data: { + code: number + desc: string + [key: string]: any + } +} + +// 接口请求列表通用参数配置 +export interface HttpListQuery { + pageNum?: number + pageSize?: number + orderNum?: number + [key: string]: any +} + +// 团队列表类型 +export interface TeamListType { + createTime?: string + description?: string + id?: number + memberNum?: number + name?: string + orderNum?: number + projectNum?: number + tenantId?: number +} + +// 批量添加团队成员列表 +export interface TeamMemberType { + id?: number + roleId?: number // 0 成员 1管理员 2 访客 + status?: number + teamId?: number + tenantId?: number + toolRole?: string + userId?: number + userTenantId?: number +} + +export enum RoleType { + '超级管理员' = 1, + '子账号', + '团队管理员', + '团队成员', + '团队访客', + '项目管理员', + '项目成员', + '项目访客' +} + +// 权限列表类型 +export interface RoleItemType { + createTime: string + id: number + roleId: number + modifyTime: string + parentId: number + remark: string + roleName: keyof RoleType + type: number + menuIds: string +} + +export interface AddTeamGroupParams { + description?: string + id?: number name: string - avatar: unknown - role: string - department: string + tenantId: number +} + +export interface AddTeamGroupMemberParams { + groupId: number + id?: number + userId: number } diff --git a/src/api/apiList.ts b/src/api/apiList.ts deleted file mode 100644 index 26000b2..0000000 --- a/src/api/apiList.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** 所有的网络请求地址列表,方便集中维护 */ -import { Method, ResponseType } from 'axios' - -interface ApiListItemType { - url: string - method: Method - resType: ResponseType -} - -/** API 模块名 */ -type ApiModuleKey = 'user' | 'article' - -/** API 模块>用户模块> 属性名 */ -type UserModuleKey = 'login' | 'register' | 'logout' - -/** API 模块>文章模块> 属性名 */ -type ArticleModuleKey = 'list' - -/** API 列表 */ -type ApiListItem = { - user: { [key in UserModuleKey]: ApiListItemType } - article: { [key in ArticleModuleKey]: ApiListItemType } -} - -/** 以对象的方式,对智能提示更好 */ -const ApiList: ApiListItem = { - user: { - login: { - url: '/login', - method: 'post', - resType: 'json' - }, - register: { - url: '/register', - method: 'post', - resType: 'json' - }, - logout: { - url: '/register', - method: 'post', - resType: 'json' - } - }, - article: { - list: { - url: '/list', - method: 'get', - resType: 'json' - } - } -} - -export default ApiList diff --git a/src/api/axios.ts b/src/api/axios.ts index baf851b..30cf4b9 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -1,4 +1,7 @@ import Axios, { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios' +import router from '@/router' +import { message } from 'ant-design-vue' +import Store from '@/store' /** * get status code @@ -57,30 +60,50 @@ const getErrorCode2text = (response: AxiosResponse): string => { */ const service = Axios.create({ baseURL: process.env.VUE_APP_BASE_URL, - timeout: 10000 + timeout: 10000, + headers: { + 'User-Type': 'bus' + } }) /** * @description 请求发起前的拦截器 * @returns {AxiosRequestConfig} config */ -service.interceptors.request.use( - async (config: AxiosRequestConfig) => { - // check network - /* TODO add http headers - const token = window.localStorage.getItem('token') - config.headers = { - ...config.headers, - Authorization: token - } */ +service.interceptors.request.use(async (config: AxiosRequestConfig) => { + // 如果是获取token接口: + if (config.url === '/auth/oauth/token') { + let userAccount = '' + // 若存在username,则为登录情况,判断user-account + if (config.params.username) { + userAccount = config.params.username.includes('-') + ? 'ACCOUNT_USER' + : 'ADMIN_USER' + } else { + // 刷新token情况,通过用户信息email是否有值判断 + userAccount = Store.state.user.userDetail.email + ? 'ADMIN_USER' + : 'ACCOUNT_USER' + } - return config + config.headers['User-Account'] = userAccount + config.headers.Authorization = 'Basic ZmViczoxMjM0NTY=' + } else { + // 如果保存有token,则取,否则不添加Authorization + if (localStorage.vuex && JSON.parse(localStorage.vuex).user?.token) { + const token = Store.state.user?.token + const tokenType = token.token_type + const accessToken = token.access_token + config.headers.Authorization = `${tokenType} ${accessToken}` + } } -) + + return config +}) /** - * @description 请求发起前的拦截器 - * @returns {} config + * @description 响应收到后的拦截器 + * @returns {} */ service.interceptors.response.use( /** 请求有响应 */ @@ -101,14 +124,20 @@ service.interceptors.response.use( } if (error.response) { - __emsg = error.response.data.msg + __emsg = error.response.data.message + ? error.response.data.message + : error.response.data.data } // timeout if (__emsg.indexOf('timeout') >= 0) { __emsg = 'timeout' } - if (error?.response?.data?.code === 401) { + if (error?.response?.status === 401) { + if (router.currentRoute.value.path !== '/entry/login') { + message.info('登录凭证已过期,请重新登录') + router.push('/entry/login') + } return Promise.reject(new Error('401')) } return Promise.reject(new Error(__emsg)) diff --git a/src/api/common.ts b/src/api/common.ts new file mode 100644 index 0000000..243b8c7 --- /dev/null +++ b/src/api/common.ts @@ -0,0 +1,17 @@ +import Axios from './axios' +import { HttpResponse } from '../../@types/index' + +/** + * @description 公共模块的的网络请求,所有通用 api 放在此处 + */ + +class CommonService { + // 添加团队 + static getRoleInfoList(): Promise { + return Axios.get('/bus/common/getRoleInfo', { + responseType: 'json' + }) + } +} + +export default CommonService diff --git a/src/api/manage.ts b/src/api/manage.ts new file mode 100644 index 0000000..c92748b --- /dev/null +++ b/src/api/manage.ts @@ -0,0 +1,130 @@ +/** + * 点击右上角头像跳转的所有管理页面接口 + */ + +import { HttpResponse } from '@types' +import Axios from './axios' + +/** + * @interface ModifyProfileParams -修改个人信息参数 + * @property {string} userId -用户id + * @property {string} nickName -昵称 + */ +interface ModifyProfileParams { + userId: number + nickName?: string +} + +/** + * @interface ChangePasswordParams -修改密码参数 + * @property {string} oldPassword -昵称 + * @property {string} newPassword -密码 + */ +interface ChangePasswordParams { + oldPassword: string + newPassword: string +} + +/** + * @interface CreateSubAccountParams -创建子账号参数 + * @property {string} username -用户名 + * @property {string} password -密码 + */ +interface CreateSubAccountParams { + username: string + password: string +} + +/** + * @interface GetSubAccountListParams -获取子账号列表参数 + * @property {number} pageNum -页码 + * @property {number} pageSize -每页数量 + */ +interface GetSubAccountListParams { + pageNum: number + pageSize: number +} + +/** + * @interface ResetSubAccountPasswordParams -重置子账号密码参数 + * @property {number} userId -用户id + * @property {string} password -新密码 + */ +interface ResetSubAccountPasswordParams { + id: number + passWord: string +} + +/** + * @interface FrezeeSubAccountParams -冻结子账号参数 + * @property {string} ids -子账号id + */ +interface FrezeeSubAccountParams { + ids: string +} + +class ManageService { + // 修改个人信息 + static modifyProfile(params: ModifyProfileParams): Promise { + return Axios('/bus/user', { + method: 'put', + responseType: 'json', + data: params + }) + } + + // 修改密码 + static changePassword(params: ChangePasswordParams): Promise { + return Axios('/bus/user/password', { + method: 'put', + responseType: 'json', + params + }) + } + + // 创建子账号 + static createSubAccount( + params: CreateSubAccountParams + ): Promise { + return Axios('/bus/subAccount', { + method: 'post', + responseType: 'json', + data: params + }) + } + + // 获取子账号列表 + static getSubAccountList( + params: GetSubAccountListParams + ): Promise { + return Axios('/bus/subAccount/list', { + method: 'get', + responseType: 'json', + params + }) + } + + // 重置子账号密码 + static resetSubAccountPassword( + params: ResetSubAccountPasswordParams + ): Promise { + return Axios('/bus/subAccount/password/reset', { + method: 'put', + responseType: 'json', + data: [params] + }) + } + + // 冻结子账号 + static frezeeSubAccount( + params: FrezeeSubAccountParams + ): Promise { + return Axios('/bus/subAccount/lock', { + method: 'put', + responseType: 'json', + params + }) + } +} + +export default ManageService diff --git a/src/api/team.ts b/src/api/team.ts new file mode 100644 index 0000000..68ffbee --- /dev/null +++ b/src/api/team.ts @@ -0,0 +1,155 @@ +import Axios from './axios' +import Store from '@/store' +import { AddTeamGroupMemberParams } from '../../@types/index' +import { StaticConfig } from '@/config/app' +import { + HttpResponse, + HttpListQuery, + TeamMemberType, + AddTeamGroupParams +} from '../../@types/index' + +/** + * @description 团队网络请求模块,所有跟团队相关的 api 放在此处 + */ + +// 新增团队类型 +interface CreateParamType { + name: string + description: string +} + +class TeamService { + // 添加团队 + static create(params: CreateParamType): Promise { + return Axios.post('/bus/team', params, { + responseType: 'json' + }) + } + + // 所有的团队信息 + static update(data: TeamMemberType): Promise { + return Axios.put('/bus/team', { + ...data + }) + } + + // 用户当前所在的团队信息 + static list(params: HttpListQuery): Promise { + return Axios.get('/bus/team/list', { + params + }) + } + + // 所有的团队信息 + static allList(params: HttpListQuery): Promise { + return Axios.get('/bus/team/listAll', { + params + }) + } + + // 所有的团队信息 + static detail(id: number): Promise { + return Axios.get(`/bus/team/${id}`) + } + + // 删除团队 + static delete(id: number): Promise { + return Axios.delete(`/bus/team/${id}`) + } + + // 获取团队成员列表 + static memberList(teamId: number): Promise { + return Axios.get(`/bus/teamMember/list/${teamId}`, { + params: { + pageSize: StaticConfig.MaxPageSize, + pageNum: 1 + } + }) + } + + // 编辑团队成员 + static updateMember(list: TeamMemberType): Promise { + return Axios(`/bus/teamMember/`, { + method: 'put', + data: list + }) + } + + // 批量添加团队成员 + static addMember(list: TeamMemberType[]): Promise { + return Axios(`/bus/teamMember/`, { + method: 'post', + data: list + }) + } + + // 批量删除团队成员 + static deleteMember(list: TeamMemberType[]): Promise { + const path = list.map(item => item.id).join(',') + console.log('deletepath', path) + return Axios(`/bus/teamMember/${path}`, { + method: 'delete', + params: { + teamId: Store.state.console.selectedTeam.id + } + }) + } + + // 添加团队分组 + static addTeamGroup(data: AddTeamGroupParams): Promise { + return Axios(`/bus/userGroup`, { + method: 'post', + data + }) + } + + // 查询团队分组列表 + static getTeamGroupList(): Promise { + return Axios(`/bus/userGroup/list`, { + method: 'get', + params: { + pageSize: StaticConfig.MaxPageSize, + pageNum: 1 + } + }) + } + + // 删除团队分组 + static deleteTeamGroup(ids: number[]): Promise { + const path = ids.join(',') + return Axios(`/bus/userGroup/${path}`, { + method: 'delete' + }) + } + + // 删除团队分组成员 + static deleteTeamGroupMember(ids: number[]): Promise { + const path = ids.join(',') + return Axios(`/bus/userGroup/userGroupMember/${path}`, { + method: 'delete' + }) + } + // 添加团队成员 + static addTeamGroupMember( + data: AddTeamGroupMemberParams[] + ): Promise { + return Axios(`/bus/userGroup/userGroupMember`, { + method: 'post', + data + }) + } + + // 获取团队分组里的成员列表 + static getTeamGroupMemberList(id: number): Promise { + return Axios(`/bus/userGroup/userGroupMember/list/${id}`, { + method: 'get', + params: { + pageSize: StaticConfig.MaxPageSize, + pageNum: 1 + } + }) + } +} + +export default TeamService diff --git a/src/api/user.ts b/src/api/user.ts index 917c5b9..2bb0a31 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,7 +1,9 @@ -import API from './axios' -import ApiList from './apiList' +/** + * 所有跟用户相关的接口 + */ -const { user } = ApiList +import { HttpResponse } from '@types' +import Axios from './axios' interface HttpParams { coinName: string @@ -10,22 +12,70 @@ interface HttpParams { /** * @interface loginParams -登录参数 - * @property {string} userName -用户名 + * @property {string} grant_type -授权类型 + * @property {string} email -邮箱 * @property {string} password -用户密码 */ interface LoginParams { - userName: string + grant_type: string + username: string password: string } /** - * @interface registerParams -登录参数 - * @property {string} confirmPassword -确认密码 - * @property {string} validateCode -验证码 + * @interface RefreshTokenParams -刷新令牌参数 + * @property {string} refresh_token -refresh_token + */ +interface RefreshTokenParams { + refresh_token: string +} + +/** + * @interface SendEmailCodeParams -发送邮件验证码参数 + * @property {string} email -邮箱 + */ +interface SendEmailCodeParams { + email: string +} + +/** + * @interface VerifyEmailCodeParams -验证邮件验证码参数 + * @property {string} email -邮箱 + * @property {string} code -验证码 + */ +interface VerifyEmailCodeParams { + email: string + code: string +} + +/** + * @interface SendPhoneCodeParams -发送手机验证码参数 + * @property {string} phone -手机号 + */ +interface SendPhoneCodeParams { + phone: string +} + +/** + * @interface BindPhoneParams -绑定手机参数 + * @property {string} phone -手机号 + * @property {string} code -手机验证码 */ -interface RegisterParams extends LoginParams { - confirmPassword: string - validateCode: string +interface BindPhoneParams { + phone: string + code: string +} + +/** + * @interface registerParams -注册参数 + * @property {string} email -邮箱 + * @property {string} password -用户密码 + * @property {string} code -验证码 + */ +interface RegisterParams { + email: string + password: string + code: string } export interface UserApi { @@ -36,28 +86,90 @@ export interface UserApi { * @example Axios.get(`https://xxx.com}`) * @todo Get the exchange rate of the current currency */ + class UserService { - static async register(params: RegisterParams): Promise { - return await API({ - method: user.register.method, - url: user.register.url, - responseType: user.register.resType, - data: { - ...params - } + // 登录 + static async login(params: LoginParams): Promise { + return Axios('/auth/oauth/token', { + method: 'post', + responseType: 'json', + params: params }) } - static async login(params: LoginParams): Promise { - return await API({ - method: user.login.method, - url: user.login.url, - responseType: user.login.resType, - data: { + // 刷新令牌 + static async refreshToken(params: RefreshTokenParams): Promise { + return Axios('/auth/oauth/token', { + method: 'post', + responseType: 'json', + params: { + // eslint-disable-next-line @typescript-eslint/camelcase + grant_type: 'refresh_token', ...params } }) } + + // 获取用户信息 + static getUserDetail(): Promise { + return Axios('/bus/user/userDetail', { + method: 'get', + responseType: 'json' + }) + } + + // 添加登录记录 + static addLoginLog(): Promise { + return Axios('/bus/user/success', { + method: 'get', + responseType: 'json' + }) + } + + // 发送邮箱验证码 + static sendEmailCode(params: SendEmailCodeParams): Promise { + return Axios('/bus/common/sendEmailCode', { + method: 'get', + responseType: 'json', + params + }) + } + + // 验证邮箱验证码 + static verifyEmailCode(params: VerifyEmailCodeParams): Promise { + return Axios('/bus/common/verifyEmailCode', { + method: 'post', + responseType: 'json', + params + }) + } + + // 发送手机验证码 + static sendPhoneCode(params: SendPhoneCodeParams): Promise { + return Axios('/bus/common/sendPhoneCode', { + method: 'get', + responseType: 'json', + params + }) + } + + // 绑定手机 + static bindPhone(params: BindPhoneParams): Promise { + return Axios('/bus/user/bindingPhone', { + method: 'post', + responseType: 'json', + params + }) + } + + // 注册 + static register(params: RegisterParams): Promise { + return Axios('/bus/user/register', { + method: 'post', + responseType: 'json', + data: params + }) + } } export default UserService diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts new file mode 100644 index 0000000..de6012e --- /dev/null +++ b/src/store/modules/user/actions.ts @@ -0,0 +1,25 @@ +import UserService from '@/api/user' +import { setStoreState } from '../../utils' +import Store from '@/store' +/** + * @description 所有跟用户相关的内容 + * @return status 返回状态 err_code:1,逻辑正确,err_code:0,发生错误。 + */ + +export default { + // 刷新令牌 + refreshToken() { + return UserService.refreshToken({ + // eslint-disable-next-line @typescript-eslint/camelcase + refresh_token: Store.state.user.token.refresh_token + }).then(res => { + setStoreState('user', 'token', res.data) + }) + }, + // 获取用户信息 + getUserDetail() { + return UserService.getUserDetail().then(res => { + setStoreState('user', 'userDetail', res.data.data) + }) + } +} diff --git a/src/store/modules/user/getters.ts b/src/store/modules/user/getters.ts new file mode 100644 index 0000000..40b8bc3 --- /dev/null +++ b/src/store/modules/user/getters.ts @@ -0,0 +1,3 @@ +export default { + // +} diff --git a/src/store/modules/user/mutations.ts b/src/store/modules/user/mutations.ts new file mode 100644 index 0000000..2675119 --- /dev/null +++ b/src/store/modules/user/mutations.ts @@ -0,0 +1,5 @@ +export default { + __set(state: any, msg: { key: string; val: any }) { + state[msg.key] = msg.val + } +} diff --git a/src/store/modules/user/state.ts b/src/store/modules/user/state.ts new file mode 100644 index 0000000..f26afe3 --- /dev/null +++ b/src/store/modules/user/state.ts @@ -0,0 +1,29 @@ +import { StateType } from '@types' +import { Module } from 'vuex' + +interface Token { + [propertys: string]: any +} + +const state = { + token: {} as Token, + userDetail: { + email: '', + userId: 0, + type: 0, + username: '', + description: '', + nickName: '', + phone: '', + tenantId: 0 + } +} +type UserStateType = typeof state + +const user: Module = { + namespaced: true, + ...state +} + +export { UserStateType, state } +export default user diff --git a/src/store/utils.ts b/src/store/utils.ts index e0091da..b09d55d 100644 --- a/src/store/utils.ts +++ b/src/store/utils.ts @@ -1,12 +1,13 @@ import store from '@/store' import { AppStateType } from './modules/app/state' import { ConsoleStateType } from './modules/console/state' +import { UserStateType } from '@/store/modules/user/state' // 定义 state 下的 module 值 -type ModuleNameType = 'app' | 'console' +type ModuleNameType = 'app' | 'console' | 'user' // 定义 module 下的 key 值 -type CommitNameType = AppStateType & ConsoleStateType +type CommitNameType = AppStateType & ConsoleStateType & UserStateType /** * @description setStoreState -方法是一个 mutaitions 的操作