first commit
This commit is contained in:
323
docs/开发指南.md
Normal file
323
docs/开发指南.md
Normal file
@@ -0,0 +1,323 @@
|
||||
# 项目开发指南(Vue 3 + Vite + Element Plus + Axios)
|
||||
|
||||
> 本文档面向日常开发与维护,覆盖环境准备、目录结构、编码规范、网络请求、UI 使用、构建部署与常见问题等。
|
||||
|
||||
## 一、项目概览
|
||||
|
||||
- 框架:Vue 3(Composition API)
|
||||
- 构建:Vite 5
|
||||
- 组件库:Element Plus
|
||||
- 网络:Axios(已内置实例与拦截器)
|
||||
- 运行脚本:`npm run dev | build | preview`
|
||||
|
||||
## 二、环境要求
|
||||
|
||||
- Node.js:建议 18+(可用 `node -v` 检查)
|
||||
- 包管理器:npm(内置于 Node)或 pnpm/yarn(任选其一)
|
||||
- 操作系统:Windows / macOS / Linux
|
||||
|
||||
## 三、目录结构
|
||||
|
||||
当前主要目录:
|
||||
|
||||
```
|
||||
├─ index.html # 应用入口 HTML
|
||||
├─ vite.config.js # Vite 配置
|
||||
├─ package.json # 脚本与依赖
|
||||
├─ src/
|
||||
│ ├─ main.js # 应用入口,注册 Element Plus
|
||||
│ ├─ App.vue # 示例页面(按钮 + 请求演示)
|
||||
│ └─ plugins/
|
||||
│ └─ http.js # Axios 实例与拦截器
|
||||
└─ docs/
|
||||
└─ 开发指南.md # 本文档
|
||||
```
|
||||
|
||||
推荐扩展(按需新增):
|
||||
|
||||
```
|
||||
src/
|
||||
├─ api/ # 接口定义与请求函数(封装到 http 实例上)
|
||||
├─ assets/ # 静态资源(图片、字体等)
|
||||
├─ components/ # 通用基础组件
|
||||
├─ views/ # 页面级组件
|
||||
├─ router/ # 路由(如使用 Vue Router)
|
||||
├─ store/ # 状态管理(如使用 Pinia)
|
||||
├─ styles/ # 全局样式、变量、主题定制
|
||||
└─ utils/ # 工具方法(格式化、校验、下载等)
|
||||
```
|
||||
|
||||
## 四、快速开始
|
||||
|
||||
- 安装依赖:`npm install`
|
||||
- 启动开发:`npm run dev`(默认 http://localhost:5173)
|
||||
- 构建产物:`npm run build`(输出至 `dist/`)
|
||||
- 本地预览:`npm run preview`
|
||||
|
||||
## 五、配置说明
|
||||
|
||||
### 1. 环境变量
|
||||
|
||||
建议使用 Vite 的环境文件管理不同环境:
|
||||
|
||||
- `.env.development`(开发)
|
||||
- `.env.production`(生产)
|
||||
|
||||
示例内容:
|
||||
|
||||
```
|
||||
# .env.development
|
||||
VITE_API_BASE=https://dev-api.example.com
|
||||
|
||||
# .env.production
|
||||
VITE_API_BASE=https://api.example.com
|
||||
```
|
||||
|
||||
在代码中使用:
|
||||
|
||||
```js
|
||||
const baseURL = import.meta.env.VITE_API_BASE
|
||||
```
|
||||
|
||||
### 2. Vite 配置(`vite.config.js`)
|
||||
|
||||
常用配置要点:
|
||||
- 别名:为 `src` 设置 `@` 方便导入。
|
||||
- 代理:开发阶段转发 API,避免 CORS。
|
||||
|
||||
示例(按需修改后替换到 `vite.config.js`):
|
||||
|
||||
```js
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import path from 'node:path'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
resolve: {
|
||||
alias: { '@': path.resolve(__dirname, 'src') },
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'https://dev-api.example.com',
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(/^\/api/, ''),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### 3. Axios 配置(`src/plugins/http.js`)
|
||||
|
||||
当前实现:
|
||||
- `baseURL: '/'`(建议改为 `import.meta.env.VITE_API_BASE`)
|
||||
- 超时 15s
|
||||
- 预留请求拦截器(注入 Token)与响应拦截器(统一错误处理)
|
||||
|
||||
建议修改:
|
||||
|
||||
```js
|
||||
const http = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE || '/',
|
||||
timeout: 15000,
|
||||
})
|
||||
```
|
||||
|
||||
统一错误处理示例(可在响应拦截器中加入):
|
||||
|
||||
```js
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
http.interceptors.response.use(
|
||||
(res) => res,
|
||||
(error) => {
|
||||
const msg = error?.response?.data?.message || error.message || '请求失败'
|
||||
ElMessage.error(msg)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## 六、代码与组件规范
|
||||
|
||||
- 组件目录:一个组件一个目录(可含 `index.vue` / `index.ts`)。
|
||||
- 命名规范:
|
||||
- 组件名:`PascalCase`(如 `UserCard.vue`)。
|
||||
- 变量/函数:`camelCase`。
|
||||
- 文件:`kebab-case`(工具类/样式)。
|
||||
- 组件结构:`<template>` / `<script setup>` / `<style scoped>` 顺序。
|
||||
- 导入顺序:Vue/第三方 → 别名 `@` → 相对路径。
|
||||
- 提交信息:语义化(feat/fix/docs/chore/refactor/style/test/build)。
|
||||
|
||||
## 七、UI 与交互(Element Plus)
|
||||
|
||||
- 全量引入已配置于 `src/main.js`:
|
||||
|
||||
```js
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
app.use(ElementPlus)
|
||||
```
|
||||
|
||||
- 主题定制:
|
||||
- 推荐在 `src/styles/variables.scss` 定义主题变量,按需覆盖 Element Plus 变量。
|
||||
- 也可使用暗色主题与自定义主题(参考官方文档)。
|
||||
|
||||
- 常用交互:
|
||||
- 消息:`ElMessage.success('保存成功')`
|
||||
- 弹窗:`ElMessageBox.confirm('确定操作吗?', '提示')`
|
||||
- 加载:`ElLoading.service({ text: '加载中...' })`
|
||||
|
||||
## 八、网络请求规范
|
||||
|
||||
- 统一通过 `src/plugins/http.js` 导出的 `http` 发起请求:
|
||||
|
||||
```js
|
||||
import http from '@/plugins/http'
|
||||
|
||||
export function fetchUser(id) {
|
||||
return http.get(`/users/${id}`)
|
||||
}
|
||||
|
||||
export function createUser(payload) {
|
||||
return http.post('/users', payload)
|
||||
}
|
||||
```
|
||||
|
||||
- 结果解构与错误处理:
|
||||
|
||||
```js
|
||||
try {
|
||||
const { data } = await fetchUser(1)
|
||||
// 根据后端约定判断 code / success
|
||||
} catch (e) {
|
||||
// 统一拦截器会提示,这里可按需记录或兜底
|
||||
}
|
||||
```
|
||||
|
||||
- 可选:取消请求(例如在切换路由或重复点击时):
|
||||
|
||||
```js
|
||||
const controller = new AbortController()
|
||||
http.get('/path', { signal: controller.signal })
|
||||
// 需要时取消
|
||||
controller.abort()
|
||||
```
|
||||
|
||||
## 九、常见开发食谱
|
||||
|
||||
- 新增页面:
|
||||
- 在 `src/views/` 新建页面组件,如 `UserList.vue`。
|
||||
- 如使用路由,在 `router` 中注册路由并在入口挂载。
|
||||
|
||||
- 调用接口 + 加载态示例(参考 `App.vue`):
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import http from '@/plugins/http'
|
||||
|
||||
const loading = ref(false)
|
||||
const data = ref(null)
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await http.get('/example')
|
||||
data.value = res.data
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
- 表单校验(Element Plus):
|
||||
- 使用 `el-form` + `rules` + `el-form-item`,提交前 `formRef.validate()`。
|
||||
|
||||
- 消息提示:
|
||||
- 成功:`ElMessage.success('操作成功')`
|
||||
- 失败:`ElMessage.error('操作失败')`
|
||||
|
||||
## 十、路由与状态(可选集成)
|
||||
|
||||
- 安装:
|
||||
- Vue Router:`npm i vue-router`
|
||||
- Pinia:`npm i pinia`
|
||||
|
||||
- 快速示例(Router):
|
||||
|
||||
```js
|
||||
// src/router/index.js
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: () => import('@/views/Home.vue') },
|
||||
]
|
||||
|
||||
export default createRouter({ history: createWebHistory(), routes })
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js
|
||||
import router from '@/router'
|
||||
app.use(router)
|
||||
```
|
||||
|
||||
- 快速示例(Pinia):
|
||||
|
||||
```js
|
||||
// src/store/index.js
|
||||
import { createPinia, defineStore } from 'pinia'
|
||||
export const pinia = createPinia()
|
||||
export const useCounter = defineStore('counter', {
|
||||
state: () => ({ count: 0 }),
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js
|
||||
import { pinia } from '@/store'
|
||||
app.use(pinia)
|
||||
```
|
||||
|
||||
## 十一、构建与部署
|
||||
|
||||
- 构建命令:`npm run build`,产物在 `dist/`
|
||||
- 预览构建:`npm run preview`
|
||||
- 静态资源路径:如需部署到子路径,设置 `base`(`vite.config.js`)或 `--base`。
|
||||
- Nginx 示例:
|
||||
|
||||
```
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass https://api.example.com/;
|
||||
}
|
||||
```
|
||||
|
||||
## 十二、质量保障(可选)
|
||||
|
||||
- 代码格式化:建议接入 Prettier + ESLint。
|
||||
- 提交规范:建议使用 Commitlint + Husky 规范提交信息。
|
||||
- 单元测试:可引入 Vitest 进行组件与函数测试。
|
||||
|
||||
## 十三、常见问题(FAQ)
|
||||
|
||||
- 无法请求跨域?
|
||||
- 开发环境配置 Vite 代理(见上文 server.proxy)。
|
||||
- 生产环境由网关或 Nginx 统一转发。
|
||||
|
||||
- 接口报错但页面无提示?
|
||||
- 确认是否已在响应拦截器中调用 `ElMessage.error`。
|
||||
|
||||
- Element Plus 主题不生效?
|
||||
- 确保样式覆盖顺序正确,且未被 `scoped` 限制。
|
||||
|
||||
---
|
||||
|
||||
如需我帮你接入 Router/Pinia、主题定制或代码规范工具链,请告诉我具体偏好与要求。
|
||||
21
docs/需求文档.md
Normal file
21
docs/需求文档.md
Normal file
@@ -0,0 +1,21 @@
|
||||
明白✅
|
||||
|
||||
1. 二界面 URL 模板
|
||||
我已把配置改成:**`域名/{codeNo}`**(文档已更新为 `https://你的域名/{codeNo}`,按运行环境替换域名即可)。
|
||||
|
||||
2. 关于 `http://36.138.184.60:12345/编号/二维码.png`
|
||||
这个是“**脚本端**”暴露出来的**静态图片**地址——**正常情况下会直接返回 PNG 图片**。如果你在页面里看不到图,常见原因有:
|
||||
|
||||
* **混合内容被拦截**:你的前端如果是 **HTTPS**,而这张图是 **HTTP**,浏览器会拦截(安全策略)。
|
||||
解决:给 `36.138.184.60:12345` 配 **HTTPS**,或让后端提供一个 **HTTPS 代理端点**(例如:`GET /api/link/{token}/qr.png`)去转发这张图片,前端只请求自己的 HTTPS 域名即可。(我已在文档里加了这条注意事项)
|
||||
* **二维码尚未生成 / 已过期**:脚本端还没把 `二维码.png` 写到对应 `编号/` 目录,或已被轮转清理 → 会 404 或显示旧图。
|
||||
解决:确保先触发“生成二维码”动作,并用返回的 `createdAt/expireAt` 做本地倒计时;必要时加 `?t=时间戳` 防缓存。
|
||||
* **编号不匹配**:前端用的 `编号` 与实际分配的机器编号不同。
|
||||
解决:以后端返回的 `machineId/编号` 为准。
|
||||
* **端口/防火墙**:12345 端口未对外放通或临时不可达。
|
||||
解决:主机/网关放行该端口并做健康检查。
|
||||
* **跨域非问题**:`<img>` 加载图片不受 CORS 限制,但若被混合内容拦截,同样会显示不出。
|
||||
|
||||
如果你愿意最省心的做法:我们在后端新增一个**图片代理接口**(HTTPS),前端统一拿这个接口的 URL,当脚本端换 IP/端口或做 HTTPS,这边都不用改前端。
|
||||
|
||||
需要的话我可以顺手把这个代理端点的 Spring Boot 代码骨架也给你(带缓存/超时/错误降级)。
|
||||
Reference in New Issue
Block a user