mat/docs/superpowers/specs/2026-04-24-h5-material-brow...

8.8 KiB
Raw Permalink Blame History

H5 材料浏览端 设计文档

  • 日期2026-04-24
  • 作者caoqianming
  • 状态:草案

1 · 背景与目标

在现有 mat3 项目PC 端材料管理 + Django 后端)基础上,新增面向手机浏览器的 H5 材料查看端。 核心诉求:只读浏览——登录后按 "大类 → 种类 → 子类 → 材料 → 详情" 的层级快速找到材料并查看详细信息。 不包含新增 / 编辑 / 导入 / 审批等写操作。

2 · 项目结构与技术栈

2.1 组织方式

新建独立项目 frontend-h5/,与现有 frontend/ 平级;独立 Vite、独立依赖、独立打包。

frontend-h5/
├── index.html
├── vite.config.js          # base: '/m/'dev proxy → 后端
├── package.json
├── tailwind.config.js
├── postcss.config.js
└── src/
    ├── main.js
    ├── App.vue
    ├── router/             # vue-router 4history 模式
    ├── store/              # pinia
    ├── api/                # 参照 frontend/src/api 复制同名文件,保持一致
    ├── composables/        # useAuth / useInfiniteScroll / useToast ...
    ├── styles/             # tailwind.css、全局变量
    ├── components/         # MaterialCard / CategoryCard / StarLevel / Chip / NavBar / Toast ...
    └── views/
        ├── Login.vue
        ├── Home.vue
        ├── CategoryDetail.vue
        └── MaterialDetail.vue

2.2 技术栈

  • Vue 3 + vue-router 4 + Pinia
  • Axios同 PC 端一致的拦截器:附 token、统一错误处理、401 跳登录)
  • Tailwind CSS(自定义设计令牌),不使用 Vant/NutUI
  • 少量自研组件Toast、NavBar、Tab、InfiniteList、StarLevel、Chip、Skeleton

