|
|
@@ -0,0 +1,267 @@
|
|
|
+# mobile-h5 全局空态(方案 B)Implementation Plan
|
|
|
+
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
+
|
|
|
+**Goal:** 将 `van-empty` 统一为方案 B(薄荷绿虚线软卡 + 圆形 inbox 插画 + 主/副文案),全站空态一致。
|
|
|
+
|
|
|
+**Architecture:** 只改 H5 shim 组件 `mobile-h5/components/van-empty/van-empty.vue`;页面经 easycom / 显式 import 自动吃到新样式。主页补可选 `tip`;demo comps 演示副文案。
|
|
|
+
|
|
|
+**Tech Stack:** uni-app Vue(Options API)、scoped CSS、三墙 Token(`#0a9f6d` 等)
|
|
|
+
|
|
|
+**Spec:** `docs/superpowers/specs/2026-08-10-mobile-h5-empty-state-design.md`
|
|
|
+**视觉参考:** `mobile-ui/zkxw-mobile-empty-state-demo.html` 方案 B
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## File map
|
|
|
+
|
|
|
+| 路径 | 职责 |
|
|
|
+|------|------|
|
|
|
+| `mobile-h5/components/van-empty/van-empty.vue` | 方案 B 结构 + 样式 + `tip` prop |
|
|
|
+| `mobile-h5/pages/index/index.vue` | 空菜单空态补 `tip` |
|
|
|
+| `mobile-h5/pages/demo/comps.vue` | 演示页补 `tip`(可选副文案) |
|
|
|
+| `mobile-h5/pages/demo/list.vue` | 保持 `description="暂无数据"`,无 tip(验证无占位) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 1: 重写 van-empty 为方案 B
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `mobile-h5/components/van-empty/van-empty.vue`
|
|
|
+
|
|
|
+- [ ] **Step 1: 替换组件全文**
|
|
|
+
|
|
|
+将文件替换为:
|
|
|
+
|
|
|
+```vue
|
|
|
+<template>
|
|
|
+ <view class="v-empty">
|
|
|
+ <view class="v-empty__card">
|
|
|
+ <view class="v-empty__blob">
|
|
|
+ <view class="v-empty__inbox">
|
|
|
+ <view class="v-empty__inbox-lid" />
|
|
|
+ <view class="v-empty__inbox-body" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <text class="v-empty__desc">{{ description || '暂无数据' }}</text>
|
|
|
+ <text v-if="tip" class="v-empty__tip">{{ tip }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ /** H5 兼容:替代 @vant/weapp van-empty(方案 B 虚线软卡) */
|
|
|
+ export default {
|
|
|
+ name: 'VanEmptyShim',
|
|
|
+ props: {
|
|
|
+ description: { type: String, default: '' },
|
|
|
+ tip: { type: String, default: '' }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+ .v-empty {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ padding: 16rpx 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__card {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 16rpx;
|
|
|
+ padding: 44rpx 28rpx 40rpx;
|
|
|
+ border-radius: 28rpx;
|
|
|
+ background: linear-gradient(165deg, #eef9f3 0%, #ffffff 55%);
|
|
|
+ border: 3rpx dashed #b7e5d0;
|
|
|
+ box-shadow: inset 0 0 0 1rpx rgba(255, 255, 255, 0.8);
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__blob {
|
|
|
+ width: 128rpx;
|
|
|
+ height: 128rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: radial-gradient(circle at 35% 30%, #ffffff, #d8f3e7 70%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* CSS 近似 inbox 图标,避免小程序/H5 对 inline SVG 兼容差异 */
|
|
|
+ .v-empty__inbox {
|
|
|
+ position: relative;
|
|
|
+ width: 56rpx;
|
|
|
+ height: 48rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__inbox-lid {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ height: 18rpx;
|
|
|
+ border: 4rpx solid #0a9f6d;
|
|
|
+ border-bottom: none;
|
|
|
+ border-radius: 8rpx 8rpx 0 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__inbox-body {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ height: 34rpx;
|
|
|
+ border: 4rpx solid #0a9f6d;
|
|
|
+ border-radius: 0 0 8rpx 8rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__inbox-body::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 10rpx;
|
|
|
+ right: 10rpx;
|
|
|
+ top: -10rpx;
|
|
|
+ height: 16rpx;
|
|
|
+ border: 4rpx solid #0a9f6d;
|
|
|
+ border-top: none;
|
|
|
+ border-radius: 0 0 6rpx 6rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__desc {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #5d746a;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 1.4;
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-empty__tip {
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: #8aa198;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 1.4;
|
|
|
+ }
|
|
|
+</style>
|
|
|
+```
|
|
|
+
|
|
|
+说明:用 CSS 拼 inbox 轮廓,避免 uni-app H5 对 `<svg><use>` 不稳定;视觉对齐 Demo B 的绿色线框收件箱。
|
|
|
+
|
|
|
+- [ ] **Step 2: 自检色值**
|
|
|
+
|
|
|
+确认文件中无 `#10b981`;主色仅为 `#0a9f6d`。
|
|
|
+
|
|
|
+- [ ] **Step 3: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add mobile-h5/components/van-empty/van-empty.vue
|
|
|
+git commit -m "feat(mobile-h5): restyle van-empty as dashed soft card (scheme B)"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 2: 调用方补 tip(主页 + comps)
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `mobile-h5/pages/index/index.vue`
|
|
|
+- Modify: `mobile-h5/pages/demo/comps.vue`
|
|
|
+- Verify only: `mobile-h5/pages/demo/list.vue`(不改,保持无 tip)
|
|
|
+
|
|
|
+- [ ] **Step 1: 主页空态加 tip**
|
|
|
+
|
|
|
+在 `mobile-h5/pages/index/index.vue` 将:
|
|
|
+
|
|
|
+```vue
|
|
|
+<VanEmpty v-else description="暂无可用菜单权限" />
|
|
|
+```
|
|
|
+
|
|
|
+改为:
|
|
|
+
|
|
|
+```vue
|
|
|
+<VanEmpty
|
|
|
+ v-else
|
|
|
+ description="暂无可用菜单权限"
|
|
|
+ tip="请联系管理员开通功能入口"
|
|
|
+/>
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: comps 演示页加 tip**
|
|
|
+
|
|
|
+在 `mobile-h5/pages/demo/comps.vue` 将:
|
|
|
+
|
|
|
+```vue
|
|
|
+<van-empty description="暂无相关数据" />
|
|
|
+```
|
|
|
+
|
|
|
+改为:
|
|
|
+
|
|
|
+```vue
|
|
|
+<van-empty
|
|
|
+ description="暂无相关数据"
|
|
|
+ tip="可下拉刷新,或点击上方按钮新增一条记录"
|
|
|
+/>
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 确认 list 页不传 tip**
|
|
|
+
|
|
|
+`mobile-h5/pages/demo/list.vue` 保持:
|
|
|
+
|
|
|
+```vue
|
|
|
+<van-empty v-if="!list.length" description="暂无数据" />
|
|
|
+```
|
|
|
+
|
|
|
+验收:无 tip 时不出现空白副文案行。
|
|
|
+
|
|
|
+- [ ] **Step 4: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add mobile-h5/pages/index/index.vue mobile-h5/pages/demo/comps.vue
|
|
|
+git commit -m "feat(mobile-h5): add empty-state tip on home and comps demo"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 3: 视觉验收
|
|
|
+
|
|
|
+**Files:** 无代码变更
|
|
|
+
|
|
|
+- [ ] **Step 1: 本地打开 / 刷新 H5**
|
|
|
+
|
|
|
+主页(菜单为空)应看到:虚线软卡、圆形插画、主文案「暂无可用菜单权限」、副文案「请联系管理员开通功能入口」;无 ∅。
|
|
|
+
|
|
|
+- [ ] **Step 2: 对照 Demo**
|
|
|
+
|
|
|
+对照 `mobile-ui/zkxw-mobile-empty-state-demo.html` 方案 B:结构与色调一致即可(inbox 为 CSS 近似)。
|
|
|
+
|
|
|
+- [ ] **Step 3: 抽查 list / comps**
|
|
|
+
|
|
|
+- comps:有 tip
|
|
|
+- list 清空数据后:仅主文案「暂无数据」,无 tip 占位
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Spec coverage checklist
|
|
|
+
|
|
|
+| Spec 要求 | Task |
|
|
|
+|-----------|------|
|
|
|
+| 方案 B 视觉(渐变虚线卡 + blob + 主/副文案) | Task 1 |
|
|
|
+| `description` + `tip` API | Task 1 |
|
|
|
+| 主页 tip | Task 2 |
|
|
|
+| comps tip 演示 | Task 2 |
|
|
|
+| list 无 tip 不占位 | Task 2 Step 3 / Task 3 |
|
|
|
+| 三墙色、无 `#10b981` | Task 1 Step 2 |
|
|
|
+| 不引入 E 变体 / 不引真实 Vant | 全计划未包含 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Out of scope
|
|
|
+
|
|
|
+- 横向紧凑变体 E
|
|
|
+- 真实 `@vant/weapp` 依赖
|
|
|
+- 改业务菜单数据源(菜单仍为空数组)
|