Просмотр исходного кода

fix: 自定义 tabBar 不显示

将 src/custom-tab-bar/index.vue 替换为微信小程序原生组件格式
(wxml/wxss/js/json),解决 uni-app Vue3 编译后未生成小程序
可识别文件导致 tabBar 完全缺失的问题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xuyunhui 1 неделя назад
Родитель
Сommit
fe7ae882ea

+ 0 - 40
emoji_report.txt

@@ -1,40 +0,0 @@
-Files with emoji/symbols: 38
-
-components\common\Toast.vue: ●, ✓, ✗
-components\task\TaskCard.vue: 👷, 📍, 🚗
-pages\common\helpCenter.vue: ▼, ✉, ❓, 🎧, 📞, 🕐
-pages\common\knowledgeDetail.vue: 🏷, 📈, 📋, 📖, 📚, 🔧, 🕐, 🛡
-pages\common\knowledgeList.vue: ✅, 💡, 📄, 📊, 🤝
-pages\common\messageDetail.vue: 🕐
-pages\common\noticeList.vue: 👁
-pages\common\profile.vue: ⚙, ❓, 👤
-pages\common\projectDetail.vue: 👤, 📅, 📋, 📍, 📞
-pages\common\projectList.vue: 👤, 📍, 🔍
-pages\common\publishTask.vue: ▼, ☁, ✅, 🏢, 🔧, 🗺
-pages\common\taskDetail.vue: 👤, 👷, 📍, 📞, 🚗
-pages\construction\dailyTask.vue: ✅, ✓
-pages\construction\helpCenter.vue: ▶, ▼, ⛑, 📋, 📞, 📧, 🕐, 🚛
-pages\construction\home.vue: ⛑, ✅, ❓, 🏠, 👤, 📋, 📚, 🔔, 🚛
-pages\construction\myPage.vue: ❓, 🏠, 👤, 👥, 📋, 📞, 🔒, 🔔
-pages\construction\noticeDetail.vue: 👤, 📢, 🕐
-pages\construction\noticeList.vue: 👁
-pages\construction\taskDetail.vue: ○, ●, ✅, ✓, ❌, 🎉, 💬, 📅, 📋, 📍, 🔧, 🚀, 🚗
-pages\dispatch\availableVehicles.vue: 👤, 🚛
-pages\dispatch\basicInfo.vue: 👤
-pages\dispatch\dutyPersonnel.vue: 🏗, 👤, 📞
-pages\dispatch\emergencyStandby.vue: 👷, 📞, 🚨
-pages\dispatch\helpCenter.vue: ▲, ▼, ❓, 📄, 📚
-pages\dispatch\home.vue: 🏠, 👤, 📅, 📊, 📋, 🔔, 🚛
-pages\dispatch\myPage.vue: ❓, 🎖, 🏠, 🏢, 👤, 📋, 📞, 🔒, 🔔
-pages\dispatch\noticeList.vue: 👁
-pages\dispatch\onDutyStaff.vue: 👷
-pages\dispatch\personnel.vue: 🏗, 👤, 📞
-pages\dispatch\publishTask.vue: ▼, ✅, 🏢, 📅, 🔧, 🚧
-pages\dispatch\schedule.vue: 👤, 🚗
-pages\dispatch\taskDetail.vue: ▼, ⚠, 👤, 👥, 📅, 📋, 📍, 🔧, 🚛
-pages\dispatch\vehicleList.vue: 👤, 🚗
-pages\login\login.vue: ✓, 👤, 🔐, 🧹
-pages\sales\basicInfo.vue: ✏, 🎖, 🏢, 👤, 📅, 📧, 📱
-pages\sales\helpCenter.vue: ▲, ▼, ✉, ❓, 🎧, 📄, 📚, 📞, 🕐
-pages\sales\home.vue: 🏠, 👤, 📁, 📋, 📢, 🔔
-pages\sales\taskReminder.vue: 📍

+ 20 - 0
openspec/changes/fix-missing-custom-tabbar/.comet.yaml

@@ -0,0 +1,20 @@
+workflow: hotfix
+phase: build
+context_compression: off
+build_mode: direct
+build_pause: null
+subagent_dispatch: null
+tdd_mode: direct
+review_mode: off
+isolation: branch
+verify_mode: light
+auto_transition: true
+base_ref: 90d1562daef8961529c03735022dab7b906a46bd
+design_doc: null
+plan: null
+verify_result: pending
+verification_report: null
+branch_status: pending
+created_at: 2026-06-24
+verified_at: null
+archived: false