2.3 部署

  • 构建产物部署到 Nginx 子路径 /m/(与 PC 端同域名)
  • vite.config.jsbase: '/m/'
  • 开发期 vite devServer 走本地端口(如 5174通过 server.proxy/api 转发到后端

2.4 登录态

  • localStorage 存 tokenkey 为 h5_token(与 PC 端 token 隔离,避免互相污染)
  • Pinia authStore 暴露 token / user / login() / logout()
  • Axios request 拦截器:存在 h5_token 则附 Authorization
  • Axios response 拦截器401 清 token 并跳 /login?redirect=<current>

3 · 路由与页面流

路径 页面 说明
/login Login 账号密码登录
/ Home 大类卡片 + 选中后展开种类区
/category/:major/:category CategoryDetail 子类 Tab + 材料列表
/material/:id MaterialDetail 材料详情(三块)

路由守卫:非 /login 页进入前校验 token无 token → 跳 /login?redirect=<原路径>;登录成功后回跳。

过渡:页面切换用右推左 slide + fade CSS 过渡。

状态保留

  • Pinia uiStore 记录 Home 选中的大类、CategoryDetail 选中的子类 Tab、列表滚动位置
  • 从详情返回时恢复选中态和滚动位置
  • 使用 <keep-alive> 缓存 Home 与 CategoryDetail

4 · 数据接口

4.1 复用现有接口

用途 接口
登录 POST /auth/login/
当前用户 GET /auth/user/
材料列表 GET /material/?major_category=&material_category=&material_subcategory=&search=&page=&page_size=
材料详情 GET /material/{id}/
选项字典 GET /material/choices/

4.2 新增接口

由于 MaterialCategoryMaterial.major_category 没有 FK 关系,"大类下的种类""种类下的子类" 需要从 Material 表按大类 distinct 计算。两个新接口都作为 MaterialViewSet@action 提供。

接口 1GET /material/categories-by-major/?major_category=architecture

  • Material 表取 major_category=X 的记录,按 material_category 分组 count
  • 响应:
    [
      { "value": "地砖", "count": 12 },
      { "value": "涂料", "count": 8 }
    ]
    

接口 2GET /material/subcategories-by-category/?major_category=&material_category=

  • 同上,按 material_subcategory 分组 count过滤空值
  • 响应:
    [
      { "value": "釉面砖", "count": 5 },
      { "value": "通体砖", "count": 3 }
    ]
    

"全部"分类不从后端返回,由前端在 Tab 第一项注入,点击时不传 material_subcategory 参数。

4.3 列表卡片使用字段

  • name(材料名称)
  • cost_compare(成本对比,百分数,负数表示更便宜)
  • advantage_display(竞争优势,取前 2 个 chip 显示)
  • importance_level(重要等级 chip
  • score_level综合评分1-3 星)
  • factory_short_name(供应商简称)

4.4 分页与加载

  • page_size = 20
  • 列表支持下拉刷新 + 上拉无限加载(基于 IntersectionObserver 的 useInfiniteScroll

5 · 视觉与交互设计

5.1 设计语言

克制的卡片式 · 暖中性色 + 墨绿品牌色

  • 背景:白 #FFFFFF + 极浅灰分层 #FAFAFA / #F5F4F2
  • 主色:#2F4F3F(墨绿),用于按钮、重点数值、选中态
  • 辅助色:红 #D2584A(核心)、蓝 #5A7FB8(优先)、灰 #8A8A8A(一般)
  • 卡片圆角 16-20px;阴影 0 1px 2px rgba(0,0,0,.04);不用重描边
  • 字体:系统栈 (-apple-system, "PingFang SC", ...);数值字段启用 font-feature-settings: "tnum" 等宽
  • 点按反馈:active:scale-[0.98] + 背景变深

以上颜色 / 圆角 / 间距在 tailwind.config.js 定义为 theme tokens后续组件直接用工具类。

5.2 关键页面

Login

  • 上 60% 留白 + 品牌标识
  • 下 40% 表单:用户名、密码、提交按钮
  • 失败信息由 Toast 从顶部下滑显示2s 自动消失

Home

  • 顶部栏:欢迎语 + 用户名 + 退出图标
  • 主体2×2 大类卡片网格(建筑/景观/设备/装修),每卡显示大类名 + 材料总数
  • 选中大类后在下方 slide-down + fade 出现种类卡片区2 列网格,卡带材料数角标)
  • 未选中时下方显示引导文案
  • 选中的大类 ID 写入 uiStore,从详情返回恢复展开状态

CategoryDetail

  • 顶部 NavBar返回按钮 + 种类名标题
  • 吸顶的子类 Tab 栏(横向滚动,"全部" 为第一项,选中下划线 + 文字加重)
  • 材料卡列表:通栏,左信息区(名称 / 供应商 / 优势 chip+ 右数值区(成本 / 评分 / 重要等级)
  • 下拉刷新、上拉无限加载
  • 空态:图标 + "暂无材料"

MaterialDetail

  • 顶部 NavBar

  • 可选顶部 bannerbrochure 宣传图16:9懒加载点击可全屏预览

  • 三个 section每个 section 是一张圆角卡:

    1. 材料信息:基础 / 应用 / 优势 / 成本 / 评分,grid-cols-[auto_1fr] 标签值布局;竞争优势、应用场景、重要等级、替代类型用 chip4 项等级用星级可视化。长文本(优势说明、成本说明、应用说明)独立成段。
    2. 品牌与供应商:品牌、供应商简称/全称、合作模式、省-市、对接人、对接人联系方式。电话字段带 tel: 链接可一键拨打。
    3. 案例信息:落地项目、案例(保留换行)、经办人、备注。

5.3 通用交互

  • Loading顶部 NProgress 细线进度条;列表用骨架屏
  • 错误:非 401 错误 Toast 提示;页面级错误态带"重试"按钮
  • 401清 token + 跳登录

6 · 后端改动清单

apps/material/views.py

  • MaterialViewSet 新增两个 @action(detail=False, methods=['get'])
    • categories_by_major
    • subcategories_by_category
  • 两者权限与现有列表一致(登录用户可访问)
  • 考虑给 material_category / material_subcategory 字段的"查询计数"加缓存(低优,后续再说)

无 model migration。

7 · 验收标准

  • 手机浏览器iOS Safari / 微信内置 / Android Chrome访问 /m/,可完成 登录 → 大类 → 种类 → 子类 → 材料详情 的完整浏览
  • 详情页三块布局、字段映射与本文档 §5.2 一致
  • 从详情返回上级页面,滚动位置与选中 Tab 保持
  • 401 时自动跳登录且登录后回跳原路径
  • 包体积:首屏 gzip 后 < 150 KB不含首图
  • 单手可达性:关键按钮在屏幕下半区
  • PC 端 / 功能不受影响

8 · 非目标

  • 新增、编辑、导入、导出、审批
  • 离线缓存 / PWA
  • 多语言
  • 手机号验证码登录(后续视需要再开 Spec

9 · 风险与开放项

  • 微信内置浏览器差异:目前未要求适配微信分享/JSSDK仅确保页面能正常打开
  • H5 与 PC 登录态隔离:使用不同 localStorage key后端 token 为同一份 JWT无服务端改动成本
  • 种类 distinct 性能:当前数据量小可直接 SQL GROUP BY;后续若过万条可再加索引或 Redis 缓存
  • 视觉最终稿:本文档只定方向,具体 mockup 由后续 frontend-design 技能产出