Files

249 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: frontend-app-common
description: app 移动端公共开发规范,基于 uni-app、Vue 和 uView Pro,覆盖页面组织、路由、组件、扫码交互、视觉字号和交付检查
globs:
- "frontend/app/**/*.vue"
- "frontend/app/**/*.js"
- "frontend/app/pages.json"
---
## 技术基线
当前 APP 位于 `frontend/app/`,使用以下技术约定:
- uni-app 页面运行模式。
- 页面采用 Vue 单文件组件(`.vue`)。
- `main.js` 注册 `@/uni_modules/uview-pro`,并注入全局主题 mixin;每个页面可直接通过 `themeMode` 获取 `light`/`dark`,根容器必须绑定 `:class="`theme-${themeMode}`"`。
- 全局主题状态由 `utils/theme.js` 管理:`applyAppTheme(mode)` 会持久化 `scanapp_theme_mode`、同步导航栏颜色并广播 `scanapp-theme-change`;设置页切换主题时必须调用它,不能只修改本页 class。
- `pages.json` 开启 uView Pro Easycom 自动组件扫描。
- uView Pro 组件使用 `u-*` 命名,例如 `u-icon`、`u-input`、`u-form`、`u-button`、`u-switch`。
- 兼容 Vue 2 和 Vue 3 入口,新增页面优先遵循现有 Options API 写法,除非项目整体迁移。
## 目录与页面组织
```text
frontend/app/
├── App.vue
├── main.js
├── pages.json
├── uni.scss
├── pages/
│ ├── auth/
│ │ ├── login.vue
│ │ └── register.vue
│ ├── entry/
│ │ ├── order.vue
│ │ └── machine.vue
│ ├── exception/
│ │ └── index.vue
│ ├── repair/
│ │ ├── index.vue
│ │ └── tasks.vue
│ ├── query/
│ │ ├── index.vue
│ │ ├── index copy.vue
│ │ └── index.vue
│ ├── settings/
│ │ └── index.vue
│ ├── statistics/
│ │ └── index.vue
│ └── index/
│ └── index.vue
└── uni_modules/
```
新增页面时:
1. 页面文件放入 `pages/<module>/`。
2. 页面入口优先使用 `index.vue`,业务模式页面可使用明确名称,例如 `entry/order.vue`。
3. 必须在 `pages.json` 的 `pages` 数组中注册路由。
4. `pages.json` 中的路径不带 `.vue` 后缀,例如 `pages/settings/index`;设置模块也允许使用与路由同名的平铺页面文件,例如 `pages/settings/feedback.vue` 对应 `pages/settings/feedback`。
5. 页面导航标题通过路由项的 `style.navigationBarTitleText` 配置。
6. 不要把未注册的副本页面当作运行页面维护;例如 `index copy.vue` 不属于正式路由。
7. `pages.json` 的首项保持为 `pages/index/index`,APP 启动默认进入首页,不把登录页放在最前面。
## 页面结构规范
页面组件按以下顺序组织:
1. `<template>`:页面结构和交互绑定。
2. `<script>`:`data`、`computed`、`watch`、`methods` 和生命周期。
3. `<style lang="scss" scoped>`:页面局部样式。
页面模板建议采用以下结构:
- 页面根节点使用语义化页面类名,例如 `.settings-page`、`.query-page`、`.entry-page`。
- 页面按业务区块拆分为卡片、列表、表单和操作区域。
- 重复数据使用 `v-for`,并使用稳定的业务字段作为 `:key`。
- 交互统一使用 `@tap` 或现有组件支持的事件写法。
- 对话框、提示和扫码等平台能力统一通过 `uni.*` API 调用。
## 组件使用规范
优先使用项目已有的 uView Pro 组件,不重复实现同类基础控件:
| 场景 | 组件或能力 |
|------|------------|
| 图标 | `u-icon` |
| 文本输入 | `u-input` |
| 表单 | `u-form`、`u-form-item` |
| 按钮 | `u-button` |
| 开关 | `u-switch` |
| 空状态 | `u-empty` |
| 页面提示 | `uni.showToast` |
| 操作选择 | `uni.showActionSheet` |
| 页面跳转 | `uni.navigateTo`、`uni.navigateBack`、`uni.reLaunch` |
| 基础相机扫码 | `uni.scanCode` |
| 相册识图 / 原生扫码体验 | `@/uni_modules/mas-code-scan` 的 `openCodeScan`(仅 App-Plus) |
使用 uView Pro 组件时:
- 通过 Easycom 直接使用 `u-*` 标签,不在页面内重复注册组件。
- 沿用项目当前属性命名和事件写法。
- 按钮、输入框、表单等控件保持页面间的尺寸、圆角和状态表现一致。
- 图标使用 `u-icon`,不手写重复的 SVG 图标。
## 页面交互规范
### 页面跳转
使用 `uni` 导航 API,并与 `pages.json` 中已注册路径保持一致:
```js
uni.navigateTo({
url: '/pages/settings/index'
})
```
APP 默认允许直接进入首页和访问普通页面;登录页只在用户点击需要登录的能力时出现。需要登录的入口先检查本地登录态,未登录时使用 `uni.showModal` 提示,再跳转 `/pages/auth/login?redirect=<目标页>`;登录成功后写入登录态并使用 `uni.redirectTo` 回到 `redirect` 指定页面。普通功能页之间使用 `uni.navigateTo`。
### 扫码
基础相机扫码可使用 `uni.scanCode`:
```js
uni.scanCode({
onlyFromCamera: true,
scanType: ['barCode', 'qrCode'],
success: (res) => {
this.form.code = String(res.result || '').trim()
},
fail: () => {
uni.showToast({ title: '未完成扫码', icon: 'none' })
}
})
```
要求:
- 扫码结果先转为字符串并去除首尾空格。
- 同时支持条码和二维码时使用 `['barCode', 'qrCode']`。
- 扫码失败必须给出中文提示。
- 扫码后的结果应回填当前字段,不要跨页面隐式修改无关状态。
- 若业务需要相册识图、图片预览加载态、智能变焦或多码点选,使用 `@/uni_modules/mas-code-scan` 的 `openCodeScan`,并以 `// #ifdef APP-PLUS` 包裹导入与调用;`success` 中读取 `result.content` 后回填字段,`9021003` 视为用户取消不提示,其他错误显示中文提示。
- 有效识别区域通过 `options.scanRegion` 传给 `openCodeScan`,结构为 `fullScreen` 或 `width`、`height`、`centerX`、`centerY` 的 0~1 比例;业务页面统一调用 `@/utils/scan-settings.js` 的 `getScanRegionSetting()`,设置按 `scanapp_settings_<userCode>` 持久化。未配置时返回空对象,保持插件原有整帧识别行为。
- APP-PLUS Android 原生 `uni.showModal` 的按钮视觉顺序与 H5 不一致时,统一由 `main.js` 的平台适配层交换显示文本,并还原 `success`/Promise 的 `confirm`、`cancel` 语义;业务页面继续按标准语义编写,不要逐个页面交换按钮或回调判断。
### 表单与提示
- 提交前先执行页面级校验。
- 校验失败通过 `uni.showToast({ title, icon: 'none' })` 提示。
- 提交期间使用 `loading` 或 `submitting` 状态防止重复提交。
- 成功、失败和异常状态使用明确的中文提示。
- 原型阶段可以使用本地 mock 数据,但要保持数据结构与真实业务字段一致,并将接口接入限制在 service/API 层,不在模板中直接拼接请求。
### 接口封装
- APP 对接后端时统一通过 `frontend/app/utils/request.js` 发起 `uni.request`,页面中不要直接调用 `uni.request`。
- 请求配置集中放在 `frontend/app/config/index.js`,当前生产插件 APP 业务端默认 `baseURL` 为 `/appapi`;主项目系统 API(例如 `/file/image` 上传)实际注册在 `/api`,调用时必须显式传入 `baseURL: config.apiBaseURL`,不能沿用默认基址。
- 业务接口按模块放入 `frontend/app/api/<module>/`,例如生产扫码接口放在 `api/produce/data-entry.js`。
- API 函数命名按页面语义表达,例如 `getProcessOptions`、`submitOrderRecord`、`getOrderStatistics`,页面只调用这些函数。
- 业务表单中的图片统一采用“本地预览、提交时上传”:选图后仅保存 `tempFilePaths` 用于立即预览;提交时调用 `@/api/upload.js` 的 `uploadImage(filePath, subDir)`,将返回的服务器 URL 放入业务请求。上传失败时中止提交并保留本地图片,便于用户重试。
- 图片上传使用 `/api/file/image` 和 `config.apiBaseURL`;公共 `normalizeImageUrl()` 会将后端本地存储返回的 `127.0.0.1` / `localhost` URL 改写为配置的局域网后端地址,避免 Android 真机将回环地址解析为手机自身。历史记录中的服务器图片地址也必须经过该方法规范化。
- 响应格式沿用后端 `Json::success` / `Json::fail`:`code === 0` 时默认返回 `data`,失败使用 `msg` 做中文提示。
- token 从本地 `scanapp_token` 读取并写入 `Authorization` 请求头;后续接真实登录接口时替换原型 token 来源,不改页面调用方式。
## 样式与视觉规范
### 基础单位
- 移动端尺寸统一使用 `rpx`。
- 不在同一页面混用无必要的 `px`、`rem` 和 `rpx`。
- 页面根节点设置 `min-height: 100vh`,并统一使用 `box-sizing: border-box`。
- 卡片、按钮和输入区域的尺寸应保持稳定,避免文字变化造成布局跳动。
### 字号层级
正式运行页面统一使用以下字号档位,不新增其他字号:
| 字号 | 使用场景 |
|------|----------|
| `38rpx` | 页面主标题、品牌主标题 |
| `32rpx` | 核心数据、关键数字、弹层主编号 |
| `28rpx` | 区块标题、记录主标题、主要设置项 |
| `26rpx` | 字段值、重点内容、次级编号 |
| `24rpx` | 操作文字、重要次级内容 |
| `22rpx` | 正文、按钮文字、表单标签 |
| `20rpx` | 说明文字、筛选项、辅助信息 |
| `18rpx` | 状态、时间、标签、脚注 |
字号要求:
- 最大字号不得超过 `38rpx`。
- 最小字号不得低于 `18rpx`。
- 不使用 `23rpx`、`30rpx`、`34rpx`、`36rpx`、`40rpx` 等非标准档位。
- 同一语义在不同页面使用相同字号,例如所有页面的卡片标题统一为 `28rpx`。
- 只因字号调整而产生的视觉问题,优先调整容器宽度或换行,不随意增加新的字号档位。
### 颜色与层级
沿用当前 APP 的清爽生产工具风格:
- 页面背景使用浅色中性背景,例如 `#f4f6fb`、`#f5f7fb`。
- 内容卡片使用白色背景和轻量阴影。
- 主色优先使用项目现有蓝色 `#1677ff` 或 `#2f6cf6`。
- 成功状态使用绿色,失败或危险状态使用红色,警告状态使用橙色或黄色。
- 文字颜色按主标题、正文、说明、辅助信息分级,不使用过多高饱和颜色。
- 不在单个页面引入与现有页面不一致的主题色、渐变方向或状态颜色。
### 布局一致性
- 页面内容使用统一的左右内边距和卡片间距,除非现场扫码等业务场景确实需要特殊布局。
- 卡片圆角、边框、阴影应与同类页面保持一致。
- 列表项使用分隔线或稳定卡片层级,不将多个卡片无意义地嵌套。
- 右侧操作统一使用开关、值文本、箭头或图标表达,不重复增加装饰性按钮。
- 小屏幕上长单号、商品编码等业务文本允许换行或使用 `word-break: break-all`。
- 安卓端需要控制图标、文字、开关之间的横向距离时,优先使用显式 `margin-left` / `margin-right` 或固定 `flex-shrink: 0`,不要把关键间距只交给 `gap`;涉及 `u-switch`、自定义开关和扫码结果卡片时尤其如此。
- 如果同一行里有图标+文字+开关这类组合,先确认安卓端真机表现,再决定是否保留 `gap`,默认把分离距离写在紧邻元素上。
## 状态与数据规范
- 页面临时状态放在当前页面 `data` 中;跨页面共享状态需要先确认项目是否已有 store 方案。
- 加载、空数据、提交中、成功、失败和禁用状态必须有明确表现。
- mock 数据仅用于原型展示,不应伪装成已接入后端。
- 不在本次样式任务中删除已有功能、字段、交互或路由。
- 修改中心样式或公共能力前,先搜索所有页面调用方。
## 维护与演进规则
当项目实际实现与本技能不一致时:
1. 先读取真实入口、路由、组件配置和页面调用方式。
2. 以项目代码为准,不强行套用旧模板。
3. 将已验证的新约定同步到本技能文件。
4. 技能更新只描述确认过的差异,不进行无关重写。
## 开发检查清单
- [ ] 页面文件位于 `frontend/app/pages/` 合适目录。
- [ ] 新页面已注册到 `pages.json`。
- [ ] 导航路径与 `pages.json` 完全一致。
- [ ] 已复用 uView Pro 组件和现有 `uni.*` 能力。
- [ ] 扫码结果已清理空格,并处理成功和失败状态。
- [ ] 表单已处理空值、重复提交和失败提示。
- [ ] 字号只使用 `18/20/22/24/26/28/32/38rpx`。
- [ ] 页面没有超过 `38rpx` 或低于 `18rpx` 的字号。
- [ ] 同类页面的标题、正文、说明、状态字号一致。
- [ ] 未修改与需求无关的功能、数据和路由。
- [ ] 真机或移动端预览已检查长文本、空状态、弹层和底部操作区域。