+ 2 - 0
openspec/changes/fix-missing-custom-tabbar/.openspec.yaml

@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-06-24

+ 36 - 0
openspec/changes/fix-missing-custom-tabbar/design.md

@@ -0,0 +1,36 @@
+# Fix: 自定义 tabBar 不显示
+
+## 根因
+
+`src/custom-tab-bar/index.vue` 使用的是 Vue 单文件组件(SFC)格式。但当前 `@dcloudio/uni-app` 版本(`3.0.0-4080420251103001`)在编译到微信小程序时,并未将 `custom-tab-bar/index.vue` 编译为微信小程序原生组件格式(`wxml`/`wxss`/`js`/`json`),而是原样复制为 `.vue` 文件输出到 `dist/build/mp-weixin/custom-tab-bar/index.vue`。微信小程序运行时无法识别 `.vue` 文件,因此自定义 tabBar 完全不渲染。
+
+验证:构建产物 `dist/build/mp-weixin/custom-tab-bar/` 下仅有 `index.vue` 与 `index.json`,缺少微信小程序所需的 `index.wxml`、`index.wxss`、`index.js`。
+
+## 修复方案
+
+将 `src/custom-tab-bar/index.vue` 替换为微信小程序原生自定义 tabBar 组件:
+
+- `src/custom-tab-bar/index.wxml`:tabBar 结构
+- `src/custom-tab-bar/index.wxss`:tabBar 样式
+- `src/custom-tab-bar/index.js`:读取 `user` 缓存判断角色、切换 tab、高亮当前 tab
+- `src/custom-tab-bar/index.json`:保持 `{ "component": true }`
+
+保留原有业务逻辑:
+- 销售/施工角色显示 3 个 tab:首页、任务、我的
+- 调度角色显示 4 个 tab:首页、排班、任务、我的
+- 使用静态图标资源 `src/static/tabbar/*.png` 替换字符图标
+
+## 实施计划
+
+1. 删除 `src/custom-tab-bar/index.vue`。
+2. 新建 `src/custom-tab-bar/index.wxml`、`index.wxss`、`index.js`。
+3. 运行 `npm run type-check` 与 `npm run build:mp-weixin`。
+4. 检查构建产物中 `custom-tab-bar/` 是否生成 `wxml`/`wxss`/`js`/`json`。
+5. 提交修复。
+
+## 验收标准
+
+- `dist/build/mp-weixin/custom-tab-bar/` 下包含 `index.wxml`、`index.wxss`、`index.js`、`index.json`。
+- 微信开发者工具/真机预览中,tabBar 页面底部出现自定义 tabBar。
+- 切换 tab 时高亮状态正确。
+- 调度角色登录后显示 4 个 tab(首页/排班/任务/我的)。

+ 25 - 0
openspec/changes/fix-missing-custom-tabbar/proposal.md

@@ -0,0 +1,25 @@
+## Why
+
+微信小程序端启用 `tabBar.custom: true` 后,自定义 tabBar(`src/custom-tab-bar/index.vue`)在页面底部完全没有渲染,用户无法通过底部导航切换页面。
+
+## What Changes
+
+- 排查并修复导致 `custom-tab-bar/index.vue` 不渲染的根因。
+- 保留现有销售/调度/施工角色化 tab 配置逻辑。
+- 不新增 capability,仅恢复已有功能。
+
+## Capabilities
+
+### New Capabilities
+
+无。
+
+### Modified Capabilities
+
+无(不涉及 spec 级别行为变更)。
+
+## Impact
+
+- `src/custom-tab-bar/index.vue`
+- `src/pages.json`(如路径/配置不匹配则调整)
+- 可能涉及 `src/manifest.json` 的 `usingComponents` 配置

+ 6 - 0
openspec/changes/fix-missing-custom-tabbar/tasks.md

