diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..3481496 --- /dev/null +++ b/.env.development @@ -0,0 +1,11 @@ +# 开发环境配置 +VITE_APP_ENV = 'development' + +# API 基础 URL +VITE_API_BASE_URL = 'https://onefeel.brother7.cn/ingress' + +# API 请求超时时间(毫秒) +VITE_API_TIMEOUT_MS = 10000 + +# Socket 基础 URL +VITE_SOCKET_BASE_URL = "wss://onefeel.brother7.cn/ingress/agent/ws/chat" \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f7bf5c8 --- /dev/null +++ b/.env.production @@ -0,0 +1,11 @@ +# 生产环境配置 +VITE_APP_ENV = 'production' + +# API 基础 URL +VITE_API_BASE_URL = 'https://biz.nianxx.cn' + +# API 请求超时时间(毫秒) +VITE_API_TIMEOUT_MS = 10000 + +# Socket 基础 URL +VITE_SOCKET_BASE_URL = "wss://biz.nianxx.cn/ingress/agent/ws/chat" \ No newline at end of file diff --git a/.env.staging b/.env.staging new file mode 100644 index 0000000..ca02cc6 --- /dev/null +++ b/.env.staging @@ -0,0 +1,11 @@ +# 生产环境配置 +VITE_APP_ENV = 'staging' + +# API 基础 URL +VITE_API_BASE_URL = 'https://onefeel.brother7.cn/ingress' + +# API 请求超时时间(毫秒) +VITE_API_TIMEOUT_MS = 10000 + +# Socket 基础 URL +VITE_SOCKET_BASE_URL = "wss://onefeel.brother7.cn/ingress/agent/ws/chat" \ No newline at end of file diff --git a/.trae/documents/统一请求库封装计划.md b/.trae/documents/统一请求库封装计划.md new file mode 100644 index 0000000..3b34fd5 --- /dev/null +++ b/.trae/documents/统一请求库封装计划.md @@ -0,0 +1,205 @@ +# 统一请求库封装计划(src/utils/request.ts 版) + +## Summary + +目标:把统一请求库集中封装在 `src/utils/request.ts`,类型集中在 `src/shared/`,实现: + +- baseURL/timeout/取消请求(Axios Web) +- 默认 header 注入:Authorization(Bearer)、clientId、X-Latitude、X-Longitude、language +- 业务错误/网络错误/HTTP 错误的统一归一化(只抛错,不做 Toast/跳转) +- 输出说明文档到 `docs/request.md` + +## Current State Analysis(以实际仓库为准) + +已确认的事实: + +- 依赖中已包含 `axios`,但 `src/` 内暂无 axios 的实际封装与使用。 +- `src/utils/request.ts` 存在但为空文件,且命名疑似历史遗留。 +- 代码中存在大量“缺失模块引用”(详见文末“历史遗留问题清单”),其中 `@/request/api/*` 属于最集中、最影响后续迁移的一类。 + +结论: + +- 本次统一请求库规划要做到“新增即可用、可渐进替换”,不依赖现有(缺失的)API 模块结构。 + +## Assumptions & Decisions(你已确认) + +- 底层实现:Axios(Web) +- baseURL:从 `import.meta.env` 的环境变量读取(本计划固定变量名为 `VITE_API_BASE_URL`) +- header 值来源:全局上下文注入(内存态),由登录/定位/语言切换时写入 +- Authorization:`Bearer `(token 为空则不带 Authorization) +- 错误处理:请求库只做错误标准化并抛错,不做 Toast/跳转 +- header 字段:`Authorization`、`clientId`、`X-Latitude`、`X-Longitude`、`language` + +## 为什么不拆得更细(回答你的问题) + +可以都放在 `src/utils/request.ts` 里完成,且更适合你现在“先落地一个可用的统一入口”的诉求: + +- 单文件落地成本低:少目录、少入口、少导出点,替换/回滚都更直接 +- 不牺牲可维护性:在单文件里用“内部分区函数 + 类型从 shared 引入”的方式,同样能保持边界清晰 +- 何时再拆分:当出现“单文件 > 300~500 行、多人同时改动频繁、需要独立单测/Mock”的情况,再把 errors/context/http 拆出去更合理 + +因此本计划采用:**实现集中在 request.ts,类型抽到 shared** 的折中方案。 + +## Proposed Changes(全新规划) + +### 1) 新增类型目录:`src/shared/` + +新增目录:`src/shared/` + +新增文件(建议): + +- `src/shared/request-types.ts` + +包含的类型定义(稳定、可复用): + +- `export interface ApiResponse { code: number; message?: string; data: T }` +- `export interface RequestOptions { signal?: AbortSignal; headers?: Record; skipAuth?: boolean }` +- `export type RequestContext = { token: string | null; clientId: string | null; latitude: number | null; longitude: number | null; language: string | null }` +- `export type NormalizedErrorKind = "business" | "http" | "network" | "unknown"` +- `export interface NormalizedError extends Error { kind: NormalizedErrorKind; code?: number; httpStatus?: number; response?: unknown }` + +### 2) 统一请求实现:`src/utils/request.ts` + +新增文件:`src/utils/request.ts` + +职责(全部在一个文件内完成): + +#### 2.1 上下文容器(内存态) + +提供以下导出函数(由业务在合适时机调用): + +- `setAuthToken(token: string | null): void` +- `setClientId(clientId: string | null): void` +- `setLocation(latitude: number | null, longitude: number | null): void` +- `setLanguage(language: string | null): void` +- `getRequestContext(): RequestContext` + +默认值策略: + +- `language`:如果未显式设置,尝试读取 `src/i18n/index.ts` 的 `getCurrentLocale()`(读取失败则不注入 language header) + +#### 2.2 Axios 实例创建与默认配置 + +- `baseURL`:`import.meta.env.VITE_API_BASE_URL` + - 若缺失:直接抛出清晰错误(提示需要配置 baseURL) +- `timeout`:可选 `import.meta.env.VITE_API_TIMEOUT_MS`,缺失则默认 15000 + +#### 2.3 请求拦截器(header 注入) + +组装 headers 规则: + +- 合并顺序:`默认headers < 上下文headers < 调用方options.headers` +- `Authorization`:仅当 token 存在时注入 `Bearer `;当 `options.skipAuth === true` 时跳过 +- `clientId`:存在则注入 +- `X-Latitude` / `X-Longitude`:存在则注入(数值转字符串) +- `language`:存在则注入 + +#### 2.4 响应处理(业务码 + 错误归一化) + +1. 正常响应: + - 若响应体符合 `ApiResponse` 且 `code === 0`:返回整个 `ApiResponse` + - 若响应体符合 `ApiResponse` 且 `code !== 0`:抛出 `NormalizedError(kind="business", code, message, response)` +2. 异常响应(axios error): + - 有 `response.status`:抛 `NormalizedError(kind="http", httpStatus, response)` + - 无 `response`:抛 `NormalizedError(kind="network")` + +对外导出(建议最小集合): + +- `export async function request(config, options?: RequestOptions): Promise>` +- 可选:`export async function requestData(...): Promise`(内部调用 request 并返回 `data`,用于未来更干净的调用风格) + +### 3) 文档输出到 `docs/` + +新增目录:`docs/` + +新增文档:`docs/request.md`(必须包含): + +- 环境变量约定:`VITE_API_BASE_URL`、`VITE_API_TIMEOUT_MS`(可选) +- 上下文写入时机: + - 登录成功:`setAuthToken(token)` + - 应用初始化:`setClientId(clientId)` + - 定位成功:`setLocation(lat, lng)` + - 语言切换:`setLanguage(locale)`(或依赖默认读取 i18n) +- 使用方式: + - 旧代码风格兼容:`const res = await request(); res.data...` + - 新代码推荐:`const data = await requestData()` +- 错误处理示例:区分 business/http/network/unknown 并给出上层建议策略 + +## 历史遗留问题清单(独立梳理,方便逐个替换) + +说明:以下均为“当前仓库扫描可证实”的问题点,按模块引用位置列出,便于你后续按优先级逐个替换/补齐。 + +### A. `@/request/api/*` 悬空引用(13 个文件) + +- `src/pages/quick/index.vue` +- `src/components/Feedback/index.vue` +- `src/components/CreateServiceOrder/index.vue` +- `src/pages/service/order/components/OrderCard/index.vue` +- `src/pages/booking/components/FooterSection/index.vue` +- `src/pages/goods/index.vue` +- `src/pages/order/order/components/FooterSection/index.vue` +- `src/pages/quick/components/Tabs/index.vue` +- `src/pages/order/order/list.vue` +- `src/pages/service/order/index.vue` +- `src/pages/booking/index.vue` +- `src/pages/login/index.vue` +- `src/pages/order/order/detail.vue` + +建议后续替换策略: + +1. 先确定“这些 API 模块的真实来源”(是否在其它分支/其它仓库/尚未迁入)。 +2. 如果确认不会迁回,则逐文件把 `@/request/api/*` 替换为基于 `src/utils/request.ts` 的真实调用(需要你提供具体 URL/参数约定)。 + +### B. `@/utils` 目录级导入缺失(6 个文件) + +当前仓库没有 `src/utils/index.*`,但以下文件在导入 `@/utils`: + +- `src/pages/quick/index.vue` +- `src/pages/booking/components/FooterSection/index.vue` +- `src/pages/goods/index.vue` +- `src/pages/order/order/components/FooterSection/index.vue` +- `src/pages/booking/index.vue` +- `src/pages/home/index.vue` + +### C. `@/store` 与实际目录 `src/stores/` 命名不一致(6 个文件) + +- `src/components/ImageSwiper/index.vue` +- `src/pages/quick/components/Card/index.vue` +- `src/pages/goods/album/index.vue` +- `src/pages/goods/index.vue` +- `src/pages/booking/index.vue` +- `src/pages/home/index.vue` + +### D. `@/hooks/*` 缺失(3 个文件) + +- `src/components/SwipeCards/index.vue` +- `src/pages/login/index.vue` +- `src/pages/home/index.vue` + +### E. `@/constant/*` 缺失(6 个文件) + +- `src/components/ModuleTitle/index.vue` +- `src/components/Feedback/index.vue` +- `src/components/SurveyQuestionnaire/index.vue` +- `src/components/CreateServiceOrder/index.vue` +- `src/pages/booking/index.vue` +- `src/pages/login/index.vue` + +### F. `src/utils/request.ts`(空文件 + 疑似拼写问题) + +- 该文件当前为空,且命名疑似应为 `requests` 或 `request` +- 建议后续统一策略:保留/替换/删除前先全仓搜索确认是否在其它分支被引用 + +## Verification(执行阶段你手动确认运行) + +你在实现完成后手动执行: + +- `yarn typecheck` +- `yarn build` +- 如有用例:`yarn test` + +验收标准: + +- `src/utils/request.ts` + `src/shared/request-types.ts` 编译通过 +- 发起请求时能注入 headers(Authorization/clientId/X-Latitude/X-Longitude/language) +- `code !== 0` 时抛出稳定结构的错误对象(上层可根据 kind 做统一处理) diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3091955 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,77 @@ +# 项目协作指南 + +本仓库是一个基于 Vite 的 H5 Web 项目。本文档用于约束自动化 Agent 在仓库内的工作方式、目录约定与验证流程。 + +## 技术栈与入口 + +- 构建:Vite 5(ESM,`package.json` 中 `"type": "module"`) +- 框架:Vue 3 + TypeScript +- 路由:vue-router 4(入口为 `src/router/index.ts`,当前路由配置较少/可能未完成) +- 状态管理:Pinia(`src/stores/`) +- UI:Vant 4 +- 样式:Tailwind CSS v4(通过 `@tailwindcss/vite`),并存在组件级 SCSS +- 国际化:vue-i18n(`src/i18n/`,含 Vant 语言同步) +- 网络/事件:axios、mitt + +入口文件: + +- 应用入口:`src/main.ts` +- 根组件:`src/App.vue`(``) +- 全局样式/主题:`src/styles/main.css` + +## 目录结构与新增代码放置 + +- 页面:`src/pages//...` +- 公共组件:`src/components//...` +- 国际化:`src/i18n/` + - 语言包按模块拆分:`src/i18n/modules/{common,home,quick}/` +- 工具/请求:`src/utils/`(当前存在 `requets.ts`,文件名可能为历史拼写;不要在未确认引用关系前擅自更名) + +组件目录常见形态(尽量遵循): + +- `src/components/Foo/index.vue` +- `src/components/Foo/styles/index.scss` +- 可选:`README.md`、`demo.vue`、`prompt.md`、`images/` + +## 代码风格约定 + +- Vue 组件优先使用 ` diff --git a/src/pages/bridge/UploadImage.vue b/src/pages/bridge/UploadImage.vue deleted file mode 100644 index 08ae2c4..0000000 --- a/src/pages/bridge/UploadImage.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/pages/order/order/README.md b/src/pages/order/order/README.md deleted file mode 100644 index d8c4a6c..0000000 --- a/src/pages/order/order/README.md +++ /dev/null @@ -1,288 +0,0 @@ -# 工单管理系统 - -## 项目概述 - -这是一个基于 uniapp + Vue3 组合式 API 开发的微信小程序工单管理系统,提供完整的工单展示、管理和操作功能。 - -## 系统架构 - -### 页面结构 - -``` -pages/order/ -├── list.vue # 工单列表主页面 -├── detail.vue # 工单详情页面 -├── demo.vue # 功能演示页面 -├── components/ # 组件目录 -│ ├── TopNavBar/ # 顶部导航栏组件 -│ ├── Tabs/ # Tab切换组件 -│ ├── OrderCard/ # 工单卡片组件 -│ ├── OrderList/ # 工单列表组件 -│ └── ConsultationBar/ # 底部咨询栏组件 -├── styles/ # 样式文件 -└── images/ # 图片资源 -``` - -## 核心组件 - -### 1. TopNavBar - 顶部导航栏组件 - -**功能特性:** -- 左侧返回按钮 -- 自适应状态栏高度 -- 支持自定义标题内容 -- 响应式设计 - -**使用示例:** -```vue - - - -``` - -### 2. Tabs - Tab切换组件 - -**功能特性:** -- 多标签页切换 -- 动态下划线指示器 -- 平滑动画过渡 -- 自定义标签内容 -- 固定15px宽度,2px圆角下划线 - -**使用示例:** -```vue - -``` - -### 3. OrderCard - 工单卡片组件 - -**功能特性:** -- 工单信息展示 -- 多种状态支持(待处理、处理中、已完成、已取消) -- 状态图标和标签 -- 操作按钮(呼叫、完成) -- 自定义操作区域 -- 响应式设计 - -**使用示例:** -```vue - -``` - -### 4. OrderList - 工单列表组件 - -**功能特性:** -- 工单列表展示 -- 下拉刷新 -- 上拉加载更多 -- 空状态显示 -- 加载状态管理 -- 蓝色渐变背景 - -**使用示例:** -```vue - -``` - -### 5. ConsultationBar - 底部咨询栏组件 - -**功能特性:** -- 客服咨询入口 -- 固定底部显示 -- 安全区域适配 -- 自定义咨询文案 -- 跳转链接支持 - -**使用示例:** -```vue - -``` - -## 数据结构 - -### 工单数据结构 - -```javascript -{ - id: String, // 工单ID - title: String, // 工单标题 - createTime: String, // 创建时间 - contactName: String, // 联系人姓名 - contactPhone: String, // 联系电话 - status: String, // 工单状态:pending/processing/completed/cancelled - type: String // 工单类型:service/order -} -``` - -### Tab数据结构 - -```javascript -{ - label: String, // 显示文本 - value: String // 值 -} -``` - -## 功能特性 - -### ✅ 已实现功能 - -1. **工单管理** - - 工单列表展示 - - 工单状态管理 - - 工单详情查看 - - 工单操作(呼叫、完成) - -2. **交互功能** - - Tab页面切换 - - 下拉刷新 - - 上拉加载更多 - - 一键拨号 - - 客服咨询 - -3. **UI/UX** - - 响应式设计 - - 暗色模式支持 - - 流畅动画效果 - - 优雅的加载状态 - - 空状态处理 - -4. **技术特性** - - Vue3 组合式 API - - TypeScript 支持 - - 组件化架构 - - SCSS 样式管理 - - 错误处理机制 - -## 使用指南 - -### 快速开始 - -1. **进入工单列表** - ```javascript - uni.navigateTo({ - url: '/pages/order/list' - }) - ``` - -2. **查看功能演示** - ```javascript - uni.navigateTo({ - url: '/pages/order/demo' - }) - ``` - -### 自定义配置 - -1. **修改Tab配置** - ```javascript - const tabList = ref([ - { label: "全部订单", value: "all" }, - { label: "服务工单", value: "service" }, - { label: "自定义Tab", value: "custom" } - ]) - ``` - -2. **自定义工单状态** - ```javascript - const statusMap = { - pending: '待处理', - processing: '处理中', - completed: '已完成', - cancelled: '已取消', - custom: '自定义状态' - } - ``` - -3. **自定义样式主题** - ```scss - :root { - --primary-color: #007AFF; - --success-color: #52C41A; - --warning-color: #FF8C00; - --danger-color: #FF3B30; - } - ``` - -## API 接口 - -### 工单相关接口 - -```javascript -// 获取工单列表 -const getOrderList = async (params) => { - return await uni.request({ - url: '/api/orders', - method: 'GET', - data: params - }) -} - -// 更新工单状态 -const updateOrderStatus = async (orderId, status) => { - return await uni.request({ - url: `/api/orders/${orderId}/status`, - method: 'PUT', - data: { status } - }) -} -``` - -## 性能优化 - -1. **虚拟滚动**:大量数据时建议使用虚拟滚动 -2. **图片懒加载**:工单图片支持懒加载 -3. **防抖处理**:搜索和筛选功能防抖优化 -4. **缓存机制**:Tab切换时数据缓存 - -## 兼容性 - -- **微信小程序**:✅ 完全支持 -- **支付宝小程序**:✅ 支持 -- **H5**:✅ 支持 -- **App**:✅ 支持 - -## 更新日志 - -### v1.0.0 (2024-01-15) -- 🎉 初始版本发布 -- ✨ 完整的工单管理功能 -- ✨ 响应式设计和暗色模式 -- ✨ 组件化架构 -- ✨ 完善的文档和演示 - -## 开发团队 - -- **开发者**:AI Assistant -- **技术栈**:uniapp + Vue3 + SCSS -- **设计规范**:微信小程序设计指南 - -## 许可证 - -MIT License - ---- - -如有问题或建议,请联系开发团队。 \ No newline at end of file diff --git a/src/pages/order/order/prompt.md b/src/pages/order/order/prompt.md deleted file mode 100644 index f80e6e0..0000000 --- a/src/pages/order/order/prompt.md +++ /dev/null @@ -1,181 +0,0 @@ -# 订单管理系统组件需求文档 - -## 项目概述 - -订单管理系统的核心组件库,包含工单卡片、工单列表、咨询栏等核心功能组件。 - -## TopNavBar 组件 - -### 功能要求 - -- 顶部导航栏展示 -- 支持自定义标题内容 -- 支持插槽扩展 - -### 设计要求 - -- 固定在页面顶部 -- 背景色与主题一致 -- 高度适中,不占用过多空间 - -## Tabs 组件 - -### 功能要求 - -- 标签页切换功能 -- 支持默认激活项 -- 切换动画效果 -- 事件回调 - -### 设计要求 - -- 标签间距均匀 -- 激活状态明显 -- 切换动画流畅 -- 响应式适配 - -## OrderCard 组件 - -### 功能要求 - -- 展示工单基本信息(标题、时间、联系人、状态等) -- 支持点击事件 -- 支持呼叫功能 -- 支持完成操作 -- 状态标识清晰 - -### 设计要求 - -- 卡片式布局,圆角设计 -- 信息层次分明 -- 操作按钮位置合理 -- 状态颜色区分明显 -- 支持不同状态的视觉反馈 - -## OrderList 组件 - -### 功能要求 - -- 显示工单列表 -- 集成z-paging组件,支持虚拟列表 -- 支持自定义下拉刷新(文案、样式、阈值) -- 支持自定义上拉加载更多(文案、样式、阈值) -- 自动管理空数据状态 -- 支持固定高度和自适应高度模式 -- 完整的事件回调机制 -- 加载状态管理 - -### 设计要求 - -- 列表项间距合理 -- 加载动画流畅 -- 空状态友好提示 -- 响应式布局 -- 虚拟列表优化大数据渲染性能 - -### z-paging配置 - -- `useVirtualList`: 是否启用虚拟列表(默认true) -- `virtualListHeight`: 虚拟列表高度(默认100%) -- `cellHeightMode`: 单元格高度模式(auto/fixed) -- `fixedHeight`: 固定高度值(当cellHeightMode为fixed时使用) -- `customEmptydiv`: 是否使用自定义空状态 - -## ConsultationBar 组件 - -### 功能要求 - -- 底部固定咨询栏 -- 显示客服信息和联系方式 -- 支持立即咨询功能 -- 默认隐藏,点击"立即呼叫"按钮后显示 -- "立即咨询"按钮单独一行显示 -- 支持显示/隐藏动画效果 - -### 设计要求 - -- 固定在页面底部 -- 背景半透明或纯色 -- 按钮样式与主题一致 -- 信息布局清晰 -- 支持安全区域适配 -- 显示/隐藏动画流畅 - -## 数据结构 - -### 工单数据结构 - -```javascript -{ - id: String, // 工单ID - title: String, // 工单标题 - createTime: String, // 创建时间 - contactName: String, // 联系人姓名 - contactPhone: String, // 联系电话 - status: String, // 状态:pending-待处理, processing-处理中, completed-已完成, cancelled-已取消 - type: String // 类型:service-服务工单, order-普通订单 -} -``` - -### Tab数据结构 - -```javascript -{ - label: String, // 显示文本 - value: String // 值 -} -``` - -## 技术要求 - -### 框架和库 - -- Vue 3 Composition API -- uni-app框架 -- z-paging组件(用于列表优化) -- SCSS样式预处理 - -### 性能优化 - -- 虚拟列表支持大数据量渲染 -- 图片懒加载 -- 组件按需加载 -- 合理的缓存策略 - -### 兼容性 - -- 支持微信小程序 -- 支持H5 -- 支持APP -- 响应式设计,适配不同屏幕尺寸 - -## 更新日志 - -### v1.2.0 (最新) - -- ✅ 集成z-paging组件到OrderList -- ✅ 支持虚拟列表,提升大数据渲染性能 -- ✅ 自定义下拉刷新和上拉加载更多 -- ✅ 自动管理空数据状态 -- ✅ 支持固定高度和自适应高度模式 -- ✅ 完整的事件回调机制 -- ✅ 创建OrderList演示页面 - -### v1.1.0 - -- ✅ 修改ConsultationBar组件布局 -- ✅ "立即咨询"按钮单独一行显示 -- ✅ 默认隐藏,点击"立即呼叫"后显示 -- ✅ 添加显示/隐藏动画效果 -- ✅ 更新相关样式和交互逻辑 - -### v1.0.0 - -- ✅ 完成OrderCard组件开发 -- ✅ 完成OrderList组件开发 -- ✅ 完成ConsultationBar组件开发 -- ✅ 完成TopNavBar组件开发 -- ✅ 完成Tabs组件开发 -- ✅ 完成订单管理页面集成 -- ✅ 创建组件演示页面 -- ✅ 编写技术文档 diff --git a/src/pages/quick/list.vue b/src/pages/quick/index.vue similarity index 73% rename from src/pages/quick/list.vue rename to src/pages/quick/index.vue index c3f402c..d62da2a 100644 --- a/src/pages/quick/list.vue +++ b/src/pages/quick/index.vue @@ -1,23 +1,14 @@ -