diff --git a/.cursor/rules/api-http-patterns.mdc b/.cursor/rules/api-http-patterns.mdc index 79026c3..ab2f15e 100644 --- a/.cursor/rules/api-http-patterns.mdc +++ b/.cursor/rules/api-http-patterns.mdc @@ -1,11 +1,9 @@ # API 和 HTTP 请求规范 ## HTTP 请求封装 -- 可以使用 `简单http` 或者 `alova` 或者 `@tanstack/vue-query` 进行请求管理 +- 可以使用 `简单http` 进行请求管理 - HTTP 配置在 [src/http/](mdc:src/http/) 目录下 - `简单http` - [src/http/http.ts](mdc:src/http/http.ts) -- `alova` - [src/http/alova.ts](mdc:src/http/alova.ts) -- `vue-query` - [src/http/vue-query.ts](mdc:src/http/vue-query.ts) - 请求拦截器在 [src/http/interceptor.ts](mdc:src/http/interceptor.ts) - 支持请求重试、缓存、错误处理 @@ -13,7 +11,7 @@ - API 接口定义在 [src/api/](mdc:src/api/) 目录下 - 按功能模块组织 API 文件 - 使用 TypeScript 定义请求和响应类型 -- 支持 `简单http`、`alova` 和 `vue-query` 三种请求方式 +- 支持 `简单http`请求方式 ## 示例代码结构 @@ -28,18 +26,6 @@ export interface LoginResponse { token: string userInfo: UserInfo } - -// alova 方式 -export const login = (params: LoginParams) => - http.Post('/api/login', params) - -// vue-query 方式 -export const useLogin = () => { - return useMutation({ - mutationFn: (params: LoginParams) => - http.post('/api/login', params) - }) -} ``` ## 错误处理 diff --git a/.vscode/settings.json b/.vscode/settings.json index b484267..405e410 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,7 +16,7 @@ "explorer.fileNesting.patterns": { "README.md": "index.html,favicon.ico,robots.txt,CHANGELOG.md", "docker.md": "Dockerfile,docker*.md,nginx*,.dockerignore", - "pages.config.ts": "manifest.config.ts,openapi-ts-request.config.ts", + "pages.config.ts": "manifest.config.ts", "package.json": "tsconfig.json,pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc", "eslint.config.mjs": ".commitlintrc.*,.prettier*,.editorconfig,.commitlint.cjs,.eslint*" }, diff --git a/openapi-ts-request.config.ts b/openapi-ts-request.config.ts deleted file mode 100644 index 37216cf..0000000 --- a/openapi-ts-request.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'openapi-ts-request' - -export default defineConfig([ - { - describe: 'unibest-openapi-test', - schemaPath: 'https://ukw0y1.laf.run/unibest-opapi-test.json', - serversPath: './src/service', - requestLibPath: `import request from '@/http/vue-query';\n import { CustomRequestOptions_ } from '@/http/types';`, - requestOptionsType: 'CustomRequestOptions_', - isGenReactQuery: false, - reactQueryMode: 'vue', - isGenJavaScript: false, - }, -]) diff --git a/package.json b/package.json index a4609e6..2c328d8 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,6 @@ "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei", "build:quickapp-webview-union": "uni build -p quickapp-webview-union", "type-check": "vue-tsc --noEmit", - "openapi": "openapi-ts", "init-husky": "git init && husky", "init-baseFiles": "node ./scripts/create-base-files.js", "init-json": "pnpm init-baseFiles", @@ -97,8 +96,6 @@ "lint:fix": "eslint --fix" }, "dependencies": { - "@alova/adapter-uniapp": "^2.0.14", - "@alova/shared": "^1.3.1", "@dcloudio/uni-app": "3.0.0-4070620250821001", "@dcloudio/uni-app-harmony": "3.0.0-4070620250821001", "@dcloudio/uni-app-plus": "3.0.0-4070620250821001", @@ -116,7 +113,6 @@ "@dcloudio/uni-mp-xhs": "3.0.0-4070620250821001", "@dcloudio/uni-quickapp-webview": "3.0.0-4070620250821001", "abortcontroller-polyfill": "^1.7.8", - "alova": "^3.3.3", "dayjs": "1.11.10", "pinia": "2.0.36", "pinia-plugin-persistedstate": "3.2.1", @@ -163,7 +159,6 @@ "husky": "^9.1.7", "lint-staged": "^15.2.10", "miniprogram-api-typings": "^4.1.0", - "openapi-ts-request": "^1.10.0", "postcss": "^8.4.49", "postcss-html": "^1.8.0", "postcss-scss": "^4.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad402c7..d030f08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,12 +12,6 @@ importers: .: dependencies: - '@alova/adapter-uniapp': - specifier: ^2.0.14 - version: 2.0.14(alova@3.3.4) - '@alova/shared': - specifier: ^1.3.1 - version: 1.3.1 '@dcloudio/uni-app': specifier: 3.0.0-4070620250821001 version: 3.0.0-4070620250821001(@dcloudio/types@3.4.19)(postcss@8.5.6)(rollup@4.50.0)(vue@3.4.21(typescript@5.8.3)) @@ -69,9 +63,6 @@ importers: abortcontroller-polyfill: specifier: ^1.7.8 version: 1.7.8 - alova: - specifier: ^3.3.3 - version: 3.3.4 dayjs: specifier: 1.11.10 version: 1.11.10 @@ -247,14 +238,6 @@ importers: packages: - '@alova/adapter-uniapp@2.0.14': - resolution: {integrity: sha512-AHrS/evdhONySkmtYHs6Sh1D+a0+zjBeOltcYY2/az/KEPN9p/l4H9Nvy+ghLhzMzfKfnITxeeMOi5ANyERimw==} - peerDependencies: - alova: ^3.0.20 - - '@alova/shared@1.3.1': - resolution: {integrity: sha512-ijSOaFLUFcVzMKSY3avoEE5C03/p9atjMDPBwvNkwnzaCrhv6/m4A121NdadF8YlHCRuifyYfz90IyEdMXTsJg==} - '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -2579,10 +2562,6 @@ packages: alien-signals@2.0.7: resolution: {integrity: sha512-wE7y3jmYeb0+h6mr5BOovuqhFv22O/MV9j5p0ndJsa7z1zJNPGQ4ph5pQk/kTTCWRC3xsA4SmtwmkzQO+7NCNg==} - alova@3.3.4: - resolution: {integrity: sha512-UKKqXdvf8aQ4C7m3brO77YWe5CDz8N59PdAUz7M8gowKUUXTutbk0Vk5DRBrCe0hMUyyNMUhdCZ38llGxCViyQ==} - engines: {node: '>= 18.0.0'} - ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -5302,9 +5281,6 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - rate-limiter-flexible@5.0.5: - resolution: {integrity: sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ==} - raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} @@ -6284,13 +6260,6 @@ packages: snapshots: - '@alova/adapter-uniapp@2.0.14(alova@3.3.4)': - dependencies: - '@alova/shared': 1.3.1 - alova: 3.3.4 - - '@alova/shared@1.3.1': {} - '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -9784,11 +9753,6 @@ snapshots: alien-signals@2.0.7: {} - alova@3.3.4: - dependencies: - '@alova/shared': 1.3.1 - rate-limiter-flexible: 5.0.5 - ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -12987,8 +12951,6 @@ snapshots: range-parser@1.2.1: {} - rate-limiter-flexible@5.0.5: {} - raw-body@2.5.2: dependencies: bytes: 3.1.2 diff --git a/src/api/foo-alova.ts b/src/api/foo-alova.ts deleted file mode 100644 index de35095..0000000 --- a/src/api/foo-alova.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { API_DOMAINS, http } from '@/http/alova' - -export interface IFoo { - id: number - name: string -} - -export function foo() { - return http.Get('/foo', { - params: { - name: '菲鸽', - page: 1, - pageSize: 10, - }, - meta: { domain: API_DOMAINS.SECONDARY }, // 用于切换请求地址 - }) -} diff --git a/src/api/foo.ts b/src/api/foo.ts deleted file mode 100644 index a500002..0000000 --- a/src/api/foo.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { http } from '@/http/http' - -export interface IFoo { - id: number - name: string -} - -export function foo() { - return http.Get('/foo', { - params: { - name: '菲鸽', - page: 1, - pageSize: 10, - }, - }) -} - -export interface IFooItem { - id: string - name: string -} - -/** GET 请求 */ -export async function getFooAPI(name: string) { - return await http.get('/foo', { name }) -} -/** GET 请求;支持 传递 header 的范例 */ -export function getFooAPI2(name: string) { - return http.get('/foo', { name }, { 'Content-Type-100': '100' }) -} - -/** POST 请求 */ -export function postFooAPI(name: string) { - return http.post('/foo', { name }) -} -/** POST 请求;需要传递 query 参数的范例;微信小程序经常有同时需要query参数和body参数的场景 */ -export function postFooAPI2(name: string) { - return http.post('/foo', { name }, { a: 1, b: 2 }) -} -/** POST 请求;支持 传递 header 的范例 */ -export function postFooAPI3(name: string) { - return http.post('/foo', { name }, { a: 1, b: 2 }, { 'Content-Type-100': '100' }) -} diff --git a/src/http/README.md b/src/http/README.md deleted file mode 100644 index 5bb5a4f..0000000 --- a/src/http/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# 请求库 - -目前unibest支持3种请求库: -- 菲鸽简单封装的 `简单版本http`,路径(src/http/http.ts),对应的示例在 src/api/foo.ts -- `alova 的 http`,路径(src/http/alova.ts),对应的示例在 src/api/foo-alova.ts -- `vue-query`, 路径(src/http/vue-query.ts), 目前主要用在自动生成接口,详情看(https://unibest.tech/base/17-generate),示例在 src/service/app 文件夹 - -## 如何选择 -如果您以前用过 alova 或者 vue-query,可以优先使用您熟悉的。 -如果您的项目简单,简单版本的http 就够了,也不会增加包体积。(发版的时候可以去掉alova和vue-query,如果没有超过包体积,留着也无所谓 ^_^) - -## roadmap -菲鸽最近在优化脚手架,后续可以选择是否使用第三方的请求库,以及选择什么请求库。还在开发中,大概月底出来(8月31号)。 \ No newline at end of file diff --git a/src/http/alova.ts b/src/http/alova.ts deleted file mode 100644 index b7b9ff6..0000000 --- a/src/http/alova.ts +++ /dev/null @@ -1,119 +0,0 @@ -import type { uniappRequestAdapter } from '@alova/adapter-uniapp' -import type { IResponse } from './types' -import AdapterUniapp from '@alova/adapter-uniapp' -import { createAlova } from 'alova' -import { createServerTokenAuthentication } from 'alova/client' -import VueHook from 'alova/vue' -import { toLoginPage } from '@/utils/toLoginPage' -import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum' - -// 配置动态Tag -export const API_DOMAINS = { - DEFAULT: import.meta.env.VITE_SERVER_BASEURL, - SECONDARY: import.meta.env.VITE_SERVER_BASEURL_SECONDARY, -} - -/** - * 创建请求实例 - */ -const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication< - typeof VueHook, - typeof uniappRequestAdapter ->({ - // 如果下面拦截不到,请使用 refreshTokenOnSuccess by 群友@琛 - refreshTokenOnError: { - isExpired: (error) => { - return error.response?.status === ResultEnum.Unauthorized - }, - handler: async () => { - try { - // await authLogin(); - } - catch (error) { - // 切换到登录页 - toLoginPage({ mode: 'reLaunch' }) - throw error - } - }, - }, -}) - -/** - * alova 请求实例 - */ -const alovaInstance = createAlova({ - baseURL: API_DOMAINS.DEFAULT, - ...AdapterUniapp(), - timeout: 5000, - statesHook: VueHook, - - beforeRequest: onAuthRequired((method) => { - // 设置默认 Content-Type - method.config.headers = { - ContentType: ContentTypeEnum.JSON, - Accept: 'application/json, text/plain, */*', - ...method.config.headers, - } - - const { config } = method - const ignoreAuth = !config.meta?.ignoreAuth - console.log('ignoreAuth===>', ignoreAuth) - // 处理认证信息 自行处理认证问题 - if (ignoreAuth) { - const token = 'getToken()' - if (!token) { - throw new Error('[请求错误]:未登录') - } - // method.config.headers.token = token; - } - - // 处理动态域名 - if (config.meta?.domain) { - method.baseURL = config.meta.domain - console.log('当前域名', method.baseURL) - } - }), - - responded: onResponseRefreshToken((response, method) => { - const { config } = method - const { requestType } = config - const { - statusCode, - data: rawData, - errMsg, - } = response as UniNamespace.RequestSuccessCallbackResult - - // 处理特殊请求类型(上传/下载) - if (requestType === 'upload' || requestType === 'download') { - return response - } - - // 处理 HTTP 状态码错误 - if (statusCode !== 200) { - const errorMessage = ShowMessage(statusCode) || `HTTP请求错误[${statusCode}]` - console.error('errorMessage===>', errorMessage) - uni.showToast({ - title: errorMessage, - icon: 'error', - }) - throw new Error(`${errorMessage}:${errMsg}`) - } - - // 处理业务逻辑错误 - const { code, message, data } = rawData as IResponse - // 0和200当做成功都很普遍,这里直接兼容两者,见 ResultEnum - if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) { - if (config.meta?.toast !== false) { - uni.showToast({ - title: message, - icon: 'none', - }) - } - throw new Error(`请求错误[${code}]:${message}`) - } - // 处理成功响应,返回业务数据 - return data - }), -}) - -export const http = alovaInstance diff --git a/src/http/types.ts b/src/http/types.ts index 8187822..9b3d09b 100644 --- a/src/http/types.ts +++ b/src/http/types.ts @@ -7,14 +7,6 @@ export type CustomRequestOptions = UniApp.RequestOptions & { hideErrorToast?: boolean } & IUniUploadFileOptions // 添加uni.uploadFile参数类型 -/** 主要提供给 openapi-ts-request 生成的代码使用 */ -export type CustomRequestOptions_ = Omit - -export interface HttpRequestResult { - promise: Promise - requestTask: UniApp.RequestTask -} - // 通用响应格式(兼容 msg + message 字段) export type IResponse = { code: number diff --git a/src/http/vue-query.ts b/src/http/vue-query.ts deleted file mode 100644 index 69ca80d..0000000 --- a/src/http/vue-query.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { CustomRequestOptions } from '@/http/types' -import { http } from './http' - -/* - * openapi-ts-request 工具的 request 跨客户端适配方法 - */ -export default function request( - url: string, - options: Omit & { - params?: Record - headers?: Record - }, -) { - const requestOptions = { - url, - ...options, - } - - if (options.params) { - requestOptions.query = requestOptions.params - delete requestOptions.params - } - - if (options.headers) { - requestOptions.header = options.headers - delete requestOptions.headers - } - - return http(requestOptions) -} diff --git a/src/service/index.ts b/src/service/index.ts deleted file mode 100644 index 3bfbb5b..0000000 --- a/src/service/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable */ -// @ts-ignore -export * from './types'; - -export * from './listAll'; -export * from './info'; diff --git a/src/service/info.ts b/src/service/info.ts deleted file mode 100644 index fe09da5..0000000 --- a/src/service/info.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable */ -// @ts-ignore -import request from '@/http/vue-query'; -import { CustomRequestOptions_ } from '@/http/types'; - -import * as API from './types'; - -/** 用户信息 GET /user/info */ -export function infoUsingGet({ options }: { options?: CustomRequestOptions_ }) { - return request('/user/info', { - method: 'GET', - ...(options || {}), - }); -} diff --git a/src/service/listAll.ts b/src/service/listAll.ts deleted file mode 100644 index bc1c683..0000000 --- a/src/service/listAll.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable */ -// @ts-ignore -import request from '@/http/vue-query'; -import { CustomRequestOptions_ } from '@/http/types'; - -import * as API from './types'; - -/** 用户列表 GET /user/listAll */ -export function listAllUsingGet({ - options, -}: { - options?: CustomRequestOptions_; -}) { - return request('/user/listAll', { - method: 'GET', - ...(options || {}), - }); -} diff --git a/src/service/types.ts b/src/service/types.ts deleted file mode 100644 index 4e46b61..0000000 --- a/src/service/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable */ -// @ts-ignore - -export type InfoUsingGetResponse = { - code: number; - msg: string; - data: UserItem; -}; - -export type InfoUsingGetResponses = { - 200: InfoUsingGetResponse; -}; - -export type ListAllUsingGetResponse = { - code: number; - msg: string; - data: UserItem[]; -}; - -export type ListAllUsingGetResponses = { - 200: ListAllUsingGetResponse; -}; - -export type UserItem = { - userId: number; - username: string; - nickname: string; - avatar: string; -};