提交 bc370862 作者: 方治民

refactor: 重构 pont 模板、统一 Mock 与正式环境的 API 响应包装类

上级 066e3038
*.sh
node_modules
*.md
......@@ -13,3 +12,5 @@ dist
.local
/bin
Dockerfile
types/auto-imports.d.ts
......@@ -7,3 +7,5 @@
**/*.sh
/public/*
types/auto-imports.d.ts
import type { Plugin } from 'vite'
// https://github.com/antfu/unplugin-auto-import
import AutoImport from 'unplugin-auto-import/vite'
/**
* unplugin-auto-import
* @returns Plugin
*/
export function configAutoImportPlugin(): Plugin {
return AutoImport({
dts: 'types/auto-imports.d.ts',
imports: ['vue', 'vue-router', { '/@/config/app': ['$app'] }, { '/@/api/services/mods': ['API'] }],
})
}
......@@ -16,6 +16,7 @@ import { configThemePlugin } from './theme'
import { configImageminPlugin } from './imagemin'
import { configSvgIconsPlugin } from './svgSprite'
import { configOptimizePlugin } from './optimize'
import { configAutoImportPlugin } from './autoImport'
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const {
......@@ -68,15 +69,16 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// vite-plugin-optimize-persist
vitePlugins.push(configOptimizePlugin())
// vite-plugin-auto-import
vitePlugins.push(configAutoImportPlugin())
// The following plugins only work in the production environment
if (isBuild) {
// vite-plugin-imagemin
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin())
// rollup-plugin-gzip
vitePlugins.push(
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE),
)
vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE))
// vite-plugin-pwa
vitePlugins.push(configPwaConfig(viteEnv))
......
// Interface data format used to return a unified format
import dayjs from 'dayjs'
import { MockMethod } from 'vite-plugin-mock'
export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
return {
code: 0,
result,
message,
type: 'success',
}
}
export function resultPageSuccess<T = any>(page: number, pageSize: number, list: T[], { message = 'ok' } = {}) {
const pageData = pagination(page, pageSize, list)
/**
* 构建 URL 请求地址
* @param path 请求地址
* @returns 拼接 BASE_URL 后的请求地址
*/
export const URL = (path: string): string => `/basic-api${path}`
return {
...resultSuccess({
items: pageData,
total: list.length,
}),
message,
/**
* 通用响应工具类
*/
export class Response {
/**
* 成功返回
* @param data 数据
* @param param 覆盖响应内容
* @returns 通用响应结果
*/
static ok<T = any>(data: T, { message = 'OK', code = 0 } = {}): defs.Result<T> {
return {
code,
message,
status: 200,
times: '0.0s',
timestamp: dayjs().format('yyyy-MM-dd HH:mm:ss'),
body: data,
}
}
}
export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
return {
code,
result,
message,
type: 'error',
/**
* 失败返回
* @param message 失败的消息
* @param status 状态码
* @param param 覆盖响应内容
* @returns 通用响应结果
*/
static no(message = 'fail', { status = 400, code = -1, details = '' } = {}): defs.Result<string> {
return {
code,
status,
message,
details,
times: '0.0s',
timestamp: dayjs().format('yyyy-MM-dd HH:mm:ss'),
body: null,
}
}
}
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
const offset = (pageNo - 1) * Number(pageSize)
const ret =
offset + Number(pageSize) >= array.length
? array.slice(offset, array.length)
: array.slice(offset, offset + Number(pageSize))
return ret
/**
* 包装正常返回的 GET 请求 MockMethod
* @param url 请求地址
* @param data 响应数据
* @returns 经过包装的 MockMethod
*/
static getOk<T = any>(url: string, data: T): MockMethod {
return {
url: URL(url),
method: 'get',
response: () => {
return Response.ok(data)
},
}
}
}
export interface requestParams {
export class Request {
method: string
body: any
headers?: { authorization?: string }
query: any
}
/**
* @description 本函数用于从request数据中获取token,请根据项目的实际情况修改
*
*/
export function getRequestToken({ headers }: requestParams): string | undefined {
return headers?.authorization
/**
* 获取 Token 值
* @param param 请求参数
* @returns token
*/
static getRequestToken({ headers }: Request): string | undefined {
return headers?.authorization
}
}
import { MockMethod } from 'vite-plugin-mock'
import { resultSuccess, resultError } from '../_util'
import { ResultEnum } from '../../src/enums/httpEnum'
import { Response } from '../_util'
import * as HTTP from '../../src/api/types'
const userInfo = {
name: 'Vben',
name: 'Basic',
userid: '00000001',
email: 'test@gmail.com',
signature: '海纳百川,有容乃大',
......@@ -49,7 +49,7 @@ export default [
timeout: 1000,
method: 'get',
response: () => {
return resultSuccess(userInfo)
return Response.ok(userInfo)
},
},
{
......@@ -57,7 +57,7 @@ export default [
method: 'post',
statusCode: 401,
response: () => {
return resultError()
return Response.no()
},
},
{
......@@ -65,7 +65,7 @@ export default [
method: 'post',
statusCode: 200,
response: () => {
return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number })
return Response.no('Token Expired!', { status: HTTP.Status.UNAUTHORIZED })
},
},
] as MockMethod[]
import { MockMethod } from 'vite-plugin-mock'
import { resultSuccess } from '../_util'
import { Response } from '../_util'
const areaList: any[] = [
{
......@@ -317,9 +317,9 @@ export default [
response: ({ body }) => {
const { parentCode } = body || {}
if (!parentCode) {
return resultSuccess(areaList.filter((it) => it.code === '430000'))
return Response.ok(areaList.filter((it) => it.code === '430000'))
}
return resultSuccess(areaList.filter((it) => it.parentCode === parentCode))
return Response.ok(areaList.filter((it) => it.parentCode === parentCode))
},
},
] as MockMethod[]
import { MockMethod } from 'vite-plugin-mock'
import { resultSuccess } from '../_util'
import { Response } from '../_util'
const demoList = (keyword, count = 20) => {
const result = {
......@@ -22,7 +22,7 @@ export default [
response: ({ query }) => {
const { keyword, count } = query
console.log(keyword)
return resultSuccess(demoList(keyword, count))
return Response.ok(demoList(keyword, count))
},
},
] as MockMethod[]
import { MockMethod } from 'vite-plugin-mock'
import { resultError, resultPageSuccess, resultSuccess } from '../_util'
import { Response } from '../_util'
const accountList = (() => {
const result: any[] = []
......@@ -135,18 +135,22 @@ export default [
url: '/basic-api/system/getAccountList',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query
return resultPageSuccess(page, pageSize, accountList)
response: () => {
return Response.ok({
data: accountList,
total: accountList.length,
})
},
},
{
url: '/basic-api/system/getRoleListByPage',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query
return resultPageSuccess(page, pageSize, roleList)
response: () => {
return Response.ok({
data: roleList,
total: roleList.length,
})
},
},
{
......@@ -155,7 +159,7 @@ export default [
method: 'post',
response: ({ query }) => {
const { id, status } = query
return resultSuccess({ id, status })
return Response.ok({ id, status })
},
},
{
......@@ -163,7 +167,7 @@ export default [
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(roleList)
return Response.ok(roleList)
},
},
{
......@@ -171,7 +175,7 @@ export default [
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(deptList)
return Response.ok(deptList)
},
},
{
......@@ -179,7 +183,7 @@ export default [
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(menuList)
return Response.ok(menuList)
},
},
{
......@@ -189,9 +193,9 @@ export default [
response: ({ body }) => {
const { account } = body || {}
if (account && account.indexOf('admin') !== -1) {
return resultError('该字段不能包含admin')
return Response.no('该字段不能包含admin')
} else {
return resultSuccess(`${account} can use`)
return Response.ok(`${account} can use`)
}
},
},
......
import { MockMethod } from 'vite-plugin-mock'
import { Random } from 'mockjs'
import { resultPageSuccess } from '../_util'
import { Response } from '../_util'
function getRandomPics(count = 10): string[] {
const arr: string[] = []
......@@ -44,9 +44,11 @@ export default [
url: '/basic-api/table/getDemoList',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query
return resultPageSuccess(page, pageSize, demoList)
response: () => {
return Response.ok({
data: demoList,
total: demoList.length,
})
},
},
] as MockMethod[]
import { MockMethod } from 'vite-plugin-mock'
import { resultSuccess } from '../_util'
import { Response } from '../_util'
const demoTreeList = (keyword) => {
const result = {
......@@ -32,7 +32,7 @@ export default [
response: ({ query }) => {
const { keyword } = query
console.log(keyword)
return resultSuccess(demoTreeList(keyword))
return Response.ok(demoTreeList(keyword))
},
},
] as MockMethod[]
import { resultSuccess, resultError, getRequestToken, requestParams } from '../_util'
import { MockMethod } from 'vite-plugin-mock'
import { createFakeUserList } from './user'
import { Response, Request } from '../_util'
// single
const dashboardRoute = {
......@@ -228,14 +228,14 @@ export default [
url: '/basic-api/getMenuList',
timeout: 1000,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request)
response: (request: Request) => {
const token = Request.getRequestToken(request)
if (!token) {
return resultError('Invalid token!')
return Response.no('Invalid token!')
}
const checkUser = createFakeUserList().find((item) => item.token === token)
if (!checkUser) {
return resultError('Invalid user token!')
return Response.no('Invalid user token!')
}
const id = checkUser.userId
let menu: Object[]
......@@ -252,7 +252,7 @@ export default [
menu = []
}
return resultSuccess(menu)
return Response.ok(menu)
},
},
] as MockMethod[]
import { MockMethod } from 'vite-plugin-mock'
import { resultError, resultSuccess, getRequestToken, requestParams } from '../_util'
import { Response, Request } from '../_util'
export function createFakeUserList() {
return [
{
userId: '1',
username: 'vben',
realName: 'Vben Admin',
username: 'basic',
realName: 'Basic Admin',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640',
desc: 'manager',
password: '123456',
......@@ -55,10 +55,10 @@ export default [
(item) => item.username === username && password === item.password,
)
if (!checkUser) {
return resultError('Incorrect account or password!')
return Response.no('Incorrect account or password!')
}
const { userId, username: _username, token, realName, desc, roles } = checkUser
return resultSuccess({
return Response.ok({
roles,
userId,
username: _username,
......@@ -71,44 +71,44 @@ export default [
{
url: '/basic-api/getUserInfo',
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request)
if (!token) return resultError('Invalid token')
response: (request: Request) => {
const token = Request.getRequestToken(request)
if (!token) return Response.no('Invalid token')
const checkUser = createFakeUserList().find((item) => item.token === token)
if (!checkUser) {
return resultError('The corresponding user information was not obtained!')
return Response.no('The corresponding user information was not obtained!')
}
return resultSuccess(checkUser)
return Response.ok(checkUser)
},
},
{
url: '/basic-api/getPermCode',
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request)
if (!token) return resultError('Invalid token')
response: (request: Request) => {
const token = Request.getRequestToken(request)
if (!token) return Response.no('Invalid token')
const checkUser = createFakeUserList().find((item) => item.token === token)
if (!checkUser) {
return resultError('Invalid token!')
return Response.no('Invalid token!')
}
const codeList = fakeCodeList[checkUser.userId]
return resultSuccess(codeList)
return Response.ok(codeList)
},
},
{
url: '/basic-api/logout',
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request)
if (!token) return resultError('Invalid token')
response: (request: Request) => {
const token = Request.getRequestToken(request)
if (!token) return Response.no('Invalid token')
const checkUser = createFakeUserList().find((item) => item.token === token)
if (!checkUser) {
return resultError('Invalid token!')
return Response.no('Invalid token!')
}
return resultSuccess(undefined, { message: 'Token has been destroyed' })
return Response.ok(undefined, { message: 'Token has been destroyed' })
},
},
{
......@@ -116,7 +116,7 @@ export default [
statusCode: 405,
method: 'get',
response: () => {
return resultError('Error!')
return Response.no('Error!')
},
},
] as MockMethod[]
......@@ -149,6 +149,7 @@
"stylelint-order": "^5.0.0",
"ts-node": "^10.7.0",
"typescript": "^4.6.2",
"unplugin-auto-import": "^0.6.6",
"vite": "^2.9.0-beta.3",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
......
import { Interface, BaseClass, Property, CodeGenerator } from 'pont-engine'
import { Interface, BaseClass, Property, CodeGenerator, Surrounding } from 'pont-engine'
export default class MyGenerator extends CodeGenerator {
export default class BasicGenerator extends CodeGenerator {
getParams(inter: Interface) {
const requestParams = inter.getRequestParams(this.surrounding)
......@@ -52,14 +52,14 @@ export default class MyGenerator extends CodeGenerator {
*/
import * as defs from '../../baseClass';
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export ${paramsCode}
export const init = ${inter.response.getInitialValue()};
export function request(${requestParams}) {
return defHttp.request({
return Http.request({
url: "${inter.path}",
method: '${method}',
${
......@@ -73,4 +73,71 @@ export default class MyGenerator extends CodeGenerator {
}
`
}
reviseModName(modName: string) {
// .replace(/\//g, '.').replace(/^\./, '').replace(/\./g, '_') 转换 / .为下划线
// exp: /api/v1/users => api_v1_users
// exp: api.v1.users => api_v1_users
return modName.replace(/\//g, '.').replace(/^\./, '').replace(/\./g, '_')
}
/** 获取所有模块的 index 入口文件 */
getModsIndex() {
const isTypeScript = this.surrounding === Surrounding.typeScript
let conclusion = `
export const API = {
${this.dataSource.mods.map((mod) => this.reviseModName(mod.name)).join(', \n')}
};
const getWindow = ()${isTypeScript ? ': any' : ''} => (typeof window === 'undefined' ? {} : window)
getWindow().API = API
`
// dataSource name means multiple dataSource
if (this.dataSource.name) {
conclusion = `
export const ${this.dataSource.name} = {
${this.dataSource.mods.map((mod) => this.reviseModName(mod.name)).join(', \n')}
};
`
}
return `
${this.dataSource.mods
.map((mod) => {
const modName = this.reviseModName(mod.name)
return `import * as ${modName} from './${modName}';`
})
.join('\n')}
${conclusion}
`
}
/** 获取接口类和基类的总的 index 入口文件代码 */
getIndex() {
const isTypeScript = this.surrounding === Surrounding.typeScript
let conclusion = `
import * as defs from './baseClass';
import './mods/';
export { defs };
const getWindow = ()${isTypeScript ? ': any' : ''} => (typeof window === 'undefined' ? {} : window)
getWindow().defs = defs
`
// dataSource name means multiple dataSource
if (this.dataSource.name) {
conclusion = `
import { ${this.dataSource.name} as defs } from './baseClass';
export { ${this.dataSource.name} } from './mods/';
export { defs };
`
}
return conclusion
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
import * as defs from './baseClass'
import './mods/'
;(window as any).defs = defs
export { defs }
const getWindow = (): any => (typeof window === 'undefined' ? {} : window)
getWindow().defs = defs
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 账号(支持用户名/手机号/邮箱) */
......@@ -15,7 +15,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/auth/login',
method: 'POST',
......
......@@ -3,14 +3,14 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/auth/logout',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 头像 */
......@@ -27,7 +27,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/auth/register',
method: 'POST',
......
......@@ -3,14 +3,14 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/hello/fail',
method: 'GET',
......
......@@ -3,14 +3,14 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/hello/',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 当前页数 */
......@@ -19,7 +19,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/hello/page',
method: 'GET',
......
......@@ -4,7 +4,8 @@ import * as minio from './minio'
import * as permission from './permission'
import * as role from './role'
import * as user from './user'
;(window as any).API = {
export const API = {
auth,
hello,
minio,
......@@ -12,3 +13,6 @@ import * as user from './user'
role,
user,
}
const getWindow = (): any => (typeof window === 'undefined' ? {} : window)
getWindow().API = API
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
......@@ -15,7 +15,7 @@ export function request(
config?: axios.RequestConfig<Params | FormData>,
options?: axios.RequestOptions,
) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/common/minio/upload',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 组件 */
......@@ -31,7 +31,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/add',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -13,7 +13,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/deleted',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -13,7 +13,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/find',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 组件 */
......@@ -33,7 +33,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/modify',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 当前页数 */
......@@ -19,7 +19,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/page',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 父级 id */
......@@ -13,7 +13,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/permission/tree',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 名称 */
......@@ -15,7 +15,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/add',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -15,7 +15,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/assign',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -13,7 +13,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/deleted',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -13,7 +13,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/find',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -17,7 +17,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/modify',
method: 'POST',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 当前页数 */
......@@ -19,7 +19,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/page',
method: 'GET',
......
......@@ -3,14 +3,14 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/manage/role/selector',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** id */
......@@ -15,7 +15,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/user/manage/assign',
method: 'POST',
......
......@@ -3,14 +3,14 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {}
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/user/info',
method: 'GET',
......
......@@ -3,7 +3,7 @@
*/
import * as defs from '../../baseClass'
import { defHttp } from '/@/utils/http/axios'
import { Http } from '/@/utils/http/axios'
export class Params {
/** 当前页数 */
......@@ -19,7 +19,7 @@ export class Params {
export const init = new defs.Result()
export function request(params: Params, config?: axios.RequestConfig<Params>, options?: axios.RequestOptions) {
return defHttp.request(
return Http.request(
{
url: '/basic-api/user/manage/page',
method: 'GET',
......
export interface Result<T = any> {
/**
* 状态码
*/
status: Status
/**
* 消息
*/
message: string
/**
* 响应时间
*/
timestamp: string
/**
* 接口耗时(不含网络通信时间)
*/
times: string
/**
* 自定义错误码
*/
code: number
/**
* 详细信息
*/
details?: string
/**
* 异常信息
*/
error?: string
/**
* 响应内容
*/
body: T
}
export enum Status {
/**
* 成功
*/
OK = 200,
/**
* 用户认证失败
*/
NON_AUTHORITATIVE_INFORMATION = 203,
/**
* 失败的请求,通常是一些验证错误(当出现该状态码时,将产生对应的业务错误编码,可以使用 Result.details 进行交互提醒)
*/
FAIL = 400,
/**
* 鉴权失败
*/
UNAUTHORIZED = 401,
/**
* Token 错误/失效
*/
FORBIDDEN = 403,
/**
* 找不到资源
*/
NOT_FOUND = 404,
/**
* 不支持的请求类型
*/
METHOD_NOT_ALLOWED = 405,
/**
* 服务器错误
*/
INTERNAL_SERVER_ERROR = 500,
/**
* 未知错误
*/
UNKNOWN_ERROR = 500,
/**
* API 未实现
*/
NOT_IMPLEMENTED = 501,
/**
* 服务异常(网关提醒)
*/
BAD_GATEWAY = 502,
/**
* 服务暂停(网关提醒)
*/
SERVICE_UNAVAILABLE = 503,
}
export function toMessage(status: Status): string {
switch (status) {
case Status.OK:
return '成功'
case Status.FAIL:
return '失败'
case Status.UNAUTHORIZED:
return '用户认证失败'
case Status.FORBIDDEN:
return '拒绝访问'
case Status.NOT_FOUND:
return '找不到资源'
case Status.INTERNAL_SERVER_ERROR:
return '服务器错误'
case Status.NOT_IMPLEMENTED:
return '未实现'
case Status.BAD_GATEWAY:
return '网关错误'
case Status.SERVICE_UNAVAILABLE:
return '服务暂停'
default:
return '未知错误'
}
}
const config: Application = {
name: __APP__.name,
version: __APP__.version,
description: __APP__.description,
author: __APP__.author,
lastBuildTime: __APP__.lastBuildTime,
}
export const $app = config
export function setupAppConfig() {
// 打印 App 信息
const infos: string[] = []
infos.push(`==================================================================`)
infos.push(`[App] name: ${config.name}`)
infos.push(`[App] version: ${config.version}`)
infos.push(`[App] description: ${config.description}`)
infos.push(`[App] author: ${config.author.name} ${config.author.url}`)
infos.push(`[App] lastBuildTime: ${config.lastBuildTime}`)
infos.push(`==================================================================`)
console.log('%c' + infos.join('\n'), 'color: #fadfa3;')
}
......@@ -13,14 +13,18 @@ import { setupRouterGuard } from '/@/router/guard'
import { setupStore } from '/@/store'
import { setupGlobDirectives } from '/@/directives'
import { setupI18n } from '/@/locales/setupI18n'
import { setupAppConfig } from '/@/config/app'
import { registerGlobComp } from '/@/components/registerGlobComp'
// 全局注入 API
import '/@/api/services/mods'
// import '/@/api/services/mods'
async function bootstrap() {
const app = createApp(App)
// App 配置
setupAppConfig()
// Configure store
setupStore(app)
......
......@@ -3,13 +3,13 @@
import type { AxiosResponse } from 'axios'
import { clone } from 'lodash-es'
import type { RequestOptions, Result } from '/#/axios'
import type { RequestOptions } from '/#/axios'
import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'
import { VAxios } from './Axios'
import { checkStatus } from './checkStatus'
import { useGlobSetting } from '/@/hooks/setting'
import { useMessage } from '/@/hooks/web/useMessage'
import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum'
import { RequestEnum, ContentTypeEnum } from '/@/enums/httpEnum'
import { isString } from '/@/utils/is'
import { getToken } from '/@/utils/auth'
import { setObjToUrlParams, deepMerge } from '/@/utils'
......@@ -18,6 +18,7 @@ import { useI18n } from '/@/hooks/web/useI18n'
import { joinTimestamp, formatRequestDate } from './helper'
import { useUserStoreWithOut } from '/@/store/modules/user'
import { AxiosRetry } from '/@/utils/http/axios/axiosRetry'
import * as HTTP from '/@/api/types'
const globSetting = useGlobSetting()
const urlPrefix = globSetting.urlPrefix
......@@ -30,7 +31,7 @@ const transform: AxiosTransform = {
/**
* @description: 处理请求数据。如果数据不是预期格式,可直接抛出错误
*/
transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
transformRequestHook: (res: AxiosResponse<defs.Result>, options: RequestOptions) => {
const { t } = useI18n()
const { isTransformResponse, isReturnNativeResponse } = options
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
......@@ -49,27 +50,29 @@ const transform: AxiosTransform = {
// return '[HTTP] Request has no return value';
throw new Error(t('sys.api.apiRequestFailed'))
}
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
const { code, result, message } = data
// 这里 status,body,message为 后台统一的字段,需要在 types.ts 内修改为项目自己的接口返回格式
const { status, body, message, details } = data
// 这里逻辑可以根据项目进行修改
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS
const hasSuccess = data && Reflect.has(data, 'status') && status === HTTP.Status.OK
if (hasSuccess) {
return result
return body
}
// 在此处根据自己项目的实际情况对不同的code执行不同的操作
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
let timeoutMsg = ''
switch (code) {
case ResultEnum.TIMEOUT:
switch (status) {
case HTTP.Status.UNAUTHORIZED:
timeoutMsg = t('sys.api.timeoutMessage')
const userStore = useUserStoreWithOut()
userStore.setToken(undefined)
userStore.logout(true)
break
default:
if (message) {
if (details) {
timeoutMsg = details
} else if (message) {
timeoutMsg = message
}
}
......@@ -251,8 +254,20 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
),
)
}
export const defHttp = createAxios()
// 自定义配置
// TODO: 实际项目所需的请求配置
// const { apiUrl } = useGlobSetting()
const apiUrl = 'http://localhost:8181'
export const Http = createAxios({
headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
requestOptions: {
apiUrl,
},
})
// other api url
// export const otherHttp = createAxios({
// requestOptions: {
......
......@@ -119,7 +119,7 @@
const rememberMe = ref(false)
const formData = reactive({
account: 'vben',
account: 'basic',
password: '123456',
})
......
import { Result } from '../utils';
import { Result } from '../utils'
const fakeUserInfo = {
userId: '1',
username: 'vben',
realName: 'Vben Admin',
desc: 'manager',
password: '123456',
token: 'fakeToken1',
roles: [
{
roleName: 'Super Admin',
value: 'super',
},
],
};
userId: '1',
username: 'vben',
realName: 'Vben Admin',
desc: 'manager',
password: '123456',
token: 'fakeToken1',
roles: [
{
roleName: 'Super Admin',
value: 'super',
},
],
}
export default class UserService {
async login() {
return Result.success(fakeUserInfo);
}
async login() {
return Result.success(fakeUserInfo)
}
async getUserInfoById() {
return Result.success(fakeUserInfo);
}
async getUserInfoById() {
return Result.success(fakeUserInfo)
}
}
/**
* App 信息
*/
type Application = {
/**
* 项目名称
*/
name: string
/**
* 版本号
*/
version: string
/**
* 项目描述信息
*/
description: string
/**
* 作者
*/
author: Author
/**
* 最后构建时间
*/
lastBuildTime: string
}
/**
* App 作者信息
*/
type Author = {
/**
* 作者名称
*/
name: string
/**
* 地址
*/
url: string
}
declare const __APP__: Application
// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
declare global {
const $app: typeof import('/@/config/app')['$app']
const API: typeof import('/@/api/services/mods')['API']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
}
export {}
interface Window {
/**
* API 接口实例 Window 挂载
* api.d.ts
*/
API: API
/**
* API 接口类型引用 Window 挂载
* api.d.ts
*/
defs: defs
}
......@@ -87,6 +87,13 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
// Suppress warning
__INTLIFY_PROD_DEVTOOLS__: false,
__APP_INFO__: JSON.stringify(__APP_INFO__),
__APP__: {
name: pkg.name,
version: pkg.version,
description: pkg.description,
author: pkg.author,
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
},
},
css: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论