From 81407d1f7bd6c0d6cabb9fa0f84c2a7a81c75708 Mon Sep 17 00:00:00 2001 From: LiuJiaNan <15703339975@163.com> Date: Tue, 10 Mar 2026 10:13:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=B7=E6=B1=82=E5=B0=81?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 6 ++ .env.production | 6 ++ app/api/index.ts | 46 ++++++++++++++ app/composables/useRequest.ts | 116 ++++++++++++++++++++++++++++++++++ app/types/runtime.d.ts | 8 +++ eslint.config.mjs | 2 + nuxt.config.ts | 6 ++ package-lock.json | 39 ++++++------ package.json | 1 + tsconfig.node.json | 6 ++ 10 files changed, 215 insertions(+), 21 deletions(-) create mode 100644 .env create mode 100644 .env.production create mode 100644 app/api/index.ts create mode 100644 app/composables/useRequest.ts create mode 100644 app/types/runtime.d.ts create mode 100644 tsconfig.node.json diff --git a/.env b/.env new file mode 100644 index 0000000..f4c5709 --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +# 开发环境配置 +# API 基础地址 +NUXT_PUBLIC_API_BASE_URL=https://gbs-gateway.qhdsafety.com + +# API 前缀 +NUXT_PUBLIC_API_PREFIX=/api diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..381bdfc --- /dev/null +++ b/.env.production @@ -0,0 +1,6 @@ +# 生产环境配置 +# API 基础地址 +NUXT_PUBLIC_API_BASE_URL=https://your-production-domain.com + +# API 前缀 +NUXT_PUBLIC_API_PREFIX=/api diff --git a/app/api/index.ts b/app/api/index.ts new file mode 100644 index 0000000..96b4841 --- /dev/null +++ b/app/api/index.ts @@ -0,0 +1,46 @@ +/** + * API 接口示例 + * 基于 useRequest 封装的各种业务接口 + */ + +// 获取用户信息 +export const getUserInfo = () => { + return useGet("/user/info", { + showLoading: true, + successMsg: "获取用户信息成功", + }); +}; + +// 用户登录 +export const login = (data: { username: string; password: string }) => { + return usePost("/user/login", { + body: data, + showLoading: true, + successMsg: "登录成功", + }); +}; + +// 获取列表数据 +export const getList = (params?: { page?: number; pageSize?: number }) => { + return useGet("/list", { + params, + showLoading: true, + }); +}; + +// 删除数据 +export const deleteItem = (id: string) => { + return useDelete(`/list/${id}`, { + showLoading: true, + successMsg: "删除成功", + }); +}; + +// 更新数据 +export const updateItem = (id: string, data: any) => { + return usePut(`/list/${id}`, { + body: data, + showLoading: true, + successMsg: "更新成功", + }); +}; diff --git a/app/composables/useRequest.ts b/app/composables/useRequest.ts new file mode 100644 index 0000000..c1a2d52 --- /dev/null +++ b/app/composables/useRequest.ts @@ -0,0 +1,116 @@ +/** + * 请求封装 - 基于 useFetch 二次封装 + * 提供统一的请求配置、错误处理、Loading 状态等 + */ + +import type { UseFetchOptions } from "nuxt/app"; + +/** + * 请求配置选项 - 继承 Nuxt UseFetchOptions 并添加自定义选项 + */ +export type RequestOptions = UseFetchOptions & { + /** 是否显示加载状态 */ + showLoading?: boolean + /** 成功提示信息 */ + successMsg?: string + /** 错误提示信息 */ + errorMsg?: string + /** 是否手动触发 */ + manual?: boolean +} + +/** + * 封装后的请求方法 + * @param url - 请求地址 + * @param options - 请求配置 + */ +export function useRequest(url: string, options: RequestOptions = {}) { + const config = useRuntimeConfig(); + + const { + // showLoading = false, + successMsg = "", + errorMsg = "", + manual = false, + ...restOptions + } = options; + + // 计算完整 URL + const fullUrl = computed(() => config.public.apiBaseUrl + url); + + // 显示成功提示 + const showSuccessTip = (msg: string) => { + if (msg) { + console.log(`[Success] ${msg}`); + } + }; + + // 显示错误提示 + const showErrorTip = (msg: string, err?: any) => { + if (msg || errorMsg) { + const tip = msg || errorMsg || (err as Error)?.message || "请求失败"; + console.error(`[Error] ${tip}`, err); + } + }; + + // 使用 useFetch 发起请求 + const { data, error, execute, ...rest } = useFetch(fullUrl, { + ...restOptions, + // 请求完成后的回调 + onResponse({ response }: any) { + if (showSuccessTip && response.ok) { + showSuccessTip(successMsg); + } + }, + // 请求出错后的回调 + onResponseError({ error }: any) { + showErrorTip(errorMsg, error); + }, + } as any); + + // 手动执行函数 + const run = async () => { + await execute(); + return { data: data.value, error: error.value }; + }; + + // 立即执行(如果 manual 为 false) + if (!manual) { + void execute(); + } + + return { + data, + error, + execute: run, + ...rest, + }; +} + +/** + * GET 请求 + */ +export function useGet(url: string, options: RequestOptions = {}) { + return useRequest(url, { ...options, method: "get" }); +} + +/** + * POST 请求 + */ +export function usePost(url: string, options: RequestOptions = {}) { + return useRequest(url, { ...options, method: "post" }); +} + +/** + * PUT 请求 + */ +export function usePut(url: string, options: RequestOptions = {}) { + return useRequest(url, { ...options, method: "put" }); +} + +/** + * DELETE 请求 + */ +export function useDelete(url: string, options: RequestOptions = {}) { + return useRequest(url, { ...options, method: "delete" }); +} diff --git a/app/types/runtime.d.ts b/app/types/runtime.d.ts new file mode 100644 index 0000000..06951b7 --- /dev/null +++ b/app/types/runtime.d.ts @@ -0,0 +1,8 @@ +declare module "nuxt" { + interface PublicRuntimeConfig { + apiBaseUrl: string + apiPrefix: string + } +} + +export {}; diff --git a/eslint.config.mjs b/eslint.config.mjs index a5f9714..a7f737c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -67,6 +67,8 @@ export default withNuxt( "no-nested-ternary": "warn", // 禁止嵌套三元表达式 "prefer-template": "warn", // 优先使用模板字符串 "no-useless-concat": "error", // 禁止无意义的字符串拼接 + + "@typescript-eslint/no-explicit-any": "off", }, }, ); diff --git a/nuxt.config.ts b/nuxt.config.ts index 5d5482d..4c634a8 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -8,4 +8,10 @@ export default defineNuxtConfig({ title: "河北秦安安全科技股份有限公司", }, }, + runtimeConfig: { + public: { + apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL, + apiPrefix: process.env.NUXT_PUBLIC_API_PREFIX, + }, + }, }); diff --git a/package-lock.json b/package-lock.json index aab04fd..8655fdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "vue-router": "^4.6.4" }, "devDependencies": { + "@types/node": "^25.3.5", "sass": "^1.97.3" } }, @@ -88,7 +89,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -4580,7 +4580,6 @@ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.7.1.tgz", "integrity": "sha512-zjTUwIsEfT+k9BmXwq1QEFYsb4afBlsI1AXFyWQBgggMzwBFOuu92pGrE5OFx90IOjNl+lUbQoTG7f8S0PkOdg==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/types": "^8.53.1", @@ -4616,8 +4615,17 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.3.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "devOptional": true, "license": "MIT", - "peer": true + "dependencies": { + "undici-types": "~7.18.0" + } }, "node_modules/@types/parse-path": { "version": "7.1.0", @@ -4674,7 +4682,6 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", @@ -4872,7 +4879,6 @@ "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.1.2.tgz", "integrity": "sha512-w5yxH/fkkLWAFAOnMSIbvAikNHYn6pgC7zGF/BasXf+K3CO1cYIPFehYAk5jpcsbiNPMc3goyyw1prGLoyD14g==", "license": "MIT", - "peer": true, "dependencies": { "hookable": "^6.0.1", "unhead": "2.1.2" @@ -5349,7 +5355,6 @@ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.28.5", "@vue/compiler-core": "3.5.27", @@ -5657,7 +5662,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6087,7 +6091,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7122,7 +7125,6 @@ "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -7190,7 +7192,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9719,7 +9720,6 @@ "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.3.0.tgz", "integrity": "sha512-99Iw3E3L5/2QtJyV4errZ0axkX/S9IAFK0AHm0pmRHkCu37OFn8mz2P4/CYTt6B/TG3mcKbXAVaeuF2FsAc1cA==", "license": "MIT", - "peer": true, "dependencies": { "@dxup/nuxt": "^0.3.2", "@nuxt/cli": "^3.32.0", @@ -9980,7 +9980,6 @@ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.110.0.tgz", "integrity": "sha512-GijUR3K1Ln/QwMyYXRsBtOyzqGaCs9ce5pOug1UtrMg8dSiE7VuuRuIcyYD4nyJbasat3K0YljiKt/PSFPdSBA==", "license": "MIT", - "peer": true, "dependencies": { "@oxc-project/types": "^0.110.0" }, @@ -10295,7 +10294,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -11086,7 +11084,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -11244,7 +11241,6 @@ "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -12211,6 +12207,13 @@ "@types/estree": "^1.0.0" } }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "devOptional": true, + "license": "MIT" + }, "node_modules/unenv": { "version": "2.0.0-rc.24", "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", @@ -12355,7 +12358,6 @@ "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -12600,7 +12602,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -12899,7 +12900,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.27", "@vue/compiler-sfc": "3.5.27", @@ -12936,7 +12936,6 @@ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0", @@ -12960,7 +12959,6 @@ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", "license": "MIT", - "peer": true, "dependencies": { "@vue/devtools-api": "^6.6.4" }, @@ -13141,7 +13139,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index 24adc4c..fdff341 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "vue-router": "^4.6.4" }, "devDependencies": { + "@types/node": "^25.3.5", "sass": "^1.97.3" } } diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..e7716d7 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,6 @@ +{ + "extends": "./.nuxt/tsconfig.node.json", + "compilerOptions": { + "types": ["node"] + } +}