@@ -0,0 +1,6 @@
+# Tasks: fix-missing-custom-tabbar
+
+- [x] 检查 `pages.json`、`manifest.json`、`custom-tab-bar/index.vue` 配置一致性
+- [x] 将 `src/custom-tab-bar/index.vue` 替换为微信小程序原生组件(wxml/wxss/js)
+- [x] 运行 `npm run type-check` 与 `npm run build:mp-weixin` 验证编译产物
+- [ ] 提交修复

+ 66 - 0
src/custom-tab-bar/index.js

@@ -0,0 +1,66 @@
+const commonTabs = [
+  { pagePath: 'pages/home/home', text: '首页', icon: '/static/tabbar/home.png', activeIcon: '/static/tabbar/home-active.png' },
+  { pagePath: 'pages/task/task', text: '任务', icon: '/static/tabbar/task.png', activeIcon: '/static/tabbar/task-active.png' },
+  { pagePath: 'pages/my/my', text: '我的', icon: '/static/tabbar/my.png', activeIcon: '/static/tabbar/my-active.png' },
+]
+
+const dispatchTabs = [
+  { pagePath: 'pages/home/home', text: '首页', icon: '/static/tabbar/home.png', activeIcon: '/static/tabbar/home-active.png' },
+  { pagePath: 'pages/schedule/schedule', text: '排班', iconText: '▤' },
+  { pagePath: 'pages/task/task', text: '任务', icon: '/static/tabbar/task.png', activeIcon: '/static/tabbar/task-active.png' },
+  { pagePath: 'pages/my/my', text: '我的', icon: '/static/tabbar/my.png', activeIcon: '/static/tabbar/my-active.png' },
+]
+
+function getRole() {
+  try {
+    const userStr = wx.getStorageSync('user')
+    if (userStr) {
+      const user = JSON.parse(userStr)
+      return user.role || ''
+    }
+  } catch (e) {
+    // ignore
+  }
+  return ''
+}
+
+Component({
+  data: {
+    selected: 0,
+    tabs: commonTabs,
+  },
+
+  lifetimes: {
+    attached() {
+      const role = getRole()
+      const tabs = role === 'dispatch' ? dispatchTabs : commonTabs
+      this.setData({ tabs })
+      this.updateSelected()
+    },
+  },
+
+  pageLifetimes: {
+    show() {
+      this.updateSelected()
+    },
+  },
+
+  methods: {
+    switchTab(e) {
+      const { index, pagepath } = e.currentTarget.dataset
+      const url = '/' + pagepath
+      this.setData({ selected: index })
+      wx.switchTab({ url })
+    },
+
+    updateSelected() {
+      const pages = getCurrentPages()
+      const currentPage = pages[pages.length - 1]
+      const route = currentPage ? currentPage.route : ''
+      const idx = this.data.tabs.findIndex(t => t.pagePath === route)
+      if (idx >= 0) {
+        this.setData({ selected: idx })
+      }
+    },
+  },
+})

+ 3 - 0
src/custom-tab-bar/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 19 - 0
src/custom-tab-bar/index.wxml

@@ -0,0 +1,19 @@
+<view class="tab-bar">
+  <view
+    wx:for="{{tabs}}"
+    wx:key="pagePath"
+    class="tab-bar-item {{selected === index ? 'active' : ''}}"
+    data-index="{{index}}"
+    data-pagepath="{{item.pagePath}}"
+    bindtap="switchTab"
+  >
+    <image
+      wx:if="{{item.icon}}"
+      class="tab-icon"
+      src="{{selected === index ? item.activeIcon : item.icon}}"
+      mode="aspectFit"
+    />
+    <view wx:else class="tab-icon tab-icon-text">{{item.iconText}}</view>
+    <view class="tab-text">{{item.text}}</view>
+  </view>
+</view>

+ 46 - 0
src/custom-tab-bar/index.wxss

@@ -0,0 +1,46 @@
+.tab-bar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 50px;
+  background: #ffffff;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  border-top: 1px solid #e5e7eb;
+  z-index: 9999;
+}
+
+.tab-bar-item {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  color: #9ca3af;
+}
+
+.tab-bar-item.active {
+  color: #2563eb;
+}
+
+.tab-icon {
+  width: 24px;
+  height: 24px;
+  margin-bottom: 2px;
+}
+
+.tab-icon-text {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 18px;
+  line-height: 24px;
+}
+
+.tab-text {
+  font-size: 10px;
+  line-height: 14px;
+}